项目开发问题汇总

创建时间:2021/11/23 14:52
更新时间:2022/6/9 17:53
作者:Chris
来源:file:///C:/Users/13622314539/AppData/Local/Youdao/YNote/markdown/index.html

开发问题汇总

1 上传aws内存溢出问题

文件上传aws时如果不设置文件内存长度,则 PutObjectRequest 会将文件全部加载到内存中来,

2 ZUUL网关响应头部不返回

https://www.jianshu.com/p/06da38e0c239

问题
默认的"Cookie",, "Set-Cookie","Authorization"会当做敏感信息头部不返回出去

解决

  1. 可以通过修改配置来调整屏蔽的敏感信息头部,甚至可以不屏蔽敏感信息头部,全都返回,因为默认是有三个敏感信息头部的,所以需要手动设置来改变这个默认配置
  2. 可以自己指定要屏蔽的response header,如果不想屏蔽,都要返回,那直接不写具体的内容即可,但是必须要增加这个配置

yml

zuul:
    sensitive-headers:

properties

zuul.sensitive-headers=

3 BigDecimal 丢失精度

/**
* 通过测试发现,当使用 double 或者 float 这些浮点数据类型时,会丢失精度,String、int 则不会
* 所以,在涉及到精度计算的过程中,我们尽量使用 String 类型来进行转换。
* <p>
* 88
* 8.8
* 8.800000000000000710542735760100185871124267578125
*/
@Test
public void test() {
    BigDecimal bigDecimal = new BigDecimal(88);
    System.out.println(bigDecimal);
    bigDecimal = new BigDecimal("8.8");
    System.out.println(bigDecimal);
    bigDecimal = new BigDecimal(8.8);
    System.out.println(bigDecimal);
}
%5BTOC%5D%0A%23%23%23%20%E5%BC%80%E5%8F%91%E9%97%AE%E9%A2%98%E6%B1%87%E6%80%BB%0A%23%23%23%23%201%20%E4%B8%8A%E4%BC%A0aws%E5%86%85%E5%AD%98%E6%BA%A2%E5%87%BA%E9%97%AE%E9%A2%98%0A%3E%20%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0aws%E6%97%B6%E5%A6%82%E6%9E%9C%E4%B8%8D%E8%AE%BE%E7%BD%AE%E6%96%87%E4%BB%B6%E5%86%85%E5%AD%98%E9%95%BF%E5%BA%A6%EF%BC%8C%E5%88%99%20%60PutObjectRequest%60%20%E4%BC%9A%E5%B0%86%E6%96%87%E4%BB%B6%E5%85%A8%E9%83%A8%E5%8A%A0%E8%BD%BD%E5%88%B0%E5%86%85%E5%AD%98%E4%B8%AD%E6%9D%A5%EF%BC%8C%0A%0A!%5B59cbbacbacb1d6788ba12fbb1bb3ddae.png%5D(en-resource%3A%2F%2Fdatabase%2F1169%3A1)%0A%0A!%5B10a03cb5d9be0ed843bc043ef02d0ad5.png%5D(en-resource%3A%2F%2Fdatabase%2F1171%3A1)%0A%0A%0A%23%23%23%23%202%20ZUUL%E7%BD%91%E5%85%B3%E5%93%8D%E5%BA%94%E5%A4%B4%E9%83%A8%E4%B8%8D%E8%BF%94%E5%9B%9E%0Ahttps%3A%2F%2Fwww.jianshu.com%2Fp%2F06da38e0c239%0A%3E%20%E9%97%AE%E9%A2%98%20%20%0A%3E%20%E9%BB%98%E8%AE%A4%E7%9A%84%22Cookie%22%2C%2C%20%22Set-Cookie%22%2C%22Authorization%22%E4%BC%9A%E5%BD%93%E5%81%9A%E6%95%8F%E6%84%9F%E4%BF%A1%E6%81%AF%E5%A4%B4%E9%83%A8%E4%B8%8D%E8%BF%94%E5%9B%9E%E5%87%BA%E5%8E%BB%20%20%0A%0A%3E%20%E8%A7%A3%E5%86%B3%20%20%20%0A%3E%201.%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE%E6%9D%A5%E8%B0%83%E6%95%B4%E5%B1%8F%E8%94%BD%E7%9A%84%E6%95%8F%E6%84%9F%E4%BF%A1%E6%81%AF%E5%A4%B4%E9%83%A8%EF%BC%8C%E7%94%9A%E8%87%B3%E5%8F%AF%E4%BB%A5%E4%B8%8D%E5%B1%8F%E8%94%BD%E6%95%8F%E6%84%9F%E4%BF%A1%E6%81%AF%E5%A4%B4%E9%83%A8%EF%BC%8C%E5%85%A8%E9%83%BD%E8%BF%94%E5%9B%9E%EF%BC%8C%E5%9B%A0%E4%B8%BA%E9%BB%98%E8%AE%A4%E6%98%AF%E6%9C%89%E4%B8%89%E4%B8%AA%E6%95%8F%E6%84%9F%E4%BF%A1%E6%81%AF%E5%A4%B4%E9%83%A8%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E6%89%8B%E5%8A%A8%E8%AE%BE%E7%BD%AE%E6%9D%A5%E6%94%B9%E5%8F%98%E8%BF%99%E4%B8%AA%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%0A%3E%202.%20%E5%8F%AF%E4%BB%A5%E8%87%AA%E5%B7%B1%E6%8C%87%E5%AE%9A%E8%A6%81%E5%B1%8F%E8%94%BD%E7%9A%84response%20header%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E6%83%B3%E5%B1%8F%E8%94%BD%EF%BC%8C%E9%83%BD%E8%A6%81%E8%BF%94%E5%9B%9E%EF%BC%8C%E9%82%A3%E7%9B%B4%E6%8E%A5%E4%B8%8D%E5%86%99%E5%85%B7%E4%BD%93%E7%9A%84%E5%86%85%E5%AE%B9%E5%8D%B3%E5%8F%AF%EF%BC%8C%E4%BD%86%E6%98%AF%E5%BF%85%E9%A1%BB%E8%A6%81%E5%A2%9E%E5%8A%A0%E8%BF%99%E4%B8%AA%E9%85%8D%E7%BD%AE%0A%0A%3E%20yml%0A%60%60%60%0Azuul%3A%0A%20%20%20%20sensitive-headers%3A%0A%60%60%60%0A%3E%20properties%0A%60%60%60%0Azuul.sensitive-headers%3D%0A%60%60%60%0A%0A%23%23%23%23%203%20BigDecimal%20%E4%B8%A2%E5%A4%B1%E7%B2%BE%E5%BA%A6%0A%60%60%60java%0A%2F**%0A*%20%E9%80%9A%E8%BF%87%E6%B5%8B%E8%AF%95%E5%8F%91%E7%8E%B0%EF%BC%8C%E5%BD%93%E4%BD%BF%E7%94%A8%20double%20%E6%88%96%E8%80%85%20float%20%E8%BF%99%E4%BA%9B%E6%B5%AE%E7%82%B9%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E6%97%B6%EF%BC%8C%E4%BC%9A%E4%B8%A2%E5%A4%B1%E7%B2%BE%E5%BA%A6%EF%BC%8CString%E3%80%81int%20%E5%88%99%E4%B8%8D%E4%BC%9A%0A*%20%E6%89%80%E4%BB%A5%EF%BC%8C%E5%9C%A8%E6%B6%89%E5%8F%8A%E5%88%B0%E7%B2%BE%E5%BA%A6%E8%AE%A1%E7%AE%97%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%EF%BC%8C%E6%88%91%E4%BB%AC%E5%B0%BD%E9%87%8F%E4%BD%BF%E7%94%A8%20String%20%E7%B1%BB%E5%9E%8B%E6%9D%A5%E8%BF%9B%E8%A1%8C%E8%BD%AC%E6%8D%A2%E3%80%82%0A*%20%3Cp%3E%0A*%2088%0A*%208.8%0A*%208.800000000000000710542735760100185871124267578125%0A*%2F%0A%40Test%0Apublic%20void%20test()%20%7B%0A%20%20%20%20BigDecimal%20bigDecimal%20%3D%20new%20BigDecimal(88)%3B%0A%20%20%20%20System.out.println(bigDecimal)%3B%0A%20%20%20%20bigDecimal%20%3D%20new%20BigDecimal(%228.8%22)%3B%0A%20%20%20%20System.out.println(bigDecimal)%3B%0A%20%20%20%20bigDecimal%20%3D%20new%20BigDecimal(8.8)%3B%0A%20%20%20%20System.out.println(bigDecimal)%3B%0A%7D%0A%60%60%60

jackson

创建时间:2022/5/23 11:25
更新时间:2022/6/7 20:08
作者:Chris
来源:https://github.com/alibaba/fastjson2/releases/tag/2.0.1

1. 核心模块

Jackson 的核心模块由三部分组成

  1. jackson-core,核心包, 提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator, Jackson内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。
  2. jackson-annotations,注解包,提供标准注解功能。
  3. jackson-databind ,数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。

2. 怎么用

2.1 引入依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
</dependency>

jackson-databind 依赖 jackson-core 和 jackson-annotations,当添加 jackson-databind 之后, jackson-core 和 jackson-annotations 也随之添加到 Java 项目工程中。在添加相关依赖包之后,就可以使用 Jackson。

2.2 对象绑定

Jackson 最常用的 API 就是基于"对象绑定" 的 ObjectMapper

@Test
public void test() throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    User user = new User();
    user.set..
    
    //序列化
    String jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
    //反序列化
    user = mapper.readValue(jsonString, User.class);
}

2.2.1 writeValue

ObjectMapper 通过 writeValue 系列方法将 java 对象序列化为 json,并将 json 存储成不同的格式:String(writeValueAsString)、Byte Array(writeValueAsBytes)、Writer、File、OutStream、DataOutput。

2.2.2 readValue

ObjectMapper 通过 readValue 系列方法从不同的数据源: String、Byte Array、Reader、File、URL、InputStream 中反序列化为 java 对象。

在调用 writeValue 或调用 readValue 方法之前,往往需要设置 ObjectMapper 的相关配置信息。这些配置信息应用 java 对象的所有属性上。

示例如下

//在反序列化时忽略在 json 中存在但 Java 对象不存在的属性 
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false); 
//在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ 
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false) 
//在序列化时忽略值为null的属性 
mapper.setSerializationInclusion(Include.NON_NULL); 
//忽略值为默认值的属性 
mapper.setDefaultPropertyInclusion(Include.NON_DEFAULT);

2.3 序列化

Jackson ObjectMapper提供了三种方法转换

writeValue()
writeValueAsString() 
writeValueAsBytes()
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car();
car.brand = "BMW";
car.doors = 4;

objectMapper.writeValue(new FileOutputStream("data/output-2.json"), car);
objectMapper.writeValue(new File("data/output-2.json"), car);
String json = objectMapper.writeValueAsString(car);
byte[] jsonBytes = objectMapper.writeValueAsBytes(car);

2.4 反序列化

从json字符串读取

ObjectMapper objectMapper = new ObjectMapper();
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
Car car = objectMapper.readValue(carJson, Car.class);

从json Reader读取

ObjectMapper objectMapper = new ObjectMapper();
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 4 }";
Reader reader = new StringReader(carJson);
Car car = objectMapper.readValue(reader, Car.class);

从json文件读取

ObjectMapper objectMapper = new ObjectMapper();
File file = new File("data/car.json");
Car car = objectMapper.readValue(file, Car.class);

从json网络文件地址读取

ObjectMapper objectMapper = new ObjectMapper();
URL url = new URL("file:data/car.json");
Car car = objectMapper.readValue(url, Car.class);

从流中读取

ObjectMapper objectMapper = new ObjectMapper();
InputStream input = new FileInputStream("data/car.json");
Car car = objectMapper.readValue(input, Car.class);

从json字节数组中读取

ObjectMapper objectMapper = new ObjectMapper();
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
byte[] bytes = carJson.getBytes("UTF-8");
Car car = objectMapper.readValue(bytes, Car.class);

2.4.1 反序列化不同类型

转换为数组

String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
ObjectMapper objectMapper = new ObjectMapper();
Car[] cars = objectMapper.readValue(jsonArray, Car[].class);

转换为集合

String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> cars = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>(){});

转换为Map

String jsonObject = "{\"brand\":\"ford\", \"doors\":5}";
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> jsonMap = objectMapper.readValue(jsonObject, new TypeReference<Map<String,Object>>(){});

2.5 时间类型格式化

Jackson 默认会将java.util.Date对象转换成long值,同时也支持将时间转换成格式化的字符串

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
objectMapper.setDateFormat(dateFormat);

String json = objectMapper.writeValueAsString(对象);

2.6 JSON树模型

Jackson 也提供了树模型(tree model)来生成和解析 json。

若想修改或访问 json 部分属性,树模型是不错的选择。树模型由 JsonNode 节点组成

String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
ObjectMapper objectMapper = new ObjectMapper();
try {
    JsonNode node = objectMapper.readValue(carJson, JsonNode.class);
    
    JsonNode brandNode = node.get("brand");
    String brand = brandNode.asText();
    System.out.println("brand = " + brand);

    JsonNode doorsNode = node.get("doors");
    int doors = doorsNode.asInt();
    System.out.println("doors = " + doors);

    JsonNode array = node.get("owners");
    JsonNode jsonNode = array.get(0);
    String john = jsonNode.asText();
    System.out.println("john  = " + john);

    JsonNode child = node.get("nestedObject");
    JsonNode childField = child.get("field");
    String field = childField.asText();
    System.out.println("field = " + field);
} catch (IOException e) {
    e.printStackTrace();
}
@Test
public void testJsonNode() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    JsonNode node = mapper.readValue(JSON_STR, JsonNode.class);
    String firstName = node.get("firstName").asText();
    JsonNode phoneNumbers = node.get("phoneNumbers");
    Iterator<JsonNode> elements = phoneNumbers.elements();

    while (elements.hasNext()) {
        JsonNode next = elements.next();
        String type = next.get("type").asText();
        String number = next.get("number").asText();
        log.info("type:{}, number:{}", type, number);
    }
}
[main] INFO com.chris.hutool.json.JackSonTest - type:iPhone, number:0123-4567-8888
[main] INFO com.chris.hutool.json.JackSonTest - type:home, number:0123-4567-8910

2.7 JsonParser

JsonParser 提供很多方法来读取 json 信息, 如 isClosed(), nextToken(), getValueAsString()等。

若想单独创建 JsonParser,可以通过 JsonFactory() 的 createParser。

String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
JsonFactory factory = new JsonFactory();
JsonParser  parser  = factory.createParser(carJson);

Car car = new Car();
while(!parser.isClosed()){
    JsonToken jsonToken = parser.nextToken();

    if(JsonToken.FIELD_NAME.equals(jsonToken)){
        String fieldName = parser.getCurrentName();
        System.out.println(fieldName);

        jsonToken = parser.nextToken();

        if("brand".equals(fieldName)){
            car.brand = parser.getValueAsString();
        } else if ("doors".equals(fieldName)){
            car.doors = parser.getValueAsInt();
        }
    }
}

System.out.println("car.brand = " + car.brand);
System.out.println("car.doors = " + car.doors);

也可以通过Reader, InputStream, URL, byte arraychar array来创建JsonParser

2.8 JsonGenerator

JsonGenerator 有多种 write 方法以支持生成复杂的类型的 json,比如 writeArray,writeTree 等 。若想单独创建 JsonGenerator,可以通过 JsonFactory() 的 createGenerator。

JsonFactory factory = new JsonFactory();

JsonGenerator generator = factory.createGenerator(new File("data/output.json"), JsonEncoding.UTF8);

generator.writeStartObject();
generator.writeStringField("brand", "Mercedes");
generator.writeNumberField("doors", 5);
generator.writeEndObject();

generator.close();

3. 配置相关属性

SerializationFeature 序列化相关属性

DeserializationFeature 反序列化相关属性

MapperFeature

JsonParser.Feature(解析器特性)

JsonGenerator

JsonFactory

4. XML 实体互转

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.5</version>
</dependency>
/*
 * Java对象转xml
 */
@Test
public void testGenXml(){
    XmlMapper xmlMapper = new XmlMapper();
    Book book = new Book("Think in Java",100);
    try {
        String xmlStr =  xmlMapper.writeValueAsString(book);
        System.out.println(xmlStr);
    } catch (JsonProcessingException e) { 
        e.printStackTrace();
    }
}

/*
 * xml转Java对象
 */
@Test
public void testGenObjByXml(){
    XmlMapper xmlMapper = new XmlMapper();
    String xmlStr = "<Book><name>Think in Java</name><price>100</price></Book>"; 
    try {
        Book book = xmlMapper.readValue(xmlStr, Book.class);
        System.out.println(book);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
%5Btoc%5D%0A%0A%23%23%201.%20%E6%A0%B8%E5%BF%83%E6%A8%A1%E5%9D%97%0A%0A%3E%20Jackson%20%E7%9A%84%E6%A0%B8%E5%BF%83%E6%A8%A1%E5%9D%97%E7%94%B1%E4%B8%89%E9%83%A8%E5%88%86%E7%BB%84%E6%88%90%0A%0A1.%20%60%20jackson-core%60%EF%BC%8C%E6%A0%B8%E5%BF%83%E5%8C%85%2C%20%E6%8F%90%E4%BE%9B%E5%9F%BA%E4%BA%8E%22%E6%B5%81%E6%A8%A1%E5%BC%8F%22%E8%A7%A3%E6%9E%90%E7%9A%84%E7%9B%B8%E5%85%B3%20API%EF%BC%8C%E5%AE%83%E5%8C%85%E6%8B%AC%20JsonPaser%20%E5%92%8C%20JsonGenerator%2C%20%20Jackson%E5%86%85%E9%83%A8%E5%AE%9E%E7%8E%B0%E6%AD%A3%E6%98%AF%E9%80%9A%E8%BF%87%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84%E6%B5%81%E6%A8%A1%E5%BC%8F%20API%20%E7%9A%84%20JsonGenerator%20%E5%92%8C%20JsonParser%20%E6%9D%A5%E7%94%9F%E6%88%90%E5%92%8C%E8%A7%A3%E6%9E%90%20json%E3%80%82%0A2.%20%20%60jackson-annotations%60%EF%BC%8C%E6%B3%A8%E8%A7%A3%E5%8C%85%EF%BC%8C%E6%8F%90%E4%BE%9B%E6%A0%87%E5%87%86%E6%B3%A8%E8%A7%A3%E5%8A%9F%E8%83%BD%E3%80%82%0A3.%20%20%60jackson-databind%60%20%EF%BC%8C%E6%95%B0%E6%8D%AE%E7%BB%91%E5%AE%9A%E5%8C%85%EF%BC%8C%20%E6%8F%90%E4%BE%9B%E5%9F%BA%E4%BA%8E%22%E5%AF%B9%E8%B1%A1%E7%BB%91%E5%AE%9A%22%20%E8%A7%A3%E6%9E%90%E7%9A%84%E7%9B%B8%E5%85%B3%20API%20%EF%BC%88%20ObjectMapper%20%EF%BC%89%20%E5%92%8C%22%E6%A0%91%E6%A8%A1%E5%9E%8B%22%20%E8%A7%A3%E6%9E%90%E7%9A%84%E7%9B%B8%E5%85%B3%20API%20%EF%BC%88JsonNode%EF%BC%89%EF%BC%9B%E5%9F%BA%E4%BA%8E%22%E5%AF%B9%E8%B1%A1%E7%BB%91%E5%AE%9A%22%20%E8%A7%A3%E6%9E%90%E7%9A%84%20API%20%E5%92%8C%22%E6%A0%91%E6%A8%A1%E5%9E%8B%22%E8%A7%A3%E6%9E%90%E7%9A%84%20API%20%E4%BE%9D%E8%B5%96%E5%9F%BA%E4%BA%8E%22%E6%B5%81%E6%A8%A1%E5%BC%8F%22%E8%A7%A3%E6%9E%90%E7%9A%84%20API%E3%80%82%0A%0A%0A%0A%23%23%202.%20%E6%80%8E%E4%B9%88%E7%94%A8%0A%0A%23%23%23%202.1%20%E5%BC%95%E5%85%A5%E4%BE%9D%E8%B5%96%0A%0A%60%60%60java%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Ecom.fasterxml.jackson.core%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Ejackson-databind%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E2.9.5%3C%2Fversion%3E%0A%3C%2Fdependency%3E%0A%60%60%60%0A%0A%3E%20jackson-databind%20%E4%BE%9D%E8%B5%96%20jackson-core%20%E5%92%8C%20jackson-annotations%EF%BC%8C%E5%BD%93%E6%B7%BB%E5%8A%A0%20jackson-databind%20%E4%B9%8B%E5%90%8E%EF%BC%8C%20jackson-core%20%E5%92%8C%20jackson-annotations%20%E4%B9%9F%E9%9A%8F%E4%B9%8B%E6%B7%BB%E5%8A%A0%E5%88%B0%20Java%20%E9%A1%B9%E7%9B%AE%E5%B7%A5%E7%A8%8B%E4%B8%AD%E3%80%82%E5%9C%A8%E6%B7%BB%E5%8A%A0%E7%9B%B8%E5%85%B3%E4%BE%9D%E8%B5%96%E5%8C%85%E4%B9%8B%E5%90%8E%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20Jackson%E3%80%82%0A%23%23%23%202.2%20%E5%AF%B9%E8%B1%A1%E7%BB%91%E5%AE%9A%0A%3E%20Jackson%20%E6%9C%80%E5%B8%B8%E7%94%A8%E7%9A%84%20%60API%60%20%E5%B0%B1%E6%98%AF%E5%9F%BA%E4%BA%8E%22%E5%AF%B9%E8%B1%A1%E7%BB%91%E5%AE%9A%22%20%E7%9A%84%20%60%20ObjectMapper%60%E3%80%82%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20test()%20throws%20IOException%20%7B%0A%20%20%20%20ObjectMapper%20mapper%20%3D%20new%20ObjectMapper()%3B%0A%20%20%20%20User%20user%20%3D%20new%20User()%3B%0A%20%20%20%20user.set..%0A%20%20%20%20%0A%20%20%20%20%2F%2F%E5%BA%8F%E5%88%97%E5%8C%96%0A%20%20%20%20String%20jsonString%20%3D%20mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user)%3B%0A%20%20%20%20%2F%2F%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%0A%20%20%20%20user%20%3D%20mapper.readValue(jsonString%2C%20User.class)%3B%0A%7D%0A%60%60%60%0A%23%23%23%23%20%202.2.1%20writeValue%0A%3E%20ObjectMapper%20%E9%80%9A%E8%BF%87%20%60writeValue%60%20%E7%B3%BB%E5%88%97%E6%96%B9%E6%B3%95%E5%B0%86%20java%20%E5%AF%B9%E8%B1%A1%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%BA%20json%EF%BC%8C%E5%B9%B6%E5%B0%86%20json%20%E5%AD%98%E5%82%A8%E6%88%90%E4%B8%8D%E5%90%8C%E7%9A%84%E6%A0%BC%E5%BC%8F%EF%BC%9A%60String%EF%BC%88writeValueAsString%EF%BC%89%E3%80%81Byte%20Array%EF%BC%88writeValueAsBytes%EF%BC%89%E3%80%81Writer%E3%80%81File%E3%80%81OutStream%E3%80%81DataOutput%E3%80%82%60%0A%0A%23%23%23%23%202.2.2%20readValue%0A%3E%20ObjectMapper%20%E9%80%9A%E8%BF%87%20%60readValue%60%20%E7%B3%BB%E5%88%97%E6%96%B9%E6%B3%95%E4%BB%8E%E4%B8%8D%E5%90%8C%E7%9A%84%E6%95%B0%E6%8D%AE%E6%BA%90%EF%BC%9A%20%60String%E3%80%81Byte%20Array%E3%80%81Reader%E3%80%81File%E3%80%81URL%E3%80%81InputStream%60%20%E4%B8%AD%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%BA%20java%20%E5%AF%B9%E8%B1%A1%E3%80%82%0A%0A%3E%20%E5%9C%A8%E8%B0%83%E7%94%A8%20writeValue%20%E6%88%96%E8%B0%83%E7%94%A8%20readValue%20%E6%96%B9%E6%B3%95%E4%B9%8B%E5%89%8D%EF%BC%8C%E5%BE%80%E5%BE%80%E9%9C%80%E8%A6%81%E8%AE%BE%E7%BD%AE%20ObjectMapper%20%E7%9A%84%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E3%80%82%E8%BF%99%E4%BA%9B%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E5%BA%94%E7%94%A8%20java%20%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%89%80%E6%9C%89%E5%B1%9E%E6%80%A7%E4%B8%8A%E3%80%82%0A%3E%0A%3E%20%E7%A4%BA%E4%BE%8B%E5%A6%82%E4%B8%8B%0A%0A%60%60%60java%0A%2F%2F%E5%9C%A8%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%97%B6%E5%BF%BD%E7%95%A5%E5%9C%A8%20json%20%E4%B8%AD%E5%AD%98%E5%9C%A8%E4%BD%86%20Java%20%E5%AF%B9%E8%B1%A1%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%9A%84%E5%B1%9E%E6%80%A7%20%0Amapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES%2Cfalse)%3B%20%0A%2F%2F%E5%9C%A8%E5%BA%8F%E5%88%97%E5%8C%96%E6%97%B6%E6%97%A5%E6%9C%9F%E6%A0%BC%E5%BC%8F%E9%BB%98%E8%AE%A4%E4%B8%BA%20yyyy-MM-dd'T'HH%3Amm%3Ass.SSSZ%20%0Amapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS%2Cfalse)%20%0A%2F%2F%E5%9C%A8%E5%BA%8F%E5%88%97%E5%8C%96%E6%97%B6%E5%BF%BD%E7%95%A5%E5%80%BC%E4%B8%BAnull%E7%9A%84%E5%B1%9E%E6%80%A7%20%0Amapper.setSerializationInclusion(Include.NON_NULL)%3B%20%0A%2F%2F%E5%BF%BD%E7%95%A5%E5%80%BC%E4%B8%BA%E9%BB%98%E8%AE%A4%E5%80%BC%E7%9A%84%E5%B1%9E%E6%80%A7%20%0Amapper.setDefaultPropertyInclusion(Include.NON_DEFAULT)%3B%0A%60%60%60%0A%0A%23%23%23%202.3%20%E5%BA%8F%E5%88%97%E5%8C%96%0A%0A%3E%20Jackson%20ObjectMapper%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%89%E7%A7%8D%E6%96%B9%E6%B3%95%E8%BD%AC%E6%8D%A2%0A%3E%0A%0A%60%60%60java%0AwriteValue()%0AwriteValueAsString()%20%0AwriteValueAsBytes()%0A%60%60%60%0A%0A%60%60%60java%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0ACar%20car%20%3D%20new%20Car()%3B%0Acar.brand%20%3D%20%22BMW%22%3B%0Acar.doors%20%3D%204%3B%0A%0AobjectMapper.writeValue(new%20FileOutputStream(%22data%2Foutput-2.json%22)%2C%20car)%3B%0AobjectMapper.writeValue(new%20File(%22data%2Foutput-2.json%22)%2C%20car)%3B%0AString%20json%20%3D%20objectMapper.writeValueAsString(car)%3B%0Abyte%5B%5D%20jsonBytes%20%3D%20objectMapper.writeValueAsBytes(car)%3B%0A%60%60%60%0A%0A%23%23%23%202.4%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%0A%0A%3E%20%E4%BB%8Ejson%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%AF%BB%E5%8F%96%0A%0A%60%60%60java%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0AString%20carJson%20%3D%20%22%7B%20%5C%22brand%5C%22%20%3A%20%5C%22Mercedes%5C%22%2C%20%5C%22doors%5C%22%20%3A%205%20%7D%22%3B%0ACar%20car%20%3D%20objectMapper.readValue(carJson%2C%20Car.class)%3B%0A%60%60%60%0A%0A%3E%E4%BB%8Ejson%20Reader%E8%AF%BB%E5%8F%96%0A%0A%60%60%60java%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0AString%20carJson%20%3D%20%22%7B%20%5C%22brand%5C%22%20%3A%20%5C%22Mercedes%5C%22%2C%20%5C%22doors%5C%22%20%3A%204%20%7D%22%3B%0AReader%20reader%20%3D%20new%20StringReader(carJson)%3B%0ACar%20car%20%3D%20objectMapper.readValue(reader%2C%20Car.class)%3B%0A%60%60%60%0A%0A%3E%20%E4%BB%8Ejson%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96%0A%0A%60%60%60java%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0AFile%20file%20%3D%20new%20File(%22data%2Fcar.json%22)%3B%0ACar%20car%20%3D%20objectMapper.readValue(file%2C%20Car.class)%3B%0A%60%60%60%0A%0A%3E%20%E4%BB%8Ejson%E7%BD%91%E7%BB%9C%E6%96%87%E4%BB%B6%E5%9C%B0%E5%9D%80%E8%AF%BB%E5%8F%96%0A%0A%60%60%60java%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0AURL%20url%20%3D%20new%20URL(%22file%3Adata%2Fcar.json%22)%3B%0ACar%20car%20%3D%20objectMapper.readValue(url%2C%20Car.class)%3B%0A%60%60%60%0A%0A%3E%20%E4%BB%8E%E6%B5%81%E4%B8%AD%E8%AF%BB%E5%8F%96%0A%0A%60%60%60java%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0AInputStream%20input%20%3D%20new%20FileInputStream(%22data%2Fcar.json%22)%3B%0ACar%20car%20%3D%20objectMapper.readValue(input%2C%20Car.class)%3B%0A%60%60%60%0A%0A%3E%20%E4%BB%8Ejson%E5%AD%97%E8%8A%82%E6%95%B0%E7%BB%84%E4%B8%AD%E8%AF%BB%E5%8F%96%0A%0A%60%60%60java%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0AString%20carJson%20%3D%20%22%7B%20%5C%22brand%5C%22%20%3A%20%5C%22Mercedes%5C%22%2C%20%5C%22doors%5C%22%20%3A%205%20%7D%22%3B%0Abyte%5B%5D%20bytes%20%3D%20carJson.getBytes(%22UTF-8%22)%3B%0ACar%20car%20%3D%20objectMapper.readValue(bytes%2C%20Car.class)%3B%0A%60%60%60%0A%0A%23%23%23%23%202.4.1%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%8D%E5%90%8C%E7%B1%BB%E5%9E%8B%0A%0A%3E%20%E8%BD%AC%E6%8D%A2%E4%B8%BA%E6%95%B0%E7%BB%84%0A%0A%60%60%60java%0AString%20jsonArray%20%3D%20%22%5B%7B%5C%22brand%5C%22%3A%5C%22ford%5C%22%7D%2C%20%7B%5C%22brand%5C%22%3A%5C%22Fiat%5C%22%7D%5D%22%3B%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0ACar%5B%5D%20cars%20%3D%20objectMapper.readValue(jsonArray%2C%20Car%5B%5D.class)%3B%0A%60%60%60%0A%0A%3E%20%E8%BD%AC%E6%8D%A2%E4%B8%BA%E9%9B%86%E5%90%88%0A%60%60%60java%0AString%20jsonArray%20%3D%20%22%5B%7B%5C%22brand%5C%22%3A%5C%22ford%5C%22%7D%2C%20%7B%5C%22brand%5C%22%3A%5C%22Fiat%5C%22%7D%5D%22%3B%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0AList%3CCar%3E%20cars%20%3D%20objectMapper.readValue(jsonArray%2C%20new%20TypeReference%3CList%3CCar%3E%3E()%7B%7D)%3B%0A%60%60%60%0A%0A%3E%20%E8%BD%AC%E6%8D%A2%E4%B8%BAMap%0A%0A%60%60%60java%0AString%20jsonObject%20%3D%20%22%7B%5C%22brand%5C%22%3A%5C%22ford%5C%22%2C%20%5C%22doors%5C%22%3A5%7D%22%3B%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0AMap%3CString%2C%20Object%3E%20jsonMap%20%3D%20objectMapper.readValue(jsonObject%2C%20new%20TypeReference%3CMap%3CString%2CObject%3E%3E()%7B%7D)%3B%0A%60%60%60%0A%0A%0A%0A%23%23%23%202.5%20%E6%97%B6%E9%97%B4%E7%B1%BB%E5%9E%8B%E6%A0%BC%E5%BC%8F%E5%8C%96%0A%0A%3E%20Jackson%20%E9%BB%98%E8%AE%A4%E4%BC%9A%E5%B0%86%60java.util.Date%60%E5%AF%B9%E8%B1%A1%E8%BD%AC%E6%8D%A2%E6%88%90%60long%60%E5%80%BC%2C%E5%90%8C%E6%97%B6%E4%B9%9F%E6%94%AF%E6%8C%81%E5%B0%86%E6%97%B6%E9%97%B4%E8%BD%AC%E6%8D%A2%E6%88%90%E6%A0%BC%E5%BC%8F%E5%8C%96%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%0A%0A%60%60%60java%0ASimpleDateFormat%20dateFormat%20%3D%20new%20SimpleDateFormat(%22yyyy-MM-dd%22)%3B%0AobjectMapper.setDateFormat(dateFormat)%3B%0A%0AString%20json%20%3D%20objectMapper.writeValueAsString(%E5%AF%B9%E8%B1%A1)%3B%0A%60%60%60%0A%0A%23%23%23%202.6%20JSON%E6%A0%91%E6%A8%A1%E5%9E%8B%0A%0A%3E%20Jackson%20%E4%B9%9F%E6%8F%90%E4%BE%9B%E4%BA%86%E6%A0%91%E6%A8%A1%E5%9E%8B%EF%BC%88tree%20model%EF%BC%89%E6%9D%A5%E7%94%9F%E6%88%90%E5%92%8C%E8%A7%A3%E6%9E%90%20json%E3%80%82%0A%3E%0A%3E%20%E8%8B%A5%E6%83%B3%E4%BF%AE%E6%94%B9%E6%88%96%E8%AE%BF%E9%97%AE%20json%20%E9%83%A8%E5%88%86%E5%B1%9E%E6%80%A7%EF%BC%8C%E6%A0%91%E6%A8%A1%E5%9E%8B%E6%98%AF%E4%B8%8D%E9%94%99%E7%9A%84%E9%80%89%E6%8B%A9%E3%80%82%E6%A0%91%E6%A8%A1%E5%9E%8B%E7%94%B1%20JsonNode%20%E8%8A%82%E7%82%B9%E7%BB%84%E6%88%90%0A%0A%60%60%60java%0AString%20carJson%20%3D%20%22%7B%20%5C%22brand%5C%22%20%3A%20%5C%22Mercedes%5C%22%2C%20%5C%22doors%5C%22%20%3A%205%20%7D%22%3B%0AObjectMapper%20objectMapper%20%3D%20new%20ObjectMapper()%3B%0Atry%20%7B%0A%20%20%20%20JsonNode%20node%20%3D%20objectMapper.readValue(carJson%2C%20JsonNode.class)%3B%0A%20%20%20%20%0A%20%20%20%20JsonNode%20brandNode%20%3D%20node.get(%22brand%22)%3B%0A%20%20%20%20String%20brand%20%3D%20brandNode.asText()%3B%0A%20%20%20%20System.out.println(%22brand%20%3D%20%22%20%2B%20brand)%3B%0A%0A%20%20%20%20JsonNode%20doorsNode%20%3D%20node.get(%22doors%22)%3B%0A%20%20%20%20int%20doors%20%3D%20doorsNode.asInt()%3B%0A%20%20%20%20System.out.println(%22doors%20%3D%20%22%20%2B%20doors)%3B%0A%0A%20%20%20%20JsonNode%20array%20%3D%20node.get(%22owners%22)%3B%0A%20%20%20%20JsonNode%20jsonNode%20%3D%20array.get(0)%3B%0A%20%20%20%20String%20john%20%3D%20jsonNode.asText()%3B%0A%20%20%20%20System.out.println(%22john%20%20%3D%20%22%20%2B%20john)%3B%0A%0A%20%20%20%20JsonNode%20child%20%3D%20node.get(%22nestedObject%22)%3B%0A%20%20%20%20JsonNode%20childField%20%3D%20child.get(%22field%22)%3B%0A%20%20%20%20String%20field%20%3D%20childField.asText()%3B%0A%20%20%20%20System.out.println(%22field%20%3D%20%22%20%2B%20field)%3B%0A%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20e.printStackTrace()%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20testJsonNode()%20throws%20JsonProcessingException%20%7B%0A%20%20%20%20ObjectMapper%20mapper%20%3D%20new%20ObjectMapper()%3B%0A%20%20%20%20JsonNode%20node%20%3D%20mapper.readValue(JSON_STR%2C%20JsonNode.class)%3B%0A%20%20%20%20String%20firstName%20%3D%20node.get(%22firstName%22).asText()%3B%0A%20%20%20%20JsonNode%20phoneNumbers%20%3D%20node.get(%22phoneNumbers%22)%3B%0A%20%20%20%20Iterator%3CJsonNode%3E%20elements%20%3D%20phoneNumbers.elements()%3B%0A%0A%20%20%20%20while%20(elements.hasNext())%20%7B%0A%20%20%20%20%20%20%20%20JsonNode%20next%20%3D%20elements.next()%3B%0A%20%20%20%20%20%20%20%20String%20type%20%3D%20next.get(%22type%22).asText()%3B%0A%20%20%20%20%20%20%20%20String%20number%20%3D%20next.get(%22number%22).asText()%3B%0A%20%20%20%20%20%20%20%20log.info(%22type%3A%7B%7D%2C%20number%3A%7B%7D%22%2C%20type%2C%20number)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60%0A%5Bmain%5D%20INFO%20com.chris.hutool.json.JackSonTest%20-%20type%3AiPhone%2C%20number%3A0123-4567-8888%0A%5Bmain%5D%20INFO%20com.chris.hutool.json.JackSonTest%20-%20type%3Ahome%2C%20number%3A0123-4567-8910%0A%60%60%60%0A%0A%23%23%23%202.7%20JsonParser%0A%0A%3E%20JsonParser%20%E6%8F%90%E4%BE%9B%E5%BE%88%E5%A4%9A%E6%96%B9%E6%B3%95%E6%9D%A5%E8%AF%BB%E5%8F%96%20json%20%E4%BF%A1%E6%81%AF%EF%BC%8C%20%E5%A6%82%20isClosed()%2C%20nextToken()%2C%20getValueAsString()%E7%AD%89%E3%80%82%0A%3E%0A%3E%20%E8%8B%A5%E6%83%B3%E5%8D%95%E7%8B%AC%E5%88%9B%E5%BB%BA%20JsonParser%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%20JsonFactory()%20%E7%9A%84%20createParser%E3%80%82%0A%0A%60%60%60java%0AString%20carJson%20%3D%20%22%7B%20%5C%22brand%5C%22%20%3A%20%5C%22Mercedes%5C%22%2C%20%5C%22doors%5C%22%20%3A%205%20%7D%22%3B%0AJsonFactory%20factory%20%3D%20new%20JsonFactory()%3B%0AJsonParser%20%20parser%20%20%3D%20factory.createParser(carJson)%3B%0A%0ACar%20car%20%3D%20new%20Car()%3B%0Awhile(!parser.isClosed())%7B%0A%20%20%20%20JsonToken%20jsonToken%20%3D%20parser.nextToken()%3B%0A%0A%20%20%20%20if(JsonToken.FIELD_NAME.equals(jsonToken))%7B%0A%20%20%20%20%20%20%20%20String%20fieldName%20%3D%20parser.getCurrentName()%3B%0A%20%20%20%20%20%20%20%20System.out.println(fieldName)%3B%0A%0A%20%20%20%20%20%20%20%20jsonToken%20%3D%20parser.nextToken()%3B%0A%0A%20%20%20%20%20%20%20%20if(%22brand%22.equals(fieldName))%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20car.brand%20%3D%20parser.getValueAsString()%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(%22doors%22.equals(fieldName))%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20car.doors%20%3D%20parser.getValueAsInt()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%0ASystem.out.println(%22car.brand%20%3D%20%22%20%2B%20car.brand)%3B%0ASystem.out.println(%22car.doors%20%3D%20%22%20%2B%20car.doors)%3B%0A%60%60%60%0A%3E%20%E4%B9%9F%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%60Reader%60%2C%20%60InputStream%60%2C%20%60URL%60%2C%20%60byte%20array%60%20%E6%88%96%20%60char%20array%60%E6%9D%A5%E5%88%9B%E5%BB%BAJsonParser%0A%0A%23%23%23%202.8%20JsonGenerator%0A%0A%3E%20JsonGenerator%20%E6%9C%89%E5%A4%9A%E7%A7%8D%20write%20%E6%96%B9%E6%B3%95%E4%BB%A5%E6%94%AF%E6%8C%81%E7%94%9F%E6%88%90%E5%A4%8D%E6%9D%82%E7%9A%84%E7%B1%BB%E5%9E%8B%E7%9A%84%20json%EF%BC%8C%E6%AF%94%E5%A6%82%20writeArray%EF%BC%8CwriteTree%20%E7%AD%89%20%E3%80%82%E8%8B%A5%E6%83%B3%E5%8D%95%E7%8B%AC%E5%88%9B%E5%BB%BA%20JsonGenerator%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%20JsonFactory()%20%E7%9A%84%20createGenerator%E3%80%82%0A%0A%60%60%60java%0AJsonFactory%20factory%20%3D%20new%20JsonFactory()%3B%0A%0AJsonGenerator%20generator%20%3D%20factory.createGenerator(new%20File(%22data%2Foutput.json%22)%2C%20JsonEncoding.UTF8)%3B%0A%0Agenerator.writeStartObject()%3B%0Agenerator.writeStringField(%22brand%22%2C%20%22Mercedes%22)%3B%0Agenerator.writeNumberField(%22doors%22%2C%205)%3B%0Agenerator.writeEndObject()%3B%0A%0Agenerator.close()%3B%0A%60%60%60%0A%0A%23%23%203.%20%E9%85%8D%E7%BD%AE%E7%9B%B8%E5%85%B3%E5%B1%9E%E6%80%A7%0A%0A%23%23%23%20SerializationFeature%20%E5%BA%8F%E5%88%97%E5%8C%96%E7%9B%B8%E5%85%B3%E5%B1%9E%E6%80%A7%0A%23%23%23%20DeserializationFeature%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E7%9B%B8%E5%85%B3%E5%B1%9E%E6%80%A7%0A%0A%23%23%23%20MapperFeature%0A%0A%23%23%23%20JsonParser.Feature%EF%BC%88%E8%A7%A3%E6%9E%90%E5%99%A8%E7%89%B9%E6%80%A7%EF%BC%89%0A%0A%23%23%23%20JsonGenerator%0A%0A%23%23%23%20JsonFactory%0A%0A%23%23%204.%20XML%20%E5%AE%9E%E4%BD%93%E4%BA%92%E8%BD%AC%0A%0A%60%60%60%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Ecom.fasterxml.jackson.dataformat%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Ejackson-dataformat-xml%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E2.9.5%3C%2Fversion%3E%0A%3C%2Fdependency%3E%0A%60%60%60%0A%0A%60%60%60java%0A%2F*%0A%20*%20Java%E5%AF%B9%E8%B1%A1%E8%BD%ACxml%0A%20*%2F%0A%40Test%0Apublic%20void%20testGenXml()%7B%0A%20%20%20%20XmlMapper%20xmlMapper%20%3D%20new%20XmlMapper()%3B%0A%20%20%20%20Book%20book%20%3D%20new%20Book(%22Think%20in%20Java%22%2C100)%3B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20String%20xmlStr%20%3D%20%20xmlMapper.writeValueAsString(book)%3B%0A%20%20%20%20%20%20%20%20System.out.println(xmlStr)%3B%0A%20%20%20%20%7D%20catch%20(JsonProcessingException%20e)%20%7B%20%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F*%0A%20*%20xml%E8%BD%ACJava%E5%AF%B9%E8%B1%A1%0A%20*%2F%0A%40Test%0Apublic%20void%20testGenObjByXml()%7B%0A%20%20%20%20XmlMapper%20xmlMapper%20%3D%20new%20XmlMapper()%3B%0A%20%20%20%20String%20xmlStr%20%3D%20%22%3CBook%3E%3Cname%3EThink%20in%20Java%3C%2Fname%3E%3Cprice%3E100%3C%2Fprice%3E%3C%2FBook%3E%22%3B%20%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20Book%20book%20%3D%20xmlMapper.readValue(xmlStr%2C%20Book.class)%3B%0A%20%20%20%20%20%20%20%20System.out.println(book)%3B%0A%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A

mybatis-plus 分页

创建时间:2022/6/7 17:54
更新时间:2022/6/7 18:59
作者:Chris
来源:https://baijiahao.baidu.com/s?id=1710052002582381873&wfr=spider&for=pc

1 配置分页插件

配置分页插件:拦截对象

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class MyBatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

2 默认分页

public IPage<VO> getxxxByPage(PageBean pageBean, VO queryVO) {
        Page<VO> page = new Page<>(pageBean.getCurrent(), pageBean.getSize());
        return tenantInfoMapper.getTenantByList(page, queryVO);
}
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

IPage<VO> getxxx(Page<VO> page, @Param("vo") TenantVO 
queryVO);

3 自定义分页

private <B, T, P extends PageBean> List<B> buildPage(P p, Page<T> result, List<B> beans) {
        int current = Integer.parseInt(String.valueOf(p.getCurrent()));
        int size = Integer.parseInt(String.valueOf(p.getSize()));
        int fromIndex = (current - 1) * size;
        int toIndex = size * current;
        if (toIndex > beans.size()) {
            toIndex = beans.size();
        }

        List<B> pageBeans = beans.subList(fromIndex, toIndex);
        double pages = Math.ceil((double) beans.size() / (double) size);

        result.setPages((long) pages).setTotal(beans.size());

        return pageBeans;
}
%5Btoc%5D%0A%23%23%23%23%201%20%E9%85%8D%E7%BD%AE%E5%88%86%E9%A1%B5%E6%8F%92%E4%BB%B6%0A%3E%20%E9%85%8D%E7%BD%AE%E5%88%86%E9%A1%B5%E6%8F%92%E4%BB%B6%3A%E6%8B%A6%E6%88%AA%E5%AF%B9%E8%B1%A1%0A%0A%60%60%60java%0Aimport%20com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor%3B%0Aimport%20org.springframework.context.annotation.Bean%3B%0Aimport%20org.springframework.context.annotation.Configuration%3B%0Aimport%20org.springframework.transaction.annotation.EnableTransactionManagement%3B%0A%0A%40Configuration%0A%40EnableTransactionManagement%0Apublic%20class%20MyBatisPlusConfig%20%7B%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20PaginationInterceptor%20paginationInterceptor()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20PaginationInterceptor()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%202%20%E9%BB%98%E8%AE%A4%E5%88%86%E9%A1%B5%0A%0A%60%60%60java%0Apublic%20IPage%3CVO%3E%20getxxxByPage(PageBean%20pageBean%2C%20VO%20queryVO)%20%7B%0A%20%20%20%20%20%20%20%20Page%3CVO%3E%20page%20%3D%20new%20Page%3C%3E(pageBean.getCurrent()%2C%20pageBean.getSize())%3B%0A%20%20%20%20%20%20%20%20return%20tenantInfoMapper.getTenantByList(page%2C%20queryVO)%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0Aimport%20com.baomidou.mybatisplus.core.metadata.IPage%3B%0Aimport%20com.baomidou.mybatisplus.extension.plugins.pagination.Page%3B%0A%0AIPage%3CVO%3E%20getxxx(Page%3CVO%3E%20page%2C%20%40Param(%22vo%22)%20TenantVO%20%0AqueryVO)%3B%0A%0A%60%60%60%0A%0A%0A%23%23%23%23%203%20%E8%87%AA%E5%AE%9A%E4%B9%89%E5%88%86%E9%A1%B5%0A%0A!%5B655e948f60409074137211504f8ba57c.png%5D(en-resource%3A%2F%2Fdatabase%2F1784%3A1)%0A%0A%60%60%60java%0Aprivate%20%3CB%2C%20T%2C%20P%20extends%20PageBean%3E%20List%3CB%3E%20buildPage(P%20p%2C%20Page%3CT%3E%20result%2C%20List%3CB%3E%20beans)%20%7B%0A%20%20%20%20%20%20%20%20int%20current%20%3D%20Integer.parseInt(String.valueOf(p.getCurrent()))%3B%0A%20%20%20%20%20%20%20%20int%20size%20%3D%20Integer.parseInt(String.valueOf(p.getSize()))%3B%0A%20%20%20%20%20%20%20%20int%20fromIndex%20%3D%20(current%20-%201)%20*%20size%3B%0A%20%20%20%20%20%20%20%20int%20toIndex%20%3D%20size%20*%20current%3B%0A%20%20%20%20%20%20%20%20if%20(toIndex%20%3E%20beans.size())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20toIndex%20%3D%20beans.size()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20List%3CB%3E%20pageBeans%20%3D%20beans.subList(fromIndex%2C%20toIndex)%3B%0A%20%20%20%20%20%20%20%20double%20pages%20%3D%20Math.ceil((double)%20beans.size()%20%2F%20(double)%20size)%3B%0A%0A%20%20%20%20%20%20%20%20result.setPages((long)%20pages).setTotal(beans.size())%3B%0A%0A%20%20%20%20%20%20%20%20return%20pageBeans%3B%0A%7D%0A%60%60%60

mybatis分页方案

创建时间:2022/6/7 16:35
更新时间:2022/6/7 17:19
作者:Chris
来源:http://loadhtml/

1 Limit分页

limit ${startPos},${pageSize}
<select  parameterType="map" resultType="dayu">
    select * from user
    <if test="startPos!=null and pageSize!=null">
        limit ${startPos},${pageSize}
    </if>
</select>
@Test
public void selectUser() {
     SqlSession session = MybatisUtils.getSession();
     UserMapper mapper = session.getMapper(UserMapper.class);
       //这里塞值
      Map<String,Object> parms = new HashMap<>();
      parms.put("startPos","0");
      parms.put("pageSize","5");
     List<User> users = mapper.getUserInfo1(parms);
     for (User map: users){
         System.out.println(map);
      }
      session.close();
  }

总结:
limit 0,10;
0 代表从第0条数据开始
10 代表查10条数据
等到第二页的时候就是 limit 10,10;

2 RowBounds分页

RowBounds 帮我们省略了limit的内容,我们只需要在业务层关注分页即可!无须再传入指定数据!
这个属于逻辑分页,即实际上 sql查询的是所有的数据,在业务层进行了分页而已,比较占用内存,而且数据更新不及时,可能会有一定的滞后性!不推荐使用!

RowBounds对象有2个属性,offset和limit。

  • offset: 起始行数
  • limit:需要的数据行数
  • 因此,取出来的数据就是:从第offset+1行开始,取limit行
@Test
public void selectUserRowBounds() {
    SqlSession session = MybatisUtils.getSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    // List<User> users = session.selectList("com.dy.mapper.UserMapper.getUserInfoRowBounds",null,new RowBounds(0, 5));
    List<User> users = mapper.getUserInfoRowBounds(new RowBounds(0,5));
    for (User map: users){
        System.out.println(map);
    }
    session.close();
}
List<User> getUserInfoRowBounds(RowBounds rowBounds);
<select  resultType="dayu">
   select * from user
</select>

3 Mybatis_PageHelper分页插件

官方GitHub地址:
https://github.com/pagehelper/Mybatis-PageHelper

<dependency>
   <groupId>com.github.pagehelper</groupId>
   <artifactId>pagehelper</artifactId>
   <version>5.1.7</version>
</dependency>

配置MyBatis核心配置文件

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
@Test
public void selectUserPageHelper() {
    SqlSession session = MybatisUtils.getSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    // 第二种,Mapper接口方式的调用,推荐这种使用方式。
    PageHelper.startPage(13);
    List<User> list = mapper.getUserInfo();
    // 用PageInfo将包装起来
    PageInfo page = new PageInfo(list);
    for (User map: list){
        System.out.println(map);
    }
    System.out.println("page:---"+page);
    session.close();
 } 

//第一种,RowBounds方 sqlSe式的调用
List<User> list =ssion.selectList("x.y.selectIf"nullnew RowBounds(010));

//第二种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.startPage(110);
List<User> list = userMapper.selectIf(1);

//第三种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.offsetPage(110);
List<User> list = userMapper.selectIf(1);

//第四种,参数方法调用
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
    List<User> selectByPageNumSize(
            @Param("user") User user,
            @Param("pageNum") int pageNum, 
            @Param("pageSize") int pageSize);
}
//配置supportMethodsArguments=true
//在代码中直接调用:
List<User> list = userMapper.selectByPageNumSize(user, 110);

//第五种,参数对象
//如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页
//有如下 User 对象
public class User {
    //其他fields
    //下面两个参数名和 params 配置的名字一致
    private Integer pageNum;
    private Integer pageSize;
}
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
    List<User> selectByPageNumSize(User user);
}
//当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页
List<User> list = userMapper.selectByPageNumSize(user);

//第六种,ISelect 接口方式
//jdk6,7用法,创建接口
Page<User> page = PageHelper.startPage(110).doSelectPage(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectGroupBy();
    }
});
//jdk8 lambda用法
Page<User> page = PageHelper.startPage(110).doSelectPage(()-> userMapper.selectGroupBy());

//也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage
pageInfo = PageHelper.startPage(110).doSelectPageInfo(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectGroupBy();
    }
});
//对应的lambda用法
pageInfo = PageHelper.startPage(110).doSelectPageInfo(() -> userMapper.selectGroupBy());

//count查询,返回一个查询语句的count数
long total = PageHelper.count(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectLike(user);
    }
});

//lambda
total = PageHelper.count(()->userMapper.selectLike(user));

拓展

//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(110);
List<User> list = userMapper.selectAll();
//用PageInfo对结果进行包装
PageInfo page = new PageInfo(list);
//测试PageInfo全部属性
//PageInfo包含了非常全面的分页属性
assertEquals(1, page.getPageNum());
assertEquals(10, page.getPageSize());
assertEquals(1, page.getStartRow());
assertEquals(10, page.getEndRow());
assertEquals(183, page.getTotal());
assertEquals(19, page.getPages());
assertEquals(1, page.getFirstPage());
assertEquals(8, page.getLastPage());
assertEquals(true, page.isFirstPage());
assertEquals(false, page.isLastPage());
assertEquals(false, page.isHasPreviousPage());
%5Btoc%5D%0A%0A%23%23%23%23%201%20Limit%E5%88%86%E9%A1%B5%0A%0A%60%60%60java%0Alimit%C2%A0%24%7BstartPos%7D%2C%24%7BpageSize%7D%0A%60%60%60%0A%60%60%60java%0A%3Cselect%C2%A0id%3D%22getUserInfo1%22%C2%A0parameterType%3D%22map%22%C2%A0resultType%3D%22dayu%22%3E%0A%C2%A0%C2%A0%C2%A0%C2%A0select%C2%A0*%C2%A0from%C2%A0user%0A%C2%A0%C2%A0%C2%A0%C2%A0%3Cif%C2%A0test%3D%22startPos!%3Dnull%C2%A0and%C2%A0pageSize!%3Dnull%22%3E%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0limit%C2%A0%24%7BstartPos%7D%2C%24%7BpageSize%7D%0A%C2%A0%C2%A0%C2%A0%C2%A0%3C%2Fif%3E%0A%3C%2Fselect%3E%0A%60%60%60%0A%60%60%60java%0A%40Test%0Apublic%C2%A0void%C2%A0selectUser()%C2%A0%7B%0A%20%20%20%20%20SqlSession%C2%A0session%C2%A0%3D%C2%A0MybatisUtils.getSession()%3B%0A%20%20%20%20%20UserMapper%C2%A0mapper%C2%A0%3D%C2%A0session.getMapper(UserMapper.class)%3B%0A%20%20%20%20%20%20%20%2F%2F%E8%BF%99%E9%87%8C%E5%A1%9E%E5%80%BC%0A%20%20%20%20%20%20Map%3CString%2CObject%3E%C2%A0parms%C2%A0%3D%C2%A0new%C2%A0HashMap%3C%3E()%3B%0A%20%20%20%20%20%20parms.put(%22startPos%22%2C%220%22)%3B%0A%20%20%20%20%20%20parms.put(%22pageSize%22%2C%225%22)%3B%0A%20%20%20%20%20List%3CUser%3E%C2%A0users%C2%A0%3D%C2%A0mapper.getUserInfo1(parms)%3B%0A%20%20%20%20%20for%C2%A0(User%C2%A0map%3A%C2%A0users)%7B%0A%20%20%20%20%20%20%20%20%20System.out.println(map)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20session.close()%3B%0A%20%20%7D%0A%60%60%60%0A!%5B46c5b6f9f90585aa936b67cfe575d32b.png%5D(en-resource%3A%2F%2Fdatabase%2F1776%3A1)%0A%0A%60%60%60%0A%E6%80%BB%E7%BB%93%EF%BC%9A%0Alimit%200%2C10%3B%0A0%20%E4%BB%A3%E8%A1%A8%E4%BB%8E%E7%AC%AC0%E6%9D%A1%E6%95%B0%E6%8D%AE%E5%BC%80%E5%A7%8B%0A10%20%E4%BB%A3%E8%A1%A8%E6%9F%A510%E6%9D%A1%E6%95%B0%E6%8D%AE%0A%E7%AD%89%E5%88%B0%E7%AC%AC%E4%BA%8C%E9%A1%B5%E7%9A%84%E6%97%B6%E5%80%99%E5%B0%B1%E6%98%AF%20limit%2010%2C10%3B%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%202%20RowBounds%E5%88%86%E9%A1%B5%0A%3E%20RowBounds%20%E5%B8%AE%E6%88%91%E4%BB%AC%E7%9C%81%E7%95%A5%E4%BA%86limit%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AA%E9%9C%80%E8%A6%81%E5%9C%A8%E4%B8%9A%E5%8A%A1%E5%B1%82%E5%85%B3%E6%B3%A8%E5%88%86%E9%A1%B5%E5%8D%B3%E5%8F%AF%EF%BC%81%E6%97%A0%E9%A1%BB%E5%86%8D%E4%BC%A0%E5%85%A5%E6%8C%87%E5%AE%9A%E6%95%B0%E6%8D%AE%EF%BC%81%0A%3E%20%E8%BF%99%E4%B8%AA%E5%B1%9E%E4%BA%8E%E9%80%BB%E8%BE%91%E5%88%86%E9%A1%B5%EF%BC%8C%E5%8D%B3%E5%AE%9E%E9%99%85%E4%B8%8A%20%60sql%E6%9F%A5%E8%AF%A2%E7%9A%84%E6%98%AF%E6%89%80%E6%9C%89%E7%9A%84%E6%95%B0%E6%8D%AE%60%EF%BC%8C%E5%9C%A8%E4%B8%9A%E5%8A%A1%E5%B1%82%E8%BF%9B%E8%A1%8C%E4%BA%86%E5%88%86%E9%A1%B5%E8%80%8C%E5%B7%B2%EF%BC%8C%E6%AF%94%E8%BE%83%E5%8D%A0%E7%94%A8%E5%86%85%E5%AD%98%EF%BC%8C%E8%80%8C%E4%B8%94%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E4%B8%8D%E5%8F%8A%E6%97%B6%EF%BC%8C%E5%8F%AF%E8%83%BD%E4%BC%9A%E6%9C%89%E4%B8%80%E5%AE%9A%E7%9A%84%E6%BB%9E%E5%90%8E%E6%80%A7%EF%BC%81%60%E4%B8%8D%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8%EF%BC%81%60%0A%0A%3E%20RowBounds%E5%AF%B9%E8%B1%A1%E6%9C%892%E4%B8%AA%E5%B1%9E%E6%80%A7%EF%BC%8Coffset%E5%92%8Climit%E3%80%82%0A%3E%20-%20offset%3A%20%E8%B5%B7%E5%A7%8B%E8%A1%8C%E6%95%B0%0A%3E%20-%20limit%EF%BC%9A%E9%9C%80%E8%A6%81%E7%9A%84%E6%95%B0%E6%8D%AE%E8%A1%8C%E6%95%B0%0A%3E%20-%20%E5%9B%A0%E6%AD%A4%EF%BC%8C%E5%8F%96%E5%87%BA%E6%9D%A5%E7%9A%84%E6%95%B0%E6%8D%AE%E5%B0%B1%E6%98%AF%EF%BC%9A%E4%BB%8E%E7%AC%ACoffset%2B1%E8%A1%8C%E5%BC%80%E5%A7%8B%EF%BC%8C%E5%8F%96limit%E8%A1%8C%0A%0A%60%60%60java%0A%40Test%0Apublic%C2%A0void%C2%A0selectUserRowBounds()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0SqlSession%C2%A0session%C2%A0%3D%C2%A0MybatisUtils.getSession()%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0UserMapper%C2%A0mapper%C2%A0%3D%C2%A0session.getMapper(UserMapper.class)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%2F%2F%C2%A0List%3CUser%3E%C2%A0users%C2%A0%3D%C2%A0session.selectList(%22com.dy.mapper.UserMapper.getUserInfoRowBounds%22%2Cnull%2Cnew%C2%A0RowBounds(0%2C%C2%A05))%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0List%3CUser%3E%C2%A0users%C2%A0%3D%C2%A0mapper.getUserInfoRowBounds(new%C2%A0RowBounds(0%2C5))%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0for%C2%A0(User%C2%A0map%3A%C2%A0users)%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0System.out.println(map)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%C2%A0%C2%A0%C2%A0%C2%A0session.close()%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0AList%3CUser%3E%C2%A0getUserInfoRowBounds(RowBounds%C2%A0rowBounds)%3B%0A%60%60%60%0A%0A%60%60%60java%0A%3Cselect%C2%A0id%3D%22getUserInfoRowBounds%22%C2%A0resultType%3D%22dayu%22%3E%0A%C2%A0%C2%A0%C2%A0select%C2%A0*%C2%A0from%C2%A0user%0A%3C%2Fselect%3E%0A%60%60%60%0A!%5B388415093a67f3bfc2a78ac9f397b1ee.png%5D(en-resource%3A%2F%2Fdatabase%2F1778%3A1)%0A%0A%0A%23%23%23%23%203%20Mybatis_PageHelper%E5%88%86%E9%A1%B5%E6%8F%92%E4%BB%B6%0A%3E%20%E5%AE%98%E6%96%B9GitHub%E5%9C%B0%E5%9D%80%EF%BC%9A%0A%3E%20%60https%3A%2F%2Fgithub.com%2Fpagehelper%2FMybatis-PageHelper%60%0A%0A%60%60%60java%0A%3Cdependency%3E%0A%20%20%20%3CgroupId%3Ecom.github.pagehelper%3C%2FgroupId%3E%0A%20%20%20%3CartifactId%3Epagehelper%3C%2FartifactId%3E%0A%20%20%20%3Cversion%3E5.1.7%3C%2Fversion%3E%0A%3C%2Fdependency%3E%0A%60%60%60%0A%0A%3E%20%E9%85%8D%E7%BD%AEMyBatis%E6%A0%B8%E5%BF%83%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%60%60%60java%0A%3Cplugins%3E%0A%C2%A0%C2%A0%C2%A0%C2%A0%3Cplugin%C2%A0interceptor%3D%22com.github.pagehelper.PageInterceptor%22%C2%A0%2F%3E%0A%3C%2Fplugins%3E%0A%60%60%60%0A%0A%60%60%60java%0A%40Test%0Apublic%C2%A0void%C2%A0selectUserPageHelper()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0SqlSession%C2%A0session%C2%A0%3D%C2%A0MybatisUtils.getSession()%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0UserMapper%C2%A0mapper%C2%A0%3D%C2%A0session.getMapper(UserMapper.class)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%2F%2F%20%E7%AC%AC%E4%BA%8C%E7%A7%8D%EF%BC%8CMapper%E6%8E%A5%E5%8F%A3%E6%96%B9%E5%BC%8F%E7%9A%84%E8%B0%83%E7%94%A8%EF%BC%8C%E6%8E%A8%E8%8D%90%E8%BF%99%E7%A7%8D%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F%E3%80%82%0A%C2%A0%C2%A0%C2%A0%C2%A0PageHelper.startPage(1%2C%C2%A03)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0List%3CUser%3E%C2%A0list%C2%A0%3D%C2%A0mapper.getUserInfo()%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%2F%2F%20%E7%94%A8PageInfo%E5%B0%86%E5%8C%85%E8%A3%85%E8%B5%B7%E6%9D%A5%0A%C2%A0%C2%A0%C2%A0%C2%A0PageInfo%C2%A0page%C2%A0%3D%C2%A0new%C2%A0PageInfo(list)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0for%C2%A0(User%C2%A0map%3A%C2%A0list)%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0System.out.println(map)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%C2%A0%C2%A0%C2%A0%C2%A0System.out.println(%22page%3A---%22%2Bpage)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0session.close()%3B%0A%20%7D%20%0A%60%60%60%0A!%5B2bb641553cf9f6d00b5cc7ad89afe8e4.png%5D(en-resource%3A%2F%2Fdatabase%2F1780%3A1)%0A%0A%0A%60%60%60java%0A%2F%2F%E7%AC%AC%E4%B8%80%E7%A7%8D%EF%BC%8CRowBounds%E6%96%B9%C2%A0sqlSe%E5%BC%8F%E7%9A%84%E8%B0%83%E7%94%A8%0AList%3CUser%3E%C2%A0list%C2%A0%3Dssion.selectList(%22x.y.selectIf%22%2C%C2%A0null%2C%C2%A0new%C2%A0RowBounds(0%2C%C2%A010))%3B%0A%0A%2F%2F%E7%AC%AC%E4%BA%8C%E7%A7%8D%EF%BC%8CMapper%E6%8E%A5%E5%8F%A3%E6%96%B9%E5%BC%8F%E7%9A%84%E8%B0%83%E7%94%A8%EF%BC%8C%E6%8E%A8%E8%8D%90%E8%BF%99%E7%A7%8D%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F%E3%80%82%0APageHelper.startPage(1%2C%C2%A010)%3B%0AList%3CUser%3E%C2%A0list%C2%A0%3D%C2%A0userMapper.selectIf(1)%3B%0A%0A%2F%2F%E7%AC%AC%E4%B8%89%E7%A7%8D%EF%BC%8CMapper%E6%8E%A5%E5%8F%A3%E6%96%B9%E5%BC%8F%E7%9A%84%E8%B0%83%E7%94%A8%EF%BC%8C%E6%8E%A8%E8%8D%90%E8%BF%99%E7%A7%8D%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F%E3%80%82%0APageHelper.offsetPage(1%2C%C2%A010)%3B%0AList%3CUser%3E%C2%A0list%C2%A0%3D%C2%A0userMapper.selectIf(1)%3B%0A%0A%2F%2F%E7%AC%AC%E5%9B%9B%E7%A7%8D%EF%BC%8C%E5%8F%82%E6%95%B0%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%0A%2F%2F%E5%AD%98%E5%9C%A8%E4%BB%A5%E4%B8%8B%C2%A0Mapper%C2%A0%E6%8E%A5%E5%8F%A3%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BD%A0%E4%B8%8D%E9%9C%80%E8%A6%81%E5%9C%A8%C2%A0xml%C2%A0%E5%A4%84%E7%90%86%E5%90%8E%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%0Apublic%C2%A0interface%C2%A0CountryMapper%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0List%3CUser%3E%C2%A0selectByPageNumSize(%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%40Param(%22user%22)%C2%A0User%C2%A0user%2C%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%40Param(%22pageNum%22)%C2%A0int%C2%A0pageNum%2C%C2%A0%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%40Param(%22pageSize%22)%C2%A0int%C2%A0pageSize)%3B%0A%7D%0A%2F%2F%E9%85%8D%E7%BD%AEsupportMethodsArguments%3Dtrue%0A%2F%2F%E5%9C%A8%E4%BB%A3%E7%A0%81%E4%B8%AD%E7%9B%B4%E6%8E%A5%E8%B0%83%E7%94%A8%EF%BC%9A%0AList%3CUser%3E%C2%A0list%C2%A0%3D%C2%A0userMapper.selectByPageNumSize(user%2C%C2%A01%2C%C2%A010)%3B%0A%0A%2F%2F%E7%AC%AC%E4%BA%94%E7%A7%8D%EF%BC%8C%E5%8F%82%E6%95%B0%E5%AF%B9%E8%B1%A1%0A%2F%2F%E5%A6%82%E6%9E%9C%C2%A0pageNum%C2%A0%E5%92%8C%C2%A0pageSize%C2%A0%E5%AD%98%E5%9C%A8%E4%BA%8E%C2%A0User%C2%A0%E5%AF%B9%E8%B1%A1%E4%B8%AD%EF%BC%8C%E5%8F%AA%E8%A6%81%E5%8F%82%E6%95%B0%E6%9C%89%E5%80%BC%EF%BC%8C%E4%B9%9F%E4%BC%9A%E8%A2%AB%E5%88%86%E9%A1%B5%0A%2F%2F%E6%9C%89%E5%A6%82%E4%B8%8B%C2%A0User%C2%A0%E5%AF%B9%E8%B1%A1%0Apublic%C2%A0class%C2%A0User%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%2F%2F%E5%85%B6%E4%BB%96fields%0A%C2%A0%C2%A0%C2%A0%C2%A0%2F%2F%E4%B8%8B%E9%9D%A2%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%E5%90%8D%E5%92%8C%C2%A0params%C2%A0%E9%85%8D%E7%BD%AE%E7%9A%84%E5%90%8D%E5%AD%97%E4%B8%80%E8%87%B4%0A%C2%A0%C2%A0%C2%A0%C2%A0private%C2%A0Integer%C2%A0pageNum%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0private%C2%A0Integer%C2%A0pageSize%3B%0A%7D%0A%2F%2F%E5%AD%98%E5%9C%A8%E4%BB%A5%E4%B8%8B%C2%A0Mapper%C2%A0%E6%8E%A5%E5%8F%A3%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BD%A0%E4%B8%8D%E9%9C%80%E8%A6%81%E5%9C%A8%C2%A0xml%C2%A0%E5%A4%84%E7%90%86%E5%90%8E%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%0Apublic%C2%A0interface%C2%A0CountryMapper%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0List%3CUser%3E%C2%A0selectByPageNumSize(User%C2%A0user)%3B%0A%7D%0A%2F%2F%E5%BD%93%C2%A0user%C2%A0%E4%B8%AD%E7%9A%84%C2%A0pageNum!%3D%C2%A0null%C2%A0%26%26%C2%A0pageSize!%3D%C2%A0null%C2%A0%E6%97%B6%EF%BC%8C%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%88%86%E9%A1%B5%0AList%3CUser%3E%C2%A0list%C2%A0%3D%C2%A0userMapper.selectByPageNumSize(user)%3B%0A%0A%2F%2F%E7%AC%AC%E5%85%AD%E7%A7%8D%EF%BC%8CISelect%C2%A0%E6%8E%A5%E5%8F%A3%E6%96%B9%E5%BC%8F%0A%2F%2Fjdk6%2C7%E7%94%A8%E6%B3%95%EF%BC%8C%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3%0APage%3CUser%3E%C2%A0page%C2%A0%3D%C2%A0PageHelper.startPage(1%2C%C2%A010).doSelectPage(new%C2%A0ISelect()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%40Override%0A%C2%A0%C2%A0%C2%A0%C2%A0public%C2%A0void%C2%A0doSelect()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0userMapper.selectGroupBy()%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%7D)%3B%0A%2F%2Fjdk8%C2%A0lambda%E7%94%A8%E6%B3%95%0APage%3CUser%3E%C2%A0page%C2%A0%3D%C2%A0PageHelper.startPage(1%2C%C2%A010).doSelectPage(()-%3E%C2%A0userMapper.selectGroupBy())%3B%0A%0A%2F%2F%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E8%BF%94%E5%9B%9EPageInfo%EF%BC%8C%E6%B3%A8%E6%84%8FdoSelectPageInfo%E6%96%B9%E6%B3%95%E5%92%8CdoSelectPage%0ApageInfo%C2%A0%3D%C2%A0PageHelper.startPage(1%2C%C2%A010).doSelectPageInfo(new%C2%A0ISelect()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%40Override%0A%C2%A0%C2%A0%C2%A0%C2%A0public%C2%A0void%C2%A0doSelect()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0userMapper.selectGroupBy()%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%7D)%3B%0A%2F%2F%E5%AF%B9%E5%BA%94%E7%9A%84lambda%E7%94%A8%E6%B3%95%0ApageInfo%C2%A0%3D%C2%A0PageHelper.startPage(1%2C%C2%A010).doSelectPageInfo(()%C2%A0-%3E%C2%A0userMapper.selectGroupBy())%3B%0A%0A%2F%2Fcount%E6%9F%A5%E8%AF%A2%EF%BC%8C%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5%E7%9A%84count%E6%95%B0%0Along%C2%A0total%C2%A0%3D%C2%A0PageHelper.count(new%C2%A0ISelect()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%40Override%0A%C2%A0%C2%A0%C2%A0%C2%A0public%C2%A0void%C2%A0doSelect()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0userMapper.selectLike(user)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%7D)%3B%0A%0A%2F%2Flambda%0Atotal%C2%A0%3D%C2%A0PageHelper.count(()-%3EuserMapper.selectLike(user))%3B%0A%60%60%60%0A%0A%3E%20%E6%8B%93%E5%B1%95%0A%60%60%60java%0A%2F%2F%E8%8E%B7%E5%8F%96%E7%AC%AC1%E9%A1%B5%EF%BC%8C10%E6%9D%A1%E5%86%85%E5%AE%B9%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%9F%A5%E8%AF%A2%E6%80%BB%E6%95%B0count%0APageHelper.startPage(1%2C%C2%A010)%3B%0AList%3CUser%3E%C2%A0list%C2%A0%3D%C2%A0userMapper.selectAll()%3B%0A%2F%2F%E7%94%A8PageInfo%E5%AF%B9%E7%BB%93%E6%9E%9C%E8%BF%9B%E8%A1%8C%E5%8C%85%E8%A3%85%0APageInfo%C2%A0page%C2%A0%3D%C2%A0new%C2%A0PageInfo(list)%3B%0A%2F%2F%E6%B5%8B%E8%AF%95PageInfo%E5%85%A8%E9%83%A8%E5%B1%9E%E6%80%A7%0A%2F%2FPageInfo%E5%8C%85%E5%90%AB%E4%BA%86%E9%9D%9E%E5%B8%B8%E5%85%A8%E9%9D%A2%E7%9A%84%E5%88%86%E9%A1%B5%E5%B1%9E%E6%80%A7%0AassertEquals(1%2C%C2%A0page.getPageNum())%3B%0AassertEquals(10%2C%C2%A0page.getPageSize())%3B%0AassertEquals(1%2C%C2%A0page.getStartRow())%3B%0AassertEquals(10%2C%C2%A0page.getEndRow())%3B%0AassertEquals(183%2C%C2%A0page.getTotal())%3B%0AassertEquals(19%2C%C2%A0page.getPages())%3B%0AassertEquals(1%2C%C2%A0page.getFirstPage())%3B%0AassertEquals(8%2C%C2%A0page.getLastPage())%3B%0AassertEquals(true%2C%C2%A0page.isFirstPage())%3B%0AassertEquals(false%2C%C2%A0page.isLastPage())%3B%0AassertEquals(false%2C%C2%A0page.isHasPreviousPage())%3B%0A%60%60%60

mybatis-3

创建时间:2020/9/2 15:31
更新时间:2022/6/6 10:40
作者:Chris

1.工具与框架的区别

1.1 工具

jdbc -> dbutils -> JdbcTemplate

1.2 框架

框架是一个整体解决方案,如何进行事务控制,如何实现查询缓存,字段映射

1.3 课程连接

https://my.oschina.net/jallenkwong/blog/4476789#h2_6

https://blog.csdn.net/u011863024/article/details/107854866

2. MyBatis

2.1 是什么

半自动化的ORM框架

以配置文件的形式手动编写SQL,非常灵活, 而将参数设置,预编译,执行,封装结果全部自动化

SQL和代码分开,实现业务与数据的解耦

2.1 去哪里下
2.1.1 源码
https://github.com/mybatis/mybatis-3
2.1.2 文档
https://mybatis.org/mybatis-3/

3. HelloWorld 案例

3.1 全局配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://192.168.140.127:3306/chris?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=CTT"/>
                <property name="username" value="root"/>
                <property name="password" value="65536"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
    <mappers>
        <mapper resource="./mapper/EmployeeMapper.xml"/>
        <mapper resource="./mapper/EmployeeServiceMapper.xml"/>
    </mappers>
</configuration>
3.2 SQL映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.employeemapper">
    <!--
    namespace:名称空间;通常指定为接口的全类名
    id:唯一标识
    resultType:返回值类型
    #{id}:从传递过来的参数中取出id值
    public Employee getEmpById(Integer id);
     -->
    <select id="getEmpById" resultType="com.mybatis.entity.Employee">
        select id, last_name lastName, email, gender
        from employee
        where id = #{id}
    </select>
</mapper>
3.3 业务类
package com.mybatis.entity;
import lombok.Data;

@Data
public class Employee {

    private int id;
    private String lastName;
    private String email;
    private String gender;
}
3.4 配置类
  1. 根据全局配置文件得到SqlSessionFactory;

  2. 使用SqlSessionFactory,获取到sqlSession对象使用他来执行增删改查 一个sqlSession就是代表和数据库的一次会话,用完关闭

  3. 使用sql的唯一标识来告诉MyBatis执行哪个sql。sql都是保存在sql映射文件中的。


private SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
}
 
@Test
public void test() throws IOException {
    // 获取sqlSession实例,能直接执行已经映射的sql语句
    // sql的唯一标识:statement Unique identifier matching the statement to use.
    // 执行sql要用的参数:parameter A parameter object to pass to the statement.

    SqlSessionFactory sqlSessionFactory;
    SqlSession openSession = null;
    try {
        sqlSessionFactory = getSqlSessionFactory();
        openSession = sqlSessionFactory.openSession();
        // 加上namesapce com.mybatis.employeemapper 可以防止调用同名方法时冲突
        Employee employee = openSession.selectOne("com.mybatis.employeemapper.getEmpById", 1);
        System.out.println(employee);
    } catch (IOException e) {
        e.printStackTrace();
        throw e;
    } finally {
        if (null != openSession) {
            openSession.close();
        }
    }
}
3.5 接口式编程
3.5.1 创建接口
package com.mybatis.dao.mapper;

import com.mybatis.entity.Employee;

public interface EmployeeMapper {
    Employee getEmployeeById(int id);
}
3.5.2 SQL映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mybatis 支持namespace与接口名称绑定 -->
<mapper namespace="com.mybatis.dao.mapper.EmployeeMapper">
    <select id="getEmployeeById" resultType="com.mybatis.entity.Employee">
        select id, last_name lastName, email, gender
        from employee
        where id = #{id}
    </select>
</mapper>
3.5.3 测试代码
/**
 * 通过接口绑定来查询数据
 *
 * @throws IOException
 */
@Test
public void test02() throws IOException {
    SqlSessionFactory sqlSessionFactory;
    SqlSession openSession = null;
    try {
        sqlSessionFactory = getSqlSessionFactory();
        openSession = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper = openSession.getMapper(EmployeeMapper.class);
        Employee employee = employeeMapper.getEmployeeById(1);
        System.out.println(employee.getClass());
        System.out.println(employee);
    } catch (IOException e) {
        e.printStackTrace();
        throw e;
    } finally {
        if (null != openSession) {
            openSession.close();
        }
    }
}

结果

class com.sun.proxy.$Proxy6
Employee(id=1, lastName=chris, email=sss@1734.com, gender=m)

4.全局配置文件

4.1 标签

全局配置中标签需要按照此顺序编写

properties
settings
typeAliases
typeHandlers
objectFactory
objectWrapperFactory
reflectorFactory
plugins
environments
databaseIdProvider
mappers
4.1.1 properties

mybatis使用properties标签来引入外部properties配置文件的内容

resource 指向类路径下的资源文件

url 引用网络路径或本地磁盘上的资源文件

  1. 建properties文件

    mybatis-chris-helloworld-2/src/main/:/dbconfig

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://192.168.140.127:3306/chris?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
    jdbc.username=root
    jdbc.password=65536
    
  2. 改全局配置文件

    mybatis-chris-helloworld-2/src/main/:/mybatis-config.xml

    <configuration>
        <properties resource="dbconfig.properties"/>
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
        <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
        <mappers>
            <mapper resource="./mapper/EmployeeMapper.xml"/>
            <mapper resource="./mapper/EmployeeServiceMapper.xml"/>
        </mappers>
    </configuration>
    
4.1.2 settings
<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
    
  <!--开启表中下划线字段A_COLUMN转JavaBean驼峰字段aColumn-->
  <setting name="mapUnderscoreToCamelCase" value="false"/>
    
  <setting name="localCacheScope" value="SESSION"/>
    
  <!--指定字段值为null时的JDBC type,默认为OTHER-->
  <setting name="jdbcTypeForNull" value="OTHER"/>
  
    <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
4.1.3 typeAliases

别名处理器,可以为Java类型起别名, 且别名不区分大小写

  1. 在全局配置中添加

    <typeAliases>
    	<!--
    	type:为Java类型的全类名,没有设置别名的情况下默认别名为类名全小写, com.mybatis.entity.Employee的默认别名为employee
    	alias: 为Java类型指定别名
    	-->
        <typeAlias type="com.mybatis.entity.Employee" alias="emp"/>
    
        <!--
        为当前包以及子包里面的类起一个默认的别名
        批量起别名时如果别名重复,可以使用@Alias("employeeAlias")为Java类指定新的别名
        -->
        <package name="com.mybatis.entity"/>
    </typeAliases>
    
  2. 业务类

    package com.mybatis.entity;
    import lombok.Data;
    import org.apache.ibatis.type.Alias;
    
    @Data
    @Alias("employeeAlias")
    public class Employee {
        private int id;
        private String lastName;
        private String email;
        private String gender;
    }
    
  3. 在SQL映射文件中指定

    <!-- 测试默认别名, 别名不区分大小写 Employee和employ都可以-->
    <select id="testDefaultAlias" resultType="Employee">
        select *
        from employee
        where id = #{id}
    </select>
    
    <!-- 测试指定别名emp, 别名不区分大小写 Emp和emp都可以 -->
    <select id="testSpecifiedAlias" resultType="Emp">
        select *
        from employee
        where id = #{id}
    </select>
    
    <!-- 在类上使用@Alias("employeeAlias")指定别名 -->
    <select id="testSpecifiedAlias" resultType="employeeAlias">
        select *
        from employee
        where id = #{id}
    </select>
    
4.1.4 typeHandlers

处理Java类型与数据库表字段类型相互转换

NOTE Since version 3.4.5, MyBatis supports JSR-310 (Date and Time API) by default.

private List<Object> templateStickerImg;
<result column="quality_accessories" property="qualityAccessories" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
4.1.5 plug-ins

MyBatis allows you to intercept calls to at certain points within the execution of a mapped statement. By default, MyBatis allows plug-ins to intercept method calls of:

4.1.6 environments

可以用来配置多种环境

org.apache.ibatis.session.Configuration

this.typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
this.typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
this.typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
this.typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
this.typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
<environment id="development">
            <!-- 有两种类型的事务控制 JDBC|MANAGED , org.apache.ibatis.session.Configuration-->
            <transactionManager type="JDBC"/>
            <!--
           数据源
           type:
               UNPOOLED:不使用连接池的数据源
               POOLED:使用边境池的数据源
               JNDI:
               自定义数据源:实现DataSourceFactory接口-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
</environment>
4.1.7 databaseIdProvider

用来白支持多数据库厂商,得到不同数据库厂商的标识,mybatis跟据不同厂商的标识执行不同的SQL

DB_VENDOR - 会通过 DatabaseMetaData#getDatabaseProductName() 返回的字符串进行设置。由于通常情况下这个字符串都非常长而且相同产品的不同版本会返回不同的值,所以最好通过设置属性别名来使其变短

this.typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
  1. mybatis-chris-helloworld-2/src/main/:/mybatis-config.xml

    <!--
    用来支持多数据库
    type: DB_VENDOR, 厂商标识由驱动自带
    -->
    <databaseIdProvider type="DB_VENDOR">
        <!--
        为不同的数据库厂商标识起别名
        name:数据库厂商标识
        value:别名
        -->
        <property name="MYSQL" value="mysql"/>
        <property name="Oracle" value="oralce"/>
        <property name="SQL Server" value="sqlserver"/>
    </databaseIdProvider>
    
  2. mybatis-chris-helloworld-2/src/main/:/mapper/Employee2Mapper.xml

    <!-- 在指定的mysql上数据库上执行,databaseId为databaseIdProvider的别名  -->
    <select id="testSpecifiedAlias" resultType="employeeAlias" databaseId="mysql">
        select *
        from employee
        where id = #{id}
    </select>
    
    <!-- 在指定的oralce上数据库上执行,databaseId为databaseIdProvider的别名  -->
    <select id="testSpecifiedAlias" resultType="employeeAlias" databaseId="oralce">
        select *
        from employees
        where id = #{id}
    </select>
    
4.1.8 mappers

将写好的sql映射文件(EmployeeMapper.xml)注册到全局配置文件(mybatis-config.xml)中

  1. mapper 单个注册

    resource: 注册类路径下的资源文件

    <mappers>
    <mapper resource="./mapper/EmployeeMapper.xml"/>
    <mapper resource="./mapper/Employee2Mapper.xml"/>
    </mappers>
    

    url: 注册网络路径或本地磁盘上的资源文件

    <mappers>
    <mapper url="file:///var/mappers/AuthorMapper.xml"/>
    <mapper url="file:///var/mappers/BlogMapper.xml"/>
    </mappers>
    

    class: 注册接口

    1. 将SQL映射文件与接口入在同一类路径下,并且与接口名称一致

      <mappers>
          <mapper resource="com.mybatis.dao.mapper.EmployeeMapper"/>
      </mappers>
      
    2. 不用SQL映射文件,基于注解的SQL映射, 不建议,因为会使代码和SQL耦合,使业务和数据逻辑混乱

      package com.mybatis.dao.mapper;
      import com.mybatis.entity.Employee;
      import org.apache.ibatis.annotations.Select;
      
      public interface EmployeeAnnotationMapper {
          @Select("select *  from employee  where id = #{id}")
          Employee getEmployeeById(int id);
      }
      
      <mappers>
          <mapper class="com.mybatis.dao.mapper.EmployeeAnnotationMapper"/>
      </mappers>
      
  2. 批量注册

    <mappers>
       <!-- 批量注册
       name:接口所在的包路径
       适用于通过注解实现SQL映射的接口,对于通过配置文件实现的SQL映射,需要将XML文件与接口放在一起,否则无法批量注册
       -->
        <package name="com.mybatis.dao.mapper"/>
    </mappers>
    

5. 映射文件

5.1 标签
cache – Configuration of the cache for a given namespace.
cache-ref – Reference to a cache configuration from another namespace.
resultMap – The most complicated and powerful element that describes how to load your objects from the database result sets.
parameterMap – Deprecated! Old-school way to map parameters. Inline parameters are preferred and this element may be removed in the future. Not documented here.
sql – A reusable chunk of SQL that can be referenced by other statements.
insert – A mapped INSERT statement.
update – A mapped UPDATE statement.
delete – A mapped DELETE statement.
select – A mapped SELECT statement.
5.2 增删改查

mybatis 自动封装了增删改的返回结果
int 和 long 表示影响的行数
boolean 表示是否执行成功
void表示什么都不返回

  1. 业务接口

    package com.mybatis.dao.mapper;
    import com.mybatis.entity.Employee;
    
    public interface EmployeeMapper {
        Employee getEmployeeById(int id);
        int addEmployee(Employee employee);
        int deleteEmployeeById(int id);
        int updateEmployee(Employee employee);
    }
    
  2. SQL映射文件

    <mapper namespace="com.mybatis.dao.mapper.EmployeeMapper">
        <select id="getEmployeeById" resultType="com.mybatis.entity.Employee">
            select *
            from employee
            where id = #{id}
        </select>
        <!--parameterType: 可以省略-->
        <insert id="addEmployee" parameterType="com.mybatis.entity.Employee">
            insert into employee (last_name, email, gender)
            values (#{lastName}, #{email}, #{gender})
        </insert>
    
        <update id="updateEmployee">
            update employee t
            set t.last_name=#{lastName},
                t.email=#{email},
                gender=#{gender}
            where t.id = #{id}
        </update>
    
        <delete id="deleteEmployeeById">
            delete
            from employee
            where id = #{id}
        </delete>x
    </mapper>
    
5.3 获取MySql自增主键
  1. 修改SQL映射文件

    <!--
    parameterType: 可以省略
    useGeneratedKeys: 设置为true,使用自增主键策略获取主键
    keyProperty: 指定对应的主键属性,即当获取主键后将值封装给JavaBean中的哪个属性
    -->
    <insert id="addEmployee" parameterType="com.mybatis.entity.Employee" useGeneratedKeys="true" keyProperty="id">
        insert into employee (last_name, email, gender)
        values (#{lastName}, #{email}, #{gender})
    </insert>
    
  2. 测试代码

    @Test
    public void addEmployee() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession();
            EmployeeMapper employeeMapper = openSession.getMapper(EmployeeMapper.class);
            Employee employee = new Employee("Cano", "Cano@gmail.com", "F");
            employeeMapper.addEmployee(employee);
            System.out.println("add user id:" + employee.getId());
            openSession.commit();
    
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
5.4 获取Oracle Sequence值
  1. 改SQL映射文件

    <!--
    使用Oracle Sequence添加员工记录前获取ID
    -->
    <insert parameterType="com.mybatis.entity.Employee" database>
        <!--
        keyProperty: 指定对应的主键属性,即当获取主键后将值封装给JavaBean中的哪个属性
        order: BEFORE 当前SQL在插入SQL之前运行
               AFTER  当前SQL在插入SQL之后运行
        resultType: 查出的数据返回类型
        -->
        <selectKey keyProperty="id" order="BEFORE" resultType="Integer">
            select EMPLOYEES_SEQ.nextval from dual
        </selectKey>
        <!-- 插入时的主键是从序列中拿到 -->
        insert into employee (id, last_name, email, gender)
        values (#{id}, #{lastName}, #{email}, #{gender})
    </insert>
    
    <!--
    使用Oracle Sequence添加员工记录后获取ID
     -->
    <insert parameterType="com.mybatis.entity.Employee" database>
        <!--
        keyProperty: 指定对应的主键属性,即当获取主键后将值封装给JavaBean中的哪个属性
        order: BEFORE 当前SQL在插入SQL之前运行
               AFTER  当前SQL在插入SQL之后运行
        resultType: 查出的数据返回类型
        -->
        <selectKey keyProperty="id" order="AFTER" resultType="Integer">
            select EMPLOYEES_SEQ.currval from dual
        </selectKey>
        <!-- 插入时的主键是从序列中拿到 -->
        insert into employee (id, last_name, email, gender)
        values (EMPLOYEES_SEQ.nextval, #{lastName}, #{email}, #{gender})
    </insert>
    
5.4 参数处理
5.4.1 单个参数
#{参数名} 

单个参数Mybatis不作特殊处理
5.4.2 多个参数
  1. Mybatis会将参数封装成Map,key从 param1~paramN

    #{参数名} 是从Map中取到指定key的值
    第一个参数: #{param1} 
    第二个参数: #{param2} 
    
  2. 命名参数

    需要在接口中的方法参数上使用@Param("lastName")
    参数会被封装成Map,key是@Param注解中指定的值
    取值#{lastName}
    
    Employee getEmployeeByIdAndName2(@Param("id") int id, @Param("lastName") String lastName);
    
    <select id="getEmployeeByIdAndName2" resultType="com.mybatis.entity.Employee">
        select *
        from employee
        where id = #{id}
          and last_name = #{lastName}
    </select>
    
5.4.3 参数封装
  1. POJO

    如果多个参数是业务字段,可以通过传POJO,通过#{业务字段名称}来取值

  2. Map

    如果多个参数不是业务字段,可以将多个参数封装为Map, 通过#{key}来取值

    <select id="getEmployeeByMap" resultType="com.mybatis.entity.Employee">
        select *
        from employee
        where id = #{p_id}
          and last_name = #{p_lastName}
    </select>
    
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("p_id", 1);
    paramMap.put("p_lastName", "Chris");
    Employee employee = employeeMapper.getEmployeeByMap(paramMap);
    openSession.commit();
    
  3. TO(Transfer Object)

    如果多个参数不是业务字段,但是经常使用,可能编写一个TO(Transfer Object)来传输数据

    Page{
     int index;
     int size;
    }
    
5.4.4 取值方式分析
  1. 简单参数

    Employee getEmployeeByIdAndName(@Param("id") int id, String lastName);
    取id的值: #{id}或#{param1}
    取lastName的值:#{param2}
    
  2. 对象参数

    Employee getEmployeeByIdAndEmp(@Param("id") int id, @Param("e")Employee emp);
    取id的值: #{id}或#{param1}
    取lastName的值:#{e.lastName}或者#{param2.lastName} --param2代表emp对象
    
  3. 集合参数

    如果是Collection类型或者数组类型,会特殊处理,将Collection类型或者数组类型封装在map中

    Collection类型: key为collection, 如果是list会进一步封装key为list

    数组类型: key为array

    Employee getEmployeeByIds(List<int> ids);
    取第一个id的值:#{list[0]}
    
5.4.5 $和#的区别
  1. $和#都可以用来获取参数

    #: 是以预编译的方式将参数设置到SQL中去,可以防止SQL注入,大多数情况下使用#取值

    $: 将取出的值直接拼装在SQL中,有SQL注入的安全风险

  2. $ 可以用来动态设置SQL中的表名和字段名称,

    原生SQL不支持占位符的地方都可以用$来处理

    /**
     * 测试 testDynamicSql
     */
    @Test
    public void testDynamicSql() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession();
            EmployeeMapper employeeMapper = openSession.getMapper(EmployeeMapper.class);
    
            //map参数
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("p_gender", "F");
            paramMap.put("tableName", "Employee");
            paramMap.put("sortFieldName", "last_name");
            paramMap.put("sort", "ASC");
    
            List<Employee> employees = employeeMapper.dynamicSql(paramMap);
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
            openSession.commit();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
    <!--动态SQL-->
    <select id="dynamicSql" resultType="com.mybatis.entity.Employee">
        select *
        from ${tableName}
        where gender = #{p_gender}
        order by ${sortFieldName} ${sort}
    </select>
    
  3. #{}可以规定参数的类型

    javaType, jdbcType, resultMap, typeHandler, jdbcTypeName

    jdbcType: 在数据为null的情况下,数据库不能识别mybatis对于null的处理比如Oracle

     <!-- 
     MyBatis将所有的null都映射为原生的 OTHER(Types.OTHER)
     Oracle无法处理Other类型
     需要指定字段值为空时的JDBC类型jdbcType=NULL
     或者在全局配置中设置 <setting name="jdbcTypeForNull" value="NULL"/>
     -->
    <insert id="addEmployeeWithNull" parameterType="com.mybatis.entity.Employee" databaseId="oracle">
        <selectKey keyProperty="id" order="BEFORE" resultType="Integer">
             select EMPLOYEES_SEQ.nextval from dual
        </selectKey>
          <!-- 插入时的主键是从序列中拿到 -->
          insert into employee (id, last_name, email, gender)
          values (#{id}, #{lastName}, #{email, jdbcType=NULL}, #{gender})
     </insert>
    
5.4.6 @的用法
    <if test="@cn.hutool.core.util.StrUtil@isNotEmpty(clientAdminBean.name) ">
        and a.name = #{clientAdminBean.name}
    </if>
    <if test="@cn.hutool.core.util.StrUtil@isNotEmpty(clientAdminBean.tableName) ">
        and a.table_name like CONCAT('%',#{clientAdminBean.tableName},'%')
    </if>
    <if test="@cn.hutool.core.util.StrUtil@isNotEmpty(clientAdminBean.mqTopic) ">
        and a.mq_topic like CONCAT('%',#{clientAdminBean.mqTopic},'%')
    </if>
5.5 返回结果封装
5.5.1 返回为集合

resultType为集合中元素的类型

5.5.2 返回为单个Map

resultType为的类型为map

<!--测试返回结果为map-->
<select id="getEmployeeReturnMap" resultType="map">
    select *
    from employee t
    where t.id = #{id}
</select>
/**
 * 测试 testMapResult
 */
@Test
public void testMapResult() throws IOException {
    SqlSessionFactory sqlSessionFactory;
    SqlSession openSession = null;
    try {
        sqlSessionFactory = getSqlSessionFactory();
        openSession = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper = openSession.getMapper(EmployeeMapper.class);

        Map<String, Object> employeeMap = employeeMapper.getEmployeeReturnMap(4);
        openSession.commit();
        for (Map.Entry<String, Object> entry : employeeMap.entrySet()) {
            System.out.println(entry.getKey() + ", " + entry.getValue());
        }
    } catch (IOException e) {
        e.printStackTrace();
        throw e;
    } finally {
        if (null != openSession) {
            openSession.close();
        }
    }
}
5.5.3 返回为多个Map

接口类

/**
  * 多条记录封装在Map<String, Employee>
  * MapKey 告诉mybatis用Employee的哪个属性作为map的key
  */
@MapKey("id")
Map<Integer, Employee> getEmployeeByGenderReturnMap(String gender);

SQL映射文件

<!--测试返回结果为多个MAP对象-->
<select id="getEmployeeByGenderReturnMap" resultType="com.mybatis.entity.Employee">
    select *
    from employee t
    where t.gender = #{gender}
</select>
/**
 * 测试返回为多个对象
 */
@Test
public void testMapResult2() throws IOException {
    SqlSessionFactory sqlSessionFactory;
    SqlSession openSession = null;
    try {
        sqlSessionFactory = getSqlSessionFactory();
        openSession = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper = openSession.getMapper(EmployeeMapper.class);

        //返回为多个对象
        Map<Integer, Employee> employeeMap = employeeMapper.getEmployeeByGenderReturnMap("F");

        openSession.commit();
        for (Map.Entry<Integer, Employee> entry : employeeMap.entrySet()) {
            System.out.println(entry.getKey() + ", " + entry.getValue());
        }
    } catch (IOException e) {
        e.printStackTrace();
        throw e;
    } finally {
        if (null != openSession) {
            openSession.close();
        }
    }
}
5.6 resultMap
5.6.1 resultType 入门

resultType 是自动封装,将表中的字段与JavaBean中的字段映射

resultMap 是自定义封装,实现高级结果集映射

  1. 定义ResultMap

    <!--
    自定义表字段名称与JavaBean属性的映射
    type: JavaBean类型
    id: resultMap唯一标识,方便被引用
    -->
    <resultMap id="employeeMap" type="com.mybatis.entity.Employee">
        <!--
        column: 表字段名称
        property: JavaBean类型属性
        -->
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
        <!--不在此处配置的列,会自动映射,但如果使用resultMap,建议把所有列都配置出来-->
    
    </resultMap>
    
    <select id="getEmployeeByGenderReturnMap" resultMap="employeeMap">
        select *
        from employee t
        where t.gender = #{gender}
    </select>
    
  2. 业务类

    /**
     * 多条记录封装在Map<String, Employee>
     * MapKey 告诉mybatis用Employee的哪个属性作为map的key
     */
    @MapKey("id")
    Map<Integer, Employee> getEmployeeByGenderReturnMap(String gender);
    
  3. 测试类

    /**
     * 测试resultMap
     */
    @Test
    public void testResultMap() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession();
            EmployeeMapper2 employeeMapper2 = openSession.getMapper(EmployeeMapper2.class);
            Map<Integer, Employee> employeeMap = employeeMapper2.getEmployeeByGenderReturnMap("F");
            openSession.commit();
            for (Map.Entry<Integer, Employee> entry : employeeMap.entrySet()) {
                System.out.println(entry.getKey() + ", " + entry.getValue());
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
5.6.2 通过级联属性的方式进行联合查询
  1. 定义ResultMap

    <!--通过级联属性的方式进行联合查询-->
    <resultMap id="empDeptMap" type="com.mybatis.entity.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
        <result column="did" property="dept.id"/>
        <result column="department_name" property="dept.name"/>
    </resultMap>
    
    <select id="getEmpAndDept" resultMap="empDeptMap">
        select t.id, t.last_name, t.email, t.gender, d.id did, d.department_name
        from employee t,
             department d
        where t.id = #{id}
          and t.department_id = d.id
    </select>
    
  2. 业务类

    @Data
    @AllArgsConstructor
    public class Employee {
    
        public Employee(String lastName, String email, String gender) {
            this.lastName = lastName;
            this.email = email;
            this.gender = gender;
        }
    
        public Employee(int id, String lastName, String email, String gender) {
            this(lastName, email, gender);
            this.id = id;
        }
    
        private int id;
        private String lastName;
        private String email;
        private String gender;
        private Department dept;
    }
    
  3. 测试类

    /**
     * 通过级联属性的方式进行联合查询
     */
    @Test
    public void testAssociateResultMap() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession();
            EmployeeMapper2 employeeMapper2 = openSession.getMapper(EmployeeMapper2.class);
            Employee employee = employeeMapper2.getEmpAndDept(1);
            openSession.commit();
            System.out.println(employee.toString());
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
5.6.3 使用association进行分步查询
  1. SQL映射文件

    DepartmentMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mybatis.dao.mapper.DepartmentMapper">
    
        <select id="getDeptById" resultType="com.mybatis.entity.Department">
             select * from department t where t.id=#{id}
         </select>
    
    </mapper>
    

    EmployeeMapper2.xml

    <!--使用association进行分步查询-->
    <resultMap id="empDeptBySteps" type="com.mybatis.entity.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
        <!--
        1.先根据员工id查询到员工信息
        2.再根据员工信息中的d_id查询部门信息
        3.再将部门信息封闭到员工对象中
        select:表示当前关联的对象是调用指定的方式查询出来的结果
        column="department_id":指定传入select中方法的参数,此参数来自于第一个方法“getEmpById”中查询的结果集里面
        -->
        <association property="dept" javaType="com.mybatis.entity.Department"
                     select="com.mybatis.dao.mapper.DepartmentMapper.getDeptById" column="department_id"/>
    </resultMap>
    
    <select id="getEmpById" resultMap="empDeptBySteps">
        select * from employee t where t.id = #{id}
    </select>
    
  2. 业务类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Department {
    
       private int id;
       private String name;
    }
    
    package com.mybatis.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Employee {
    
        private int id;
        private String lastName;
        private String email;
        private String gender;
        private Department dept;
    
    
        public Employee(String lastName, String email, String gender) {
            this.lastName = lastName;
            this.email = email;
            this.gender = gender;
        }
    
        public Employee(int id, String lastName, String email, String gender) {
            this(lastName, email, gender);
            this.id = id;
        }
    
    
    }
    
  3. 测试类

    /**
     * 使用association进行分步查询
     */
    @Test
    public void testEmpDeptBySteps() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession();
            EmployeeMapper2 employeeMapper2 = openSession.getMapper(EmployeeMapper2.class);
            Employee employee = employeeMapper2.getEmpById(1);
            openSession.commit();
            System.out.println(employee.toString());
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
5.6.4 分步查询时延时加载
  1. 全局配置文件

    <!--开启全局延时加载-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!--关闭积极加载-->
    <setting name="aggressiveLazyLoading" value="false"/>
    <setting name="lazyLoadTriggerMethods" value=""/>
    
  2. 业务类

    一般业务类中使用@Data注解会触发toString方法,可以将@Data替换成@Getter和@Setter注解

    package com.mybatis.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    
    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor
    public class Employee {
    
       private int id;
       private String lastName;
       private String email;
       private String gender;
       private Department dept;
    
    
       public Employee(String lastName, String email, String gender) {
          this.lastName = lastName;
          this.email = email;
          this.gender = gender;
       }
    
       public Employee(int id, String lastName, String email, String gender) {
          this(lastName, email, gender);
          this.id = id;
       }
    }
    
5.6.5 使用Collection 关联集合查询
  1. SQL映射文件

    <!--嵌套结果集关联查询-->
      <resultMap id="deptWithEmps" type="com.mybatis.entity.Department">
          <id column="did" property="id"/>
          <result column="name" property="name"/>
          <!--
          定义集合类型的属性
          ofType:指定集合里面的元素类型
          -->
          <collection property="emps" ofType="com.mybatis.entity.Employee">
              <id column="id" property="id"/>
              <result column="last_name" property="lastName"/>
              <result column="email" property="email"/>
              <result column="gender" property="gender"/>
          </collection>
      </resultMap>
    
      <select id="getDeptById2" resultMap="deptWithEmps">
    	SELECT d.id did, d.department_name, e.id, e.email, e.gender, e.last_name, e.department_id
          FROM department d
        LEFT JOIN employee e ON e.department_id = d.id
        WHERE d.id = #{id}
      </select>
    
  2. 业务类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Department {
    
        private int id;
        private String name;
        private List<Employee> emps;
    }
    
  3. 测试类

    /**
     * 使用collection进行关联对象的集合查询
     */
    @Test
    public void testDeptWithEmps() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession();
            DepartmentMapper departmentMapper = openSession.getMapper(DepartmentMapper.class);
            Department dept = departmentMapper.getDeptById2(1);
            openSession.commit();
            System.out.println(dept.toString());
            System.out.println(dept.getEmps().toString());
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
5.6.6 使用Collection 分步和延时查询
  1. SQL映射文件

    DepartmentMapper.xml

    
    <!--
    分步查询部门下的员工信息
    1.先查询出部门信息
    2.再根据部门ID查询出员工信息
    -->
    <resultMap id="deptWithEmpsByStep" type="com.mybatis.entity.Department">
        <id column="id" property="id"/>
        <result column="department_name" property="name"/>
        <!--
        column="id":指定传入select中方法的参数,此参数来自于第一个方法“getDeptByIdStep”中查询的结果集里面
        多个参数时column={key1=value1,key2=value2} key要和也分步查询方法里面的参数名称保持一致
        javaType:返回结果集的类型
        fetchType: 即使全局打开了延时加载,也可以指定针对此关联查询是否要进行延时加载,
                   eager:立即加载,lazy:延时加载
        -->
        <collection property="emps" select="com.mybatis.dao.mapper.EmployeeMapper.getEmployeeByDeptId" column="id"
                    javaType="List" fetchType="lazy"/>
    </resultMap>
    <select id="getDeptByIdStep" resultMap="deptWithEmpsByStep">
        select * from department t where t.id=#{id}
    </select>
    

    EmployeeMapper.xml

    <!--
    分步查询部门下的员工信息
    1.先查询出部门信息
    2.再根据部门ID查询出员工信息
    -->
    <select id="getEmployeeByDeptId" resultType="com.mybatis.entity.Employee">
        select *
        from employee
        where department_id = #{department_id}
    </select>
    
  2. 业务类

    package com.mybatis.dao.mapper;
    
    import com.mybatis.entity.Employee;
    import org.apache.ibatis.annotations.MapKey;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    import java.util.Map;
    
    public interface EmployeeMapper {
        Employee getEmployeeByDeptId(int i);
    }
    
  3. 测试类

    /**
     * 使用collection进行关联对象的集合分步查询
     */
    @Test
    public void testDeptWithEmpsBySteps() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession();
            DepartmentMapper departmentMapper = openSession.getMapper(DepartmentMapper.class);
            Department dept = departmentMapper.getDeptByIdStep(2);
            openSession.commit();
            System.out.println(dept.toString());
            System.out.println(dept.getEmps().toString());
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
5.6.7 鉴别器
  1. SQL映射文件

    EmployeeMapper2

    <!--
      discriminator
      鉴别器
      mybatis可以根据discriminator判断某列的值,根据值来改变封装行为
      封装employee
      1.如果查询出来的是女生,则把对应的部门信息查询出来,否则不查询
      2.如果查询出来的是男生,则把lastName这一列赋值到email上
      -->
    <resultMap id="empDeptByStepsWithDiscriminator" type="com.mybatis.entity.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
        <!--如果查询出来的是女生,则把对应的部门信息查询出来,否则不查询-->
        <discriminator javaType="String" column="gender">
            <case value="F" resultType="com.mybatis.entity.Employee">
                <association property="dept" select="com.mybatis.dao.mapper.DepartmentMapper.getDeptById"
                             javaType="com.mybatis.entity.Employee"
                             column="department_id" fetchType="eager"/>
            </case>
    
            <!--如果查询出来的是男生,则把lastName这一列赋值到email上-->
            <case value="M" resultType="com.mybatis.entity.Employee">
                <id column="id" property="id"/>
                <result column="last_name" property="lastName"/>
                <result column="last_name" property="email"/>
                <result column="gender" property="gender"/>
            </case>
        </discriminator>
    </resultMap>
    
    <select id="getEmpByIdwithDiscriminator" resultMap="empDeptByStepsWithDiscriminator">
        select * from employee
    </select>
    

    DepartmentMapper.xml

    <select id="getDeptById" resultType="com.mybatis.entity.Department">
         select id, department_name name from department t where t.id=#{id}
    </select>
    
  2. 业务类

    public interface EmployeeMapper2 {
        List<Employee> getEmpByIdwithDiscriminator();
    }
    
  3. 测试类

    @Test
    public void testEmpByUsingDiscriminator() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession(true);
            EmployeeMapper2 employeeMapper2 = openSession.getMapper(EmployeeMapper2.class);
            List<Employee> emps = employeeMapper2.getEmpByIdwithDiscriminator();
            for (Employee emp : emps) {
                System.out.println(emp.toString());
                if (null != emp.getDept()) {
                    System.out.println(emp.getDept().toString());
                }
            }
    
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
  4. 结果

    Employee{id=1, lastName='Chris', email='Chris', gender='M'}
    Employee{id=3, lastName='Hedy', email='Hedy', gender='M'}
    Employee{id=4, lastName='Nancy', email='Nancy@gmail.com', gender='F'}
    Department(id=1, name=开发部, emps=null)
    Employee{id=7, lastName='Cano', email='Cano@gmail.com', gender='F'}
    Department(id=2, name=测试部, emps=null)
    
5.7 动态SQL
5.7.1 if
<select id="getempsbyconditionIf" resultType="com.mybatis.entity.Employee">
    select * from employee t
    <!--
    where:用来封装查询条件,会将SQL中多出来的and和or去掉,但是只去掉第一个and和or
    -->
    <where>
        /* 1. test:判断表达式,使用OGNL表达式
        https://commons.apache.org/proper/commons-ognl/language-guide.html
        遇见特殊符号应该转为转义字符*/
        <if test="id != null">
            t.id = #{id}
        </if>
        <if test="lastName != null and lastName!= '' ">
            and t.last_name=#{lastName}
        </if>
        <if test="email != null and email.trim() !='' ">
            and t.email=#{email}
        </if>
        <if test='gender != null and (gender =="F" || gender =="M")'>
            and t.gender=#{gender}
        </if>
    </where>
</select>
5.7.2 trim
<select id="getempsbyconditionTrim" resultType="com.mybatis.entity.Employee">
    select * from employee t

    <!--
        prefix: 对trim中整个字符串拼串后的结果加一个前缀
        prefixOverrides: 前缀覆盖,去掉整个拼串前面多余的字符串
        suffix: 对trim中整个字符串拼串后的结果加一个后缀
        suffixOverrides: 后缀覆盖,去掉整个拼串前面多余的字符串
    -->
    <trim prefix="where" suffixOverrides="and">
        <if test="id != null">
            t.id = #{id} and
        </if>
        <if test="lastName != null and lastName!= '' ">
            t.last_name=#{lastName} and
        </if>
        <if test="email != null and email.trim() !='' ">
            t.email=#{email} and
        </if>
        <if test='gender != null and (gender =="F" || gender =="M")'>
            t.gender=#{gender}
        </if>
    </trim>
</select>
5.7.3 choose
<select id="getempsbyconditionChoose" resultType="com.mybatis.entity.Employee">
    select * from employee t
    <where>
        <choose>
            <when test="id!=null">id=#{id}</when>
            <when test="lastName!=null">last_name=#{lastName}</when>
            <when test="email!=null and email.trim()!='' ">email=#{email}</when>
            <otherwise>
                <!--查询所有-->
                1 = 1
            </otherwise>
        </choose>
    </where>
</select>
<select id="getRolePrincileByFormIdandRoleKey" resultMap="BaseResultMap">
        SELECT
        <include refid="Base_Column_List"/>
        FROM
        t_wf_role_principle p
        WHERE
        p.formId = #{formId}
        <choose>
            <when test="null != roleKeys and roleKeys.size > 1">
                <foreach collection="roleKeys" item="key" open=" and p.roleKey in (" close=")"
                         separator=",">
                    #{key}
                </foreach>
            </when>
            <when test="null != roleKeys and roleKeys.size == 1">
                and p.roleKey = #{roleKeys[0]}
            </when>
        </choose>
</select>
5.7.4 set
<!--
参数中带了哪一个参数则更新此参数对应的字段
<set>用来封装修改字段
也可以用tirm替换set标签
<trim prefix="set" prefixOverrides=",">
-->
<update id="updateEmp">
    update employee t
    <set>
        <if test="lastName!=null and lastName.trim()!=''">
            t.last_name=#{lastName},
        </if>
        <if test="email!=null and email.trim()!=''">
            t.email=#{email},
        </if>
        <if test='gender!=null and  (gender =="F" || gender =="M")'>
            t.gender=#{gender},
        </if>
    </set>
    where t.id = #{id}
</update>
5.7.5 foreach
<!--
   connection:指定要遍历的集合名称
        list类型的参数会特殊处理封装在map中,这个map的key名称是list
   item:将当前遍历出的值赋值给指定变更
   separator元素之间的分隔符
   open:封装遍历结果的开始字符
   close:封装遍历结果的结束字符
   index:索引,遍历list时,index是当前元素的索引,item为当前元素的值
         遍历map时,index是当前元素的key,item为当前元素的值
   #{变量名}就能取出变量的值也就是当前遍历出的元素
-->
<select id="getEmpsByConditionForeach" resultType="com.mybatis.entity.Employee">
    select * from employee where id in
    <foreach collection="list" item="id" separator="," open="(" close=")" index="inx">
        #{id}
    </foreach>
</select>
public interface DynamicSqlMapper {
    List<Employee> getEmpsByConditionForeach(List<Integer> ids);
}
/**
 * 测试foreach
 */
@Test
public void testForeach() throws IOException {
    SqlSessionFactory sqlSessionFactory;
    SqlSession openSession = null;
    try {
        sqlSessionFactory = getSqlSessionFactory();
        openSession = sqlSessionFactory.openSession(true);
        DynamicSqlMapper dynamicSqlMapper = openSession.getMapper(DynamicSqlMapper.class);
        List<Employee> employees = dynamicSqlMapper.getEmpsByConditionForeach(Arrays.asList(1, 3, 4));
        openSession.commit();
        for (Employee employee : employees) {
            System.out.println(employee.toString());
        }
    } catch (IOException e) {
        e.printStackTrace();
        throw e;
    } finally {
        if (null != openSession) {
            openSession.close();
        }
    }
}
5.7.6 foreach insert for mysql

方式一

  1. SQL映射文件

    <insert id="addEmpsInBatch">
        insert into employee (last_name, email,gender,department_id)
        <foreach collection="emps" item="emp" open="values" separator=",">
            (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
        </foreach>
    </insert>
    
  2. 业务类

    int addEmpsInBatch(@Param("emps") List<Employee> employees);
    
  3. 测试类

    /**
     * 测试foreach insert
     */
    @Test
    public void testForeachInsert() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession(true);
            DynamicSqlMapper dynamicSqlMapper = openSession.getMapper(DynamicSqlMapper.class);
            Employee emp1 = new Employee("S4", "s4@gmail.com", "F", new Department(1));
            Employee emp2 = new Employee("S5", "s5@gmail.com", "M", new Department(2));
            Employee emp3 = new Employee("S6", "s6@gmail.com", "F", new Department(2));
            int count = dynamicSqlMapper.addEmpsInBatch(Arrays.asList(emp1, emp2, emp3));
            System.out.println("new added employee count:" + count);
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    

方式二

  1. SQL映射文件

    <!-- Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insert into employee (last_name, email,gender,department_id)values
     (' at line 4
     需要打开MYSQL的批量写入模式:allowMultiQueries=true
        jdbc.home.url=jdbc:mysql://192.168.101.127:3306/chris?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
     -->
     <insert id="addEmpsInBatch2">
         <foreach collection="emps" item="emp"  separator=";">
             insert into employee (last_name, email,gender,department_id)values
             (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
         </foreach>
     </insert>
    
5.7.7 foreach insert for oracle
  1. SQL中映射文件

    <!--
     oracle 不支持mysql这种批量写入数据库
     insert into employee(last_name, email,gender,department_id) values (),()
     但是支持如下三种
     1. 将多条语句放在begin和end之间
     begin
        insert into employee(last_name, email,gender,department_id) values ();
        insert into employee(last_name, email,gender,department_id) values ();
        insert into employee(last_name, email,gender,department_id) values ();
     end;
     2. 利用中间表
         insert into employee(last_name, email,gender,department_id) select employees_seq.nextval, last_name, email from (
            select 'test_a_01' last_name, 'test_a_01@163.com' email from dual;
            union
            select 'test_a_02' last_name, 'test_a_02@gmail.com' email from dual;
            union
            select 'test_a_03' last_name, 'test_a_03@gmail.com' email from dual;
         )
    -->
    
    <!--1. 将多条语句放在begin和end之间-->
    <insert id="addEmpsInBatchInOracle" databaseId="oracle">
        <foreach collection="emps" item="emp" open="begin" close="end;" separator=";">
            insert into employee (last_name, email,gender,department_id)
            (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
        </foreach>
    </insert>
    
    <!--2. 利用中间表-->
    <insert id="addEmpsInBatch2InOracle" databaseId="oracle">
        insert into employee(last_name, email,gender,department_id)
        <foreach collection="emps" item="emp"
                 open="select employees_seq.nextval, last_name, email, gender, department_id from(" close=")"
                 separator="union">
            select #{emp.lastName} last_name, #{emp.email} email, #{emp.gender} gender, #{emp.dept.id} department_id
            from dual;
        </foreach>
    
    </insert>
    
5.7.8 内置参数
<!--
两个内置参数
1. _parameter: 代表传入方法的整个参数
    如果是一个参数,_parameter就表示这个参数
    如果是多个参数,参数会被mybatis封装成为一个map,_parameter就代表这个map
2. _databaseId: 如果配置了databaseIdProvider,_databaseIdy就是代表当前使用的数据库别名
-->

<!--根据当启用的数据库来进行不同的查询-->
<select resultType="com.mybatis.entity.Employee">
    <if test="_databaseId=='mysql'">
        select * from employee
        <where>
            <if test="_parameter!=null">
                last_name = #{_parameter.lastName}
            </if>
        </where>

    </if>
    <if test="_databaseId=='mysql'">
        select * from t_employee
    </if>

</select>
5.7.9 bind
  1. SQL映射文件

    <!--如果lastName有值则进行模糊查询-->
    <select id="getEmpByBind" resultType="com.mybatis.entity.Employee">
        <!--bind 将OGNL表达式的值绑定到一个变量中,方便后面引用这个变量的值-->
        <bind name="_lastName" value="'%'+lastName+'%'"/>
        select * from employee
        <where>
            <if test="_parameter != null and lastName !='' ">
                last_name LIKE #{_lastName}
            </if>
        </where>
    </select>
    
  2. 业务类

    public interface DynamicSqlMapper {
        List<Employee> getEmpByBind(Employee emp);
    }
    
  3. 测试类

    /**
     * 测试bind
     */
    @Test
    public void testBind() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession(true);
            DynamicSqlMapper dynamicSqlMapper = openSession.getMapper(DynamicSqlMapper.class);
            Employee emp = new Employee();
            // 查询名称中包括a的员工记录
            emp.setLastName("a");
    
            List<Employee> emps = dynamicSqlMapper.getEmpByBind(emp);
            for (Employee employee : emps) {
                System.out.println(employee.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
5.8.0 sql片断
  1. SQL映射文件

    <!--
    include 
    1.可以引用sql标签中定义的SQL片断
    2.可以定义属性变量,可以在sql标签使用${testColumn}来获取属性变量的值
    -->
    <insert id="addEmpsWithCondistionInclude">
        insert into employee (
        <include refid="emp_insert_fields">
            <property name="testColumn" value="abc"/>
        </include>
        )
        <foreach collection="emps" item="emp" open="values" separator=",">
            (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
        </foreach>
    </insert>
    
    <!--
    sql标签用来抽取可重用的sql片段
    1.将常用的列名抽取出来,方便查询或插入中引用
    2.include来引用sql标签中的sql片断
    -->
    <sql id="emp_insert_fields">
        last_name, email,gender,department_id,${testColumn}
    </sql>
    

6 缓存

6.1 mybatis 缓存

mybatis中默认定义了两级缓存

默认情况有只开启一级缓存,也称为本地缓存,即SqlSesssion级别的缓存

二级缓存为全局缓存,需要手动配置和开启,它是基于namespace级别的缓存

为了提高扩展性,mybatis提供了缓存接口Cache,可以通过实现Cache接口来实现二级缓存

6.2 一级缓存

与数据库同一次会话期间查询到的数据会放在一级缓存中,以后如果需要获取相同的数据,直接从一级缓存中查

6.2.1 使用一级缓存
  1. SQL映射

    <select id="getEmpById" resultType="com.mybatis.entity.Employee">
        select * from employee where id = #{id}
    </select>
    
  2. 测试类

    /**
     * 测试Cache
     */
    @Test
    public void testCache() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession = sqlSessionFactory.openSession(true);
            CacheMapper cacheMapper = openSession.getMapper(CacheMapper.class);
    
            // 第一次查询
            Employee emp = cacheMapper.getEmpById(1);
            System.out.println(emp.toString());
    
            // 第二次查询
            Employee emp2 = cacheMapper.getEmpById(1);
            System.out.println(emp2.toString());
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (null != openSession) {
                openSession.close();
            }
        }
    }
    
  3. 测试结果

    DEBUG - ==>  Preparing: select * from employee where id = ?
    DEBUG - ==> Parameters: 1(Integer)
    DEBUG - <==      Total: 1
    Employee{id=1, lastName='Chris', email='chris@gmail.com', gender='M'}
    Employee{id=1, lastName='Chris', email='chris@gmail.com', gender='M'}
    
6.2.2 一级缓存失效
  1. SqlSession不是同一个,则一级缓存失效

  2. SqlSession相同,但是需要查询的数据在一级缓存中没有,则不走缓存,需要去数据库中查询

  3. SqlSession相同,但是两次查询中间有增删改的SQL操作,因为mybatis认为增删改可能对之后的查询有影响

  4. SqlSession相同,但是手动清除了一级缓存

    openSession.clearCache();
    
6.3 二级缓存
6.3.1 工作机制
  1. 一个会话查询一条数据,这条数据会被放在当前会话的一级缓存中

  2. 如果当前会话关闭,此会话对应的一级缓存中的数据会被保存到二级缓存中,新的会话查询信息时,就会参照二级缓存

  3. 如果sqlsession即有employee信息又有department信息,二级缓存会根据不同对象信息的namespace缓存数据

    EmployeeMapper -> employee

    DeapartmentMapper-> department

6.3.2 使用二级缓存
  1. 全局配置文件中开启二级缓存

    <!--全局开启二级缓存,默认已开启-->
    <setting name="cacheEnabled" value="true"/>
    
  2. 需要使用二级缓存的映射文件处使用cache配置缓存

    <cache />
    
  3. POJO需要实现序列化接口

    public class Department implements Serializable 
    
    public class Employee implements Serializable
    
  4. 测试类

    查出的数据都会先放在一级缓存中

    只有会话被关闭,一级缓存中的数据才会转移到二级缓存中,其它SqlSesssion才能在二级缓存中获取此数据

    /**
     * 测试二级缓存
     */
    @Test
    public void testSecondCache() throws IOException {
        SqlSessionFactory sqlSessionFactory;
        SqlSession openSession_1 = null;
        SqlSession openSession_2 = null;
        try {
            sqlSessionFactory = getSqlSessionFactory();
            openSession_1 = sqlSessionFactory.openSession(true);
            CacheMapper cacheMapper1 = openSession_1.getMapper(CacheMapper.class);
    
            openSession_2 = sqlSessionFactory.openSession(true);
            CacheMapper cacheMapper2 = openSession_2.getMapper(CacheMapper.class);
    
            // 第一次查询
            Employee emp = cacheMapper1.getEmpById(1);
            System.out.println(emp.toString());
            // 查出的数据都会先放在一级缓存中,只有会话被关闭,一级缓存中的数据才会转移到二级缓存中,其它opensesssion才能在二级缓存中获取
            closeSession(openSession_1);
    
            // 第二次查询
            Employee emp2 = cacheMapper2.getEmpById(1);
            System.out.println(emp2.toString());
            closeSession(openSession_2);
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            closeSession(openSession_1, openSession_2);
        }
    }
    
  5. 结果

    DEBUG - Cache Hit Ratio [com.mybatis.dao.mapper.CacheMapper]: 0.5

    DEBUG - ==>  Preparing: select * from employee where id = ?
    DEBUG - ==> Parameters: 1(Integer)
    DEBUG - <==      Total: 1
    Employee{id=1, lastName='Chris', email='chris@gmail.com', gender='M'}
    DEBUG - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27c6e487]
    DEBUG - Returned connection 667346055 to pool.
    DEBUG - Cache Hit Ratio [com.mybatis.dao.mapper.CacheMapper]: 0.5
    Employee{id=1, lastName='Chris', email='chris@gmail.com', gender='M'}
    
6.4 和缓存有关的配置
6.4.1 cacheEnabled

全局开启二级缓存,默认已开启 ,

false:仅关闭二级缓存,但是一级缓存仍然可用

<setting name="cacheEnabled" value="true"/>
6.4.2 useCache

每一个select标签都有一个useCache="true"

ture: 表示使用二级缓存,但是必须将全局二级缓存打开

false:表示不使用二级缓存,但一级缓存仍然可用

<select id="getEmpById" resultType="com.mybatis.entity.Employee" useCache="true">
    select * from employee where id = #{id}
</select>
6.4.3 flushCache
  1. 每一个查询标签都有一个flushCache="fase",如何改为flushCache="true"表示查询执行完之后都会清除一级和二级缓存

  2. 每一个增删改标签都有一个flushCache="true",表示增删改执行完之后都会清除一级和二级缓存

    测试
    虽然去缓存中找数据,但是数据已经被清除

    DEBUG - ==>  Preparing: select * from employee where id = ?
    DEBUG - ==> Parameters: 1(Integer)
    DEBUG - <==      Total: 1
    Employee{id=1, lastName='Chris', email='chris@gmail.com', gender='M'}
    DEBUG - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27c6e487]
    DEBUG - Returned connection 667346055 to pool.
    DEBUG - Opening JDBC Connection
    DEBUG - Checked out connection 667346055 from pool.
    DEBUG - ==>  Preparing: insert into employee ( last_name, email, gender, department_id ) values (?,?,?,?)
    DEBUG - ==> Parameters: shawn(String), shawn@qq.com(String), M(String), 1(Integer)
    DEBUG - <==    Updates: 1
    DEBUG - Cache Hit Ratio [com.mybatis.dao.mapper.CacheMapper]: 0.5
    DEBUG - ==>  Preparing: select * from employee where id = ?
    DEBUG - ==> Parameters: 1(Integer)
    DEBUG - <==      Total: 1
    Employee{id=1, lastName='Chris', email='chris@gmail.com', gender='M'}
    DEBUG - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27c6e487]
    DEBUG - Returned connection 667346055 to pool.
    

    flushCache="false"

    增删改后,查询时会使用二级缓存

    DEBUG - ==>  Preparing: select * from employee where id = ?
    DEBUG - ==> Parameters: 1(Integer)
    DEBUG - <==      Total: 1
    Employee{id=1, lastName='Chris', email='chris@gmail.com', gender='M'}
    DEBUG - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27c6e487]
    DEBUG - Returned connection 667346055 to pool.
    DEBUG - Opening JDBC Connection
    DEBUG - Checked out connection 667346055 from pool.
    DEBUG - ==>  Preparing: insert into employee ( last_name, email, gender, department_id ) values (?,?,?,?)
    DEBUG - ==> Parameters: shawn(String), shawn@qq.com(String), M(String), 1(Integer)
    DEBUG - <==    Updates: 1
    DEBUG - Cache Hit Ratio [com.mybatis.dao.mapper.CacheMapper]: 0.5
    Employee{id=1, lastName='Chris', email='chris@gmail.com', gender='M'}
    DEBUG - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27c6e487]
    DEBUG - Returned connection 667346055 to pool.
    
6.4.5 SqlSession.clearCache()

只清空一级缓存,不会清空二级缓存,因为clearCache方法属于sqlsession级的方式,不是namesapce级别的方式

6.4.6 localCacheScope
<!--
本地缓存作用域,默认 SESSION
SESSION | STATEMENT
1.SESSION:当前会话sqlsession的所有查询数据都会被缓存
2.STATEMENT:同一会话的两次不同的sql间不会共享数据发,即可以禁用一级缓存
-->
<setting name="localCacheScope" value="SESSION"/>
6.5 缓存原理

6.6 mybatis整合ehcache
6.6.1 ehcache 源码

https://github.com/mybatis/ehcache-cache

6.6.2 官方文档

http://mybatis.org/ehcache-cache/

6.6.3 集成步骤
  1. 改pom

    <dependency>
        <groupId>org.mybatis.caches</groupId>
        <artifactId>mybatis-ehcache</artifactId>
        <version>${mybatis.ehcache.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
  2. 建ehcache.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    
        <!--
           属性说明:
            diskStore:指定数据在磁盘中的存储位置。
            defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
    
           以下属性是必须的:
            maxElementsInMemory - 在内存中缓存的element的最大数目
            maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
            eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
            overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
    
           以下属性是可选的:
            timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
            timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
            diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
            diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
            diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
            memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
            -->
    
        <!-- 磁盘保存路径 -->
        <diskStore path="D:\\ehcache"/>
        <defaultCache
                maxElementsInMemory="10000"
                maxElementsOnDisk="10000000"
                eternal="false"
                overflowToDisk="true"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
        </defaultCache>
    </ehcache>
    
    
  3. 在SQL映射文件中引入ehcache实现类

    <!--
     type:自定义缓存的全类名,自定义缓存需要实现Cache接口
     -->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    
6.7 mybatis整合Spring
6.7.1 官方源码

https://github.com/mybatis/spring

6.7.2 官方文档

http://mybatis.org/spring/

6.7.3 版本兼容

%5Btoc%5D%0A%0A%23%23%23%23%201.%E5%B7%A5%E5%85%B7%E4%B8%8E%E6%A1%86%E6%9E%B6%E7%9A%84%E5%8C%BA%E5%88%AB%0A%0A%23%23%23%23%23%201.1%20%E5%B7%A5%E5%85%B7%0A%0A%3E%20jdbc%20-%3E%20dbutils%20-%3E%20JdbcTemplate%20%0A%0A%23%23%23%23%23%201.2%20%E6%A1%86%E6%9E%B6%0A%0A%3E%20%E6%A1%86%E6%9E%B6%E6%98%AF%E4%B8%80%E4%B8%AA%E6%95%B4%E4%BD%93%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%2C%E5%A6%82%E4%BD%95%E8%BF%9B%E8%A1%8C%E4%BA%8B%E5%8A%A1%E6%8E%A7%E5%88%B6%EF%BC%8C%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E6%9F%A5%E8%AF%A2%E7%BC%93%E5%AD%98%EF%BC%8C%E5%AD%97%E6%AE%B5%E6%98%A0%E5%B0%84%0A%0A%23%23%23%23%23%201.3%20%E8%AF%BE%E7%A8%8B%E8%BF%9E%E6%8E%A5%0A%0Ahttps%3A%2F%2Fmy.oschina.net%2Fjallenkwong%2Fblog%2F4476789%23h2_6%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2Fu011863024%2Farticle%2Fdetails%2F107854866%0A%0A%0A%0A%23%23%23%23%202.%20MyBatis%0A%0A%23%23%23%23%23%202.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E5%8D%8A%E8%87%AA%E5%8A%A8%E5%8C%96%E7%9A%84ORM%E6%A1%86%E6%9E%B6%0A%3E%0A%3E%20%E4%BB%A5%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%BD%A2%E5%BC%8F%E6%89%8B%E5%8A%A8%E7%BC%96%E5%86%99SQL%2C%E9%9D%9E%E5%B8%B8%E7%81%B5%E6%B4%BB%2C%20%E8%80%8C%E5%B0%86%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE%EF%BC%8C%E9%A2%84%E7%BC%96%E8%AF%91%EF%BC%8C%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%B0%81%E8%A3%85%E7%BB%93%E6%9E%9C%E5%85%A8%E9%83%A8%E8%87%AA%E5%8A%A8%E5%8C%96%0A%3E%0A%3E%20SQL%E5%92%8C%E4%BB%A3%E7%A0%81%E5%88%86%E5%BC%80%EF%BC%8C%E5%AE%9E%E7%8E%B0%E4%B8%9A%E5%8A%A1%E4%B8%8E%E6%95%B0%E6%8D%AE%E7%9A%84%E8%A7%A3%E8%80%A6%0A%0A%0A%0A%23%23%23%23%23%202.1%20%E5%8E%BB%E5%93%AA%E9%87%8C%E4%B8%8B%0A%0A%23%23%23%23%23%23%202.1.1%20%E6%BA%90%E7%A0%81%0A%0A%09https%3A%2F%2Fgithub.com%2Fmybatis%2Fmybatis-3%0A%0A%23%23%23%23%23%23%202.1.2%20%E6%96%87%E6%A1%A3%0A%0A%09https%3A%2F%2Fmybatis.org%2Fmybatis-3%2F%0A%0A%23%23%23%23%203.%20HelloWorld%20%E6%A1%88%E4%BE%8B%0A%0A%23%23%23%23%23%203.1%20%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%0A%60%60%60xml%0A%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20%3F%3E%0A%3C!DOCTYPE%20configuration%0A%20%20%20%20%20%20%20%20PUBLIC%20%22-%2F%2Fmybatis.org%2F%2FDTD%20Config%203.0%2F%2FEN%22%0A%20%20%20%20%20%20%20%20%22http%3A%2F%2Fmybatis.org%2Fdtd%2Fmybatis-3-config.dtd%22%3E%0A%3Cconfiguration%3E%0A%20%20%20%20%3Cenvironments%20default%3D%22development%22%3E%0A%20%20%20%20%20%20%20%20%3Cenvironment%20id%3D%22development%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CtransactionManager%20type%3D%22JDBC%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CdataSource%20type%3D%22POOLED%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22driver%22%20value%3D%22com.mysql.cj.jdbc.Driver%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22url%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%3D%22jdbc%3Amysql%3A%2F%2F192.168.140.127%3A3306%2Fchris%3FuseSSL%3Dfalse%26amp%3BuseUnicode%3Dtrue%26amp%3BcharacterEncoding%3DUTF-8%26amp%3BserverTimezone%3DCTT%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22username%22%20value%3D%22root%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22password%22%20value%3D%2265536%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2FdataSource%3E%0A%20%20%20%20%20%20%20%20%3C%2Fenvironment%3E%0A%20%20%20%20%3C%2Fenvironments%3E%0A%20%20%20%20%3C!--%20%E5%B0%86%E6%88%91%E4%BB%AC%E5%86%99%E5%A5%BD%E7%9A%84sql%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%EF%BC%88EmployeeMapper.xml%EF%BC%89%E4%B8%80%E5%AE%9A%E8%A6%81%E6%B3%A8%E5%86%8C%E5%88%B0%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%EF%BC%88mybatis-config.xml%EF%BC%89%E4%B8%AD%20--%3E%0A%20%20%20%20%3Cmappers%3E%0A%20%20%20%20%20%20%20%20%3Cmapper%20resource%3D%22.%2Fmapper%2FEmployeeMapper.xml%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cmapper%20resource%3D%22.%2Fmapper%2FEmployeeServiceMapper.xml%22%2F%3E%0A%20%20%20%20%3C%2Fmappers%3E%0A%3C%2Fconfiguration%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%203.2%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%60%60%60xml%0A%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20%3F%3E%0A%3C!DOCTYPE%20mapper%0A%20%20%20%20%20%20%20%20PUBLIC%20%22-%2F%2Fmybatis.org%2F%2FDTD%20Mapper%203.0%2F%2FEN%22%0A%20%20%20%20%20%20%20%20%22http%3A%2F%2Fmybatis.org%2Fdtd%2Fmybatis-3-mapper.dtd%22%3E%0A%3Cmapper%20namespace%3D%22com.mybatis.employeemapper%22%3E%0A%20%20%20%20%3C!--%0A%20%20%20%20namespace%3A%E5%90%8D%E7%A7%B0%E7%A9%BA%E9%97%B4%3B%E9%80%9A%E5%B8%B8%E6%8C%87%E5%AE%9A%E4%B8%BA%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%85%A8%E7%B1%BB%E5%90%8D%0A%20%20%20%20id%EF%BC%9A%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86%0A%20%20%20%20resultType%EF%BC%9A%E8%BF%94%E5%9B%9E%E5%80%BC%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%23%7Bid%7D%EF%BC%9A%E4%BB%8E%E4%BC%A0%E9%80%92%E8%BF%87%E6%9D%A5%E7%9A%84%E5%8F%82%E6%95%B0%E4%B8%AD%E5%8F%96%E5%87%BAid%E5%80%BC%0A%20%20%20%20public%20Employee%20getEmpById(Integer%20id)%3B%0A%20%20%20%20%20--%3E%0A%20%20%20%20%3Cselect%20id%3D%22getEmpById%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%20select%20id%2C%20last_name%20lastName%2C%20email%2C%20gender%0A%20%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%3C%2Fselect%3E%0A%3C%2Fmapper%3E%0A%60%60%60%0A%0A%23%23%23%23%23%203.3%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%60%60%60java%0Apackage%20com.mybatis.entity%3B%0Aimport%20lombok.Data%3B%0A%0A%40Data%0Apublic%20class%20Employee%20%7B%0A%0A%20%20%20%20private%20int%20id%3B%0A%20%20%20%20private%20String%20lastName%3B%0A%20%20%20%20private%20String%20email%3B%0A%20%20%20%20private%20String%20gender%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%203.4%20%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A%3E%201.%20%E6%A0%B9%E6%8D%AE%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%BE%97%E5%88%B0SqlSessionFactory%EF%BC%9B%0A%3E%0A%3E%202.%20%E4%BD%BF%E7%94%A8SqlSessionFactory%EF%BC%8C%E8%8E%B7%E5%8F%96%E5%88%B0sqlSession%E5%AF%B9%E8%B1%A1%E4%BD%BF%E7%94%A8%E4%BB%96%E6%9D%A5%E6%89%A7%E8%A1%8C%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5%20%E4%B8%80%E4%B8%AAsqlSession%E5%B0%B1%E6%98%AF%E4%BB%A3%E8%A1%A8%E5%92%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E4%B8%80%E6%AC%A1%E4%BC%9A%E8%AF%9D%EF%BC%8C%E7%94%A8%E5%AE%8C%E5%85%B3%E9%97%AD%0A%3E%0A%3E%203.%20%E4%BD%BF%E7%94%A8sql%E7%9A%84%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86%E6%9D%A5%E5%91%8A%E8%AF%89MyBatis%E6%89%A7%E8%A1%8C%E5%93%AA%E4%B8%AAsql%E3%80%82sql%E9%83%BD%E6%98%AF%E4%BF%9D%E5%AD%98%E5%9C%A8sql%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E3%80%82%0A%0A%60%60%60java%0A%0Aprivate%20SqlSessionFactory%20getSqlSessionFactory()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20%20String%20resource%20%3D%20%22mybatis-config.xml%22%3B%0A%20%20%20%20%20%20%20%20InputStream%20inputStream%20%3D%20Resources.getResourceAsStream(resource)%3B%0A%20%20%20%20%20%20%20%20return%20new%20SqlSessionFactoryBuilder().build(inputStream)%3B%0A%7D%0A%20%0A%40Test%0Apublic%20void%20test()%20throws%20IOException%20%7B%0A%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96sqlSession%E5%AE%9E%E4%BE%8B%EF%BC%8C%E8%83%BD%E7%9B%B4%E6%8E%A5%E6%89%A7%E8%A1%8C%E5%B7%B2%E7%BB%8F%E6%98%A0%E5%B0%84%E7%9A%84sql%E8%AF%AD%E5%8F%A5%0A%20%20%20%20%2F%2F%20sql%E7%9A%84%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86%EF%BC%9Astatement%20Unique%20identifier%20matching%20the%20statement%20to%20use.%0A%20%20%20%20%2F%2F%20%E6%89%A7%E8%A1%8Csql%E8%A6%81%E7%94%A8%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%9Aparameter%20A%20parameter%20object%20to%20pass%20to%20the%20statement.%0A%0A%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E5%8A%A0%E4%B8%8Anamesapce%20com.mybatis.employeemapper%20%E5%8F%AF%E4%BB%A5%E9%98%B2%E6%AD%A2%E8%B0%83%E7%94%A8%E5%90%8C%E5%90%8D%E6%96%B9%E6%B3%95%E6%97%B6%E5%86%B2%E7%AA%81%0A%20%20%20%20%20%20%20%20Employee%20employee%20%3D%20openSession.selectOne(%22com.mybatis.employeemapper.getEmpById%22%2C%201)%3B%0A%20%20%20%20%20%20%20%20System.out.println(employee)%3B%0A%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%203.5%20%E6%8E%A5%E5%8F%A3%E5%BC%8F%E7%BC%96%E7%A8%8B%0A%0A%23%23%23%23%23%23%203.5.1%20%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3%0A%0A%60%60%60java%0Apackage%20com.mybatis.dao.mapper%3B%0A%0Aimport%20com.mybatis.entity.Employee%3B%0A%0Apublic%20interface%20EmployeeMapper%20%7B%0A%20%20%20%20Employee%20getEmployeeById(int%20id)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%203.5.2%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%60%60%60xml%0A%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20%3F%3E%0A%3C!DOCTYPE%20mapper%0A%20%20%20%20%20%20%20%20PUBLIC%20%22-%2F%2Fmybatis.org%2F%2FDTD%20Mapper%203.0%2F%2FEN%22%0A%20%20%20%20%20%20%20%20%22http%3A%2F%2Fmybatis.org%2Fdtd%2Fmybatis-3-mapper.dtd%22%3E%0A%3C!--%20mybatis%20%E6%94%AF%E6%8C%81namespace%E4%B8%8E%E6%8E%A5%E5%8F%A3%E5%90%8D%E7%A7%B0%E7%BB%91%E5%AE%9A%20--%3E%0A%3Cmapper%20namespace%3D%22com.mybatis.dao.mapper.EmployeeMapper%22%3E%0A%20%20%20%20%3Cselect%20id%3D%22getEmployeeById%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%20select%20id%2C%20last_name%20lastName%2C%20email%2C%20gender%0A%20%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%3C%2Fselect%3E%0A%3C%2Fmapper%3E%0A%60%60%60%0A%0A%23%23%23%23%23%23%203.5.3%20%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%A3%E7%BB%91%E5%AE%9A%E6%9D%A5%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%0A%20*%0A%20*%20%40throws%20IOException%0A%20*%2F%0A%40Test%0Apublic%20void%20test02()%20throws%20IOException%20%7B%0A%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20EmployeeMapper%20employeeMapper%20%3D%20openSession.getMapper(EmployeeMapper.class)%3B%0A%20%20%20%20%20%20%20%20Employee%20employee%20%3D%20employeeMapper.getEmployeeById(1)%3B%0A%20%20%20%20%20%20%20%20System.out.println(employee.getClass())%3B%0A%20%20%20%20%20%20%20%20System.out.println(employee)%3B%0A%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%E7%BB%93%E6%9E%9C%0A%0A%60%60%60%0Aclass%20com.sun.proxy.%24Proxy6%0AEmployee(id%3D1%2C%20lastName%3Dchris%2C%20email%3Dsss%401734.com%2C%20gender%3Dm)%0A%60%60%60%0A%0A%23%23%23%23%204.%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%0A%23%23%23%23%23%204.1%20%E6%A0%87%E7%AD%BE%0A%0A%3E%20%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E4%B8%AD%E6%A0%87%E7%AD%BE%E9%9C%80%E8%A6%81%E6%8C%89%E7%85%A7%E6%AD%A4%E9%A1%BA%E5%BA%8F%E7%BC%96%E5%86%99%0A%0A%60%60%60%0Aproperties%0Asettings%0AtypeAliases%0AtypeHandlers%0AobjectFactory%0AobjectWrapperFactory%0AreflectorFactory%0Aplugins%0Aenvironments%0AdatabaseIdProvider%0Amappers%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%204.1.1%20properties%0A%0A%3E%20mybatis%E4%BD%BF%E7%94%A8properties%E6%A0%87%E7%AD%BE%E6%9D%A5%E5%BC%95%E5%85%A5%E5%A4%96%E9%83%A8properties%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%86%85%E5%AE%B9%0A%3E%0A%3E%20resource%20%E6%8C%87%E5%90%91%E7%B1%BB%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%9A%84%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6%0A%3E%0A%3E%20url%20%E5%BC%95%E7%94%A8%E7%BD%91%E7%BB%9C%E8%B7%AF%E5%BE%84%E6%88%96%E6%9C%AC%E5%9C%B0%E7%A3%81%E7%9B%98%E4%B8%8A%E7%9A%84%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6%0A%0A1.%20%E5%BB%BAproperties%E6%96%87%E4%BB%B6%0A%0A%20%20%20%3E%20mybatis-chris-helloworld-2%2Fsrc%2Fmain%2F%3A%2Fdbconfig%0A%0A%20%20%20%60%60%60%0A%20%20%20jdbc.driver%3Dcom.mysql.cj.jdbc.Driver%0A%20%20%20jdbc.url%3Djdbc%3Amysql%3A%2F%2F192.168.140.127%3A3306%2Fchris%3FuseSSL%3Dfalse%26useUnicode%3Dtrue%26characterEncoding%3DUTF-8%26serverTimezone%3DCTT%0A%20%20%20jdbc.username%3Droot%0A%20%20%20jdbc.password%3D65536%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A2.%20%E6%94%B9%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%0A%20%20%20%3E%20mybatis-chris-helloworld-2%2Fsrc%2Fmain%2F%3A%2Fmybatis-config.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cconfiguration%3E%0A%20%20%20%20%20%20%20%3Cproperties%20resource%3D%22dbconfig.properties%22%2F%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Cenvironments%20default%3D%22development%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cenvironment%20id%3D%22development%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CtransactionManager%20type%3D%22JDBC%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CdataSource%20type%3D%22POOLED%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22driver%22%20value%3D%22%24%7Bjdbc.driver%7D%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22url%22%20value%3D%22%24%7Bjdbc.url%7D%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22username%22%20value%3D%22%24%7Bjdbc.username%7D%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22password%22%20value%3D%22%24%7Bjdbc.password%7D%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2FdataSource%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fenvironment%3E%0A%20%20%20%20%20%20%20%3C%2Fenvironments%3E%0A%20%20%20%20%20%20%20%3C!--%20%E5%B0%86%E6%88%91%E4%BB%AC%E5%86%99%E5%A5%BD%E7%9A%84sql%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%EF%BC%88EmployeeMapper.xml%EF%BC%89%E4%B8%80%E5%AE%9A%E8%A6%81%E6%B3%A8%E5%86%8C%E5%88%B0%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%EF%BC%88mybatis-config.xml%EF%BC%89%E4%B8%AD%20--%3E%0A%20%20%20%20%20%20%20%3Cmappers%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cmapper%20resource%3D%22.%2Fmapper%2FEmployeeMapper.xml%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cmapper%20resource%3D%22.%2Fmapper%2FEmployeeServiceMapper.xml%22%2F%3E%0A%20%20%20%20%20%20%20%3C%2Fmappers%3E%0A%20%20%20%3C%2Fconfiguration%3E%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%204.1.2%20settings%0A%0A%60%60%60xml%0A%3Csettings%3E%0A%20%20%3Csetting%20name%3D%22cacheEnabled%22%20value%3D%22true%22%2F%3E%0A%20%20%3Csetting%20name%3D%22lazyLoadingEnabled%22%20value%3D%22true%22%2F%3E%0A%20%20%3Csetting%20name%3D%22multipleResultSetsEnabled%22%20value%3D%22true%22%2F%3E%0A%20%20%3Csetting%20name%3D%22useColumnLabel%22%20value%3D%22true%22%2F%3E%0A%20%20%3Csetting%20name%3D%22useGeneratedKeys%22%20value%3D%22false%22%2F%3E%0A%20%20%3Csetting%20name%3D%22autoMappingBehavior%22%20value%3D%22PARTIAL%22%2F%3E%0A%20%20%3Csetting%20name%3D%22autoMappingUnknownColumnBehavior%22%20value%3D%22WARNING%22%2F%3E%0A%20%20%3Csetting%20name%3D%22defaultExecutorType%22%20value%3D%22SIMPLE%22%2F%3E%0A%20%20%3Csetting%20name%3D%22defaultStatementTimeout%22%20value%3D%2225%22%2F%3E%0A%20%20%3Csetting%20name%3D%22defaultFetchSize%22%20value%3D%22100%22%2F%3E%0A%20%20%3Csetting%20name%3D%22safeRowBoundsEnabled%22%20value%3D%22false%22%2F%3E%0A%20%20%20%20%0A%20%20%3C!--%E5%BC%80%E5%90%AF%E8%A1%A8%E4%B8%AD%E4%B8%8B%E5%88%92%E7%BA%BF%E5%AD%97%E6%AE%B5A_COLUMN%E8%BD%ACJavaBean%E9%A9%BC%E5%B3%B0%E5%AD%97%E6%AE%B5aColumn--%3E%0A%20%20%3Csetting%20name%3D%22mapUnderscoreToCamelCase%22%20value%3D%22false%22%2F%3E%0A%20%20%20%20%0A%20%20%3Csetting%20name%3D%22localCacheScope%22%20value%3D%22SESSION%22%2F%3E%0A%20%20%20%20%0A%20%20%3C!--%E6%8C%87%E5%AE%9A%E5%AD%97%E6%AE%B5%E5%80%BC%E4%B8%BAnull%E6%97%B6%E7%9A%84JDBC%20type%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAOTHER--%3E%0A%20%20%3Csetting%20name%3D%22jdbcTypeForNull%22%20value%3D%22OTHER%22%2F%3E%0A%20%20%0A%20%20%20%20%3Csetting%20name%3D%22lazyLoadTriggerMethods%22%20value%3D%22equals%2Cclone%2ChashCode%2CtoString%22%2F%3E%0A%3C%2Fsettings%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%204.1.3%20typeAliases%0A%0A%3E%20%E5%88%AB%E5%90%8D%E5%A4%84%E7%90%86%E5%99%A8%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%B8%BAJava%E7%B1%BB%E5%9E%8B%E8%B5%B7%E5%88%AB%E5%90%8D%2C%20%E4%B8%94%E5%88%AB%E5%90%8D%E4%B8%8D%E5%8C%BA%E5%88%86%E5%A4%A7%E5%B0%8F%E5%86%99%0A%0A1.%20%E5%9C%A8%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E4%B8%AD%E6%B7%BB%E5%8A%A0%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3CtypeAliases%3E%0A%20%20%20%09%3C!--%0A%20%20%20%09type%3A%E4%B8%BAJava%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%85%A8%E7%B1%BB%E5%90%8D%EF%BC%8C%E6%B2%A1%E6%9C%89%E8%AE%BE%E7%BD%AE%E5%88%AB%E5%90%8D%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E9%BB%98%E8%AE%A4%E5%88%AB%E5%90%8D%E4%B8%BA%E7%B1%BB%E5%90%8D%E5%85%A8%E5%B0%8F%E5%86%99%2C%20com.mybatis.entity.Employee%E7%9A%84%E9%BB%98%E8%AE%A4%E5%88%AB%E5%90%8D%E4%B8%BAemployee%0A%20%20%20%09alias%3A%20%E4%B8%BAJava%E7%B1%BB%E5%9E%8B%E6%8C%87%E5%AE%9A%E5%88%AB%E5%90%8D%0A%20%20%20%09--%3E%0A%20%20%20%20%20%20%20%3CtypeAlias%20type%3D%22com.mybatis.entity.Employee%22%20alias%3D%22emp%22%2F%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20%E4%B8%BA%E5%BD%93%E5%89%8D%E5%8C%85%E4%BB%A5%E5%8F%8A%E5%AD%90%E5%8C%85%E9%87%8C%E9%9D%A2%E7%9A%84%E7%B1%BB%E8%B5%B7%E4%B8%80%E4%B8%AA%E9%BB%98%E8%AE%A4%E7%9A%84%E5%88%AB%E5%90%8D%0A%20%20%20%20%20%20%20%E6%89%B9%E9%87%8F%E8%B5%B7%E5%88%AB%E5%90%8D%E6%97%B6%E5%A6%82%E6%9E%9C%E5%88%AB%E5%90%8D%E9%87%8D%E5%A4%8D%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%40Alias(%22employeeAlias%22)%E4%B8%BAJava%E7%B1%BB%E6%8C%87%E5%AE%9A%E6%96%B0%E7%9A%84%E5%88%AB%E5%90%8D%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cpackage%20name%3D%22com.mybatis.entity%22%2F%3E%0A%20%20%20%3C%2FtypeAliases%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.mybatis.entity%3B%0A%20%20%20import%20lombok.Data%3B%0A%20%20%20import%20org.apache.ibatis.type.Alias%3B%0A%20%20%20%0A%20%20%20%40Data%0A%20%20%20%40Alias(%22employeeAlias%22)%0A%20%20%20public%20class%20Employee%20%7B%0A%20%20%20%20%20%20%20private%20int%20id%3B%0A%20%20%20%20%20%20%20private%20String%20lastName%3B%0A%20%20%20%20%20%20%20private%20String%20email%3B%0A%20%20%20%20%20%20%20private%20String%20gender%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E5%9C%A8SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%E4%B8%AD%E6%8C%87%E5%AE%9A%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%20%E6%B5%8B%E8%AF%95%E9%BB%98%E8%AE%A4%E5%88%AB%E5%90%8D%2C%20%E5%88%AB%E5%90%8D%E4%B8%8D%E5%8C%BA%E5%88%86%E5%A4%A7%E5%B0%8F%E5%86%99%20Employee%E5%92%8Cemploy%E9%83%BD%E5%8F%AF%E4%BB%A5--%3E%0A%20%20%20%3Cselect%20id%3D%22testDefaultAlias%22%20resultType%3D%22Employee%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%0A%20%20%20%3C!--%20%E6%B5%8B%E8%AF%95%E6%8C%87%E5%AE%9A%E5%88%AB%E5%90%8Demp%2C%20%E5%88%AB%E5%90%8D%E4%B8%8D%E5%8C%BA%E5%88%86%E5%A4%A7%E5%B0%8F%E5%86%99%20Emp%E5%92%8Cemp%E9%83%BD%E5%8F%AF%E4%BB%A5%20--%3E%0A%20%20%20%3Cselect%20id%3D%22testSpecifiedAlias%22%20resultType%3D%22Emp%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%0A%20%20%20%3C!--%20%E5%9C%A8%E7%B1%BB%E4%B8%8A%E4%BD%BF%E7%94%A8%40Alias(%22employeeAlias%22)%E6%8C%87%E5%AE%9A%E5%88%AB%E5%90%8D%20--%3E%0A%20%20%20%3Cselect%20id%3D%22testSpecifiedAlias%22%20resultType%3D%22employeeAlias%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%204.1.4%20typeHandlers%0A%0A%3E%20%20%E5%A4%84%E7%90%86Java%E7%B1%BB%E5%9E%8B%E4%B8%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E8%A1%A8%E5%AD%97%E6%AE%B5%E7%B1%BB%E5%9E%8B%E7%9B%B8%E4%BA%92%E8%BD%AC%E6%8D%A2%0A%3E%0A%3E%20%20**NOTE**%20Since%20version%203.4.5%2C%20MyBatis%20supports%20JSR-310%20(Date%20and%20Time%20API)%20by%20default.%0A%0A%60%60%60java%0Aprivate%20List%3CObject%3E%20templateStickerImg%3B%0A%60%60%60%0A%0A%60%60%60%0A%3Cresult%20column%3D%22quality_accessories%22%20property%3D%22qualityAccessories%22%20typeHandler%3D%22com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler%22%2F%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%204.1.5%20plug-ins%0A%0AMyBatis%20allows%20you%20to%20intercept%20calls%20to%20at%20certain%20points%20within%20the%20execution%20of%20a%20mapped%20statement.%20By%20default%2C%20MyBatis%20allows%20plug-ins%20to%20intercept%20method%20calls%20of%3A%0A%0A-%20Executor%20(update%2C%20query%2C%20flushStatements%2C%20commit%2C%20rollback%2C%20getTransaction%2C%20close%2C%20isClosed)%0A-%20ParameterHandler%20(getParameterObject%2C%20setParameters)%0A-%20ResultSetHandler%20(handleResultSets%2C%20handleOutputParameters)%0A-%20StatementHandler%20(prepare%2C%20parameterize%2C%20batch%2C%20update%2C%20query)%0A%0A%0A%0A%23%23%23%23%23%23%204.1.6%20environments%0A%0A%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E9%85%8D%E7%BD%AE%E5%A4%9A%E7%A7%8D%E7%8E%AF%E5%A2%83%0A%0A%3E%20org.apache.ibatis.session.Configuration%0A%0A%60%60%60%0Athis.typeAliasRegistry.registerAlias(%22JDBC%22%2C%20JdbcTransactionFactory.class)%3B%0Athis.typeAliasRegistry.registerAlias(%22MANAGED%22%2C%20ManagedTransactionFactory.class)%3B%0Athis.typeAliasRegistry.registerAlias(%22JNDI%22%2C%20JndiDataSourceFactory.class)%3B%0Athis.typeAliasRegistry.registerAlias(%22POOLED%22%2C%20PooledDataSourceFactory.class)%3B%0Athis.typeAliasRegistry.registerAlias(%22UNPOOLED%22%2C%20UnpooledDataSourceFactory.class)%3B%0A%60%60%60%0A%0A%60%60%60xml%0A%3Cenvironment%20id%3D%22development%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%20%E6%9C%89%E4%B8%A4%E7%A7%8D%E7%B1%BB%E5%9E%8B%E7%9A%84%E4%BA%8B%E5%8A%A1%E6%8E%A7%E5%88%B6%20JDBC%7CMANAGED%20%2C%20org.apache.ibatis.session.Configuration--%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CtransactionManager%20type%3D%22JDBC%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20%20%20%20%20%E6%95%B0%E6%8D%AE%E6%BA%90%0A%20%20%20%20%20%20%20%20%20%20%20type%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20UNPOOLED%3A%E4%B8%8D%E4%BD%BF%E7%94%A8%E8%BF%9E%E6%8E%A5%E6%B1%A0%E7%9A%84%E6%95%B0%E6%8D%AE%E6%BA%90%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20POOLED%3A%E4%BD%BF%E7%94%A8%E8%BE%B9%E5%A2%83%E6%B1%A0%E7%9A%84%E6%95%B0%E6%8D%AE%E6%BA%90%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20JNDI%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%BA%90%3A%E5%AE%9E%E7%8E%B0DataSourceFactory%E6%8E%A5%E5%8F%A3--%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CdataSource%20type%3D%22POOLED%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22driver%22%20value%3D%22%24%7Bjdbc.driver%7D%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22url%22%20value%3D%22%24%7Bjdbc.url%7D%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22username%22%20value%3D%22%24%7Bjdbc.username%7D%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22password%22%20value%3D%22%24%7Bjdbc.password%7D%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2FdataSource%3E%0A%3C%2Fenvironment%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%204.1.7%20databaseIdProvider%0A%0A%3E%20%E7%94%A8%E6%9D%A5%E7%99%BD%E6%94%AF%E6%8C%81%E5%A4%9A%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%82%E5%95%86%EF%BC%8C%E5%BE%97%E5%88%B0%E4%B8%8D%E5%90%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%82%E5%95%86%E7%9A%84%E6%A0%87%E8%AF%86%EF%BC%8Cmybatis%E8%B7%9F%E6%8D%AE%E4%B8%8D%E5%90%8C%E5%8E%82%E5%95%86%E7%9A%84%E6%A0%87%E8%AF%86%E6%89%A7%E8%A1%8C%E4%B8%8D%E5%90%8C%E7%9A%84SQL%0A%3E%0A%3E%20DB_VENDOR%20-%20%E4%BC%9A%E9%80%9A%E8%BF%87%20DatabaseMetaData%23getDatabaseProductName()%20%E8%BF%94%E5%9B%9E%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BF%9B%E8%A1%8C%E8%AE%BE%E7%BD%AE%E3%80%82%E7%94%B1%E4%BA%8E%E9%80%9A%E5%B8%B8%E6%83%85%E5%86%B5%E4%B8%8B%E8%BF%99%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%83%BD%E9%9D%9E%E5%B8%B8%E9%95%BF%E8%80%8C%E4%B8%94%E7%9B%B8%E5%90%8C%E4%BA%A7%E5%93%81%E7%9A%84%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%E4%BC%9A%E8%BF%94%E5%9B%9E%E4%B8%8D%E5%90%8C%E7%9A%84%E5%80%BC%EF%BC%8C%E6%89%80%E4%BB%A5**%E6%9C%80%E5%A5%BD%E9%80%9A%E8%BF%87%E8%AE%BE%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%AB%E5%90%8D%E6%9D%A5%E4%BD%BF%E5%85%B6%E5%8F%98%E7%9F%AD**%0A%0A%60%60%60java%0Athis.typeAliasRegistry.registerAlias(%22DB_VENDOR%22%2C%20VendorDatabaseIdProvider.class)%3B%0A%60%60%60%0A%0A1.%20mybatis-chris-helloworld-2%2Fsrc%2Fmain%2F%3A%2Fmybatis-config.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%0A%20%20%20%E7%94%A8%E6%9D%A5%E6%94%AF%E6%8C%81%E5%A4%9A%E6%95%B0%E6%8D%AE%E5%BA%93%0A%20%20%20type%3A%20DB_VENDOR%2C%20%E5%8E%82%E5%95%86%E6%A0%87%E8%AF%86%E7%94%B1%E9%A9%B1%E5%8A%A8%E8%87%AA%E5%B8%A6%0A%20%20%20--%3E%0A%20%20%20%3CdatabaseIdProvider%20type%3D%22DB_VENDOR%22%3E%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20%E4%B8%BA%E4%B8%8D%E5%90%8C%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%82%E5%95%86%E6%A0%87%E8%AF%86%E8%B5%B7%E5%88%AB%E5%90%8D%0A%20%20%20%20%20%20%20name%3A%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%82%E5%95%86%E6%A0%87%E8%AF%86%0A%20%20%20%20%20%20%20value%3A%E5%88%AB%E5%90%8D%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cproperty%20name%3D%22MYSQL%22%20value%3D%22mysql%22%2F%3E%0A%20%20%20%20%20%20%20%3Cproperty%20name%3D%22Oracle%22%20value%3D%22oralce%22%2F%3E%0A%20%20%20%20%20%20%20%3Cproperty%20name%3D%22SQL%20Server%22%20value%3D%22sqlserver%22%2F%3E%0A%20%20%20%3C%2FdatabaseIdProvider%3E%0A%20%20%20%60%60%60%0A%0A2.%20mybatis-chris-helloworld-2%2Fsrc%2Fmain%2F%3A%2Fmapper%2FEmployee2Mapper.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%20%E5%9C%A8%E6%8C%87%E5%AE%9A%E7%9A%84mysql%E4%B8%8A%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8A%E6%89%A7%E8%A1%8C%EF%BC%8CdatabaseId%E4%B8%BAdatabaseIdProvider%E7%9A%84%E5%88%AB%E5%90%8D%20%20--%3E%0A%20%20%20%3Cselect%20id%3D%22testSpecifiedAlias%22%20resultType%3D%22employeeAlias%22%20databaseId%3D%22mysql%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%0A%20%20%20%3C!--%20%E5%9C%A8%E6%8C%87%E5%AE%9A%E7%9A%84oralce%E4%B8%8A%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8A%E6%89%A7%E8%A1%8C%EF%BC%8CdatabaseId%E4%B8%BAdatabaseIdProvider%E7%9A%84%E5%88%AB%E5%90%8D%20%20--%3E%0A%20%20%20%3Cselect%20id%3D%22testSpecifiedAlias%22%20resultType%3D%22employeeAlias%22%20databaseId%3D%22oralce%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employees%0A%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%204.1.8%20mappers%0A%0A%E5%B0%86%E5%86%99%E5%A5%BD%E7%9A%84sql%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%EF%BC%88EmployeeMapper.xml%EF%BC%89%E6%B3%A8%E5%86%8C%E5%88%B0%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%EF%BC%88mybatis-config.xml%EF%BC%89%E4%B8%AD%0A%0A1.%20mapper%20%E5%8D%95%E4%B8%AA%E6%B3%A8%E5%86%8C%0A%0A%20%20%20%3E%20resource%3A%20%E6%B3%A8%E5%86%8C%E7%B1%BB%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%9A%84%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6%0A%20%20%20%3E%0A%20%20%20%3E%20%60%60%60xml%0A%20%20%20%3E%20%3Cmappers%3E%0A%20%20%20%3E%20%3Cmapper%20resource%3D%22.%2Fmapper%2FEmployeeMapper.xml%22%2F%3E%0A%20%20%20%3E%20%3Cmapper%20resource%3D%22.%2Fmapper%2FEmployee2Mapper.xml%22%2F%3E%0A%20%20%20%3E%20%3C%2Fmappers%3E%0A%20%20%20%3E%20%60%60%60%0A%20%20%20%3E%0A%20%20%20%3E%20url%3A%20%E6%B3%A8%E5%86%8C%E7%BD%91%E7%BB%9C%E8%B7%AF%E5%BE%84%E6%88%96%E6%9C%AC%E5%9C%B0%E7%A3%81%E7%9B%98%E4%B8%8A%E7%9A%84%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6%0A%20%20%20%3E%0A%20%20%20%3E%20%60%60%60xml%0A%20%20%20%3E%20%3Cmappers%3E%0A%20%20%20%3E%20%3Cmapper%20url%3D%22file%3A%2F%2F%2Fvar%2Fmappers%2FAuthorMapper.xml%22%2F%3E%0A%20%20%20%3E%20%3Cmapper%20url%3D%22file%3A%2F%2F%2Fvar%2Fmappers%2FBlogMapper.xml%22%2F%3E%0A%20%20%20%3E%20%3C%2Fmappers%3E%0A%20%20%20%3E%20%60%60%60%0A%20%20%20%3E%0A%20%20%20%3E%20class%3A%20%E6%B3%A8%E5%86%8C%E6%8E%A5%E5%8F%A3%0A%20%20%20%3E%0A%20%20%20%3E%201.%20%E5%B0%86SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%E4%B8%8E%E6%8E%A5%E5%8F%A3%E5%85%A5%E5%9C%A8%E5%90%8C%E4%B8%80%E7%B1%BB%E8%B7%AF%E5%BE%84%E4%B8%8B%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%B8%8E%E6%8E%A5%E5%8F%A3%E5%90%8D%E7%A7%B0%E4%B8%80%E8%87%B4%0A%20%20%20%3E%0A%20%20%20%3E%20%20%20%20%60%60%60xml%0A%20%20%20%3E%20%20%20%20%3Cmappers%3E%0A%20%20%20%3E%20%20%20%20%20%20%20%20%3Cmapper%20resource%3D%22com.mybatis.dao.mapper.EmployeeMapper%22%2F%3E%0A%20%20%20%3E%20%20%20%20%3C%2Fmappers%3E%0A%20%20%20%3E%20%20%20%20%60%60%60%0A%20%20%20%3E%20%20%20%20%0A%20%20%20%3E%20%20%20%20%0A%20%20%20%3E%20%20%20%20%0A%20%20%20%3E%202.%20%E4%B8%8D%E7%94%A8SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%EF%BC%8C%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E7%9A%84SQL%E6%98%A0%E5%B0%84%EF%BC%8C%20**%E4%B8%8D%E5%BB%BA%E8%AE%AE%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%BC%9A%E4%BD%BF%E4%BB%A3%E7%A0%81%E5%92%8CSQL%E8%80%A6%E5%90%88%EF%BC%8C%E4%BD%BF%E4%B8%9A%E5%8A%A1%E5%92%8C%E6%95%B0%E6%8D%AE%E9%80%BB%E8%BE%91%E6%B7%B7%E4%B9%B1**%0A%20%20%20%3E%0A%20%20%20%3E%20%20%20%20%60%60%60java%0A%20%20%20%3E%20%20%20%20package%20com.mybatis.dao.mapper%3B%0A%20%20%20%3E%20%20%20%20import%20com.mybatis.entity.Employee%3B%0A%20%20%20%3E%20%20%20%20import%20org.apache.ibatis.annotations.Select%3B%0A%20%20%20%3E%20%20%20%20%0A%20%20%20%3E%20%20%20%20public%20interface%20EmployeeAnnotationMapper%20%7B%0A%20%20%20%3E%20%20%20%20%20%20%20%20%40Select(%22select%20*%20%20from%20employee%20%20where%20id%20%3D%20%23%7Bid%7D%22)%0A%20%20%20%3E%20%20%20%20%20%20%20%20Employee%20getEmployeeById(int%20id)%3B%0A%20%20%20%3E%20%20%20%20%7D%0A%20%20%20%3E%20%20%20%20%60%60%60%0A%20%20%20%3E%0A%20%20%20%3E%20%20%20%20%60%60%60xml%0A%20%20%20%3E%20%20%20%20%3Cmappers%3E%0A%20%20%20%3E%20%20%20%20%20%20%20%20%3Cmapper%20class%3D%22com.mybatis.dao.mapper.EmployeeAnnotationMapper%22%2F%3E%0A%20%20%20%3E%20%20%20%20%3C%2Fmappers%3E%0A%20%20%20%3E%20%20%20%20%60%60%60%0A%0A%0A%0A2.%20%E6%89%B9%E9%87%8F%E6%B3%A8%E5%86%8C%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cmappers%3E%0A%20%20%20%20%20%20%3C!--%20%E6%89%B9%E9%87%8F%E6%B3%A8%E5%86%8C%0A%20%20%20%20%20%20name%3A%E6%8E%A5%E5%8F%A3%E6%89%80%E5%9C%A8%E7%9A%84%E5%8C%85%E8%B7%AF%E5%BE%84%0A%20%20%20%20%20%20%E9%80%82%E7%94%A8%E4%BA%8E%E9%80%9A%E8%BF%87%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0SQL%E6%98%A0%E5%B0%84%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%AF%B9%E4%BA%8E%E9%80%9A%E8%BF%87%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%AE%9E%E7%8E%B0%E7%9A%84SQL%E6%98%A0%E5%B0%84%EF%BC%8C%E9%9C%80%E8%A6%81%E5%B0%86XML%E6%96%87%E4%BB%B6%E4%B8%8E%E6%8E%A5%E5%8F%A3%E6%94%BE%E5%9C%A8%E4%B8%80%E8%B5%B7%EF%BC%8C%E5%90%A6%E5%88%99%E6%97%A0%E6%B3%95%E6%89%B9%E9%87%8F%E6%B3%A8%E5%86%8C%0A%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cpackage%20name%3D%22com.mybatis.dao.mapper%22%2F%3E%0A%20%20%20%3C%2Fmappers%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%205.%20%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%23%23%23%23%23%205.1%20%E6%A0%87%E7%AD%BE%0A%0A%60%60%60%0Acache%20%E2%80%93%20Configuration%20of%20the%20cache%20for%20a%20given%20namespace.%0Acache-ref%20%E2%80%93%20Reference%20to%20a%20cache%20configuration%20from%20another%20namespace.%0AresultMap%20%E2%80%93%20The%20most%20complicated%20and%20powerful%20element%20that%20describes%20how%20to%20load%20your%20objects%20from%20the%20database%20result%20sets.%0AparameterMap%20%E2%80%93%20Deprecated!%20Old-school%20way%20to%20map%20parameters.%20Inline%20parameters%20are%20preferred%20and%20this%20element%20may%20be%20removed%20in%20the%20future.%20Not%20documented%20here.%0Asql%20%E2%80%93%20A%20reusable%20chunk%20of%20SQL%20that%20can%20be%20referenced%20by%20other%20statements.%0Ainsert%20%E2%80%93%20A%20mapped%20INSERT%20statement.%0Aupdate%20%E2%80%93%20A%20mapped%20UPDATE%20statement.%0Adelete%20%E2%80%93%20A%20mapped%20DELETE%20statement.%0Aselect%20%E2%80%93%20A%20mapped%20SELECT%20statement.%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%23%205.2%20%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5%0A%0A%3E%20mybatis%20%E8%87%AA%E5%8A%A8%E5%B0%81%E8%A3%85%E4%BA%86%E5%A2%9E%E5%88%A0%E6%94%B9%E7%9A%84%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%0A%3E%20int%20%E5%92%8C%20long%20%E8%A1%A8%E7%A4%BA%E5%BD%B1%E5%93%8D%E7%9A%84%E8%A1%8C%E6%95%B0%0A%3E%20boolean%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E6%89%A7%E8%A1%8C%E6%88%90%E5%8A%9F%0A%3E%20void%E8%A1%A8%E7%A4%BA%E4%BB%80%E4%B9%88%E9%83%BD%E4%B8%8D%E8%BF%94%E5%9B%9E%0A%0A1.%20%E4%B8%9A%E5%8A%A1%E6%8E%A5%E5%8F%A3%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.mybatis.dao.mapper%3B%0A%20%20%20import%20com.mybatis.entity.Employee%3B%0A%20%20%20%0A%20%20%20public%20interface%20EmployeeMapper%20%7B%0A%20%20%20%20%20%20%20Employee%20getEmployeeById(int%20id)%3B%0A%20%20%20%20%20%20%20int%20addEmployee(Employee%20employee)%3B%0A%20%20%20%20%20%20%20int%20deleteEmployeeById(int%20id)%3B%0A%20%20%20%20%20%20%20int%20updateEmployee(Employee%20employee)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A2.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cmapper%20namespace%3D%22com.mybatis.dao.mapper.EmployeeMapper%22%3E%0A%20%20%20%20%20%20%20%3Cselect%20id%3D%22getEmployeeById%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%20%20%20%3C%2Fselect%3E%0A%20%20%20%20%20%20%20%3C!--parameterType%3A%20%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5--%3E%0A%20%20%20%20%20%20%20%3Cinsert%20id%3D%22addEmployee%22%20parameterType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20insert%20into%20employee%20(last_name%2C%20email%2C%20gender)%0A%20%20%20%20%20%20%20%20%20%20%20values%20(%23%7BlastName%7D%2C%20%23%7Bemail%7D%2C%20%23%7Bgender%7D)%0A%20%20%20%20%20%20%20%3C%2Finsert%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Cupdate%20id%3D%22updateEmployee%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20update%20employee%20t%0A%20%20%20%20%20%20%20%20%20%20%20set%20t.last_name%3D%23%7BlastName%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t.email%3D%23%7Bemail%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gender%3D%23%7Bgender%7D%0A%20%20%20%20%20%20%20%20%20%20%20where%20t.id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%20%20%20%3C%2Fupdate%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Cdelete%20id%3D%22deleteEmployeeById%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20delete%0A%20%20%20%20%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%20%20%20%3C%2Fdelete%3Ex%0A%20%20%20%3C%2Fmapper%3E%0A%20%20%20%60%60%60%0A%20%20%20%0A%0A%0A%0A%23%23%23%23%23%205.3%20%E8%8E%B7%E5%8F%96MySql%E8%87%AA%E5%A2%9E%E4%B8%BB%E9%94%AE%0A%0A%0A%0A1.%20%E4%BF%AE%E6%94%B9SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%0A%20%20%20parameterType%3A%20%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%20%20%20useGeneratedKeys%3A%20%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%EF%BC%8C%E4%BD%BF%E7%94%A8%E8%87%AA%E5%A2%9E%E4%B8%BB%E9%94%AE%E7%AD%96%E7%95%A5%E8%8E%B7%E5%8F%96%E4%B8%BB%E9%94%AE%0A%20%20%20keyProperty%3A%20%E6%8C%87%E5%AE%9A%E5%AF%B9%E5%BA%94%E7%9A%84%E4%B8%BB%E9%94%AE%E5%B1%9E%E6%80%A7%EF%BC%8C%E5%8D%B3%E5%BD%93%E8%8E%B7%E5%8F%96%E4%B8%BB%E9%94%AE%E5%90%8E%E5%B0%86%E5%80%BC%E5%B0%81%E8%A3%85%E7%BB%99JavaBean%E4%B8%AD%E7%9A%84%E5%93%AA%E4%B8%AA%E5%B1%9E%E6%80%A7%0A%20%20%20--%3E%0A%20%20%20%3Cinsert%20id%3D%22addEmployee%22%20parameterType%3D%22com.mybatis.entity.Employee%22%20useGeneratedKeys%3D%22true%22%20keyProperty%3D%22id%22%3E%0A%20%20%20%20%20%20%20insert%20into%20employee%20(last_name%2C%20email%2C%20gender)%0A%20%20%20%20%20%20%20values%20(%23%7BlastName%7D%2C%20%23%7Bemail%7D%2C%20%23%7Bgender%7D)%0A%20%20%20%3C%2Finsert%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Test%0A%20%20%20public%20void%20addEmployee()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20%20%20%20EmployeeMapper%20employeeMapper%20%3D%20openSession.getMapper(EmployeeMapper.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20employee%20%3D%20new%20Employee(%22Cano%22%2C%20%22Cano%40gmail.com%22%2C%20%22F%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20employeeMapper.addEmployee(employee)%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22add%20user%20id%3A%22%20%2B%20employee.getId())%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%205.4%20%E8%8E%B7%E5%8F%96Oracle%20Sequence%E5%80%BC%0A%0A1.%20%E6%94%B9SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60java%0A%20%20%20%3C!--%0A%20%20%20%E4%BD%BF%E7%94%A8Oracle%20Sequence%E6%B7%BB%E5%8A%A0%E5%91%98%E5%B7%A5%E8%AE%B0%E5%BD%95%E5%89%8D%E8%8E%B7%E5%8F%96ID%0A%20%20%20--%3E%0A%20%20%20%3Cinsert%20id%3D%22addEmployee%22%20parameterType%3D%22com.mybatis.entity.Employee%22%20databaseId%3D%22oracle%22%3E%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20keyProperty%3A%20%E6%8C%87%E5%AE%9A%E5%AF%B9%E5%BA%94%E7%9A%84%E4%B8%BB%E9%94%AE%E5%B1%9E%E6%80%A7%EF%BC%8C%E5%8D%B3%E5%BD%93%E8%8E%B7%E5%8F%96%E4%B8%BB%E9%94%AE%E5%90%8E%E5%B0%86%E5%80%BC%E5%B0%81%E8%A3%85%E7%BB%99JavaBean%E4%B8%AD%E7%9A%84%E5%93%AA%E4%B8%AA%E5%B1%9E%E6%80%A7%0A%20%20%20%20%20%20%20order%3A%20BEFORE%20%E5%BD%93%E5%89%8DSQL%E5%9C%A8%E6%8F%92%E5%85%A5SQL%E4%B9%8B%E5%89%8D%E8%BF%90%E8%A1%8C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20AFTER%20%20%E5%BD%93%E5%89%8DSQL%E5%9C%A8%E6%8F%92%E5%85%A5SQL%E4%B9%8B%E5%90%8E%E8%BF%90%E8%A1%8C%0A%20%20%20%20%20%20%20resultType%3A%20%E6%9F%A5%E5%87%BA%E7%9A%84%E6%95%B0%E6%8D%AE%E8%BF%94%E5%9B%9E%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3CselectKey%20keyProperty%3D%22id%22%20order%3D%22BEFORE%22%20resultType%3D%22Integer%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20select%20EMPLOYEES_SEQ.nextval%20from%20dual%0A%20%20%20%20%20%20%20%3C%2FselectKey%3E%0A%20%20%20%20%20%20%20%3C!--%20%E6%8F%92%E5%85%A5%E6%97%B6%E7%9A%84%E4%B8%BB%E9%94%AE%E6%98%AF%E4%BB%8E%E5%BA%8F%E5%88%97%E4%B8%AD%E6%8B%BF%E5%88%B0%20--%3E%0A%20%20%20%20%20%20%20insert%20into%20employee%20(id%2C%20last_name%2C%20email%2C%20gender)%0A%20%20%20%20%20%20%20values%20(%23%7Bid%7D%2C%20%23%7BlastName%7D%2C%20%23%7Bemail%7D%2C%20%23%7Bgender%7D)%0A%20%20%20%3C%2Finsert%3E%0A%20%20%20%0A%20%20%20%3C!--%0A%20%20%20%E4%BD%BF%E7%94%A8Oracle%20Sequence%E6%B7%BB%E5%8A%A0%E5%91%98%E5%B7%A5%E8%AE%B0%E5%BD%95%E5%90%8E%E8%8E%B7%E5%8F%96ID%0A%20%20%20%20--%3E%0A%20%20%20%3Cinsert%20id%3D%22addEmployee%22%20parameterType%3D%22com.mybatis.entity.Employee%22%20databaseId%3D%22oracle%22%3E%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20keyProperty%3A%20%E6%8C%87%E5%AE%9A%E5%AF%B9%E5%BA%94%E7%9A%84%E4%B8%BB%E9%94%AE%E5%B1%9E%E6%80%A7%EF%BC%8C%E5%8D%B3%E5%BD%93%E8%8E%B7%E5%8F%96%E4%B8%BB%E9%94%AE%E5%90%8E%E5%B0%86%E5%80%BC%E5%B0%81%E8%A3%85%E7%BB%99JavaBean%E4%B8%AD%E7%9A%84%E5%93%AA%E4%B8%AA%E5%B1%9E%E6%80%A7%0A%20%20%20%20%20%20%20order%3A%20BEFORE%20%E5%BD%93%E5%89%8DSQL%E5%9C%A8%E6%8F%92%E5%85%A5SQL%E4%B9%8B%E5%89%8D%E8%BF%90%E8%A1%8C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20AFTER%20%20%E5%BD%93%E5%89%8DSQL%E5%9C%A8%E6%8F%92%E5%85%A5SQL%E4%B9%8B%E5%90%8E%E8%BF%90%E8%A1%8C%0A%20%20%20%20%20%20%20resultType%3A%20%E6%9F%A5%E5%87%BA%E7%9A%84%E6%95%B0%E6%8D%AE%E8%BF%94%E5%9B%9E%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3CselectKey%20keyProperty%3D%22id%22%20order%3D%22AFTER%22%20resultType%3D%22Integer%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20select%20EMPLOYEES_SEQ.currval%20from%20dual%0A%20%20%20%20%20%20%20%3C%2FselectKey%3E%0A%20%20%20%20%20%20%20%3C!--%20%E6%8F%92%E5%85%A5%E6%97%B6%E7%9A%84%E4%B8%BB%E9%94%AE%E6%98%AF%E4%BB%8E%E5%BA%8F%E5%88%97%E4%B8%AD%E6%8B%BF%E5%88%B0%20--%3E%0A%20%20%20%20%20%20%20insert%20into%20employee%20(id%2C%20last_name%2C%20email%2C%20gender)%0A%20%20%20%20%20%20%20values%20(EMPLOYEES_SEQ.nextval%2C%20%23%7BlastName%7D%2C%20%23%7Bemail%7D%2C%20%23%7Bgender%7D)%0A%20%20%20%3C%2Finsert%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%205.4%20%E5%8F%82%E6%95%B0%E5%A4%84%E7%90%86%0A%0A%23%23%23%23%23%23%205.4.1%20%E5%8D%95%E4%B8%AA%E5%8F%82%E6%95%B0%0A%0A%09%23%7B%E5%8F%82%E6%95%B0%E5%90%8D%7D%20%0A%09%0A%09%E5%8D%95%E4%B8%AA%E5%8F%82%E6%95%B0Mybatis%E4%B8%8D%E4%BD%9C%E7%89%B9%E6%AE%8A%E5%A4%84%E7%90%86%0A%0A%23%23%23%23%23%23%205.4.2%20%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%0A%0A1.%20Mybatis%E4%BC%9A%E5%B0%86%E5%8F%82%E6%95%B0%E5%B0%81%E8%A3%85%E6%88%90Map%EF%BC%8Ckey%E4%BB%8E%20param1~paramN%0A%0A%20%20%20%60%60%60%0A%20%20%20%23%7B%E5%8F%82%E6%95%B0%E5%90%8D%7D%20%E6%98%AF%E4%BB%8EMap%E4%B8%AD%E5%8F%96%E5%88%B0%E6%8C%87%E5%AE%9Akey%E7%9A%84%E5%80%BC%0A%20%20%20%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%9A%20%23%7Bparam1%7D%20%0A%20%20%20%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%9A%20%23%7Bparam2%7D%20%0A%20%20%20%60%60%60%0A%0A2.%20%E5%91%BD%E5%90%8D%E5%8F%82%E6%95%B0%0A%0A%20%20%20%60%60%60%0A%20%20%20%E9%9C%80%E8%A6%81%E5%9C%A8%E6%8E%A5%E5%8F%A3%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E4%B8%8A%E4%BD%BF%E7%94%A8%40Param(%22lastName%22)%0A%20%20%20%E5%8F%82%E6%95%B0%E4%BC%9A%E8%A2%AB%E5%B0%81%E8%A3%85%E6%88%90Map%EF%BC%8Ckey%E6%98%AF%40Param%E6%B3%A8%E8%A7%A3%E4%B8%AD%E6%8C%87%E5%AE%9A%E7%9A%84%E5%80%BC%0A%20%20%20%E5%8F%96%E5%80%BC%23%7BlastName%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20Employee%20getEmployeeByIdAndName2(%40Param(%22id%22)%20int%20id%2C%20%40Param(%22lastName%22)%20String%20lastName)%3B%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cselect%20id%3D%22getEmployeeByIdAndName2%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%20%20%20%20%20and%20last_name%20%3D%20%23%7BlastName%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.4.3%20%E5%8F%82%E6%95%B0%E5%B0%81%E8%A3%85%0A%0A1.%20POJO%0A%0A%20%20%20%3E%20%E5%A6%82%E6%9E%9C%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%E6%98%AF%E4%B8%9A%E5%8A%A1%E5%AD%97%E6%AE%B5%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E4%BC%A0POJO%EF%BC%8C%E9%80%9A%E8%BF%87%23%7B%E4%B8%9A%E5%8A%A1%E5%AD%97%E6%AE%B5%E5%90%8D%E7%A7%B0%7D%E6%9D%A5%E5%8F%96%E5%80%BC%0A%0A2.%20Map%0A%0A%20%20%20%3E%20%E5%A6%82%E6%9E%9C%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%E4%B8%8D%E6%98%AF%E4%B8%9A%E5%8A%A1%E5%AD%97%E6%AE%B5%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%B0%86%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%E5%B0%81%E8%A3%85%E4%B8%BAMap%EF%BC%8C%20%E9%80%9A%E8%BF%87%23%7Bkey%7D%E6%9D%A5%E5%8F%96%E5%80%BC%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cselect%20id%3D%22getEmployeeByMap%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20where%20id%20%3D%20%23%7Bp_id%7D%0A%20%20%20%20%20%20%20%20%20and%20last_name%20%3D%20%23%7Bp_lastName%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20Map%3CString%2C%20Object%3E%20paramMap%20%3D%20new%20HashMap%3C%3E()%3B%0A%20%20%20paramMap.put(%22p_id%22%2C%201)%3B%0A%20%20%20paramMap.put(%22p_lastName%22%2C%20%22Chris%22)%3B%0A%20%20%20Employee%20employee%20%3D%20employeeMapper.getEmployeeByMap(paramMap)%3B%0A%20%20%20openSession.commit()%3B%0A%20%20%20%60%60%60%0A%0A3.%20TO%EF%BC%88Transfer%20Object%EF%BC%89%0A%0A%20%20%20%3E%20%E5%A6%82%E6%9E%9C%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%E4%B8%8D%E6%98%AF%E4%B8%9A%E5%8A%A1%E5%AD%97%E6%AE%B5%EF%BC%8C%E4%BD%86%E6%98%AF%E7%BB%8F%E5%B8%B8%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%8F%AF%E8%83%BD%E7%BC%96%E5%86%99%E4%B8%80%E4%B8%AATO%EF%BC%88Transfer%20Object%EF%BC%89%E6%9D%A5%E4%BC%A0%E8%BE%93%E6%95%B0%E6%8D%AE%0A%0A%20%20%20%60%60%60%0A%20%20%20Page%7B%0A%20%20%20%20int%20index%3B%0A%20%20%20%20int%20size%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%205.4.4%20%E5%8F%96%E5%80%BC%E6%96%B9%E5%BC%8F%E5%88%86%E6%9E%90%0A%0A1.%20%E7%AE%80%E5%8D%95%E5%8F%82%E6%95%B0%0A%0A%20%20%20%60%60%60%0A%20%20%20Employee%20getEmployeeByIdAndName(%40Param(%22id%22)%20int%20id%2C%20String%20lastName)%3B%0A%20%20%20%E5%8F%96id%E7%9A%84%E5%80%BC%EF%BC%9A%20%23%7Bid%7D%E6%88%96%23%7Bparam1%7D%0A%20%20%20%E5%8F%96lastName%E7%9A%84%E5%80%BC%EF%BC%9A%23%7Bparam2%7D%0A%20%20%20%60%60%60%0A%0A2.%20%E5%AF%B9%E8%B1%A1%E5%8F%82%E6%95%B0%0A%0A%20%20%20%60%60%60%0A%20%20%20Employee%20getEmployeeByIdAndEmp(%40Param(%22id%22)%20int%20id%2C%20%40Param(%22e%22)Employee%20emp)%3B%0A%20%20%20%E5%8F%96id%E7%9A%84%E5%80%BC%EF%BC%9A%20%23%7Bid%7D%E6%88%96%23%7Bparam1%7D%0A%20%20%20%E5%8F%96lastName%E7%9A%84%E5%80%BC%EF%BC%9A%23%7Be.lastName%7D%E6%88%96%E8%80%85%23%7Bparam2.lastName%7D%20--param2%E4%BB%A3%E8%A1%A8emp%E5%AF%B9%E8%B1%A1%0A%20%20%20%60%60%60%0A%0A3.%20%E9%9B%86%E5%90%88%E5%8F%82%E6%95%B0%0A%0A%20%20%20%3E%20%E5%A6%82%E6%9E%9C%E6%98%AFCollection%E7%B1%BB%E5%9E%8B%E6%88%96%E8%80%85%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%EF%BC%8C%E4%BC%9A%E7%89%B9%E6%AE%8A%E5%A4%84%E7%90%86%EF%BC%8C%E5%B0%86Collection%E7%B1%BB%E5%9E%8B%E6%88%96%E8%80%85%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%E5%B0%81%E8%A3%85%E5%9C%A8map%E4%B8%AD%0A%20%20%20%3E%0A%20%20%20%3E%20Collection%E7%B1%BB%E5%9E%8B%3A%20key%E4%B8%BAcollection%2C%20%E5%A6%82%E6%9E%9C%E6%98%AFlist%E4%BC%9A%E8%BF%9B%E4%B8%80%E6%AD%A5%E5%B0%81%E8%A3%85key%E4%B8%BAlist%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%3A%20key%E4%B8%BAarray%0A%0A%20%20%20%60%60%60%0A%20%20%20Employee%20getEmployeeByIds(List%3Cint%3E%20ids)%3B%0A%20%20%20%E5%8F%96%E7%AC%AC%E4%B8%80%E4%B8%AAid%E7%9A%84%E5%80%BC%EF%BC%9A%23%7Blist%5B0%5D%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.4.5%20%24%E5%92%8C%23%E7%9A%84%E5%8C%BA%E5%88%AB%0A%0A1.%20%24%E5%92%8C%23%E9%83%BD%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E8%8E%B7%E5%8F%96%E5%8F%82%E6%95%B0%0A%0A%20%20%20%3E%20%23%3A%20%E6%98%AF%E4%BB%A5%E9%A2%84%E7%BC%96%E8%AF%91%E7%9A%84%E6%96%B9%E5%BC%8F%E5%B0%86%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE%E5%88%B0SQL%E4%B8%AD%E5%8E%BB%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%98%B2%E6%AD%A2SQL%E6%B3%A8%E5%85%A5%EF%BC%8C%E5%A4%A7%E5%A4%9A%E6%95%B0%E6%83%85%E5%86%B5%E4%B8%8B%E4%BD%BF%E7%94%A8%23%E5%8F%96%E5%80%BC%0A%20%20%20%3E%0A%20%20%20%3E%20%24%3A%20%E5%B0%86%E5%8F%96%E5%87%BA%E7%9A%84%E5%80%BC%E7%9B%B4%E6%8E%A5%E6%8B%BC%E8%A3%85%E5%9C%A8SQL%E4%B8%AD%EF%BC%8C%E6%9C%89SQL%E6%B3%A8%E5%85%A5%E7%9A%84%E5%AE%89%E5%85%A8%E9%A3%8E%E9%99%A9%0A%0A2.%20%24%20%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E5%8A%A8%E6%80%81%E8%AE%BE%E7%BD%AESQL%E4%B8%AD%E7%9A%84%E8%A1%A8%E5%90%8D%E5%92%8C%E5%AD%97%E6%AE%B5%E5%90%8D%E7%A7%B0%2C%0A%0A%20%20%20%3E%20%E5%8E%9F%E7%94%9FSQL%E4%B8%8D%E6%94%AF%E6%8C%81%E5%8D%A0%E4%BD%8D%E7%AC%A6%E7%9A%84%E5%9C%B0%E6%96%B9%E9%83%BD%E5%8F%AF%E4%BB%A5%E7%94%A8%24%E6%9D%A5%E5%A4%84%E7%90%86%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%B5%8B%E8%AF%95%20testDynamicSql%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testDynamicSql()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20%20%20%20EmployeeMapper%20employeeMapper%20%3D%20openSession.getMapper(EmployeeMapper.class)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2Fmap%E5%8F%82%E6%95%B0%0A%20%20%20%20%20%20%20%20%20%20%20Map%3CString%2C%20Object%3E%20paramMap%20%3D%20new%20HashMap%3C%3E()%3B%0A%20%20%20%20%20%20%20%20%20%20%20paramMap.put(%22p_gender%22%2C%20%22F%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20paramMap.put(%22tableName%22%2C%20%22Employee%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20paramMap.put(%22sortFieldName%22%2C%20%22last_name%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20paramMap.put(%22sort%22%2C%20%22ASC%22)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20List%3CEmployee%3E%20employees%20%3D%20employeeMapper.dynamicSql(paramMap)%3B%0A%20%20%20%20%20%20%20%20%20%20%20for%20(Employee%20employee%20%3A%20employees)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(employee.toString())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E5%8A%A8%E6%80%81SQL--%3E%0A%20%20%20%3Cselect%20id%3D%22dynamicSql%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20%24%7BtableName%7D%0A%20%20%20%20%20%20%20where%20gender%20%3D%20%23%7Bp_gender%7D%0A%20%20%20%20%20%20%20order%20by%20%24%7BsortFieldName%7D%20%24%7Bsort%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A3.%20%23%7B%7D%E5%8F%AF%E4%BB%A5%E8%A7%84%E5%AE%9A%E5%8F%82%E6%95%B0%E7%9A%84%E7%B1%BB%E5%9E%8B%0A%0A%20%20%20%3E%20javaType%2C%20jdbcType%2C%20resultMap%2C%20typeHandler%2C%20jdbcTypeName%0A%20%20%20%3E%0A%20%20%20%3E%20jdbcType%3A%20%E5%9C%A8%E6%95%B0%E6%8D%AE%E4%B8%BAnull%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8D%E8%83%BD%E8%AF%86%E5%88%ABmybatis%E5%AF%B9%E4%BA%8Enull%E7%9A%84%E5%A4%84%E7%90%86%E6%AF%94%E5%A6%82Oracle%0A%20%20%20%3E%0A%20%20%20%60%60%60xml%0A%20%20%20%20%3C!--%20%0A%20%20%20%20MyBatis%E5%B0%86%E6%89%80%E6%9C%89%E7%9A%84null%E9%83%BD%E6%98%A0%E5%B0%84%E4%B8%BA%E5%8E%9F%E7%94%9F%E7%9A%84%20OTHER(Types.OTHER)%0A%20%20%20%20Oracle%E6%97%A0%E6%B3%95%E5%A4%84%E7%90%86Other%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%E9%9C%80%E8%A6%81%E6%8C%87%E5%AE%9A%E5%AD%97%E6%AE%B5%E5%80%BC%E4%B8%BA%E7%A9%BA%E6%97%B6%E7%9A%84JDBC%E7%B1%BB%E5%9E%8BjdbcType%3DNULL%0A%20%20%20%20%E6%88%96%E8%80%85%E5%9C%A8%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E4%B8%AD%E8%AE%BE%E7%BD%AE%20%3Csetting%20name%3D%22jdbcTypeForNull%22%20value%3D%22NULL%22%2F%3E%0A%20%20%20%20--%3E%0A%20%20%20%3Cinsert%20id%3D%22addEmployeeWithNull%22%20parameterType%3D%22com.mybatis.entity.Employee%22%20databaseId%3D%22oracle%22%3E%0A%20%20%20%20%20%20%20%3CselectKey%20keyProperty%3D%22id%22%20order%3D%22BEFORE%22%20resultType%3D%22Integer%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20select%20EMPLOYEES_SEQ.nextval%20from%20dual%0A%20%20%20%20%20%20%20%3C%2FselectKey%3E%0A%20%20%20%20%20%20%20%20%20%3C!--%20%E6%8F%92%E5%85%A5%E6%97%B6%E7%9A%84%E4%B8%BB%E9%94%AE%E6%98%AF%E4%BB%8E%E5%BA%8F%E5%88%97%E4%B8%AD%E6%8B%BF%E5%88%B0%20--%3E%0A%20%20%20%20%20%20%20%20%20insert%20into%20employee%20(id%2C%20last_name%2C%20email%2C%20gender)%0A%20%20%20%20%20%20%20%20%20values%20(%23%7Bid%7D%2C%20%23%7BlastName%7D%2C%20%23%7Bemail%2C%20jdbcType%3DNULL%7D%2C%20%23%7Bgender%7D)%0A%20%20%20%20%3C%2Finsert%3E%0A%20%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%205.4.6%20%40%E7%9A%84%E7%94%A8%E6%B3%95%0A%60%60%60java%0A%20%20%20%20%3Cif%20test%3D%22%40cn.hutool.core.util.StrUtil%40isNotEmpty(clientAdminBean.name)%20%22%3E%0A%20%20%20%20%20%20%20%20and%20a.name%20%3D%20%23%7BclientAdminBean.name%7D%0A%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%3Cif%20test%3D%22%40cn.hutool.core.util.StrUtil%40isNotEmpty(clientAdminBean.tableName)%20%22%3E%0A%20%20%20%20%20%20%20%20and%20a.table_name%20like%20CONCAT('%25'%2C%23%7BclientAdminBean.tableName%7D%2C'%25')%0A%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%3Cif%20test%3D%22%40cn.hutool.core.util.StrUtil%40isNotEmpty(clientAdminBean.mqTopic)%20%22%3E%0A%20%20%20%20%20%20%20%20and%20a.mq_topic%20like%20CONCAT('%25'%2C%23%7BclientAdminBean.mqTopic%7D%2C'%25')%0A%20%20%20%20%3C%2Fif%3E%0A%60%60%60%0A%0A%23%23%23%23%23%205.5%20%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E5%B0%81%E8%A3%85%0A%0A%23%23%23%23%23%23%205.5.1%20%E8%BF%94%E5%9B%9E%E4%B8%BA%E9%9B%86%E5%90%88%0A%0A%3E%20resultType%E4%B8%BA%E9%9B%86%E5%90%88%E4%B8%AD%E5%85%83%E7%B4%A0%E7%9A%84%E7%B1%BB%E5%9E%8B%0A%0A%23%23%23%23%23%23%205.5.2%20%E8%BF%94%E5%9B%9E%E4%B8%BA%E5%8D%95%E4%B8%AAMap%0A%0A%3E%20resultType%E4%B8%BA%E7%9A%84%E7%B1%BB%E5%9E%8B%E4%B8%BAmap%0A%0A%60%60%60xml%0A%3C!--%E6%B5%8B%E8%AF%95%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E4%B8%BAmap--%3E%0A%3Cselect%20id%3D%22getEmployeeReturnMap%22%20resultType%3D%22map%22%3E%0A%20%20%20%20select%20*%0A%20%20%20%20from%20employee%20t%0A%20%20%20%20where%20t.id%20%3D%20%23%7Bid%7D%0A%3C%2Fselect%3E%0A%60%60%60%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E6%B5%8B%E8%AF%95%20testMapResult%0A%20*%2F%0A%40Test%0Apublic%20void%20testMapResult()%20throws%20IOException%20%7B%0A%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20EmployeeMapper%20employeeMapper%20%3D%20openSession.getMapper(EmployeeMapper.class)%3B%0A%0A%20%20%20%20%20%20%20%20Map%3CString%2C%20Object%3E%20employeeMap%20%3D%20employeeMapper.getEmployeeReturnMap(4)%3B%0A%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%20for%20(Map.Entry%3CString%2C%20Object%3E%20entry%20%3A%20employeeMap.entrySet())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(entry.getKey()%20%2B%20%22%2C%20%22%20%2B%20entry.getValue())%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.5.3%20%E8%BF%94%E5%9B%9E%E4%B8%BA%E5%A4%9A%E4%B8%AAMap%0A%0A%3E%20%E6%8E%A5%E5%8F%A3%E7%B1%BB%0A%0A%60%60%60java%0A%2F**%0A%20%20*%20%E5%A4%9A%E6%9D%A1%E8%AE%B0%E5%BD%95%E5%B0%81%E8%A3%85%E5%9C%A8Map%3CString%2C%20Employee%3E%0A%20%20*%20MapKey%20%E5%91%8A%E8%AF%89mybatis%E7%94%A8Employee%E7%9A%84%E5%93%AA%E4%B8%AA%E5%B1%9E%E6%80%A7%E4%BD%9C%E4%B8%BAmap%E7%9A%84key%0A%20%20*%2F%0A%40MapKey(%22id%22)%0AMap%3CInteger%2C%20Employee%3E%20getEmployeeByGenderReturnMap(String%20gender)%3B%0A%60%60%60%0A%0A%3E%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%60%60%60xml%0A%3C!--%E6%B5%8B%E8%AF%95%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E4%B8%BA%E5%A4%9A%E4%B8%AAMAP%E5%AF%B9%E8%B1%A1--%3E%0A%3Cselect%20id%3D%22getEmployeeByGenderReturnMap%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20select%20*%0A%20%20%20%20from%20employee%20t%0A%20%20%20%20where%20t.gender%20%3D%20%23%7Bgender%7D%0A%3C%2Fselect%3E%0A%60%60%60%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E6%B5%8B%E8%AF%95%E8%BF%94%E5%9B%9E%E4%B8%BA%E5%A4%9A%E4%B8%AA%E5%AF%B9%E8%B1%A1%0A%20*%2F%0A%40Test%0Apublic%20void%20testMapResult2()%20throws%20IOException%20%7B%0A%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20EmployeeMapper%20employeeMapper%20%3D%20openSession.getMapper(EmployeeMapper.class)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%E8%BF%94%E5%9B%9E%E4%B8%BA%E5%A4%9A%E4%B8%AA%E5%AF%B9%E8%B1%A1%0A%20%20%20%20%20%20%20%20Map%3CInteger%2C%20Employee%3E%20employeeMap%20%3D%20employeeMapper.getEmployeeByGenderReturnMap(%22F%22)%3B%0A%0A%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%20for%20(Map.Entry%3CInteger%2C%20Employee%3E%20entry%20%3A%20employeeMap.entrySet())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(entry.getKey()%20%2B%20%22%2C%20%22%20%2B%20entry.getValue())%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%205.6%20resultMap%20%0A%0A%23%23%23%23%23%23%205.6.1%20resultType%20%E5%85%A5%E9%97%A8%0A%0A%3E%20resultType%20%E6%98%AF%E8%87%AA%E5%8A%A8%E5%B0%81%E8%A3%85%EF%BC%8C%E5%B0%86%E8%A1%A8%E4%B8%AD%E7%9A%84%E5%AD%97%E6%AE%B5%E4%B8%8EJavaBean%E4%B8%AD%E7%9A%84%E5%AD%97%E6%AE%B5%E6%98%A0%E5%B0%84%0A%3E%0A%3E%20resultMap%20%E6%98%AF%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B0%81%E8%A3%85%EF%BC%8C%E5%AE%9E%E7%8E%B0%E9%AB%98%E7%BA%A7%E7%BB%93%E6%9E%9C%E9%9B%86%E6%98%A0%E5%B0%84%0A%0A1.%20%E5%AE%9A%E4%B9%89ResultMap%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%0A%20%20%20%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A1%A8%E5%AD%97%E6%AE%B5%E5%90%8D%E7%A7%B0%E4%B8%8EJavaBean%E5%B1%9E%E6%80%A7%E7%9A%84%E6%98%A0%E5%B0%84%0A%20%20%20type%3A%20JavaBean%E7%B1%BB%E5%9E%8B%0A%20%20%20id%3A%20resultMap%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86%EF%BC%8C%E6%96%B9%E4%BE%BF%E8%A2%AB%E5%BC%95%E7%94%A8%0A%20%20%20--%3E%0A%20%20%20%3CresultMap%20id%3D%22employeeMap%22%20type%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20column%3A%20%E8%A1%A8%E5%AD%97%E6%AE%B5%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20property%3A%20JavaBean%E7%B1%BB%E5%9E%8B%E5%B1%9E%E6%80%A7%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22last_name%22%20property%3D%22lastName%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22email%22%20property%3D%22email%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22gender%22%20property%3D%22gender%22%2F%3E%0A%20%20%20%20%20%20%20%3C!--%E4%B8%8D%E5%9C%A8%E6%AD%A4%E5%A4%84%E9%85%8D%E7%BD%AE%E7%9A%84%E5%88%97%EF%BC%8C%E4%BC%9A%E8%87%AA%E5%8A%A8%E6%98%A0%E5%B0%84%EF%BC%8C%E4%BD%86%E5%A6%82%E6%9E%9C%E4%BD%BF%E7%94%A8resultMap%2C%E5%BB%BA%E8%AE%AE%E6%8A%8A%E6%89%80%E6%9C%89%E5%88%97%E9%83%BD%E9%85%8D%E7%BD%AE%E5%87%BA%E6%9D%A5--%3E%0A%20%20%20%0A%20%20%20%3C%2FresultMap%3E%0A%20%20%20%0A%20%20%20%3Cselect%20id%3D%22getEmployeeByGenderReturnMap%22%20resultMap%3D%22employeeMap%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employee%20t%0A%20%20%20%20%20%20%20where%20t.gender%20%3D%20%23%7Bgender%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E5%A4%9A%E6%9D%A1%E8%AE%B0%E5%BD%95%E5%B0%81%E8%A3%85%E5%9C%A8Map%3CString%2C%20Employee%3E%0A%20%20%20%20*%20MapKey%20%E5%91%8A%E8%AF%89mybatis%E7%94%A8Employee%E7%9A%84%E5%93%AA%E4%B8%AA%E5%B1%9E%E6%80%A7%E4%BD%9C%E4%B8%BAmap%E7%9A%84key%0A%20%20%20%20*%2F%0A%20%20%20%40MapKey(%22id%22)%0A%20%20%20Map%3CInteger%2C%20Employee%3E%20getEmployeeByGenderReturnMap(String%20gender)%3B%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%B5%8B%E8%AF%95resultMap%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testResultMap()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20%20%20%20EmployeeMapper2%20employeeMapper2%20%3D%20openSession.getMapper(EmployeeMapper2.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20Map%3CInteger%2C%20Employee%3E%20employeeMap%20%3D%20employeeMapper2.getEmployeeByGenderReturnMap(%22F%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%20%20%20%20for%20(Map.Entry%3CInteger%2C%20Employee%3E%20entry%20%3A%20employeeMap.entrySet())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(entry.getKey()%20%2B%20%22%2C%20%22%20%2B%20entry.getValue())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.6.2%20%20%E9%80%9A%E8%BF%87%E7%BA%A7%E8%81%94%E5%B1%9E%E6%80%A7%E7%9A%84%E6%96%B9%E5%BC%8F%E8%BF%9B%E8%A1%8C%E8%81%94%E5%90%88%E6%9F%A5%E8%AF%A2%0A%0A1.%20%E5%AE%9A%E4%B9%89ResultMap%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E9%80%9A%E8%BF%87%E7%BA%A7%E8%81%94%E5%B1%9E%E6%80%A7%E7%9A%84%E6%96%B9%E5%BC%8F%E8%BF%9B%E8%A1%8C%E8%81%94%E5%90%88%E6%9F%A5%E8%AF%A2--%3E%0A%20%20%20%3CresultMap%20id%3D%22empDeptMap%22%20type%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22last_name%22%20property%3D%22lastName%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22email%22%20property%3D%22email%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22gender%22%20property%3D%22gender%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22did%22%20property%3D%22dept.id%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22department_name%22%20property%3D%22dept.name%22%2F%3E%0A%20%20%20%3C%2FresultMap%3E%0A%20%20%20%0A%20%20%20%3Cselect%20id%3D%22getEmpAndDept%22%20resultMap%3D%22empDeptMap%22%3E%0A%20%20%20%20%20%20%20select%20t.id%2C%20t.last_name%2C%20t.email%2C%20t.gender%2C%20d.id%20did%2C%20d.department_name%0A%20%20%20%20%20%20%20from%20employee%20t%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20department%20d%0A%20%20%20%20%20%20%20where%20t.id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%20%20%20%20%20and%20t.department_id%20%3D%20d.id%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A%202.%20%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%20%20%60%60%60java%0A%20%20%20%20%20%40Data%0A%20%20%20%20%20%40AllArgsConstructor%0A%20%20%20%20%20public%20class%20Employee%20%7B%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20public%20Employee(String%20lastName%2C%20String%20email%2C%20String%20gender)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20this.lastName%20%3D%20lastName%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20this.email%20%3D%20email%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20this.gender%20%3D%20gender%3B%0A%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20public%20Employee(int%20id%2C%20String%20lastName%2C%20String%20email%2C%20String%20gender)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20this(lastName%2C%20email%2C%20gender)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20this.id%20%3D%20id%3B%0A%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20private%20int%20id%3B%0A%20%20%20%20%20%20%20%20%20private%20String%20lastName%3B%0A%20%20%20%20%20%20%20%20%20private%20String%20email%3B%0A%20%20%20%20%20%20%20%20%20private%20String%20gender%3B%0A%20%20%20%20%20%20%20%20%20private%20Department%20dept%3B%0A%20%20%20%20%20%7D%0A%20%20%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E9%80%9A%E8%BF%87%E7%BA%A7%E8%81%94%E5%B1%9E%E6%80%A7%E7%9A%84%E6%96%B9%E5%BC%8F%E8%BF%9B%E8%A1%8C%E8%81%94%E5%90%88%E6%9F%A5%E8%AF%A2%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testAssociateResultMap()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20%20%20%20EmployeeMapper2%20employeeMapper2%20%3D%20openSession.getMapper(EmployeeMapper2.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20employee%20%3D%20employeeMapper2.getEmpAndDept(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(employee.toString())%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%205.6.3%20%20%E4%BD%BF%E7%94%A8association%E8%BF%9B%E8%A1%8C%E5%88%86%E6%AD%A5%E6%9F%A5%E8%AF%A2%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20DepartmentMapper.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20%3F%3E%0A%20%20%20%3C!DOCTYPE%20mapper%0A%20%20%20%20%20%20%20%20%20%20%20PUBLIC%20%22-%2F%2Fmybatis.org%2F%2FDTD%20Mapper%203.0%2F%2FEN%22%0A%20%20%20%20%20%20%20%20%20%20%20%22http%3A%2F%2Fmybatis.org%2Fdtd%2Fmybatis-3-mapper.dtd%22%3E%0A%20%20%20%3Cmapper%20namespace%3D%22com.mybatis.dao.mapper.DepartmentMapper%22%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Cselect%20id%3D%22getDeptById%22%20resultType%3D%22com.mybatis.entity.Department%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20select%20*%20from%20department%20t%20where%20t.id%3D%23%7Bid%7D%0A%20%20%20%20%20%20%20%20%3C%2Fselect%3E%0A%20%20%20%0A%20%20%20%3C%2Fmapper%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20EmployeeMapper2.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E4%BD%BF%E7%94%A8association%E8%BF%9B%E8%A1%8C%E5%88%86%E6%AD%A5%E6%9F%A5%E8%AF%A2--%3E%0A%20%20%20%3CresultMap%20id%3D%22empDeptBySteps%22%20type%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22last_name%22%20property%3D%22lastName%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22email%22%20property%3D%22email%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22gender%22%20property%3D%22gender%22%2F%3E%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%201.%E5%85%88%E6%A0%B9%E6%8D%AE%E5%91%98%E5%B7%A5id%E6%9F%A5%E8%AF%A2%E5%88%B0%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%202.%E5%86%8D%E6%A0%B9%E6%8D%AE%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF%E4%B8%AD%E7%9A%84d_id%E6%9F%A5%E8%AF%A2%E9%83%A8%E9%97%A8%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%203.%E5%86%8D%E5%B0%86%E9%83%A8%E9%97%A8%E4%BF%A1%E6%81%AF%E5%B0%81%E9%97%AD%E5%88%B0%E5%91%98%E5%B7%A5%E5%AF%B9%E8%B1%A1%E4%B8%AD%0A%20%20%20%20%20%20%20select%EF%BC%9A%E8%A1%A8%E7%A4%BA%E5%BD%93%E5%89%8D%E5%85%B3%E8%81%94%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%98%AF%E8%B0%83%E7%94%A8%E6%8C%87%E5%AE%9A%E7%9A%84%E6%96%B9%E5%BC%8F%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%E7%9A%84%E7%BB%93%E6%9E%9C%0A%20%20%20%20%20%20%20column%3D%22department_id%22%3A%E6%8C%87%E5%AE%9A%E4%BC%A0%E5%85%A5select%E4%B8%AD%E6%96%B9%E6%B3%95%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%8C%E6%AD%A4%E5%8F%82%E6%95%B0%E6%9D%A5%E8%87%AA%E4%BA%8E%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%E2%80%9CgetEmpById%E2%80%9D%E4%B8%AD%E6%9F%A5%E8%AF%A2%E7%9A%84%E7%BB%93%E6%9E%9C%E9%9B%86%E9%87%8C%E9%9D%A2%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cassociation%20property%3D%22dept%22%20javaType%3D%22com.mybatis.entity.Department%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20select%3D%22com.mybatis.dao.mapper.DepartmentMapper.getDeptById%22%20column%3D%22department_id%22%2F%3E%0A%20%20%20%3C%2FresultMap%3E%0A%20%20%20%0A%20%20%20%3Cselect%20id%3D%22getEmpById%22%20resultMap%3D%22empDeptBySteps%22%3E%0A%20%20%20%20%20%20%20select%20*%20from%20employee%20t%20where%20t.id%20%3D%20%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Data%0A%20%20%20%40AllArgsConstructor%0A%20%20%20%40NoArgsConstructor%0A%20%20%20public%20class%20Department%20%7B%0A%20%20%20%0A%20%20%20%20%20%20private%20int%20id%3B%0A%20%20%20%20%20%20private%20String%20name%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.mybatis.entity%3B%0A%20%20%20%0A%20%20%20import%20lombok.AllArgsConstructor%3B%0A%20%20%20import%20lombok.Data%3B%0A%20%20%20import%20lombok.NoArgsConstructor%3B%0A%20%20%20%0A%20%20%20%40Data%0A%20%20%20%40AllArgsConstructor%0A%20%20%20%40NoArgsConstructor%0A%20%20%20public%20class%20Employee%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20private%20int%20id%3B%0A%20%20%20%20%20%20%20private%20String%20lastName%3B%0A%20%20%20%20%20%20%20private%20String%20email%3B%0A%20%20%20%20%20%20%20private%20String%20gender%3B%0A%20%20%20%20%20%20%20private%20Department%20dept%3B%0A%20%20%20%0A%20%20%20%0A%20%20%20%20%20%20%20public%20Employee(String%20lastName%2C%20String%20email%2C%20String%20gender)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20this.lastName%20%3D%20lastName%3B%0A%20%20%20%20%20%20%20%20%20%20%20this.email%20%3D%20email%3B%0A%20%20%20%20%20%20%20%20%20%20%20this.gender%20%3D%20gender%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20public%20Employee(int%20id%2C%20String%20lastName%2C%20String%20email%2C%20String%20gender)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20this(lastName%2C%20email%2C%20gender)%3B%0A%20%20%20%20%20%20%20%20%20%20%20this.id%20%3D%20id%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E4%BD%BF%E7%94%A8association%E8%BF%9B%E8%A1%8C%E5%88%86%E6%AD%A5%E6%9F%A5%E8%AF%A2%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testEmpDeptBySteps()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20%20%20%20EmployeeMapper2%20employeeMapper2%20%3D%20openSession.getMapper(EmployeeMapper2.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20employee%20%3D%20employeeMapper2.getEmpById(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(employee.toString())%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%205.6.4%20%20%E5%88%86%E6%AD%A5%E6%9F%A5%E8%AF%A2%E6%97%B6%E5%BB%B6%E6%97%B6%E5%8A%A0%E8%BD%BD%0A1.%20%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E5%BC%80%E5%90%AF%E5%85%A8%E5%B1%80%E5%BB%B6%E6%97%B6%E5%8A%A0%E8%BD%BD--%3E%0A%20%20%20%3Csetting%20name%3D%22lazyLoadingEnabled%22%20value%3D%22true%22%2F%3E%0A%20%20%20%3C!--%E5%85%B3%E9%97%AD%E7%A7%AF%E6%9E%81%E5%8A%A0%E8%BD%BD--%3E%0A%20%20%20%3Csetting%20name%3D%22aggressiveLazyLoading%22%20value%3D%22false%22%2F%3E%0A%20%20%20%3Csetting%20name%3D%22lazyLoadTriggerMethods%22%20value%3D%22%22%2F%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%3E%20%E4%B8%80%E8%88%AC%E4%B8%9A%E5%8A%A1%E7%B1%BB%E4%B8%AD%E4%BD%BF%E7%94%A8%40Data%E6%B3%A8%E8%A7%A3%E4%BC%9A%E8%A7%A6%E5%8F%91toString%E6%96%B9%E6%B3%95%2C%E5%8F%AF%E4%BB%A5%E5%B0%86%40Data%E6%9B%BF%E6%8D%A2%E6%88%90%40Getter%E5%92%8C%40Setter%E6%B3%A8%E8%A7%A3%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.mybatis.entity%3B%0A%20%20%20%0A%20%20%20import%20lombok.AllArgsConstructor%3B%0A%20%20%20import%20lombok.Data%3B%0A%20%20%20import%20lombok.Getter%3B%0A%20%20%20import%20lombok.NoArgsConstructor%3B%0A%20%20%20import%20lombok.Setter%3B%0A%20%20%20%0A%20%20%20%40Getter%0A%20%20%20%40Setter%0A%20%20%20%40AllArgsConstructor%0A%20%20%20%40NoArgsConstructor%0A%20%20%20public%20class%20Employee%20%7B%0A%20%20%20%0A%20%20%20%20%20%20private%20int%20id%3B%0A%20%20%20%20%20%20private%20String%20lastName%3B%0A%20%20%20%20%20%20private%20String%20email%3B%0A%20%20%20%20%20%20private%20String%20gender%3B%0A%20%20%20%20%20%20private%20Department%20dept%3B%0A%20%20%20%0A%20%20%20%0A%20%20%20%20%20%20public%20Employee(String%20lastName%2C%20String%20email%2C%20String%20gender)%20%7B%0A%20%20%20%20%20%20%20%20%20this.lastName%20%3D%20lastName%3B%0A%20%20%20%20%20%20%20%20%20this.email%20%3D%20email%3B%0A%20%20%20%20%20%20%20%20%20this.gender%20%3D%20gender%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20public%20Employee(int%20id%2C%20String%20lastName%2C%20String%20email%2C%20String%20gender)%20%7B%0A%20%20%20%20%20%20%20%20%20this(lastName%2C%20email%2C%20gender)%3B%0A%20%20%20%20%20%20%20%20%20this.id%20%3D%20id%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%20%20%20%0A%20%20%23%23%23%23%23%23%205.6.5%20%E4%BD%BF%E7%94%A8Collection%20%E5%85%B3%E8%81%94%E9%9B%86%E5%90%88%E6%9F%A5%E8%AF%A2%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E5%B5%8C%E5%A5%97%E7%BB%93%E6%9E%9C%E9%9B%86%E5%85%B3%E8%81%94%E6%9F%A5%E8%AF%A2--%3E%0A%20%20%20%20%20%3CresultMap%20id%3D%22deptWithEmps%22%20type%3D%22com.mybatis.entity.Department%22%3E%0A%20%20%20%20%20%20%20%20%20%3Cid%20column%3D%22did%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22name%22%20property%3D%22name%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20%20%20%E5%AE%9A%E4%B9%89%E9%9B%86%E5%90%88%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%B1%9E%E6%80%A7%0A%20%20%20%20%20%20%20%20%20ofType%3A%E6%8C%87%E5%AE%9A%E9%9B%86%E5%90%88%E9%87%8C%E9%9D%A2%E7%9A%84%E5%85%83%E7%B4%A0%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%20%20%3Ccollection%20property%3D%22emps%22%20ofType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22last_name%22%20property%3D%22lastName%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22email%22%20property%3D%22email%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22gender%22%20property%3D%22gender%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%3C%2Fcollection%3E%0A%20%20%20%20%20%3C%2FresultMap%3E%0A%20%20%20%0A%20%20%20%20%20%3Cselect%20id%3D%22getDeptById2%22%20resultMap%3D%22deptWithEmps%22%3E%0A%20%20%20%09SELECT%20d.id%20did%2C%20d.department_name%2C%20e.id%2C%20e.email%2C%20e.gender%2C%20e.last_name%2C%20e.department_id%0A%20%20%20%20%20%20%20%20%20FROM%20department%20d%0A%20%20%20%20%20%20%20LEFT%20JOIN%20employee%20e%20ON%20e.department_id%20%3D%20d.id%0A%20%20%20%20%20%20%20WHERE%20d.id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Data%0A%20%20%20%40AllArgsConstructor%0A%20%20%20%40NoArgsConstructor%0A%20%20%20public%20class%20Department%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20private%20int%20id%3B%0A%20%20%20%20%20%20%20private%20String%20name%3B%0A%20%20%20%20%20%20%20private%20List%3CEmployee%3E%20emps%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E4%BD%BF%E7%94%A8collection%E8%BF%9B%E8%A1%8C%E5%85%B3%E8%81%94%E5%AF%B9%E8%B1%A1%E7%9A%84%E9%9B%86%E5%90%88%E6%9F%A5%E8%AF%A2%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testDeptWithEmps()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20%20%20%20DepartmentMapper%20departmentMapper%20%3D%20openSession.getMapper(DepartmentMapper.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20Department%20dept%20%3D%20departmentMapper.getDeptById2(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(dept.toString())%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(dept.getEmps().toString())%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.6.6%20%E4%BD%BF%E7%94%A8Collection%20%E5%88%86%E6%AD%A5%E5%92%8C%E5%BB%B6%E6%97%B6%E6%9F%A5%E8%AF%A2%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20DepartmentMapper.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%0A%20%20%20%3C!--%0A%20%20%20%E5%88%86%E6%AD%A5%E6%9F%A5%E8%AF%A2%E9%83%A8%E9%97%A8%E4%B8%8B%E7%9A%84%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF%0A%20%20%201.%E5%85%88%E6%9F%A5%E8%AF%A2%E5%87%BA%E9%83%A8%E9%97%A8%E4%BF%A1%E6%81%AF%0A%20%20%202.%E5%86%8D%E6%A0%B9%E6%8D%AE%E9%83%A8%E9%97%A8ID%E6%9F%A5%E8%AF%A2%E5%87%BA%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF%0A%20%20%20--%3E%0A%20%20%20%3CresultMap%20id%3D%22deptWithEmpsByStep%22%20type%3D%22com.mybatis.entity.Department%22%3E%0A%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22department_name%22%20property%3D%22name%22%2F%3E%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20column%3D%22id%22%3A%E6%8C%87%E5%AE%9A%E4%BC%A0%E5%85%A5select%E4%B8%AD%E6%96%B9%E6%B3%95%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%8C%E6%AD%A4%E5%8F%82%E6%95%B0%E6%9D%A5%E8%87%AA%E4%BA%8E%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%E2%80%9CgetDeptByIdStep%E2%80%9D%E4%B8%AD%E6%9F%A5%E8%AF%A2%E7%9A%84%E7%BB%93%E6%9E%9C%E9%9B%86%E9%87%8C%E9%9D%A2%0A%20%20%20%20%20%20%20%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%E6%97%B6column%3D%7Bkey1%3Dvalue1%2Ckey2%3Dvalue2%7D%20key%E8%A6%81%E5%92%8C%E4%B9%9F%E5%88%86%E6%AD%A5%E6%9F%A5%E8%AF%A2%E6%96%B9%E6%B3%95%E9%87%8C%E9%9D%A2%E7%9A%84%E5%8F%82%E6%95%B0%E5%90%8D%E7%A7%B0%E4%BF%9D%E6%8C%81%E4%B8%80%E8%87%B4%0A%20%20%20%20%20%20%20javaType%3A%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E9%9B%86%E7%9A%84%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20fetchType%3A%20%E5%8D%B3%E4%BD%BF%E5%85%A8%E5%B1%80%E6%89%93%E5%BC%80%E4%BA%86%E5%BB%B6%E6%97%B6%E5%8A%A0%E8%BD%BD%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E9%92%88%E5%AF%B9%E6%AD%A4%E5%85%B3%E8%81%94%E6%9F%A5%E8%AF%A2%E6%98%AF%E5%90%A6%E8%A6%81%E8%BF%9B%E8%A1%8C%E5%BB%B6%E6%97%B6%E5%8A%A0%E8%BD%BD%EF%BC%8C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20eager%EF%BC%9A%E7%AB%8B%E5%8D%B3%E5%8A%A0%E8%BD%BD%EF%BC%8Clazy%3A%E5%BB%B6%E6%97%B6%E5%8A%A0%E8%BD%BD%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Ccollection%20property%3D%22emps%22%20select%3D%22com.mybatis.dao.mapper.EmployeeMapper.getEmployeeByDeptId%22%20column%3D%22id%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20javaType%3D%22List%22%20fetchType%3D%22lazy%22%2F%3E%0A%20%20%20%3C%2FresultMap%3E%0A%20%20%20%3Cselect%20id%3D%22getDeptByIdStep%22%20resultMap%3D%22deptWithEmpsByStep%22%3E%0A%20%20%20%20%20%20%20select%20*%20from%20department%20t%20where%20t.id%3D%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A%09EmployeeMapper.xml%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%0A%20%20%20%E5%88%86%E6%AD%A5%E6%9F%A5%E8%AF%A2%E9%83%A8%E9%97%A8%E4%B8%8B%E7%9A%84%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF%0A%20%20%201.%E5%85%88%E6%9F%A5%E8%AF%A2%E5%87%BA%E9%83%A8%E9%97%A8%E4%BF%A1%E6%81%AF%0A%20%20%202.%E5%86%8D%E6%A0%B9%E6%8D%AE%E9%83%A8%E9%97%A8ID%E6%9F%A5%E8%AF%A2%E5%87%BA%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF%0A%20%20%20--%3E%0A%20%20%20%3Cselect%20id%3D%22getEmployeeByDeptId%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20from%20employee%0A%20%20%20%20%20%20%20where%20department_id%20%3D%20%23%7Bdepartment_id%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.mybatis.dao.mapper%3B%0A%20%20%20%0A%20%20%20import%20com.mybatis.entity.Employee%3B%0A%20%20%20import%20org.apache.ibatis.annotations.MapKey%3B%0A%20%20%20import%20org.apache.ibatis.annotations.Param%3B%0A%20%20%20%0A%20%20%20import%20java.util.List%3B%0A%20%20%20import%20java.util.Map%3B%0A%20%20%20%0A%20%20%20public%20interface%20EmployeeMapper%20%7B%0A%20%20%20%20%20%20%20Employee%20getEmployeeByDeptId(int%20i)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E4%BD%BF%E7%94%A8collection%E8%BF%9B%E8%A1%8C%E5%85%B3%E8%81%94%E5%AF%B9%E8%B1%A1%E7%9A%84%E9%9B%86%E5%90%88%E5%88%86%E6%AD%A5%E6%9F%A5%E8%AF%A2%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testDeptWithEmpsBySteps()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession()%3B%0A%20%20%20%20%20%20%20%20%20%20%20DepartmentMapper%20departmentMapper%20%3D%20openSession.getMapper(DepartmentMapper.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20Department%20dept%20%3D%20departmentMapper.getDeptByIdStep(2)%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(dept.toString())%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(dept.getEmps().toString())%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%23%23%23%23%23%23%205.6.7%20%E9%89%B4%E5%88%AB%E5%99%A8%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20EmployeeMapper2%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%0A%20%20%20%20%20discriminator%0A%20%20%20%20%20%E9%89%B4%E5%88%AB%E5%99%A8%0A%20%20%20%20%20mybatis%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AEdiscriminator%E5%88%A4%E6%96%AD%E6%9F%90%E5%88%97%E7%9A%84%E5%80%BC%EF%BC%8C%E6%A0%B9%E6%8D%AE%E5%80%BC%E6%9D%A5%E6%94%B9%E5%8F%98%E5%B0%81%E8%A3%85%E8%A1%8C%E4%B8%BA%0A%20%20%20%20%20%E5%B0%81%E8%A3%85employee%0A%20%20%20%20%201.%E5%A6%82%E6%9E%9C%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%E7%9A%84%E6%98%AF%E5%A5%B3%E7%94%9F%EF%BC%8C%E5%88%99%E6%8A%8A%E5%AF%B9%E5%BA%94%E7%9A%84%E9%83%A8%E9%97%A8%E4%BF%A1%E6%81%AF%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%EF%BC%8C%E5%90%A6%E5%88%99%E4%B8%8D%E6%9F%A5%E8%AF%A2%0A%20%20%20%20%202.%E5%A6%82%E6%9E%9C%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%E7%9A%84%E6%98%AF%E7%94%B7%E7%94%9F%EF%BC%8C%E5%88%99%E6%8A%8AlastName%E8%BF%99%E4%B8%80%E5%88%97%E8%B5%8B%E5%80%BC%E5%88%B0email%E4%B8%8A%0A%20%20%20%20%20--%3E%0A%20%20%20%3CresultMap%20id%3D%22empDeptByStepsWithDiscriminator%22%20type%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22last_name%22%20property%3D%22lastName%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22email%22%20property%3D%22email%22%2F%3E%0A%20%20%20%20%20%20%20%3Cresult%20column%3D%22gender%22%20property%3D%22gender%22%2F%3E%0A%20%20%20%20%20%20%20%3C!--%E5%A6%82%E6%9E%9C%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%E7%9A%84%E6%98%AF%E5%A5%B3%E7%94%9F%EF%BC%8C%E5%88%99%E6%8A%8A%E5%AF%B9%E5%BA%94%E7%9A%84%E9%83%A8%E9%97%A8%E4%BF%A1%E6%81%AF%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%EF%BC%8C%E5%90%A6%E5%88%99%E4%B8%8D%E6%9F%A5%E8%AF%A2--%3E%0A%20%20%20%20%20%20%20%3Cdiscriminator%20javaType%3D%22String%22%20column%3D%22gender%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Ccase%20value%3D%22F%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cassociation%20property%3D%22dept%22%20select%3D%22com.mybatis.dao.mapper.DepartmentMapper.getDeptById%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20javaType%3D%22com.mybatis.entity.Employee%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20column%3D%22department_id%22%20fetchType%3D%22eager%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fcase%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%3C!--%E5%A6%82%E6%9E%9C%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%E7%9A%84%E6%98%AF%E7%94%B7%E7%94%9F%EF%BC%8C%E5%88%99%E6%8A%8AlastName%E8%BF%99%E4%B8%80%E5%88%97%E8%B5%8B%E5%80%BC%E5%88%B0email%E4%B8%8A--%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Ccase%20value%3D%22M%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22last_name%22%20property%3D%22lastName%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22last_name%22%20property%3D%22email%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22gender%22%20property%3D%22gender%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fcase%3E%0A%20%20%20%20%20%20%20%3C%2Fdiscriminator%3E%0A%20%20%20%3C%2FresultMap%3E%0A%20%20%20%0A%20%20%20%3Cselect%20id%3D%22getEmpByIdwithDiscriminator%22%20resultMap%3D%22empDeptByStepsWithDiscriminator%22%3E%0A%20%20%20%20%20%20%20select%20*%20from%20employee%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20DepartmentMapper.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cselect%20id%3D%22getDeptById%22%20resultType%3D%22com.mybatis.entity.Department%22%3E%0A%20%20%20%20%20%20%20%20select%20id%2C%20department_name%20name%20from%20department%20t%20where%20t.id%3D%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20interface%20EmployeeMapper2%20%7B%0A%20%20%20%20%20%20%20List%3CEmployee%3E%20getEmpByIdwithDiscriminator()%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Test%0A%20%20%20public%20void%20testEmpByUsingDiscriminator()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20EmployeeMapper2%20employeeMapper2%20%3D%20openSession.getMapper(EmployeeMapper2.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20List%3CEmployee%3E%20emps%20%3D%20employeeMapper2.getEmpByIdwithDiscriminator()%3B%0A%20%20%20%20%20%20%20%20%20%20%20for%20(Employee%20emp%20%3A%20emps)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(emp.toString())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20emp.getDept())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(emp.getDept().toString())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A4.%20%E7%BB%93%E6%9E%9C%0A%0A%20%20%20%60%60%60%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'Chris'%2C%20gender%3D'M'%7D%0A%20%20%20Employee%7Bid%3D3%2C%20lastName%3D'Hedy'%2C%20email%3D'Hedy'%2C%20gender%3D'M'%7D%0A%20%20%20Employee%7Bid%3D4%2C%20lastName%3D'Nancy'%2C%20email%3D'Nancy%40gmail.com'%2C%20gender%3D'F'%7D%0A%20%20%20Department(id%3D1%2C%20name%3D%E5%BC%80%E5%8F%91%E9%83%A8%2C%20emps%3Dnull)%0A%20%20%20Employee%7Bid%3D7%2C%20lastName%3D'Cano'%2C%20email%3D'Cano%40gmail.com'%2C%20gender%3D'F'%7D%0A%20%20%20Department(id%3D2%2C%20name%3D%E6%B5%8B%E8%AF%95%E9%83%A8%2C%20emps%3Dnull)%0A%20%20%20%60%60%60%0A%20%20%20%0A%20%20%0A%20%20%0A%0A%23%23%23%23%23%205.7%20%E5%8A%A8%E6%80%81SQL%0A%0A%23%23%23%23%23%23%205.7.1%20if%0A%0A%60%60%60xml%0A%3Cselect%20id%3D%22getempsbyconditionIf%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20select%20*%20from%20employee%20t%0A%20%20%20%20%3C!--%0A%20%20%20%20where%3A%E7%94%A8%E6%9D%A5%E5%B0%81%E8%A3%85%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%EF%BC%8C%E4%BC%9A%E5%B0%86SQL%E4%B8%AD%E5%A4%9A%E5%87%BA%E6%9D%A5%E7%9A%84and%E5%92%8Cor%E5%8E%BB%E6%8E%89%2C%E4%BD%86%E6%98%AF%E5%8F%AA%E5%8E%BB%E6%8E%89%E7%AC%AC%E4%B8%80%E4%B8%AAand%E5%92%8Cor%0A%20%20%20%20--%3E%0A%20%20%20%20%3Cwhere%3E%0A%20%20%20%20%20%20%20%20%2F*%201.%20test%3A%E5%88%A4%E6%96%AD%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%8C%E4%BD%BF%E7%94%A8OGNL%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%20%20%20%20%20%20%20%20https%3A%2F%2Fcommons.apache.org%2Fproper%2Fcommons-ognl%2Flanguage-guide.html%0A%20%20%20%20%20%20%20%20%E9%81%87%E8%A7%81%E7%89%B9%E6%AE%8A%E7%AC%A6%E5%8F%B7%E5%BA%94%E8%AF%A5%E8%BD%AC%E4%B8%BA%E8%BD%AC%E4%B9%89%E5%AD%97%E7%AC%A6*%2F%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D%22id%20!%3D%20null%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20t.id%20%3D%20%23%7Bid%7D%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D%22lastName%20!%3D%20null%20and%20lastName!%3D%20''%20%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20and%20t.last_name%3D%23%7BlastName%7D%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D%22email%20!%3D%20null%20and%20email.trim()%20!%3D''%20%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20and%20t.email%3D%23%7Bemail%7D%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D'gender%20!%3D%20null%20and%20(gender%20%3D%3D%22F%22%20%7C%7C%20gender%20%3D%3D%22M%22)'%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20and%20t.gender%3D%23%7Bgender%7D%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%3C%2Fwhere%3E%0A%3C%2Fselect%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.7.2%20trim%0A%0A%60%60%60xml%0A%3Cselect%20id%3D%22getempsbyconditionTrim%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20select%20*%20from%20employee%20t%0A%0A%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20%20prefix%3A%20%E5%AF%B9trim%E4%B8%AD%E6%95%B4%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8B%BC%E4%B8%B2%E5%90%8E%E7%9A%84%E7%BB%93%E6%9E%9C%E5%8A%A0%E4%B8%80%E4%B8%AA%E5%89%8D%E7%BC%80%0A%20%20%20%20%20%20%20%20prefixOverrides%3A%20%E5%89%8D%E7%BC%80%E8%A6%86%E7%9B%96%EF%BC%8C%E5%8E%BB%E6%8E%89%E6%95%B4%E4%B8%AA%E6%8B%BC%E4%B8%B2%E5%89%8D%E9%9D%A2%E5%A4%9A%E4%BD%99%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%0A%20%20%20%20%20%20%20%20suffix%3A%20%E5%AF%B9trim%E4%B8%AD%E6%95%B4%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8B%BC%E4%B8%B2%E5%90%8E%E7%9A%84%E7%BB%93%E6%9E%9C%E5%8A%A0%E4%B8%80%E4%B8%AA%E5%90%8E%E7%BC%80%0A%20%20%20%20%20%20%20%20suffixOverrides%3A%20%E5%90%8E%E7%BC%80%E8%A6%86%E7%9B%96%EF%BC%8C%E5%8E%BB%E6%8E%89%E6%95%B4%E4%B8%AA%E6%8B%BC%E4%B8%B2%E5%89%8D%E9%9D%A2%E5%A4%9A%E4%BD%99%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%0A%20%20%20%20--%3E%0A%20%20%20%20%3Ctrim%20prefix%3D%22where%22%20suffixOverrides%3D%22and%22%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D%22id%20!%3D%20null%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20t.id%20%3D%20%23%7Bid%7D%20and%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D%22lastName%20!%3D%20null%20and%20lastName!%3D%20''%20%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20t.last_name%3D%23%7BlastName%7D%20and%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D%22email%20!%3D%20null%20and%20email.trim()%20!%3D''%20%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20t.email%3D%23%7Bemail%7D%20and%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D'gender%20!%3D%20null%20and%20(gender%20%3D%3D%22F%22%20%7C%7C%20gender%20%3D%3D%22M%22)'%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20t.gender%3D%23%7Bgender%7D%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%3C%2Ftrim%3E%0A%3C%2Fselect%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.7.3%20choose%0A%0A%60%60%60xml%0A%3Cselect%20id%3D%22getempsbyconditionChoose%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20select%20*%20from%20employee%20t%0A%20%20%20%20%3Cwhere%3E%0A%20%20%20%20%20%20%20%20%3Cchoose%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cwhen%20test%3D%22id!%3Dnull%22%3Eid%3D%23%7Bid%7D%3C%2Fwhen%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cwhen%20test%3D%22lastName!%3Dnull%22%3Elast_name%3D%23%7BlastName%7D%3C%2Fwhen%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cwhen%20test%3D%22email!%3Dnull%20and%20email.trim()!%3D''%20%22%3Eemail%3D%23%7Bemail%7D%3C%2Fwhen%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cotherwise%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89--%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%201%20%3D%201%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fotherwise%3E%0A%20%20%20%20%20%20%20%20%3C%2Fchoose%3E%0A%20%20%20%20%3C%2Fwhere%3E%0A%3C%2Fselect%3E%0A%60%60%60%0A%60%60%60xml%0A%3Cselect%20id%3D%22getRolePrincileByFormIdandRoleKey%22%20resultMap%3D%22BaseResultMap%22%3E%0A%20%20%20%20%20%20%20%20SELECT%0A%20%20%20%20%20%20%20%20%3Cinclude%20refid%3D%22Base_Column_List%22%2F%3E%0A%20%20%20%20%20%20%20%20FROM%0A%20%20%20%20%20%20%20%20t_wf_role_principle%20p%0A%20%20%20%20%20%20%20%20WHERE%0A%20%20%20%20%20%20%20%20p.formId%20%3D%20%23%7BformId%7D%0A%20%20%20%20%20%20%20%20%3Cchoose%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cwhen%20test%3D%22null%20!%3D%20roleKeys%20and%20roleKeys.size%20%3E%201%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cforeach%20collection%3D%22roleKeys%22%20item%3D%22key%22%20open%3D%22%20and%20p.roleKey%20in%20(%22%20close%3D%22)%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20separator%3D%22%2C%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%7Bkey%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fforeach%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fwhen%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cwhen%20test%3D%22null%20!%3D%20roleKeys%20and%20roleKeys.size%20%3D%3D%201%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20and%20p.roleKey%20%3D%20%23%7BroleKeys%5B0%5D%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fwhen%3E%0A%20%20%20%20%20%20%20%20%3C%2Fchoose%3E%0A%3C%2Fselect%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.7.4%20set%0A%0A%60%60%60xml%0A%3C!--%0A%E5%8F%82%E6%95%B0%E4%B8%AD%E5%B8%A6%E4%BA%86%E5%93%AA%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%E5%88%99%E6%9B%B4%E6%96%B0%E6%AD%A4%E5%8F%82%E6%95%B0%E5%AF%B9%E5%BA%94%E7%9A%84%E5%AD%97%E6%AE%B5%0A%3Cset%3E%E7%94%A8%E6%9D%A5%E5%B0%81%E8%A3%85%E4%BF%AE%E6%94%B9%E5%AD%97%E6%AE%B5%0A%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%94%A8tirm%E6%9B%BF%E6%8D%A2set%E6%A0%87%E7%AD%BE%0A%3Ctrim%20prefix%3D%22set%22%20prefixOverrides%3D%22%2C%22%3E%0A--%3E%0A%3Cupdate%20id%3D%22updateEmp%22%3E%0A%20%20%20%20update%20employee%20t%0A%20%20%20%20%3Cset%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D%22lastName!%3Dnull%20and%20lastName.trim()!%3D''%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20t.last_name%3D%23%7BlastName%7D%2C%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D%22email!%3Dnull%20and%20email.trim()!%3D''%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20t.email%3D%23%7Bemail%7D%2C%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3Cif%20test%3D'gender!%3Dnull%20and%20%20(gender%20%3D%3D%22F%22%20%7C%7C%20gender%20%3D%3D%22M%22)'%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20t.gender%3D%23%7Bgender%7D%2C%0A%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%3C%2Fset%3E%0A%20%20%20%20where%20t.id%20%3D%20%23%7Bid%7D%0A%3C%2Fupdate%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.7.5%20foreach%0A%0A%60%60%60xml%0A%3C!--%0A%20%20%20connection%3A%E6%8C%87%E5%AE%9A%E8%A6%81%E9%81%8D%E5%8E%86%E7%9A%84%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20list%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%82%E6%95%B0%E4%BC%9A%E7%89%B9%E6%AE%8A%E5%A4%84%E7%90%86%E5%B0%81%E8%A3%85%E5%9C%A8map%E4%B8%AD%2C%E8%BF%99%E4%B8%AAmap%E7%9A%84key%E5%90%8D%E7%A7%B0%E6%98%AFlist%0A%20%20%20item%3A%E5%B0%86%E5%BD%93%E5%89%8D%E9%81%8D%E5%8E%86%E5%87%BA%E7%9A%84%E5%80%BC%E8%B5%8B%E5%80%BC%E7%BB%99%E6%8C%87%E5%AE%9A%E5%8F%98%E6%9B%B4%0A%20%20%20separator%E5%85%83%E7%B4%A0%E4%B9%8B%E9%97%B4%E7%9A%84%E5%88%86%E9%9A%94%E7%AC%A6%0A%20%20%20open%EF%BC%9A%E5%B0%81%E8%A3%85%E9%81%8D%E5%8E%86%E7%BB%93%E6%9E%9C%E7%9A%84%E5%BC%80%E5%A7%8B%E5%AD%97%E7%AC%A6%0A%20%20%20close%EF%BC%9A%E5%B0%81%E8%A3%85%E9%81%8D%E5%8E%86%E7%BB%93%E6%9E%9C%E7%9A%84%E7%BB%93%E6%9D%9F%E5%AD%97%E7%AC%A6%0A%20%20%20index%3A%E7%B4%A2%E5%BC%95%EF%BC%8C%E9%81%8D%E5%8E%86list%E6%97%B6%EF%BC%8Cindex%E6%98%AF%E5%BD%93%E5%89%8D%E5%85%83%E7%B4%A0%E7%9A%84%E7%B4%A2%E5%BC%95%EF%BC%8Citem%E4%B8%BA%E5%BD%93%E5%89%8D%E5%85%83%E7%B4%A0%E7%9A%84%E5%80%BC%0A%20%20%20%20%20%20%20%20%20%E9%81%8D%E5%8E%86map%E6%97%B6%EF%BC%8Cindex%E6%98%AF%E5%BD%93%E5%89%8D%E5%85%83%E7%B4%A0%E7%9A%84key%EF%BC%8Citem%E4%B8%BA%E5%BD%93%E5%89%8D%E5%85%83%E7%B4%A0%E7%9A%84%E5%80%BC%0A%20%20%20%23%7B%E5%8F%98%E9%87%8F%E5%90%8D%7D%E5%B0%B1%E8%83%BD%E5%8F%96%E5%87%BA%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%BD%93%E5%89%8D%E9%81%8D%E5%8E%86%E5%87%BA%E7%9A%84%E5%85%83%E7%B4%A0%0A--%3E%0A%3Cselect%20id%3D%22getEmpsByConditionForeach%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20select%20*%20from%20employee%20where%20id%20in%0A%20%20%20%20%3Cforeach%20collection%3D%22list%22%20item%3D%22id%22%20separator%3D%22%2C%22%20open%3D%22(%22%20close%3D%22)%22%20index%3D%22inx%22%3E%0A%20%20%20%20%20%20%20%20%23%7Bid%7D%0A%20%20%20%20%3C%2Fforeach%3E%0A%3C%2Fselect%3E%0A%60%60%60%0A%0A%60%60%60java%0Apublic%20interface%20DynamicSqlMapper%20%7B%0A%20%20%20%20List%3CEmployee%3E%20getEmpsByConditionForeach(List%3CInteger%3E%20ids)%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E6%B5%8B%E8%AF%95foreach%0A%20*%2F%0A%40Test%0Apublic%20void%20testForeach()%20throws%20IOException%20%7B%0A%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession(true)%3B%0A%20%20%20%20%20%20%20%20DynamicSqlMapper%20dynamicSqlMapper%20%3D%20openSession.getMapper(DynamicSqlMapper.class)%3B%0A%20%20%20%20%20%20%20%20List%3CEmployee%3E%20employees%20%3D%20dynamicSqlMapper.getEmpsByConditionForeach(Arrays.asList(1%2C%203%2C%204))%3B%0A%20%20%20%20%20%20%20%20openSession.commit()%3B%0A%20%20%20%20%20%20%20%20for%20(Employee%20employee%20%3A%20employees)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(employee.toString())%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%23%23%23%23%23%23%205.7.6%20foreach%20insert%20for%20mysql%20%0A%0A%E6%96%B9%E5%BC%8F%E4%B8%80%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cinsert%20id%3D%22addEmpsInBatch%22%3E%0A%20%20%20%20%20%20%20insert%20into%20employee%20(last_name%2C%20email%2Cgender%2Cdepartment_id)%0A%20%20%20%20%20%20%20%3Cforeach%20collection%3D%22emps%22%20item%3D%22emp%22%20open%3D%22values%22%20separator%3D%22%2C%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20(%23%7Bemp.lastName%7D%2C%23%7Bemp.email%7D%2C%23%7Bemp.gender%7D%2C%23%7Bemp.dept.id%7D)%0A%20%20%20%20%20%20%20%3C%2Fforeach%3E%0A%20%20%20%3C%2Finsert%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20int%20addEmpsInBatch(%40Param(%22emps%22)%20List%3CEmployee%3E%20employees)%3B%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%B5%8B%E8%AF%95foreach%20insert%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testForeachInsert()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20DynamicSqlMapper%20dynamicSqlMapper%20%3D%20openSession.getMapper(DynamicSqlMapper.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20emp1%20%3D%20new%20Employee(%22S4%22%2C%20%22s4%40gmail.com%22%2C%20%22F%22%2C%20new%20Department(1))%3B%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20emp2%20%3D%20new%20Employee(%22S5%22%2C%20%22s5%40gmail.com%22%2C%20%22M%22%2C%20new%20Department(2))%3B%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20emp3%20%3D%20new%20Employee(%22S6%22%2C%20%22s6%40gmail.com%22%2C%20%22F%22%2C%20new%20Department(2))%3B%0A%20%20%20%20%20%20%20%20%20%20%20int%20count%20%3D%20dynamicSqlMapper.addEmpsInBatch(Arrays.asList(emp1%2C%20emp2%2C%20emp3))%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22new%20added%20employee%20count%3A%22%20%2B%20count)%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%E6%96%B9%E5%BC%8F%E4%BA%8C%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%20Caused%20by%3A%20java.sql.SQLSyntaxErrorException%3A%20You%20have%20an%20error%20in%20your%20SQL%20syntax%3B%20check%20the%20manual%20that%20corresponds%20to%20your%20MySQL%20server%20version%20for%20the%20right%20syntax%20to%20use%20near%20'insert%20into%20employee%20(last_name%2C%20email%2Cgender%2Cdepartment_id)values%0A%20%20%20%20('%20at%20line%204%0A%20%20%20%20%E9%9C%80%E8%A6%81%E6%89%93%E5%BC%80MYSQL%E7%9A%84%E6%89%B9%E9%87%8F%E5%86%99%E5%85%A5%E6%A8%A1%E5%BC%8F%3AallowMultiQueries%3Dtrue%0A%20%20%20%20%20%20%20jdbc.home.url%3Djdbc%3Amysql%3A%2F%2F192.168.101.127%3A3306%2Fchris%3FallowMultiQueries%3Dtrue%26useSSL%3Dfalse%26useUnicode%3Dtrue%26characterEncoding%3DUTF-8%26serverTimezone%3DCTT%0A%20%20%20%20--%3E%0A%20%20%20%20%3Cinsert%20id%3D%22addEmpsInBatch2%22%3E%0A%20%20%20%20%20%20%20%20%3Cforeach%20collection%3D%22emps%22%20item%3D%22emp%22%20%20separator%3D%22%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20insert%20into%20employee%20(last_name%2C%20email%2Cgender%2Cdepartment_id)values%0A%20%20%20%20%20%20%20%20%20%20%20%20(%23%7Bemp.lastName%7D%2C%23%7Bemp.email%7D%2C%23%7Bemp.gender%7D%2C%23%7Bemp.dept.id%7D)%0A%20%20%20%20%20%20%20%20%3C%2Fforeach%3E%0A%20%20%20%20%3C%2Finsert%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.7.7%20foreach%20insert%20for%20oracle%0A%0A1.%20SQL%E4%B8%AD%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%0A%20%20%20%20oracle%20%E4%B8%8D%E6%94%AF%E6%8C%81mysql%E8%BF%99%E7%A7%8D%E6%89%B9%E9%87%8F%E5%86%99%E5%85%A5%E6%95%B0%E6%8D%AE%E5%BA%93%0A%20%20%20%20insert%20into%20employee(last_name%2C%20email%2Cgender%2Cdepartment_id)%20values%20()%2C()%0A%20%20%20%20%E4%BD%86%E6%98%AF%E6%94%AF%E6%8C%81%E5%A6%82%E4%B8%8B%E4%B8%89%E7%A7%8D%0A%20%20%20%201.%20%E5%B0%86%E5%A4%9A%E6%9D%A1%E8%AF%AD%E5%8F%A5%E6%94%BE%E5%9C%A8begin%E5%92%8Cend%E4%B9%8B%E9%97%B4%0A%20%20%20%20begin%0A%20%20%20%20%20%20%20insert%20into%20employee(last_name%2C%20email%2Cgender%2Cdepartment_id)%20values%20()%3B%0A%20%20%20%20%20%20%20insert%20into%20employee(last_name%2C%20email%2Cgender%2Cdepartment_id)%20values%20()%3B%0A%20%20%20%20%20%20%20insert%20into%20employee(last_name%2C%20email%2Cgender%2Cdepartment_id)%20values%20()%3B%0A%20%20%20%20end%3B%0A%20%20%20%202.%20%E5%88%A9%E7%94%A8%E4%B8%AD%E9%97%B4%E8%A1%A8%0A%20%20%20%20%20%20%20%20insert%20into%20employee(last_name%2C%20email%2Cgender%2Cdepartment_id)%20select%20employees_seq.nextval%2C%20last_name%2C%20email%20from%20(%0A%20%20%20%20%20%20%20%20%20%20%20select%20'test_a_01'%20last_name%2C%20'test_a_01%40163.com'%20email%20from%20dual%3B%0A%20%20%20%20%20%20%20%20%20%20%20union%0A%20%20%20%20%20%20%20%20%20%20%20select%20'test_a_02'%20last_name%2C%20'test_a_02%40gmail.com'%20email%20from%20dual%3B%0A%20%20%20%20%20%20%20%20%20%20%20union%0A%20%20%20%20%20%20%20%20%20%20%20select%20'test_a_03'%20last_name%2C%20'test_a_03%40gmail.com'%20email%20from%20dual%3B%0A%20%20%20%20%20%20%20%20)%0A%20%20%20--%3E%0A%20%20%20%0A%20%20%20%3C!--1.%20%E5%B0%86%E5%A4%9A%E6%9D%A1%E8%AF%AD%E5%8F%A5%E6%94%BE%E5%9C%A8begin%E5%92%8Cend%E4%B9%8B%E9%97%B4--%3E%0A%20%20%20%3Cinsert%20id%3D%22addEmpsInBatchInOracle%22%20databaseId%3D%22oracle%22%3E%0A%20%20%20%20%20%20%20%3Cforeach%20collection%3D%22emps%22%20item%3D%22emp%22%20open%3D%22begin%22%20close%3D%22end%3B%22%20separator%3D%22%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20insert%20into%20employee%20(last_name%2C%20email%2Cgender%2Cdepartment_id)%0A%20%20%20%20%20%20%20%20%20%20%20(%23%7Bemp.lastName%7D%2C%23%7Bemp.email%7D%2C%23%7Bemp.gender%7D%2C%23%7Bemp.dept.id%7D)%0A%20%20%20%20%20%20%20%3C%2Fforeach%3E%0A%20%20%20%3C%2Finsert%3E%0A%20%20%20%0A%20%20%20%3C!--2.%20%E5%88%A9%E7%94%A8%E4%B8%AD%E9%97%B4%E8%A1%A8--%3E%0A%20%20%20%3Cinsert%20id%3D%22addEmpsInBatch2InOracle%22%20databaseId%3D%22oracle%22%3E%0A%20%20%20%20%20%20%20insert%20into%20employee(last_name%2C%20email%2Cgender%2Cdepartment_id)%0A%20%20%20%20%20%20%20%3Cforeach%20collection%3D%22emps%22%20item%3D%22emp%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20open%3D%22select%20employees_seq.nextval%2C%20last_name%2C%20email%2C%20gender%2C%20department_id%20from(%22%20close%3D%22)%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20separator%3D%22union%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20select%20%23%7Bemp.lastName%7D%20last_name%2C%20%23%7Bemp.email%7D%20email%2C%20%23%7Bemp.gender%7D%20gender%2C%20%23%7Bemp.dept.id%7D%20department_id%0A%20%20%20%20%20%20%20%20%20%20%20from%20dual%3B%0A%20%20%20%20%20%20%20%3C%2Fforeach%3E%0A%20%20%20%0A%20%20%20%3C%2Finsert%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.7.8%20%E5%86%85%E7%BD%AE%E5%8F%82%E6%95%B0%0A%0A%60%60%60%0A%3C!--%0A%E4%B8%A4%E4%B8%AA%E5%86%85%E7%BD%AE%E5%8F%82%E6%95%B0%0A1.%20_parameter%3A%20%E4%BB%A3%E8%A1%A8%E4%BC%A0%E5%85%A5%E6%96%B9%E6%B3%95%E7%9A%84%E6%95%B4%E4%B8%AA%E5%8F%82%E6%95%B0%0A%20%20%20%20%E5%A6%82%E6%9E%9C%E6%98%AF%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C_parameter%E5%B0%B1%E8%A1%A8%E7%A4%BA%E8%BF%99%E4%B8%AA%E5%8F%82%E6%95%B0%0A%20%20%20%20%E5%A6%82%E6%9E%9C%E6%98%AF%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%8F%82%E6%95%B0%E4%BC%9A%E8%A2%ABmybatis%E5%B0%81%E8%A3%85%E6%88%90%E4%B8%BA%E4%B8%80%E4%B8%AAmap%EF%BC%8C_parameter%E5%B0%B1%E4%BB%A3%E8%A1%A8%E8%BF%99%E4%B8%AAmap%0A2.%20_databaseId%3A%20%E5%A6%82%E6%9E%9C%E9%85%8D%E7%BD%AE%E4%BA%86databaseIdProvider%2C_databaseIdy%E5%B0%B1%E6%98%AF%E4%BB%A3%E8%A1%A8%E5%BD%93%E5%89%8D%E4%BD%BF%E7%94%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E5%88%AB%E5%90%8D%0A--%3E%0A%0A%3C!--%E6%A0%B9%E6%8D%AE%E5%BD%93%E5%90%AF%E7%94%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E6%9D%A5%E8%BF%9B%E8%A1%8C%E4%B8%8D%E5%90%8C%E7%9A%84%E6%9F%A5%E8%AF%A2--%3E%0A%3Cselect%20id%3D%22getInnerParameters%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%3Cif%20test%3D%22_databaseId%3D%3D'mysql'%22%3E%0A%20%20%20%20%20%20%20%20select%20*%20from%20employee%0A%20%20%20%20%20%20%20%20%3Cwhere%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cif%20test%3D%22_parameter!%3Dnull%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20last_name%20%3D%20%23%7B_parameter.lastName%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%20%3C%2Fwhere%3E%0A%0A%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%3Cif%20test%3D%22_databaseId%3D%3D'mysql'%22%3E%0A%20%20%20%20%20%20%20%20select%20*%20from%20t_employee%0A%20%20%20%20%3C%2Fif%3E%0A%0A%3C%2Fselect%3E%0A%60%60%60%0A%0A%23%23%23%23%23%23%205.7.9%20bind%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E5%A6%82%E6%9E%9ClastName%E6%9C%89%E5%80%BC%E5%88%99%E8%BF%9B%E8%A1%8C%E6%A8%A1%E7%B3%8A%E6%9F%A5%E8%AF%A2--%3E%0A%20%20%20%3Cselect%20id%3D%22getEmpByBind%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20%3C!--bind%20%E5%B0%86OGNL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E5%80%BC%E7%BB%91%E5%AE%9A%E5%88%B0%E4%B8%80%E4%B8%AA%E5%8F%98%E9%87%8F%E4%B8%AD%EF%BC%8C%E6%96%B9%E4%BE%BF%E5%90%8E%E9%9D%A2%E5%BC%95%E7%94%A8%E8%BF%99%E4%B8%AA%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC--%3E%0A%20%20%20%20%20%20%20%3Cbind%20name%3D%22_lastName%22%20value%3D%22'%25'%2BlastName%2B'%25'%22%2F%3E%0A%20%20%20%20%20%20%20select%20*%20from%20employee%0A%20%20%20%20%20%20%20%3Cwhere%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cif%20test%3D%22_parameter%20!%3D%20null%20and%20lastName%20!%3D''%20%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20last_name%20LIKE%20%23%7B_lastName%7D%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fif%3E%0A%20%20%20%20%20%20%20%3C%2Fwhere%3E%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20interface%20DynamicSqlMapper%20%7B%0A%20%20%20%20%20%20%20List%3CEmployee%3E%20getEmpByBind(Employee%20emp)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%B5%8B%E8%AF%95bind%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testBind()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20DynamicSqlMapper%20dynamicSqlMapper%20%3D%20openSession.getMapper(DynamicSqlMapper.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20emp%20%3D%20new%20Employee()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E6%9F%A5%E8%AF%A2%E5%90%8D%E7%A7%B0%E4%B8%AD%E5%8C%85%E6%8B%ACa%E7%9A%84%E5%91%98%E5%B7%A5%E8%AE%B0%E5%BD%95%0A%20%20%20%20%20%20%20%20%20%20%20emp.setLastName(%22a%22)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20List%3CEmployee%3E%20emps%20%3D%20dynamicSqlMapper.getEmpByBind(emp)%3B%0A%20%20%20%20%20%20%20%20%20%20%20for%20(Employee%20employee%20%3A%20emps)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(employee.toString())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%205.8.0%20sql%E7%89%87%E6%96%AD%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%0A%20%20%20include%20%0A%20%20%201.%E5%8F%AF%E4%BB%A5%E5%BC%95%E7%94%A8sql%E6%A0%87%E7%AD%BE%E4%B8%AD%E5%AE%9A%E4%B9%89%E7%9A%84SQL%E7%89%87%E6%96%AD%0A%20%20%202.%E5%8F%AF%E4%BB%A5%E5%AE%9A%E4%B9%89%E5%B1%9E%E6%80%A7%E5%8F%98%E9%87%8F%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%9C%A8sql%E6%A0%87%E7%AD%BE%E4%BD%BF%E7%94%A8%24%7BtestColumn%7D%E6%9D%A5%E8%8E%B7%E5%8F%96%E5%B1%9E%E6%80%A7%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%0A%20%20%20--%3E%0A%20%20%20%3Cinsert%20id%3D%22addEmpsWithCondistionInclude%22%3E%0A%20%20%20%20%20%20%20insert%20into%20employee%20(%0A%20%20%20%20%20%20%20%3Cinclude%20refid%3D%22emp_insert_fields%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cproperty%20name%3D%22testColumn%22%20value%3D%22abc%22%2F%3E%0A%20%20%20%20%20%20%20%3C%2Finclude%3E%0A%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%3Cforeach%20collection%3D%22emps%22%20item%3D%22emp%22%20open%3D%22values%22%20separator%3D%22%2C%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20(%23%7Bemp.lastName%7D%2C%23%7Bemp.email%7D%2C%23%7Bemp.gender%7D%2C%23%7Bemp.dept.id%7D)%0A%20%20%20%20%20%20%20%3C%2Fforeach%3E%0A%20%20%20%3C%2Finsert%3E%0A%20%20%20%0A%20%20%20%3C!--%0A%20%20%20sql%E6%A0%87%E7%AD%BE%E7%94%A8%E6%9D%A5%E6%8A%BD%E5%8F%96%E5%8F%AF%E9%87%8D%E7%94%A8%E7%9A%84sql%E7%89%87%E6%AE%B5%0A%20%20%201.%E5%B0%86%E5%B8%B8%E7%94%A8%E7%9A%84%E5%88%97%E5%90%8D%E6%8A%BD%E5%8F%96%E5%87%BA%E6%9D%A5%EF%BC%8C%E6%96%B9%E4%BE%BF%E6%9F%A5%E8%AF%A2%E6%88%96%E6%8F%92%E5%85%A5%E4%B8%AD%E5%BC%95%E7%94%A8%0A%20%20%202.include%E6%9D%A5%E5%BC%95%E7%94%A8sql%E6%A0%87%E7%AD%BE%E4%B8%AD%E7%9A%84sql%E7%89%87%E6%96%AD%0A%20%20%20--%3E%0A%20%20%20%3Csql%20id%3D%22emp_insert_fields%22%3E%0A%20%20%20%20%20%20%20last_name%2C%20email%2Cgender%2Cdepartment_id%2C%24%7BtestColumn%7D%0A%20%20%20%3C%2Fsql%3E%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%206%20%E7%BC%93%E5%AD%98%0A%0A%23%23%23%23%23%206.1%20mybatis%20%E7%BC%93%E5%AD%98%0A%0A%3E%20mybatis%E4%B8%AD%E9%BB%98%E8%AE%A4%E5%AE%9A%E4%B9%89%E4%BA%86%E4%B8%A4%E7%BA%A7%E7%BC%93%E5%AD%98%0A%3E%0A%3E%20%E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5%E6%9C%89%E5%8F%AA%E5%BC%80%E5%90%AF%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%EF%BC%8C%E4%B9%9F%E7%A7%B0%E4%B8%BA%E6%9C%AC%E5%9C%B0%E7%BC%93%E5%AD%98%EF%BC%8C%E5%8D%B3SqlSesssion%E7%BA%A7%E5%88%AB%E7%9A%84%E7%BC%93%E5%AD%98%0A%3E%0A%3E%20%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%BA%E5%85%A8%E5%B1%80%E7%BC%93%E5%AD%98%EF%BC%8C%E9%9C%80%E8%A6%81%E6%89%8B%E5%8A%A8%E9%85%8D%E7%BD%AE%E5%92%8C%E5%BC%80%E5%90%AF%EF%BC%8C%E5%AE%83%E6%98%AF%E5%9F%BA%E4%BA%8Enamespace%E7%BA%A7%E5%88%AB%E7%9A%84%E7%BC%93%E5%AD%98%0A%3E%0A%3E%20%E4%B8%BA%E4%BA%86%E6%8F%90%E9%AB%98%E6%89%A9%E5%B1%95%E6%80%A7%EF%BC%8Cmybatis%E6%8F%90%E4%BE%9B%E4%BA%86%E7%BC%93%E5%AD%98%E6%8E%A5%E5%8F%A3Cache%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%AE%9E%E7%8E%B0Cache%E6%8E%A5%E5%8F%A3%E6%9D%A5%E5%AE%9E%E7%8E%B0%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A%0A%0A%23%23%23%23%23%206.2%20%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A%E4%B8%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E5%90%8C%E4%B8%80%E6%AC%A1%E4%BC%9A%E8%AF%9D%E6%9C%9F%E9%97%B4%E6%9F%A5%E8%AF%A2%E5%88%B0%E7%9A%84%E6%95%B0%E6%8D%AE%E4%BC%9A%E6%94%BE%E5%9C%A8%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%EF%BC%8C%E4%BB%A5%E5%90%8E%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E8%8E%B7%E5%8F%96%E7%9B%B8%E5%90%8C%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E7%9B%B4%E6%8E%A5%E4%BB%8E%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%E6%9F%A5%0A%0A%23%23%23%23%23%23%206.2.1%20%E4%BD%BF%E7%94%A8%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A1.%20SQL%E6%98%A0%E5%B0%84%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cselect%20id%3D%22getEmpById%22%20resultType%3D%22com.mybatis.entity.Employee%22%3E%0A%20%20%20%20%20%20%20select%20*%20from%20employee%20where%20id%20%3D%20%23%7Bid%7D%0A%20%20%20%3C%2Fselect%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%B5%8B%E8%AF%95Cache%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testCache()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession%20%3D%20sqlSessionFactory.openSession(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20CacheMapper%20cacheMapper%20%3D%20openSession.getMapper(CacheMapper.class)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%9F%A5%E8%AF%A2%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20emp%20%3D%20cacheMapper.getEmpById(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(emp.toString())%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E7%AC%AC%E4%BA%8C%E6%AC%A1%E6%9F%A5%E8%AF%A2%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20emp2%20%3D%20cacheMapper.getEmpById(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(emp2.toString())%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20openSession)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20openSession.close()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%E7%BB%93%E6%9E%9C%0A%0A%20%20%20%60%60%60%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20%20Preparing%3A%20select%20*%20from%20employee%20where%20id%20%3D%20%3F%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20Parameters%3A%201(Integer)%0A%20%20%20DEBUG%20-%20%3C%3D%3D%20%20%20%20%20%20Total%3A%201%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'chris%40gmail.com'%2C%20gender%3D'M'%7D%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'chris%40gmail.com'%2C%20gender%3D'M'%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%206.2.2%20%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E5%A4%B1%E6%95%88%0A%0A1.%20SqlSession%E4%B8%8D%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AA%EF%BC%8C%E5%88%99%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E5%A4%B1%E6%95%88%0A%0A2.%20SqlSession%E7%9B%B8%E5%90%8C%EF%BC%8C%E4%BD%86%E6%98%AF%E9%9C%80%E8%A6%81%E6%9F%A5%E8%AF%A2%E7%9A%84%E6%95%B0%E6%8D%AE%E5%9C%A8%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%E6%B2%A1%E6%9C%89%EF%BC%8C%E5%88%99%E4%B8%8D%E8%B5%B0%E7%BC%93%E5%AD%98%EF%BC%8C%E9%9C%80%E8%A6%81%E5%8E%BB%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E6%9F%A5%E8%AF%A2%0A%0A3.%20SqlSession%E7%9B%B8%E5%90%8C%EF%BC%8C%E4%BD%86%E6%98%AF%E4%B8%A4%E6%AC%A1%E6%9F%A5%E8%AF%A2%E4%B8%AD%E9%97%B4%E6%9C%89%E5%A2%9E%E5%88%A0%E6%94%B9%E7%9A%84SQL%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%9B%A0%E4%B8%BAmybatis%E8%AE%A4%E4%B8%BA%E5%A2%9E%E5%88%A0%E6%94%B9%E5%8F%AF%E8%83%BD%E5%AF%B9%E4%B9%8B%E5%90%8E%E7%9A%84%E6%9F%A5%E8%AF%A2%E6%9C%89%E5%BD%B1%E5%93%8D%0A%0A4.%20SqlSession%E7%9B%B8%E5%90%8C%EF%BC%8C%E4%BD%86%E6%98%AF%E6%89%8B%E5%8A%A8%E6%B8%85%E9%99%A4%E4%BA%86%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A%20%20%20%60%60%60java%0A%20%20%20openSession.clearCache()%3B%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%206.3%20%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A%23%23%23%23%23%23%206.3.1%20%E5%B7%A5%E4%BD%9C%E6%9C%BA%E5%88%B6%0A%0A1.%20%E4%B8%80%E4%B8%AA%E4%BC%9A%E8%AF%9D%E6%9F%A5%E8%AF%A2%E4%B8%80%E6%9D%A1%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%BF%99%E6%9D%A1%E6%95%B0%E6%8D%AE%E4%BC%9A%E8%A2%AB%E6%94%BE%E5%9C%A8%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9D%E7%9A%84%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%0A%0A2.%20%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9D%E5%85%B3%E9%97%AD%EF%BC%8C%E6%AD%A4%E4%BC%9A%E8%AF%9D%E5%AF%B9%E5%BA%94%E7%9A%84%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E4%BC%9A%E8%A2%AB%E4%BF%9D%E5%AD%98%E5%88%B0%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%EF%BC%8C%E6%96%B0%E7%9A%84%E4%BC%9A%E8%AF%9D%E6%9F%A5%E8%AF%A2%E4%BF%A1%E6%81%AF%E6%97%B6%EF%BC%8C%E5%B0%B1%E4%BC%9A%E5%8F%82%E7%85%A7%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A3.%20%E5%A6%82%E6%9E%9Csqlsession%E5%8D%B3%E6%9C%89employee%E4%BF%A1%E6%81%AF%E5%8F%88%E6%9C%89department%E4%BF%A1%E6%81%AF%EF%BC%8C%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E4%BC%9A%E6%A0%B9%E6%8D%AE%E4%B8%8D%E5%90%8C%E5%AF%B9%E8%B1%A1%E4%BF%A1%E6%81%AF%E7%9A%84namespace%E7%BC%93%E5%AD%98%E6%95%B0%E6%8D%AE%0A%0A%20%20%20EmployeeMapper%20-%3E%20employee%0A%0A%20%20%20DeapartmentMapper-%3E%20department%0A%0A%23%23%23%23%23%23%206.3.2%20%E4%BD%BF%E7%94%A8%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A1.%20%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E5%BC%80%E5%90%AF%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E5%85%A8%E5%B1%80%E5%BC%80%E5%90%AF%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%2C%E9%BB%98%E8%AE%A4%E5%B7%B2%E5%BC%80%E5%90%AF--%3E%0A%20%20%20%3Csetting%20name%3D%22cacheEnabled%22%20value%3D%22true%22%2F%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E7%9A%84%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%E5%A4%84%E4%BD%BF%E7%94%A8cache%E9%85%8D%E7%BD%AE%E7%BC%93%E5%AD%98%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Ccache%20%2F%3E%0A%20%20%20%60%60%60%0A%0A3.%20POJO%E9%9C%80%E8%A6%81%E5%AE%9E%E7%8E%B0%E5%BA%8F%E5%88%97%E5%8C%96%E6%8E%A5%E5%8F%A3%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20class%20Department%20implements%20Serializable%20%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20class%20Employee%20implements%20Serializable%0A%20%20%20%60%60%60%0A%0A4.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%3E%20%E6%9F%A5%E5%87%BA%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E4%BC%9A%E5%85%88%E6%94%BE%E5%9C%A8%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%8F%AA%E6%9C%89%E4%BC%9A%E8%AF%9D%E8%A2%AB%E5%85%B3%E9%97%AD%EF%BC%8C%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E6%89%8D%E4%BC%9A%E8%BD%AC%E7%A7%BB%E5%88%B0%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%EF%BC%8C%E5%85%B6%E5%AE%83SqlSesssion%E6%89%8D%E8%83%BD%E5%9C%A8%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%E8%8E%B7%E5%8F%96%E6%AD%A4%E6%95%B0%E6%8D%AE%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%B5%8B%E8%AF%95%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%20%20%20%20*%2F%0A%20%20%20%40Test%0A%20%20%20public%20void%20testSecondCache()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20SqlSessionFactory%20sqlSessionFactory%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession_1%20%3D%20null%3B%0A%20%20%20%20%20%20%20SqlSession%20openSession_2%20%3D%20null%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sqlSessionFactory%20%3D%20getSqlSessionFactory()%3B%0A%20%20%20%20%20%20%20%20%20%20%20openSession_1%20%3D%20sqlSessionFactory.openSession(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20CacheMapper%20cacheMapper1%20%3D%20openSession_1.getMapper(CacheMapper.class)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20openSession_2%20%3D%20sqlSessionFactory.openSession(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20CacheMapper%20cacheMapper2%20%3D%20openSession_2.getMapper(CacheMapper.class)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%9F%A5%E8%AF%A2%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20emp%20%3D%20cacheMapper1.getEmpById(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(emp.toString())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E6%9F%A5%E5%87%BA%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E4%BC%9A%E5%85%88%E6%94%BE%E5%9C%A8%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%EF%BC%8C%E5%8F%AA%E6%9C%89%E4%BC%9A%E8%AF%9D%E8%A2%AB%E5%85%B3%E9%97%AD%EF%BC%8C%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E6%89%8D%E4%BC%9A%E8%BD%AC%E7%A7%BB%E5%88%B0%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%EF%BC%8C%E5%85%B6%E5%AE%83opensesssion%E6%89%8D%E8%83%BD%E5%9C%A8%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E4%B8%AD%E8%8E%B7%E5%8F%96%0A%20%20%20%20%20%20%20%20%20%20%20closeSession(openSession_1)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E7%AC%AC%E4%BA%8C%E6%AC%A1%E6%9F%A5%E8%AF%A2%0A%20%20%20%20%20%20%20%20%20%20%20Employee%20emp2%20%3D%20cacheMapper2.getEmpById(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(emp2.toString())%3B%0A%20%20%20%20%20%20%20%20%20%20%20closeSession(openSession_2)%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20e%3B%0A%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20closeSession(openSession_1%2C%20openSession_2)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E7%BB%93%E6%9E%9C%0A%0A%20%20%20%3E%20DEBUG%20-%20Cache%20Hit%20Ratio%20%5Bcom.mybatis.dao.mapper.CacheMapper%5D%3A%200.5%0A%0A%20%20%20%60%60%60%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20%20Preparing%3A%20select%20*%20from%20employee%20where%20id%20%3D%20%3F%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20Parameters%3A%201(Integer)%0A%20%20%20DEBUG%20-%20%3C%3D%3D%20%20%20%20%20%20Total%3A%201%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'chris%40gmail.com'%2C%20gender%3D'M'%7D%0A%20%20%20DEBUG%20-%20Closing%20JDBC%20Connection%20%5Bcom.mysql.cj.jdbc.ConnectionImpl%4027c6e487%5D%0A%20%20%20DEBUG%20-%20Returned%20connection%20667346055%20to%20pool.%0A%20%20%20DEBUG%20-%20Cache%20Hit%20Ratio%20%5Bcom.mybatis.dao.mapper.CacheMapper%5D%3A%200.5%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'chris%40gmail.com'%2C%20gender%3D'M'%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%206.4%20%E5%92%8C%E7%BC%93%E5%AD%98%E6%9C%89%E5%85%B3%E7%9A%84%E9%85%8D%E7%BD%AE%0A%0A%23%23%23%23%23%23%206.4.1%20cacheEnabled%0A%0A%3E%20%E5%85%A8%E5%B1%80%E5%BC%80%E5%90%AF%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%2C%E9%BB%98%E8%AE%A4%E5%B7%B2%E5%BC%80%E5%90%AF%20%2C%0A%3E%0A%3E%20false%3A%E4%BB%85%E5%85%B3%E9%97%AD%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%EF%BC%8C%E4%BD%86%E6%98%AF%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%BB%8D%E7%84%B6%E5%8F%AF%E7%94%A8%0A%0A%60%60%60xml%0A%3Csetting%20name%3D%22cacheEnabled%22%20value%3D%22true%22%2F%3E%0A%60%60%60%0A%0A%23%23%23%23%23%23%206.4.2%20useCache%0A%0A%3E%20%E6%AF%8F%E4%B8%80%E4%B8%AAselect%E6%A0%87%E7%AD%BE%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AAuseCache%3D%22true%22%0A%3E%0A%3E%20ture%3A%20%E8%A1%A8%E7%A4%BA%E4%BD%BF%E7%94%A8%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%EF%BC%8C%E4%BD%86%E6%98%AF%E5%BF%85%E9%A1%BB%E5%B0%86%E5%85%A8%E5%B1%80%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%E6%89%93%E5%BC%80%0A%3E%0A%3E%20false%3A%E8%A1%A8%E7%A4%BA%E4%B8%8D%E4%BD%BF%E7%94%A8%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%EF%BC%8C%E4%BD%86%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%E4%BB%8D%E7%84%B6%E5%8F%AF%E7%94%A8%0A%0A%60%60%60xml%0A%3Cselect%20id%3D%22getEmpById%22%20resultType%3D%22com.mybatis.entity.Employee%22%20useCache%3D%22true%22%3E%0A%20%20%20%20select%20*%20from%20employee%20where%20id%20%3D%20%23%7Bid%7D%0A%3C%2Fselect%3E%0A%60%60%60%0A%0A%23%23%23%23%23%23%206.4.3%20flushCache%0A%0A1.%20%E6%AF%8F%E4%B8%80%E4%B8%AA%E6%9F%A5%E8%AF%A2%E6%A0%87%E7%AD%BE%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AAflushCache%3D%22fase%22%2C%E5%A6%82%E4%BD%95%E6%94%B9%E4%B8%BAflushCache%3D%22true%22%E8%A1%A8%E7%A4%BA%E6%9F%A5%E8%AF%A2%E6%89%A7%E8%A1%8C%E5%AE%8C%E4%B9%8B%E5%90%8E%E9%83%BD%E4%BC%9A%E6%B8%85%E9%99%A4%E4%B8%80%E7%BA%A7%E5%92%8C%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A2.%20%E6%AF%8F%E4%B8%80%E4%B8%AA%E5%A2%9E%E5%88%A0%E6%94%B9%E6%A0%87%E7%AD%BE%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AAflushCache%3D%22true%22%2C%E8%A1%A8%E7%A4%BA%E5%A2%9E%E5%88%A0%E6%94%B9%E6%89%A7%E8%A1%8C%E5%AE%8C%E4%B9%8B%E5%90%8E%E9%83%BD%E4%BC%9A%E6%B8%85%E9%99%A4%E4%B8%80%E7%BA%A7%E5%92%8C%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A%20%20%20%3E%20%E6%B5%8B%E8%AF%95%0A%20%20%20%3E%20%E8%99%BD%E7%84%B6%E5%8E%BB%E7%BC%93%E5%AD%98%E4%B8%AD%E6%89%BE%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BD%86%E6%98%AF%E6%95%B0%E6%8D%AE%E5%B7%B2%E7%BB%8F%E8%A2%AB%E6%B8%85%E9%99%A4%0A%0A%20%20%20%60%60%60%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20%20Preparing%3A%20select%20*%20from%20employee%20where%20id%20%3D%20%3F%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20Parameters%3A%201(Integer)%0A%20%20%20DEBUG%20-%20%3C%3D%3D%20%20%20%20%20%20Total%3A%201%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'chris%40gmail.com'%2C%20gender%3D'M'%7D%0A%20%20%20DEBUG%20-%20Closing%20JDBC%20Connection%20%5Bcom.mysql.cj.jdbc.ConnectionImpl%4027c6e487%5D%0A%20%20%20DEBUG%20-%20Returned%20connection%20667346055%20to%20pool.%0A%20%20%20DEBUG%20-%20Opening%20JDBC%20Connection%0A%20%20%20DEBUG%20-%20Checked%20out%20connection%20667346055%20from%20pool.%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20%20Preparing%3A%20insert%20into%20employee%20(%20last_name%2C%20email%2C%20gender%2C%20department_id%20)%20values%20(%3F%2C%3F%2C%3F%2C%3F)%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20Parameters%3A%20shawn(String)%2C%20shawn%40qq.com(String)%2C%20M(String)%2C%201(Integer)%0A%20%20%20DEBUG%20-%20%3C%3D%3D%20%20%20%20Updates%3A%201%0A%20%20%20DEBUG%20-%20Cache%20Hit%20Ratio%20%5Bcom.mybatis.dao.mapper.CacheMapper%5D%3A%200.5%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20%20Preparing%3A%20select%20*%20from%20employee%20where%20id%20%3D%20%3F%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20Parameters%3A%201(Integer)%0A%20%20%20DEBUG%20-%20%3C%3D%3D%20%20%20%20%20%20Total%3A%201%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'chris%40gmail.com'%2C%20gender%3D'M'%7D%0A%20%20%20DEBUG%20-%20Closing%20JDBC%20Connection%20%5Bcom.mysql.cj.jdbc.ConnectionImpl%4027c6e487%5D%0A%20%20%20DEBUG%20-%20Returned%20connection%20667346055%20to%20pool.%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20flushCache%3D%22false%22%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%A2%9E%E5%88%A0%E6%94%B9%E5%90%8E%EF%BC%8C%E6%9F%A5%E8%AF%A2%E6%97%B6%E4%BC%9A%E4%BD%BF%E7%94%A8%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%0A%0A%20%20%20%60%60%60%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20%20Preparing%3A%20select%20*%20from%20employee%20where%20id%20%3D%20%3F%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20Parameters%3A%201(Integer)%0A%20%20%20DEBUG%20-%20%3C%3D%3D%20%20%20%20%20%20Total%3A%201%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'chris%40gmail.com'%2C%20gender%3D'M'%7D%0A%20%20%20DEBUG%20-%20Closing%20JDBC%20Connection%20%5Bcom.mysql.cj.jdbc.ConnectionImpl%4027c6e487%5D%0A%20%20%20DEBUG%20-%20Returned%20connection%20667346055%20to%20pool.%0A%20%20%20DEBUG%20-%20Opening%20JDBC%20Connection%0A%20%20%20DEBUG%20-%20Checked%20out%20connection%20667346055%20from%20pool.%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20%20Preparing%3A%20insert%20into%20employee%20(%20last_name%2C%20email%2C%20gender%2C%20department_id%20)%20values%20(%3F%2C%3F%2C%3F%2C%3F)%0A%20%20%20DEBUG%20-%20%3D%3D%3E%20Parameters%3A%20shawn(String)%2C%20shawn%40qq.com(String)%2C%20M(String)%2C%201(Integer)%0A%20%20%20DEBUG%20-%20%3C%3D%3D%20%20%20%20Updates%3A%201%0A%20%20%20DEBUG%20-%20Cache%20Hit%20Ratio%20%5Bcom.mybatis.dao.mapper.CacheMapper%5D%3A%200.5%0A%20%20%20Employee%7Bid%3D1%2C%20lastName%3D'Chris'%2C%20email%3D'chris%40gmail.com'%2C%20gender%3D'M'%7D%0A%20%20%20DEBUG%20-%20Closing%20JDBC%20Connection%20%5Bcom.mysql.cj.jdbc.ConnectionImpl%4027c6e487%5D%0A%20%20%20DEBUG%20-%20Returned%20connection%20667346055%20to%20pool.%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%206.4.5%20SqlSession.clearCache()%0A%0A%3E%20%E5%8F%AA%E6%B8%85%E7%A9%BA%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%EF%BC%8C%E4%B8%8D%E4%BC%9A%E6%B8%85%E7%A9%BA%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98%EF%BC%8C%E5%9B%A0%E4%B8%BAclearCache%E6%96%B9%E6%B3%95%E5%B1%9E%E4%BA%8Esqlsession%E7%BA%A7%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E4%B8%8D%E6%98%AFnamesapce%E7%BA%A7%E5%88%AB%E7%9A%84%E6%96%B9%E5%BC%8F%0A%0A%0A%0A%23%23%23%23%23%23%206.4.6%20localCacheScope%0A%0A%60%60%60xml%0A%3C!--%0A%E6%9C%AC%E5%9C%B0%E7%BC%93%E5%AD%98%E4%BD%9C%E7%94%A8%E5%9F%9F%2C%E9%BB%98%E8%AE%A4%20SESSION%0ASESSION%20%7C%20STATEMENT%0A1.SESSION%EF%BC%9A%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9Dsqlsession%E7%9A%84%E6%89%80%E6%9C%89%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E9%83%BD%E4%BC%9A%E8%A2%AB%E7%BC%93%E5%AD%98%0A2.STATEMENT%3A%E5%90%8C%E4%B8%80%E4%BC%9A%E8%AF%9D%E7%9A%84%E4%B8%A4%E6%AC%A1%E4%B8%8D%E5%90%8C%E7%9A%84sql%E9%97%B4%E4%B8%8D%E4%BC%9A%E5%85%B1%E4%BA%AB%E6%95%B0%E6%8D%AE%E5%8F%91%EF%BC%8C%E5%8D%B3%E5%8F%AF%E4%BB%A5%E7%A6%81%E7%94%A8%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98%0A--%3E%0A%3Csetting%20name%3D%22localCacheScope%22%20value%3D%22SESSION%22%2F%3E%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%23%206.5%20%E7%BC%93%E5%AD%98%E5%8E%9F%E7%90%86%0A!%5B9ed21fde2287ed083526d223af7b72b9.png%5D(en-resource%3A%2F%2Fdatabase%2F690%3A1)%0A%0A%23%23%23%23%23%206.6%20mybatis%E6%95%B4%E5%90%88ehcache%0A%0A%23%23%23%23%23%23%206.6.1%20ehcache%20%E6%BA%90%E7%A0%81%0A%0Ahttps%3A%2F%2Fgithub.com%2Fmybatis%2Fehcache-cache%0A%0A%23%23%23%23%23%23%206.6.2%20%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%0A%0Ahttp%3A%2F%2Fmybatis.org%2Fehcache-cache%2F%0A%0A%23%23%23%23%23%23%206.6.3%20%E9%9B%86%E6%88%90%E6%AD%A5%E9%AA%A4%0A%0A1.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.mybatis.caches%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Emybatis-ehcache%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3Cversion%3E%24%7Bmybatis.ehcache.version%7D%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%3Cexclusions%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cexclusion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.slf4j%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Eslf4j-api%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fexclusion%3E%0A%20%20%20%20%20%20%20%3C%2Fexclusions%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E5%BB%BAehcache.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%20%20%20%3Cehcache%20xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22%0A%20%20%20%20%20%20%20%20%20%20%20%20xsi%3AnoNamespaceSchemaLocation%3D%22..%2Fconfig%2Fehcache.xsd%22%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20%20%20%20%E5%B1%9E%E6%80%A7%E8%AF%B4%E6%98%8E%EF%BC%9A%0A%20%20%20%20%20%20%20%20%20%20%20diskStore%EF%BC%9A%E6%8C%87%E5%AE%9A%E6%95%B0%E6%8D%AE%E5%9C%A8%E7%A3%81%E7%9B%98%E4%B8%AD%E7%9A%84%E5%AD%98%E5%82%A8%E4%BD%8D%E7%BD%AE%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%20defaultCache%EF%BC%9A%E5%BD%93%E5%80%9F%E5%8A%A9CacheManager.add(%22demoCache%22)%E5%88%9B%E5%BB%BACache%E6%97%B6%EF%BC%8CEhCache%E4%BE%BF%E4%BC%9A%E9%87%87%E7%94%A8%3CdefalutCache%2F%3E%E6%8C%87%E5%AE%9A%E7%9A%84%E7%9A%84%E7%AE%A1%E7%90%86%E7%AD%96%E7%95%A5%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%E4%BB%A5%E4%B8%8B%E5%B1%9E%E6%80%A7%E6%98%AF%E5%BF%85%E9%A1%BB%E7%9A%84%EF%BC%9A%0A%20%20%20%20%20%20%20%20%20%20%20maxElementsInMemory%20-%20%E5%9C%A8%E5%86%85%E5%AD%98%E4%B8%AD%E7%BC%93%E5%AD%98%E7%9A%84element%E7%9A%84%E6%9C%80%E5%A4%A7%E6%95%B0%E7%9B%AE%0A%20%20%20%20%20%20%20%20%20%20%20maxElementsOnDisk%20-%20%E5%9C%A8%E7%A3%81%E7%9B%98%E4%B8%8A%E7%BC%93%E5%AD%98%E7%9A%84element%E7%9A%84%E6%9C%80%E5%A4%A7%E6%95%B0%E7%9B%AE%EF%BC%8C%E8%8B%A5%E6%98%AF0%E8%A1%A8%E7%A4%BA%E6%97%A0%E7%A9%B7%E5%A4%A7%0A%20%20%20%20%20%20%20%20%20%20%20eternal%20-%20%E8%AE%BE%E5%AE%9A%E7%BC%93%E5%AD%98%E7%9A%84elements%E6%98%AF%E5%90%A6%E6%B0%B8%E8%BF%9C%E4%B8%8D%E8%BF%87%E6%9C%9F%E3%80%82%E5%A6%82%E6%9E%9C%E4%B8%BAtrue%EF%BC%8C%E5%88%99%E7%BC%93%E5%AD%98%E7%9A%84%E6%95%B0%E6%8D%AE%E5%A7%8B%E7%BB%88%E6%9C%89%E6%95%88%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%BAfalse%E9%82%A3%E4%B9%88%E8%BF%98%E8%A6%81%E6%A0%B9%E6%8D%AEtimeToIdleSeconds%EF%BC%8CtimeToLiveSeconds%E5%88%A4%E6%96%AD%0A%20%20%20%20%20%20%20%20%20%20%20overflowToDisk%20-%20%E8%AE%BE%E5%AE%9A%E5%BD%93%E5%86%85%E5%AD%98%E7%BC%93%E5%AD%98%E6%BA%A2%E5%87%BA%E7%9A%84%E6%97%B6%E5%80%99%E6%98%AF%E5%90%A6%E5%B0%86%E8%BF%87%E6%9C%9F%E7%9A%84element%E7%BC%93%E5%AD%98%E5%88%B0%E7%A3%81%E7%9B%98%E4%B8%8A%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%E4%BB%A5%E4%B8%8B%E5%B1%9E%E6%80%A7%E6%98%AF%E5%8F%AF%E9%80%89%E7%9A%84%EF%BC%9A%0A%20%20%20%20%20%20%20%20%20%20%20timeToIdleSeconds%20-%20%E5%BD%93%E7%BC%93%E5%AD%98%E5%9C%A8EhCache%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%89%8D%E5%90%8E%E4%B8%A4%E6%AC%A1%E8%AE%BF%E9%97%AE%E7%9A%84%E6%97%B6%E9%97%B4%E8%B6%85%E8%BF%87timeToIdleSeconds%E7%9A%84%E5%B1%9E%E6%80%A7%E5%8F%96%E5%80%BC%E6%97%B6%EF%BC%8C%E8%BF%99%E4%BA%9B%E6%95%B0%E6%8D%AE%E4%BE%BF%E4%BC%9A%E5%88%A0%E9%99%A4%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%80%BC%E6%98%AF0%2C%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%8F%AF%E9%97%B2%E7%BD%AE%E6%97%B6%E9%97%B4%E6%97%A0%E7%A9%B7%E5%A4%A7%0A%20%20%20%20%20%20%20%20%20%20%20timeToLiveSeconds%20-%20%E7%BC%93%E5%AD%98element%E7%9A%84%E6%9C%89%E6%95%88%E7%94%9F%E5%91%BD%E6%9C%9F%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%98%AF0.%2C%E4%B9%9F%E5%B0%B1%E6%98%AFelement%E5%AD%98%E6%B4%BB%E6%97%B6%E9%97%B4%E6%97%A0%E7%A9%B7%E5%A4%A7%0A%20%20%20%20%20%20%20%20%20%20%20diskSpoolBufferSizeMB%20%E8%BF%99%E4%B8%AA%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AEDiskStore(%E7%A3%81%E7%9B%98%E7%BC%93%E5%AD%98)%E7%9A%84%E7%BC%93%E5%AD%98%E5%8C%BA%E5%A4%A7%E5%B0%8F.%E9%BB%98%E8%AE%A4%E6%98%AF30MB.%E6%AF%8F%E4%B8%AACache%E9%83%BD%E5%BA%94%E8%AF%A5%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E4%B8%80%E4%B8%AA%E7%BC%93%E5%86%B2%E5%8C%BA.%0A%20%20%20%20%20%20%20%20%20%20%20diskPersistent%20-%20%E5%9C%A8VM%E9%87%8D%E5%90%AF%E7%9A%84%E6%97%B6%E5%80%99%E6%98%AF%E5%90%A6%E5%90%AF%E7%94%A8%E7%A3%81%E7%9B%98%E4%BF%9D%E5%AD%98EhCache%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%98%AFfalse%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%20diskExpiryThreadIntervalSeconds%20-%20%E7%A3%81%E7%9B%98%E7%BC%93%E5%AD%98%E7%9A%84%E6%B8%85%E7%90%86%E7%BA%BF%E7%A8%8B%E8%BF%90%E8%A1%8C%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%98%AF120%E7%A7%92%E3%80%82%E6%AF%8F%E4%B8%AA120s%EF%BC%8C%E7%9B%B8%E5%BA%94%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%BC%9A%E8%BF%9B%E8%A1%8C%E4%B8%80%E6%AC%A1EhCache%E4%B8%AD%E6%95%B0%E6%8D%AE%E7%9A%84%E6%B8%85%E7%90%86%E5%B7%A5%E4%BD%9C%0A%20%20%20%20%20%20%20%20%20%20%20memoryStoreEvictionPolicy%20-%20%E5%BD%93%E5%86%85%E5%AD%98%E7%BC%93%E5%AD%98%E8%BE%BE%E5%88%B0%E6%9C%80%E5%A4%A7%EF%BC%8C%E6%9C%89%E6%96%B0%E7%9A%84element%E5%8A%A0%E5%85%A5%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%20%E7%A7%BB%E9%99%A4%E7%BC%93%E5%AD%98%E4%B8%ADelement%E7%9A%84%E7%AD%96%E7%95%A5%E3%80%82%E9%BB%98%E8%AE%A4%E6%98%AFLRU%EF%BC%88%E6%9C%80%E8%BF%91%E6%9C%80%E5%B0%91%E4%BD%BF%E7%94%A8%EF%BC%89%EF%BC%8C%E5%8F%AF%E9%80%89%E7%9A%84%E6%9C%89LFU%EF%BC%88%E6%9C%80%E4%B8%8D%E5%B8%B8%E4%BD%BF%E7%94%A8%EF%BC%89%E5%92%8CFIFO%EF%BC%88%E5%85%88%E8%BF%9B%E5%85%88%E5%87%BA%EF%BC%89%0A%20%20%20%20%20%20%20%20%20%20%20--%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%20%E7%A3%81%E7%9B%98%E4%BF%9D%E5%AD%98%E8%B7%AF%E5%BE%84%20--%3E%0A%20%20%20%20%20%20%20%3CdiskStore%20path%3D%22D%3A%5C%5Cehcache%22%2F%3E%0A%20%20%20%20%20%20%20%3CdefaultCache%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20maxElementsInMemory%3D%2210000%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20maxElementsOnDisk%3D%2210000000%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20eternal%3D%22false%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20overflowToDisk%3D%22true%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20timeToIdleSeconds%3D%22120%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20timeToLiveSeconds%3D%22120%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20diskExpiryThreadIntervalSeconds%3D%22120%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20memoryStoreEvictionPolicy%3D%22LRU%22%3E%0A%20%20%20%20%20%20%20%3C%2FdefaultCache%3E%0A%20%20%20%3C%2Fehcache%3E%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A3.%20%E5%9C%A8SQL%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%E4%B8%AD%E5%BC%95%E5%85%A5ehcache%E5%AE%9E%E7%8E%B0%E7%B1%BB%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%0A%20%20%20%20type%EF%BC%9A%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BC%93%E5%AD%98%E7%9A%84%E5%85%A8%E7%B1%BB%E5%90%8D%EF%BC%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BC%93%E5%AD%98%E9%9C%80%E8%A6%81%E5%AE%9E%E7%8E%B0Cache%E6%8E%A5%E5%8F%A3%0A%20%20%20%20--%3E%0A%20%20%20%3Ccache%20type%3D%22org.mybatis.caches.ehcache.EhcacheCache%22%2F%3E%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%206.7%20mybatis%E6%95%B4%E5%90%88Spring%0A%0A%23%23%23%23%23%23%206.7.1%20%E5%AE%98%E6%96%B9%E6%BA%90%E7%A0%81%0A%0Ahttps%3A%2F%2Fgithub.com%2Fmybatis%2Fspring%0A%0A%23%23%23%23%23%23%206.7.2%20%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%0A%0Ahttp%3A%2F%2Fmybatis.org%2Fspring%2F%0A%0A%23%23%23%23%23%23%206.7.3%20%E7%89%88%E6%9C%AC%E5%85%BC%E5%AE%B9%0A!%5B6d26b27072caac1a0cc7b8ec216a4868.png%5D(en-resource%3A%2F%2Fdatabase%2F689%3A1)%0A

Deque

创建时间:2022/12/15 22:24
更新时间:2023/1/4 17:37
作者:Chris
来源:https://blog.csdn.net/SeekN/article/details/114231727

  • 1. Deque
  • 2. 方法的区别
  • 3. Deque作为队列和堆栈的介绍
    • 3.1 Deque作为队列
    • 3.1 Deque作为堆栈
  • 4. LinkedList
  • 5. ArrayDeque
    • 5.1 ArrayDeque 作为栈使用
    • 5.2 ArrayDeque 作为队列使用

1. Deque

双端队列(Double Ended Queue),学名Deque
Java集合提供了接口Deque来实现一个双端队列,
它的功能是:
既可以添加到队尾,也可以添加到队首; 既可以从队首获取,又可以从队尾获取。

2. 方法的区别

  1. add()和offer()区别
    add()和offer()都是向队列中添加一个元素。一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,调用 add() 方法就会抛出一个 unchecked 异常,而调用 offer() 方法会返回 false。因此就可以在程序中进行有效的判断!
  2. poll()和remove()区别
    remove() 和 poll() 方法都是从队列中删除第一个元素。如果队列元素为空,调用remove() 的行为与 Collection 接口的版本相似会抛出异常,但是新的 poll() 方法在用空集合调用时只是返回 null。因此新的方法更适合容易出现异常条件的情况。
  3. element() 和 peek()区别
    element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null。

3. Deque作为队列和堆栈的介绍

3.1 Deque作为队列

Queue的数据结构是一个队列,即:FIFO(先进先出)。从队尾添加元素,从对头删除元素。Deque也有等效的方法作为一个FIFO队列,具体方法如下:

3.1 Deque作为堆栈

Deque(双端队列)也可以用作LIFO(后进先出)堆栈(也就是栈)。在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。堆栈方法完全等效于Deque 方法,如下表所示:

4. LinkedList

LinkedList 实现了 Deque 接口。
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
LinkedList 本质是双向链表,是可以当做队列或栈使用的。因为他有
push pop(栈操作方法)
addFirst、addLast、removeFirst、removeLast(队列操作方法)
add 与 offer 将 LinkedList 当作链表或队列来使用。
而 push 操作是将 LinkedList 当作栈来使用。
add(不带索引默认添加到链表的最后)与 offer一样都是添加操作,唯一的区别就是 offer 没有带索引参数的方法,并且如果队列满了 > add 会抛出异常,而 offer 不会。
LinkedList 的取出操作只有 pop 和 get。并且如果一个 LinkedList 中既有 add 或 offer 的添加,又有 push 的添加,那么 pop 操作会先取栈元素,再取队列元素。

5. ArrayDeque

ArrayDeque 是 Deque 的一个实现。
ArrayDeque 俗称数组双端队列,是一种允许我们从俩端进行存取操作的可扩容数组。
ArrayDeque 的底层是由一个数组来实现的,这个数组会在其塞满的时候,把容量扩大一倍。该数组初始化大小为16,它通过维护俩个指针:head、tail 实现了双端队列。

5.1 ArrayDeque 作为栈使用

jshell> Deque<Integer> stack = new ArrayDeque<>();
stack ==> []
jshell> stack.push(1) // 头插入
jshell> stack.push(2)
jshell> stack.push(3)
jshell> stack
stack ==> [3, 2, 1]
jshell> stack.pop() // 头删除
$14 ==> 3
jshell> stack.peek() // 检查头部元素
$22 ==> 3
当用户使用 push 方法向其中添加元素时,它会把 head 头指针向前移动一位。当从栈中弹出一个元素时,它会把 head 位置处的元素设置为 null (这样的话,此元素就可以被垃圾回收),并且把 head 指针向后移动一位。

5.2 ArrayDeque 作为队列使用

jshell> Deque<Integer> queue = new ArrayDeque<>();
queue ==> []
jshell> queue.offer(1)
$24 ==> true
jshell> queue.add(2)
$27 ==> true
jshell> queue
queue ==> [1, 2]
jshell> queue.peek()
$34 ==> 1
jshell> queue.poll()
$29 ==> 1
使用 offer 向队列中添加元素,tail 尾指针会向后移动一位。而当用户从队列中拉取一个元素时,它会把 head 位置处的元素设置为 null,并且把 head 指针向后移动一位。
%5Btoc%5D%0A%23%23%201.%20Deque%0A%0A%3E%20%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%EF%BC%88Double%20Ended%20Queue%EF%BC%89%EF%BC%8C%E5%AD%A6%E5%90%8DDeque%0A%0A%3E%20Java%E9%9B%86%E5%90%88%E6%8F%90%E4%BE%9B%E4%BA%86%E6%8E%A5%E5%8F%A3Deque%E6%9D%A5%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%EF%BC%8C%0A%3E%20%E5%AE%83%E7%9A%84%E5%8A%9F%E8%83%BD%E6%98%AF%EF%BC%9A%0A%60%E6%97%A2%E5%8F%AF%E4%BB%A5%E6%B7%BB%E5%8A%A0%E5%88%B0%E9%98%9F%E5%B0%BE%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%B7%BB%E5%8A%A0%E5%88%B0%E9%98%9F%E9%A6%96%EF%BC%9B%20%E6%97%A2%E5%8F%AF%E4%BB%A5%E4%BB%8E%E9%98%9F%E9%A6%96%E8%8E%B7%E5%8F%96%EF%BC%8C%E5%8F%88%E5%8F%AF%E4%BB%A5%E4%BB%8E%E9%98%9F%E5%B0%BE%E8%8E%B7%E5%8F%96%E3%80%82%60%0A%0A!%5Bf8a66bbf2635c163961c1d375ea447ed.png%5D(en-resource%3A%2F%2Fdatabase%2F1533%3A1)%0A%0A%23%23%202.%20%E6%96%B9%E6%B3%95%E7%9A%84%E5%8C%BA%E5%88%AB%0A1.%20add()%E5%92%8Coffer()%E5%8C%BA%E5%88%AB%0A%20%20%20%20%3E%20add()%E5%92%8Coffer()%E9%83%BD%E6%98%AF%E5%90%91%E9%98%9F%E5%88%97%E4%B8%AD%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E3%80%82%E4%B8%80%E4%BA%9B%E9%98%9F%E5%88%97%E6%9C%89%E5%A4%A7%E5%B0%8F%E9%99%90%E5%88%B6%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%A6%82%E6%9E%9C%E6%83%B3%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%BB%A1%E7%9A%84%E9%98%9F%E5%88%97%E4%B8%AD%E5%8A%A0%E5%85%A5%E4%B8%80%E4%B8%AA%E6%96%B0%E9%A1%B9%EF%BC%8C%E8%B0%83%E7%94%A8%20add()%20%E6%96%B9%E6%B3%95%E5%B0%B1%E4%BC%9A%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%20unchecked%20%E5%BC%82%E5%B8%B8%EF%BC%8C%E8%80%8C%E8%B0%83%E7%94%A8%20offer()%20%E6%96%B9%E6%B3%95%E4%BC%9A%E8%BF%94%E5%9B%9E%20false%E3%80%82%E5%9B%A0%E6%AD%A4%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%9C%A8%E7%A8%8B%E5%BA%8F%E4%B8%AD%E8%BF%9B%E8%A1%8C%E6%9C%89%E6%95%88%E7%9A%84%E5%88%A4%E6%96%AD%EF%BC%81%0A%0A2.%20poll()%E5%92%8Cremove()%E5%8C%BA%E5%88%AB%0A%20%20%20%20%3E%20remove()%20%E5%92%8C%20poll()%20%E6%96%B9%E6%B3%95%E9%83%BD%E6%98%AF%E4%BB%8E%E9%98%9F%E5%88%97%E4%B8%AD%E5%88%A0%E9%99%A4%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E3%80%82%E5%A6%82%E6%9E%9C%E9%98%9F%E5%88%97%E5%85%83%E7%B4%A0%E4%B8%BA%E7%A9%BA%EF%BC%8C%E8%B0%83%E7%94%A8remove()%20%E7%9A%84%E8%A1%8C%E4%B8%BA%E4%B8%8E%20Collection%20%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%89%88%E6%9C%AC%E7%9B%B8%E4%BC%BC%E4%BC%9A%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%EF%BC%8C%E4%BD%86%E6%98%AF%E6%96%B0%E7%9A%84%20poll()%20%E6%96%B9%E6%B3%95%E5%9C%A8%E7%94%A8%E7%A9%BA%E9%9B%86%E5%90%88%E8%B0%83%E7%94%A8%E6%97%B6%E5%8F%AA%E6%98%AF%E8%BF%94%E5%9B%9E%20null%E3%80%82%E5%9B%A0%E6%AD%A4%E6%96%B0%E7%9A%84%E6%96%B9%E6%B3%95%E6%9B%B4%E9%80%82%E5%90%88%E5%AE%B9%E6%98%93%E5%87%BA%E7%8E%B0%E5%BC%82%E5%B8%B8%E6%9D%A1%E4%BB%B6%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%0A%0A3.%20element()%20%E5%92%8C%20peek()%E5%8C%BA%E5%88%AB%0A%20%20%20%20%3E%20element()%20%E5%92%8C%20peek()%20%E7%94%A8%E4%BA%8E%E5%9C%A8%E9%98%9F%E5%88%97%E7%9A%84%E5%A4%B4%E9%83%A8%E6%9F%A5%E8%AF%A2%E5%85%83%E7%B4%A0%E3%80%82%E4%B8%8E%20remove()%20%E6%96%B9%E6%B3%95%E7%B1%BB%E4%BC%BC%EF%BC%8C%E5%9C%A8%E9%98%9F%E5%88%97%E4%B8%BA%E7%A9%BA%E6%97%B6%EF%BC%8C%20element()%20%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%E5%BC%82%E5%B8%B8%EF%BC%8C%E8%80%8C%20peek()%20%E8%BF%94%E5%9B%9E%20null%E3%80%82%0A%0A%23%23%203.%20Deque%E4%BD%9C%E4%B8%BA%E9%98%9F%E5%88%97%E5%92%8C%E5%A0%86%E6%A0%88%E7%9A%84%E4%BB%8B%E7%BB%8D%0A%0A%23%23%23%203.1%20Deque%E4%BD%9C%E4%B8%BA%E9%98%9F%E5%88%97%0A%3E%20Queue%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E6%98%AF%E4%B8%80%E4%B8%AA%E9%98%9F%E5%88%97%EF%BC%8C%E5%8D%B3%EF%BC%9AFIFO(%E5%85%88%E8%BF%9B%E5%85%88%E5%87%BA)%E3%80%82%E4%BB%8E%E9%98%9F%E5%B0%BE%E6%B7%BB%E5%8A%A0%E5%85%83%E7%B4%A0%EF%BC%8C%E4%BB%8E%E5%AF%B9%E5%A4%B4%E5%88%A0%E9%99%A4%E5%85%83%E7%B4%A0%E3%80%82Deque%E4%B9%9F%E6%9C%89%E7%AD%89%E6%95%88%E7%9A%84%E6%96%B9%E6%B3%95%E4%BD%9C%E4%B8%BA%E4%B8%80%E4%B8%AAFIFO%E9%98%9F%E5%88%97%EF%BC%8C%E5%85%B7%E4%BD%93%E6%96%B9%E6%B3%95%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A!%5Bcdb0c82cdd920a8a750c83c167ce32c5.png%5D(en-resource%3A%2F%2Fdatabase%2F1535%3A1)%0A%0A%0A%23%23%23%203.1%20Deque%E4%BD%9C%E4%B8%BA%E5%A0%86%E6%A0%88%0A%3E%20Deque(%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97)%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%94%A8%E4%BD%9CLIFO%EF%BC%88%E5%90%8E%E8%BF%9B%E5%85%88%E5%87%BA%EF%BC%89%E5%A0%86%E6%A0%88%EF%BC%88%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%A0%88%EF%BC%89%E3%80%82%E5%9C%A8%E5%B0%86%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%E7%94%A8%E4%BD%9C%E5%A0%86%E6%A0%88%E6%97%B6%EF%BC%8C%E5%85%83%E7%B4%A0%E8%A2%AB%E6%8E%A8%E5%85%A5%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%E7%9A%84%E5%BC%80%E5%A4%B4%E5%B9%B6%E4%BB%8E%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%E5%BC%80%E5%A4%B4%E5%BC%B9%E5%87%BA%E3%80%82%E5%A0%86%E6%A0%88%E6%96%B9%E6%B3%95%E5%AE%8C%E5%85%A8%E7%AD%89%E6%95%88%E4%BA%8EDeque%C2%A0%E6%96%B9%E6%B3%95%EF%BC%8C%E5%A6%82%E4%B8%8B%E8%A1%A8%E6%89%80%E7%A4%BA%EF%BC%9A%0A%0A!%5B4f7ec4e08c21ba970b43a20129f38119.png%5D(en-resource%3A%2F%2Fdatabase%2F1537%3A1)%0A%0A%0A%0A%23%23%204.%20LinkedList%0ALinkedList%20%E5%AE%9E%E7%8E%B0%E4%BA%86%20Deque%20%E6%8E%A5%E5%8F%A3%E3%80%82%0A%60%60%60java%0Apublic%20class%20LinkedList%3CE%3E%20extends%20AbstractSequentialList%3CE%3E%20implements%20List%3CE%3E%2C%20Deque%3CE%3E%2C%20Cloneable%2C%20java.io.Serializable%0A%60%60%60%0A%0A%3E%20LinkedList%20%E6%9C%AC%E8%B4%A8%E6%98%AF%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8%EF%BC%8C%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%BD%93%E5%81%9A%E9%98%9F%E5%88%97%E6%88%96%E6%A0%88%E4%BD%BF%E7%94%A8%E7%9A%84%E3%80%82%E5%9B%A0%E4%B8%BA%E4%BB%96%E6%9C%89%20%0A%3E%20push%20pop%EF%BC%88%E6%A0%88%E6%93%8D%E4%BD%9C%E6%96%B9%E6%B3%95%EF%BC%89%0A%3E%20addFirst%E3%80%81addLast%E3%80%81removeFirst%E3%80%81removeLast%EF%BC%88%E9%98%9F%E5%88%97%E6%93%8D%E4%BD%9C%E6%96%B9%E6%B3%95%EF%BC%89%0A%0A%3E%20add%20%E4%B8%8E%20offer%20%E5%B0%86%20LinkedList%20%E5%BD%93%E4%BD%9C%E9%93%BE%E8%A1%A8%E6%88%96%E9%98%9F%E5%88%97%E6%9D%A5%E4%BD%BF%E7%94%A8%E3%80%82%0A%3E%20%E8%80%8C%20push%20%E6%93%8D%E4%BD%9C%E6%98%AF%E5%B0%86%20LinkedList%20%E5%BD%93%E4%BD%9C%E6%A0%88%E6%9D%A5%E4%BD%BF%E7%94%A8%E3%80%82%0A%3E%20add%EF%BC%88%E4%B8%8D%E5%B8%A6%E7%B4%A2%E5%BC%95%E9%BB%98%E8%AE%A4%E6%B7%BB%E5%8A%A0%E5%88%B0%E9%93%BE%E8%A1%A8%E7%9A%84%E6%9C%80%E5%90%8E%EF%BC%89%E4%B8%8E%20offer%E4%B8%80%E6%A0%B7%E9%83%BD%E6%98%AF%E6%B7%BB%E5%8A%A0%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%94%AF%E4%B8%80%E7%9A%84%E5%8C%BA%E5%88%AB%E5%B0%B1%E6%98%AF%20offer%20%E6%B2%A1%E6%9C%89%E5%B8%A6%E7%B4%A2%E5%BC%95%E5%8F%82%E6%95%B0%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%A6%82%E6%9E%9C%E9%98%9F%E5%88%97%E6%BB%A1%E4%BA%86%20%3E%20add%20%E4%BC%9A%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%EF%BC%8C%E8%80%8C%20offer%20%E4%B8%8D%E4%BC%9A%E3%80%82%0A%0A%3E%20LinkedList%20%E7%9A%84%E5%8F%96%E5%87%BA%E6%93%8D%E4%BD%9C%E5%8F%AA%E6%9C%89%20pop%20%E5%92%8C%20get%E3%80%82%E5%B9%B6%E4%B8%94%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%20LinkedList%20%E4%B8%AD%E6%97%A2%E6%9C%89%20add%20%E6%88%96%20offer%20%E7%9A%84%E6%B7%BB%E5%8A%A0%EF%BC%8C%E5%8F%88%E6%9C%89%20push%20%E7%9A%84%E6%B7%BB%E5%8A%A0%EF%BC%8C%E9%82%A3%E4%B9%88%20pop%20%E6%93%8D%E4%BD%9C%E4%BC%9A%E5%85%88%E5%8F%96%E6%A0%88%E5%85%83%E7%B4%A0%EF%BC%8C%E5%86%8D%E5%8F%96%E9%98%9F%E5%88%97%E5%85%83%E7%B4%A0%E3%80%82%0A%0A%0A%23%23%205.%20ArrayDeque%0A%0A%3E%20ArrayDeque%20%E6%98%AF%20Deque%20%E7%9A%84%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%8E%B0%E3%80%82%0A%3E%20ArrayDeque%20%E4%BF%97%E7%A7%B0%E6%95%B0%E7%BB%84%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%EF%BC%8C%E6%98%AF%E4%B8%80%E7%A7%8D%E5%85%81%E8%AE%B8%E6%88%91%E4%BB%AC%E4%BB%8E%E4%BF%A9%E7%AB%AF%E8%BF%9B%E8%A1%8C%E5%AD%98%E5%8F%96%E6%93%8D%E4%BD%9C%E7%9A%84%E5%8F%AF%E6%89%A9%E5%AE%B9%E6%95%B0%E7%BB%84%E3%80%82%0A%3E%20ArrayDeque%20%E7%9A%84%E5%BA%95%E5%B1%82%E6%98%AF%E7%94%B1%E4%B8%80%E4%B8%AA%E6%95%B0%E7%BB%84%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%95%B0%E7%BB%84%E4%BC%9A%E5%9C%A8%E5%85%B6%E5%A1%9E%E6%BB%A1%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E6%8A%8A%E5%AE%B9%E9%87%8F%E6%89%A9%E5%A4%A7%E4%B8%80%E5%80%8D%E3%80%82%E8%AF%A5%E6%95%B0%E7%BB%84%E5%88%9D%E5%A7%8B%E5%8C%96%E5%A4%A7%E5%B0%8F%E4%B8%BA16%EF%BC%8C%E5%AE%83%E9%80%9A%E8%BF%87%E7%BB%B4%E6%8A%A4%E4%BF%A9%E4%B8%AA%E6%8C%87%E9%92%88%EF%BC%9Ahead%E3%80%81tail%20%E5%AE%9E%E7%8E%B0%E4%BA%86%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%E3%80%82%0A%0A%23%23%23%205.1%20ArrayDeque%20%E4%BD%9C%E4%B8%BA%E6%A0%88%E4%BD%BF%E7%94%A8%0A%60%60%60java%0Ajshell%3E%20Deque%3CInteger%3E%20stack%20%3D%20new%20ArrayDeque%3C%3E()%3B%0Astack%20%3D%3D%3E%20%5B%5D%0Ajshell%3E%20stack.push(1)%20%2F%2F%20%E5%A4%B4%E6%8F%92%E5%85%A5%0Ajshell%3E%20stack.push(2)%0Ajshell%3E%20stack.push(3)%0Ajshell%3E%20stack%0Astack%20%3D%3D%3E%20%5B3%2C%202%2C%201%5D%0Ajshell%3E%20stack.pop()%20%2F%2F%20%E5%A4%B4%E5%88%A0%E9%99%A4%0A%2414%20%3D%3D%3E%203%0Ajshell%3E%20stack.peek()%20%2F%2F%20%E6%A3%80%E6%9F%A5%E5%A4%B4%E9%83%A8%E5%85%83%E7%B4%A0%0A%2422%20%3D%3D%3E%203%0A%60%60%60%0A%3E%20%E5%BD%93%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%20push%20%E6%96%B9%E6%B3%95%E5%90%91%E5%85%B6%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%85%83%E7%B4%A0%E6%97%B6%EF%BC%8C%E5%AE%83%E4%BC%9A%E6%8A%8A%20head%20%E5%A4%B4%E6%8C%87%E9%92%88%E5%90%91%E5%89%8D%E7%A7%BB%E5%8A%A8%E4%B8%80%E4%BD%8D%E3%80%82%E5%BD%93%E4%BB%8E%E6%A0%88%E4%B8%AD%E5%BC%B9%E5%87%BA%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E6%97%B6%EF%BC%8C%E5%AE%83%E4%BC%9A%E6%8A%8A%20head%20%E4%BD%8D%E7%BD%AE%E5%A4%84%E7%9A%84%E5%85%83%E7%B4%A0%E8%AE%BE%E7%BD%AE%E4%B8%BA%20null%20(%E8%BF%99%E6%A0%B7%E7%9A%84%E8%AF%9D%EF%BC%8C%E6%AD%A4%E5%85%83%E7%B4%A0%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%A2%AB%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6)%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%8A%8A%20head%20%E6%8C%87%E9%92%88%E5%90%91%E5%90%8E%E7%A7%BB%E5%8A%A8%E4%B8%80%E4%BD%8D%E3%80%82%0A%0A%23%23%23%205.2%20ArrayDeque%20%E4%BD%9C%E4%B8%BA%E9%98%9F%E5%88%97%E4%BD%BF%E7%94%A8%0A%0A%60%60%60java%0Ajshell%3E%20Deque%3CInteger%3E%20queue%20%3D%20new%20ArrayDeque%3C%3E()%3B%0Aqueue%20%3D%3D%3E%20%5B%5D%0Ajshell%3E%20queue.offer(1)%0A%2424%20%3D%3D%3E%20true%0Ajshell%3E%20queue.add(2)%0A%2427%20%3D%3D%3E%20true%0Ajshell%3E%20queue%0Aqueue%20%3D%3D%3E%20%5B1%2C%202%5D%0Ajshell%3E%20queue.peek()%0A%2434%20%3D%3D%3E%201%0Ajshell%3E%20queue.poll()%0A%2429%20%3D%3D%3E%201%0A%60%60%60%0A%0A%3E%20%E4%BD%BF%E7%94%A8%20offer%20%E5%90%91%E9%98%9F%E5%88%97%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%85%83%E7%B4%A0%EF%BC%8Ctail%20%E5%B0%BE%E6%8C%87%E9%92%88%E4%BC%9A%E5%90%91%E5%90%8E%E7%A7%BB%E5%8A%A8%E4%B8%80%E4%BD%8D%E3%80%82%E8%80%8C%E5%BD%93%E7%94%A8%E6%88%B7%E4%BB%8E%E9%98%9F%E5%88%97%E4%B8%AD%E6%8B%89%E5%8F%96%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E6%97%B6%EF%BC%8C%E5%AE%83%E4%BC%9A%E6%8A%8A%20head%20%E4%BD%8D%E7%BD%AE%E5%A4%84%E7%9A%84%E5%85%83%E7%B4%A0%E8%AE%BE%E7%BD%AE%E4%B8%BA%20null%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%8A%8A%20head%20%E6%8C%87%E9%92%88%E5%90%91%E5%90%8E%E7%A7%BB%E5%8A%A8%E4%B8%80%E4%BD%8D%E3%80%82

mongodb

创建时间:2022/12/17 23:26
更新时间:2022/12/18 21:17
作者:Chris

官网地址

MongoDB 官网地址:https://www.mongodb.com/

MongoDB 官方英文文档:https://www.mongodb.com/docs/v5.0/

https://www.mongodb.com/docs/v5.0/reference/operator/query/#std-label-query-selectors

概述

MongoDB是由C++编写的基于分布式文件存储的数据库,旨在为web应用提供可扩展高性能的数据存储解决方案。

特点

  1. 数据结构非常宽松,类似Json的Bson格式,因此可以存储比较复杂的数据类型
  2. 查询语言非常强大,语法类似面向对象查询语言几乎可以实现类似关系型数据库单表查询的大部分功能
  3. 支持对数据建立索引
  4. 支持强事务,但只 支持单条事务不支持集合事务
  5. 支持多种语言,如RUBY, PYTHON, JAVA, C++, PHP等
  6. 支持复制,故障恢复和分片

应用场景

  1. 游戏应用: 使用云数据库MongoDB作为游戏服务器的数据库存储用户信息。 用户的游戏装备,积分等直接以内嵌文档的形式存储,方便进行查询和和更新。
  2. 物流应用: 用云数据库MongoDB存储订单信息,订单状态运送过程中不断更新,用云数据库MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来,方便快捷且一目了然。
  3. 社交应用:使用云数据库MongoDB存储用户发表的朋友圈信息,聊天记录,因为它提供了非常丰富的查询,并在写入和读取方面都相对较快
  4. 大数库应用:使用云数据库MongoDB随时进行数据提取分析,掌握行业动态。

相辅相成

关系型数据库和非关系型数据是相辅相成了

关系型数据库的强事务特性在非关系型数据是没有的,所以一些关键的核心业务数据还是要存储在关系型数据库中,比如用户的订单,帐户金额等

对于一些查询写入速度要求高但对事务要求不高的数据可以放到非关系型数据中去存储

历史

  1. 2009年2月,MongoDB首次在数据库领域亮相,打破了关系性数据库一统天下的局面

  2. 2010年8月,MongoDB1.6版本发布,最大的一个功能就是支持Sharding自动分片

  3. 2014年12月,MongoDB 3.0版本发布,由于收购了WiredTiger存储引擎,大幅提升了MongoDB写入性能

  4. 2015年12月,MongoDB3.2版本发布,开始支持关联查询,查以一次性查询多个MongoDB集合

  5. 2016年,MongoDB推出Atlas, 在AWS, Azure和GCP上的MongoDB托管服务

  6. 2017年10月,MongoDB成功在纳斯达克上市

  7. 2018年6月, MongoDB4.0版本发布推出ACID事务支持,成为第一个支持强事务的NOSQL数据库

安装

传统安装

下载

http://mongodb.com/try/download/community

bin目录

bin目录用来存放启动和关闭的脚本

install_compass 是来用安装compass工具
mongo是用来启动mongodb客户端
mongod是用来启动mongo服务的启动脚本
mongos路由脚本

启动mongodb

mkdir ../datas ../logs
./mongod --port=27017 --dbpath=../data --logpath=../logs/mongo.log
--port 指定服务监听商品号默认27017
--dbpath  指定mongodb数据存放目录,启动时目录必须存在
--logpath 指定mongodb日志文件存放位置
./mongod --help

docker安装

搜索mongo

进入 mongo


[root@master ~]# docker search mongo
[root@master ~]# docker pull mongo:5.0.5
[root@master ~]# docker run -d --name="mongo" -p 27017:27017 mongo:5.0.5
[root@master ~]# docker exec -it mongo /bin/bash
root@a4634a4f15c7:/# mongo	 ##启动mongdodb
> show dbs;
admin   0.000GB
config  0.000GB
local   0.000GB
> exit  ##只是退出当前mongodb的客户端
bye
root@a4634a4f15c7:/# 

核心概念

库-DataBase

mongodb中的库的概念类似于传统关系型数据库中库的概念,用来隔离不同应用的数据
mongodb中可以创建多个库,每一个库都有自己的集合和权限,不同的数据库放置在不同的文件中
默认数据库为test,数据存储在启动时指定的目录中。

集合-Collection

集合就是MongoDB中文档组,类似于关系型数据库中表的概念
集合存在于数据库中,一个库可以有多个集合,每个集合没有固定的结构,这意味着可以对集合插入不同格式和类型的数据,但通常情况下插入集合的数据都会有一定的关联性

文档-Document

文档是集合中的一条条记录,是一组键值key-value对即Bson. 
MongoDB的文档不需要设置相同的字段,并且相同的字段不需要相同的类型,这与关系型数据库有很大的区分,也是MongoDB非常突出的特点。

一个简单的文档如下:

{"site":"www.baidu.com", "name":"chris"}

关系总结

库操作

  1. 查询所有库

show dbs; | show databases;

db 查询当前所在的库

> show dbs;
admin   0.000GB
config  0.000GB
local   0.000GB
> db
test
> use chris
switched to db chris
> show dbs;
admin   0.000GB
config  0.000GB
local   0.000GB
> db.users.insert({'name':'chris'})
WriteResult({ "nInserted" : 1 })
> show dbs;
admin   0.000GB
chris   0.000GB
config  0.000GB
local   0.000GB

admin: 从权限的角度来看,这人是root 数据库,要是将一个用户添加到这个数据库,这个用户自动继承所有的数据库权限,一些特殊的服务器端命令也只能从这个数据库运行,比如列出所有数据库或者关闭服务器。

local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合

config: 当MongoDB分片设置时,config数据库在内部使用,用于保存分片相关的信息

当打开客户端时默认连接是test库

root@a4634a4f15c7:/# mongo
MongoDB shell version v5.0.5
  1. 创建数据库

当库存在时切换库,库不存在时创建并使用库,当库里面没有数据默念不显示这个库

use 数据库名称

  1. 删除当前库

    db.dropDatabase();

    > db
    chris
    > db.dropDatabase()
    { "ok" : 1 }
    > db
    chris
    

集合操作

  1. 查看库中的集合

    show collections | show tables

> show collections;
users
> show tables;
users
  1. 创建集合

    db.createCollection('集合名称',[options])

> db.createCollection('users');
{
        "ok" : 0,
        "errmsg" : "Collection already exists. NS: chris.users",
        "code" : 48,
        "codeName" : "NamespaceExists"
}
> db.createCollection('products');
{ "ok" : 1 }

options:

字段类型描述
capped布尔如果为ture必须指定size参数,则创建固定集合,固定集合是指有固定大小的集合,当达到最大值时,会自动覆盖掉最最早的文档。
size数值为固定集合指定一个最大值,即字节数
max数值指定固定集合中包含文档的最大数量

当集合不存在时,向集合中插入文档也会自动创建集合

  1. 删除集合

    db.集合名称.drop();

    db.orders.drop();
    

文档操作

https://docs.mongodb.com/manual/reference/method

https://www.mongodb.com/docs/v5.0/crud/

文档插入

单条

db.集合名称.insert({name:'chris',age:12})

多条
db.集合名称.insertMany(
	[<doc1>,<doc2>],
    {
    	writeConcern:1,//写入策略,默认为1即要求确认写操作,0是不要求
    	ordered:true //是否按顺序写入,默认是true
    }

db.users.insertMany([
	{name:'John', age:23},
	{name:'Rebecca', age:64}
]);
db.users.insert([
	{name:'Wonderful', age:32, birthday:'2010-12-31 21:23:21'},
	{name:'Dave', age:22, birthday:'2010-03-12 11:27:11'}
]);

-- 返回结果
BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 2,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})
脚本方式
for(let i=0; i<10; i++){
	db.users.insert({_id:i,name:'Chris_'+i,age:32+i});
}

在mongodb中每个文档都会有一个_id 作为文档的唯一标识,_id默认会自动生成,如果手动指定将使用手动指定的_id值。

查询

  1. 查询所有

    db.集合名称.find();

  2. 条件查询

    db.集合名称.find(query, projection).pretty();
    

    query: 可选,指定的查询条件

    projection:可选

    pretty():对超过一定长度的文档进行格式化显示

关系运算符
操作格式例子类比SQL
等于{key:value}db.users.find({name:'chris'}).pretty();where name='chris'
小于{key:{$lt:value}}db.users.find({age:{$lt:23}}).pretty();where age<23
小于等于{key:{$lte:value}}db.users.find({age:{$lte:23}}).pretty();where age<=23
大于{key:{$gt:value}}db.users.find({age:{$gt:23}}).pretty();where age>23
大于等于{key:{$gte:value}}db.users.find({age:{$gte:23}}).pretty();where age>=23
不等于{key:{$ne:value}}db.users.find({age:{$ne:23}}).pretty();where age!=23
逻辑运算符
  1. AND

    db.user.find({key1:value1,key2:value2...}).pretty()

db.users.find({name:'Chris', age:33}) --查询 name=Chris 并且 age=33 的文档
db.users.find({age:12, age:{$gt:33}}) --查询 age=12 并且 age>=33 的文档,相同字段出现多次时会以最后一次出现为准
  1. OR

    db.users.find({ $or:[ {key1:value1},{key2:value2}... ] });

    --查询 name=John 或者age>33 的文档
    db.users.find({
     $or:[
     	{name:'John'},{age:{$gt:33}}
     ]
    });
    
    --结果
    { "_id" : ObjectId("638df6d54d72a1b3fad46b35"), "name" : "John", "age" : 23 }
    { "_id" : ObjectId("638df6d54d72a1b3fad46b36"), "name" : "Rebecca", "age" : 64 }
    { "_id" : ObjectId("638df6fb4d72a1b3fad46b37"), "name" : "John", "age" : 23 }
    { "_id" : ObjectId("638df6fb4d72a1b3fad46b38"), "name" : "Rebecca", "age" : 64 }
    { "_id" : 9, "name" : "Chris_9", "age" : 41 }
    { "_id" : ObjectId("638e007512b0b293386f7153"), "age" : 45 }
    
  2. AND 和 OR联合

    db.users.find({key1:value, $or:[ {key1:value1},{key2:value2}... ] });

    --查询 age>33 的并且名字是 John或者Rebecca 的文档
    db.users.find({
     {age:{$gt:33},
     $or:[
     	{name:'John'},{name:'Rebecca'}
     ]
    });
    
    
in
> db.users.find({name:{$in:['John','Rebecca']}})
{ "_id" : ObjectId("638df6d54d72a1b3fad46b35"), "name" : "John", "age" : 31 }
{ "_id" : ObjectId("638df6d54d72a1b3fad46b36"), "name" : "Rebecca", "age" : 42 }
{ "_id" : ObjectId("638df6fb4d72a1b3fad46b37"), "name" : "John", "age" : 23 }
{ "_id" : ObjectId("638df6fb4d72a1b3fad46b38"), "name" : "Rebecca", "age" : 64 }
数组中的查询
--测试数据
db.users.insert([{ name : "Ethan", age : 33, birthday : "2020-03-12 11:27:11", likes : [ "read", "play toy", "running"]},
name : "Dave", age : 23, birthday : "2010-03-12 11:27:11", likes : [ "read", "girl", "running" ]]);

--查询likes字段有running的文档
db.users.find({likes:"running"})

{ "_id" : ObjectId("638df7174d72a1b3fad46b3a"), "name" : "Dave", "age" : 23, "birthday" : "2010-03-12 11:27:11", "likes" : [ "read", "girl", "running" ] }
{ "_id" : ObjectId("639d9d49b5512c2b26224951"), "name" : "Ethan", "age" : 33, "birthday" : "2020-03-12 11:27:11", "likes" : [ "read", "play toy", "running" ] }

--查询likes字段只有read和running的文档
db.users.find({likes:["read","running"]})

--查询likes字段长度为3的文档
db.users.find({likes:{$size:3}})
{ "_id" : ObjectId("638df7174d72a1b3fad46b3a"), "name" : "Dave", "age" : 23, "birthday" : "2010-03-12 11:27:11", "likes" : [ "read", "girl", "running" ] }
{ "_id" : ObjectId("639d9d49b5512c2b26224951"), "name" : "Ethan", "age" : 33, "birthday" : "2020-03-12 11:27:11", "likes" : [ "read", "play toy", "running" ] }
模糊查询

在mongodb中的模糊查询是通过正则表达式来实现的

--查询名字中包含Chris的文档
db.users.find({name:/Chris/})
--查询名字以Chris开头的文档
db.users.find({name:/^Chris/})
--查询爱好字段中有toy的文档
db.users.find({likes:/toy/})
{ "_id" : ObjectId("639d9d49b5512c2b26224951"), "name" : "Ethan", "age" : 33, "birthday" : "2020-03-12 11:27:11", "likes" : [ "read", "play toy", "running" ] }
排序

1 : 升序, -1 : 降序

--按名字降序,如果名字相同则按年龄升序排列
db.users.find().sort({name:-1,age:1})

{ "_id" : ObjectId("638df6d54d72a1b3fad46b36"), "name" : "Rebecca", "age" : 42 }
{ "_id" : ObjectId("638df6fb4d72a1b3fad46b38"), "name" : "Rebecca", "age" : 64 }
{ "_id" : ObjectId("638df6fb4d72a1b3fad46b37"), "name" : "John", "age" : 23 }
{ "_id" : ObjectId("638df6d54d72a1b3fad46b35"), "name" : "John", "age" : 31 }
{ "_id" : ObjectId("639d9d49b5512c2b26224951"), "name" : "Ethan", "age" : 33, "birthday" : "2020-03-12 11:27:11", "likes" : [ "read", "play toy", "running" ] }
{ "_id" : ObjectId("638df7174d72a1b3fad46b3a"), "name" : "Dave", "age" : 23, "birthday" : "2010-03-12 11:27:11", "likes" : [ "read", "girl", "running" ] }
{ "_id" : 9, "name" : "Chris_9", "age" : 41 }
{ "_id" : 8, "name" : "Chris_8", "age" : 40 }
{ "_id" : 7, "name" : "Chris_7", "age" : 39 }
{ "_id" : 6, "name" : "Chris_6", "age" : 38 }
{ "_id" : 5, "name" : "Chris_5", "age" : 37 }
{ "_id" : 4, "name" : "Chris_4", "age" : 36 }
{ "_id" : 3, "name" : "Chris_3", "age" : 35 }
{ "_id" : 2, "name" : "Chris_2", "age" : 34 }
{ "_id" : 1, "name" : "Chris_1", "age" : 33 }
{ "_id" : 0, "name" : "Chris_0", "age" : 31 }
分页查询

类似于sql中的 limit start, rows

start 从 0 开始 :

算法:(页数 -1)x 显示条数

db.users.find().sort({name:-1,age:1}).skip(start).limit(rows);

-- 第1页
db.users.find().sort({name:-1,age:1}).skip(0).limit(2);
-- 第2页
db.users.find().sort({name:-1,age:1}).skip(2).limit(2);
-- 第3页
db.users.find().sort({name:-1,age:1}).skip(4).limit(2);
-- 第4页
db.users.find().sort({name:-1,age:1}).skip(6).limit(2);
总条数

类似于 select count(*) from T where name='Rebecca'

db.users.count()
db.users.find({name:'Rebecca').count();
去重
db.users.distinct('age')
[ 23, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 64 ]
返回指定字段

1: 返回该字段

0:不返回该字段

注意 1 和 0 不能同时使用

--默认返回所有字段
> db.users.find({},{});

--查询结果只返回name字段, 注意 _id是默认都返回的,
> db.users.find({},{name:1});

{ "_id" : ObjectId("638df6d54d72a1b3fad46b35"), "name" : "John" }
{ "_id" : ObjectId("638df6d54d72a1b3fad46b36"), "name" : "Rebecca" }
{ "_id" : ObjectId("638df6fb4d72a1b3fad46b37"), "name" : "John" }
{ "_id" : ObjectId("638df6fb4d72a1b3fad46b38"), "name" : "Rebecca" }
{ "_id" : ObjectId("638df7174d72a1b3fad46b39") }
{ "_id" : ObjectId("638df7174d72a1b3fad46b3a"), "name" : "Dave" }
{ "_id" : 0, "name" : "Chris_0" }
{ "_id" : 1, "name" : "Chris_1" }
{ "_id" : 2, "name" : "Chris_2" }
{ "_id" : 3, "name" : "Chris_3" }
{ "_id" : 4, "name" : "Chris_4" }
{ "_id" : 5, "name" : "Chris_5" }
{ "_id" : 6, "name" : "Chris_6" }
{ "_id" : 7, "name" : "Chris_7" }
{ "_id" : 8, "name" : "Chris_8" }
{ "_id" : 9, "name" : "Chris_9" }
{ "_id" : ObjectId("638e007512b0b293386f7153") }
{ "_id" : ObjectId("639d9d49b5512c2b26224951"), "name" : "Ethan" }

--查询时除过_id字段外,其它字段的0和1不能同时使用
> db.users.find({},{_id:1,age:0})
{ "_id" : ObjectId("638df6d54d72a1b3fad46b35"), "name" : "John" }
{ "_id" : ObjectId("638df6d54d72a1b3fad46b36"), "name" : "Rebecca" }
> db.users.find({},{_id:1,age:1})
{ "_id" : ObjectId("638df6d54d72a1b3fad46b35"), "age" : 31 }
{ "_id" : ObjectId("638df6d54d72a1b3fad46b36"), "age" : 42 }
> db.users.find({},{name:1,age:0})
Error: error: {
        "ok" : 0,
        "errmsg" : "Cannot do exclusion on field age in inclusion projection",
        "code" : 31254,
        "codeName" : "Location31254"
}
$type

$type 操作符是基于Bson类型来检索集合中配置的数据类型并返回结果

当文档中同一个字段的类型不同时可以用$type进行过滤

https://www.mongodb.com/docs/v5.0/reference/operator/query/type/#mongodb-query-op.-type

Bson type

https://www.mongodb.com/docs/v5.0/reference/bson-types/

Mongodb中的数据类型如下

TypeNumberAliasNotes
Double1"double"mongodb中数字默认都是double类型
String2"string"
Object3"object"
Array4"array"
Binary data5"binData"
Undefined6"undefined"Deprecated.
ObjectId7"objectId"
Boolean8"bool"
Date9"date"
Null10"null"
Regular Expression11"regex"
DBPointer12"dbPointer"Deprecated.
JavaScript13"javascript"
Symbol14"symbol"Deprecated.
JavaScript code with scope15"javascriptWithScope"Deprecated in MongoDB 4.4.
32-bit integer16"int"
Timestamp17"timestamp"
64-bit integer18"long"
Decimal12819"decimal"
Min key-1"minKey"
Max key127"maxKey"

查询数据的具体的Bson type类型

ExampleResults
{ $type: "a" }"string"
{ $type: /a/ }"regex"
{ $type: 1 }"double"
{ $type: NumberLong(627) }"long"
{ $type: { x: 1 } }"object"
{ $type: [ [ 1, 2, 3 ] ] }"array"
--查询age类型为string的数据
> db.users.find({age:{$type:2}})
> db.users.find({age:{$type:'string'}})

{ "_id" : ObjectId("639d9d49b5512c2b26224951"), "name" : "Ethan", "age" : "3", "birthday" : "2020-03-12 11:27:11", "likes" : [ "read", "play toy", "running" ] }

--查询age类型为double的数据
> db.users.find({age:{$type:1}})
> db.users.find({age:{$type:'double'}})
{ "_id" : ObjectId("638df6d54d72a1b3fad46b35"), "name" : "John", "age" : 31 }
{ "_id" : ObjectId("638df6d54d72a1b3fad46b36"), "name" : "Rebecca", "age" : 42 }
{ "_id" : ObjectId("638df6fb4d72a1b3fad46b37"), "name" : "John", "age" : 23 }
{ "_id" : ObjectId("638df6fb4d72a1b3fad46b38"), "name" : "Rebecca", "age" : 64 }
{ "_id" : ObjectId("638df7174d72a1b3fad46b39"), "age" : 31 }
{ "_id" : ObjectId("638df7174d72a1b3fad46b3a"), "name" : "Dave", "age" : 23, "birthday" : "2010-03-12 11:27:11", "likes" : [ "read", "girl", "running" ] }
{ "_id" : 0, "name" : "Chris_0", "age" : 31 }
{ "_id" : 1, "name" : "Chris_1", "age" : 33 }
{ "_id" : 2, "name" : "Chris_2", "age" : 34 }
{ "_id" : 3, "name" : "Chris_3", "age" : 35 }
{ "_id" : 4, "name" : "Chris_4", "age" : 36 }
{ "_id" : 5, "name" : "Chris_5", "age" : 37 }
{ "_id" : 6, "name" : "Chris_6", "age" : 38 }
{ "_id" : 7, "name" : "Chris_7", "age" : 39 }
{ "_id" : 8, "name" : "Chris_8", "age" : 40 }
{ "_id" : 9, "name" : "Chris_9", "age" : 41 }
{ "_id" : ObjectId("638e007512b0b293386f7153"), "age" : 45 }

删除

db.集合名称.remove(
	<query>,
	{
		justOne:<boolean>,
		writeConcern:<document>
	}
)

query: 可选,删除文档的条件

justOne: 可选,如果设置成true或1,则只删除一个文档,如果不设置或使用默认值false,则删除所有匹配条件的文档。

writeConcern:可选,抛出异常的级别

db.users.remove({}) --删除所有文档
db.users.remove({name:'Chris'}) --删除 name=chris 的文档

> db.users.find()
{ "_id" : ObjectId("638c28e34ce7551b9100bb94"), "name" : "chris" }

db.users.remove({_id:ObjectId("638c28e34ce7551b9100bb94")});--删除自动生成的_id是638c28e34ce7551b9100bb94的文档

更新

db.集合名称.update(
	<query>,
	<update>,
	{
		upsert:<boolean>,
		multi:<boolean>,
		writeConcern:<document>
	}
)

query: 更新文档的查询条件,类型sql update中where后面的条件

update: update的对象和一些更新的操作符,如(,inc...)等,可以理解为sql update 中set中的内容

upsert: 可选,如查更新的文档不存在则插入一个,默认为false

multi: 可选,默认是false,只更新找到的第一条记录,如果设置成true则更新按条件查询出来的全部记录

writeConcern:可选,抛出异常的级别

--会先将 age=32 的删除掉,再插入一条 age=31 的新记录
db.users.update({age:32},{age:31}); 

--如果要保存原来的记录需要加 $set, 更新的时候也可以新增字段
db.users.update({age:32},{$set:{age:31}}); 
db.users.update({name:'John'},{$set:{age:41}});

--更新的时候也可以新增字段
db.users.update({age:22},{$set:{age:23, likes:['read','girl','running']}}); 
--结果 
{ "_id" : ObjectId("638df7174d72a1b3fad46b3a"), "name" : "Dave", "age" : 23, "birthday" : "2010-03-12 11:27:11", "likes" : [ "read", "girl", "running" ] }

--将 age=32 的所有记录的age更新为45,如果没有配置到的记录则插入一条新的记录
db.users.update({age:32},{$set:{age:45}},{multi:true,upsert:true}); 
--结果
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1,
        "nModified" : 0,
        "_id" : ObjectId("638e007512b0b293386f7153")
})

> db.users.find()
{ "_id" : ObjectId("638e007512b0b293386f7153"), "age" : 45 }

索引

https://www.mongodb.com/docs/v5.0/indexes/

索引是一种特殊的数据结构,存储在一个易于遍历读取的数据集合中,是对数据库中一列或多列值进行排序的一种结构。

如果没有索引,mongodb在读取数据时需要扫描集合中的每个文档,并选取那些符合查询条件的记录,这种扫描全集合的查询效率是非常低的,特别是在处理大量数据时。

mongodb在集合层面上定义了索引,并支持对mongodb集合中的任何字段或文档的子字段进行索引。

默认_id索引: 在创建集合时,mongodb会自动在_id字段上创建唯一索引. _id字段防止写入两个· _id 一样的文档,并且_id上的唯一索引是不能删除的

原理

创建索引

--key值为你要创建索引的字段, 1:指定按升序创建索引,-1:指定按降序来创建索引
db.users.createIndex(keys, options)

--在字段name和age字段上创建索引,在name字段升序创建索引,当age字段相同时,再在age字段按降序创建索引
db.users.createIndex({name:1, age:-1})

--创建索引时,指定索引名称为 name_age_inx,且为唯一索引
> db.users.createIndex({name:1, age:-1},{name:'name_age_inx', unique:true});
{
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}
> db.users.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "name" : 1,
                        "age" : -1
                },
                "name" : "name_age_inx",
                "unique" : true
        }
]

--创建索引时,指定索引名称为,且指定过期时间为10秒
> db.users.createIndex({name:1},{expireAfterSeconds:10})
{
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}

> db.users.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "name" : 1,
                        "age" : -1
                },
                "name" : "name_age_inx",
                "unique" : true
        },
        {
                "v" : 2,
                "key" : {
                        "name" : 1
                },
                "name" : "name_1",
                "expireAfterSeconds" : 10
        }
]
ParametertypeDesc
backgroundBooelean【可选】默认为false, 索引创建时会阻塞其它数据库操作,可以指定后台创建。
uniqueBoolean【可选】默认为false, 是否创建唯一索引
nameString【可选】索引名称, 如果不指定,默认按照字段名称+排序顺序生成一个名称
expireAftertSecondsInteger【可选】索引过期时间, 单位为秒,只能指定在单字段索引的过期时间
vindex version索引的版本号,默认取决于mongodb创建索引时运行的版本

查询集合中的索引

--查询一个集合里面的索引
> db.users.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]

--查询集合索引大小
db.users.totalIndexSize()
36864 --字节

删除集合中的索引

--删除集合中所有的索引
db.users.dropIndexes()

--删除集合中名称为'name_index'的索引
db.users.dropIndex('name_index')

复合索引

复合索引生效和mysql一样,适用左包含原则,

https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/#std-lable-sort-on-multiple-fields

if the sort keys correspond to the index keys or an index prefix, MongoDB can use the index to sort the query results. A prefix of a compound index is a subset that consists of one or more keys at the start of the index key pattern.

For example, create a compound index on the data collection:

db.data.createIndex( { a:1, b: 1, c: 1, d: 1 } )

Then, the following are prefixes for that index:

{ a: 1 }
{ a: 1, b: 1 }
{ a: 1, b: 1, c: 1 }
{ a: 1, b: 1, c: 1, d: 1 }

b a c d 也是可以走复合索引的同,

如果检索的字段包含复合索引的全部字段但是顺序不同,引擎会自动优化来使用复合索引

mongodb中排序也是可以使用索引的

The following query and sort operations use the index prefixes to sort the results. These operations do not need to sort the result set in memory.

ExampleIndex Prefix
db.data.find().sort( { a: 1 } ){ a: 1 }
db.data.find().sort( { a: -1 } ){ a: 1 }
db.data.find().sort( { a: 1, b: 1 } ){ a: 1, b: 1 }
db.data.find().sort( { a: -1, b: -1 } ){ a: 1, b: 1 }
db.data.find().sort( { a: 1, b: 1, c: 1 } ){ a: 1, b: 1, c: 1 }
db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } ){ a: 1, b: 1 }

聚合查询

mongodb中的聚合主要用于处理数据,如统计平均值,求和等,并返回计算后的数据结果,类似于mysql中的count()

%5Btoc%5D%0A%0A%23%23%20%E5%AE%98%E7%BD%91%E5%9C%B0%E5%9D%80%0A%0AMongoDB%20%E5%AE%98%E7%BD%91%E5%9C%B0%E5%9D%80%EF%BC%9Ahttps%3A%2F%2Fwww.mongodb.com%2F%0A%0AMongoDB%20%E5%AE%98%E6%96%B9%E8%8B%B1%E6%96%87%E6%96%87%E6%A1%A3%EF%BC%9Ahttps%3A%2F%2Fwww.mongodb.com%2Fdocs%2Fv5.0%2F%0A%0Ahttps%3A%2F%2Fwww.mongodb.com%2Fdocs%2Fv5.0%2Freference%2Foperator%2Fquery%2F%23std-label-query-selectors%0A%0A%0A%23%23%20%E6%A6%82%E8%BF%B0%0A%0A%60MongoDB%E6%98%AF%E7%94%B1C%2B%2B%E7%BC%96%E5%86%99%E7%9A%84%E5%9F%BA%E4%BA%8E%E5%88%86%E5%B8%83%E5%BC%8F%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%8C%E6%97%A8%E5%9C%A8%E4%B8%BAweb%E5%BA%94%E7%94%A8%E6%8F%90%E4%BE%9B%E5%8F%AF%E6%89%A9%E5%B1%95%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%E3%80%82%60%0A%0A%23%23%23%20%E7%89%B9%E7%82%B9%0A%0A1.%20%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E9%9D%9E%E5%B8%B8%E5%AE%BD%E6%9D%BE%EF%BC%8C%E7%B1%BB%E4%BC%BCJson%E7%9A%84Bson%E6%A0%BC%E5%BC%8F%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%8F%AF%E4%BB%A5%E5%AD%98%E5%82%A8%E6%AF%94%E8%BE%83%E5%A4%8D%E6%9D%82%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%0A2.%20%E6%9F%A5%E8%AF%A2%E8%AF%AD%E8%A8%80%E9%9D%9E%E5%B8%B8%E5%BC%BA%E5%A4%A7%EF%BC%8C%E8%AF%AD%E6%B3%95%E7%B1%BB%E4%BC%BC%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E6%9F%A5%E8%AF%A2%E8%AF%AD%E8%A8%80%E5%87%A0%E4%B9%8E%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%E7%B1%BB%E4%BC%BC%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8D%95%E8%A1%A8%E6%9F%A5%E8%AF%A2%E7%9A%84%E5%A4%A7%E9%83%A8%E5%88%86%E5%8A%9F%E8%83%BD%0A3.%20%E6%94%AF%E6%8C%81%E5%AF%B9%E6%95%B0%E6%8D%AE%E5%BB%BA%E7%AB%8B%E7%B4%A2%E5%BC%95%0A4.%20%E6%94%AF%E6%8C%81%E5%BC%BA%E4%BA%8B%E5%8A%A1%EF%BC%8C%E4%BD%86%E5%8F%AA%20%E6%94%AF%E6%8C%81%E5%8D%95%E6%9D%A1%E4%BA%8B%E5%8A%A1%E4%B8%8D%E6%94%AF%E6%8C%81%E9%9B%86%E5%90%88%E4%BA%8B%E5%8A%A1%0A5.%20%E6%94%AF%E6%8C%81%E5%A4%9A%E7%A7%8D%E8%AF%AD%E8%A8%80%EF%BC%8C%E5%A6%82RUBY%2C%20PYTHON%2C%20JAVA%2C%20C%2B%2B%2C%20PHP%E7%AD%89%0A6.%20%E6%94%AF%E6%8C%81%E5%A4%8D%E5%88%B6%EF%BC%8C%E6%95%85%E9%9A%9C%E6%81%A2%E5%A4%8D%E5%92%8C%E5%88%86%E7%89%87%0A%0A%0A%0A%23%23%23%20%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%0A%0A1.%20%E6%B8%B8%E6%88%8F%E5%BA%94%E7%94%A8%EF%BC%9A%20%E4%BD%BF%E7%94%A8%E4%BA%91%E6%95%B0%E6%8D%AE%E5%BA%93MongoDB%E4%BD%9C%E4%B8%BA%E6%B8%B8%E6%88%8F%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AD%98%E5%82%A8%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF%E3%80%82%20%E7%94%A8%E6%88%B7%E7%9A%84%E6%B8%B8%E6%88%8F%E8%A3%85%E5%A4%87%EF%BC%8C%E7%A7%AF%E5%88%86%E7%AD%89%E7%9B%B4%E6%8E%A5%E4%BB%A5%E5%86%85%E5%B5%8C%E6%96%87%E6%A1%A3%E7%9A%84%E5%BD%A2%E5%BC%8F%E5%AD%98%E5%82%A8%EF%BC%8C%E6%96%B9%E4%BE%BF%E8%BF%9B%E8%A1%8C%E6%9F%A5%E8%AF%A2%E5%92%8C%E5%92%8C%E6%9B%B4%E6%96%B0%E3%80%82%0A2.%20%E7%89%A9%E6%B5%81%E5%BA%94%E7%94%A8%EF%BC%9A%20%E7%94%A8%E4%BA%91%E6%95%B0%E6%8D%AE%E5%BA%93MongoDB%E5%AD%98%E5%82%A8%E8%AE%A2%E5%8D%95%E4%BF%A1%E6%81%AF%EF%BC%8C%E8%AE%A2%E5%8D%95%E7%8A%B6%E6%80%81%E8%BF%90%E9%80%81%E8%BF%87%E7%A8%8B%E4%B8%AD%E4%B8%8D%E6%96%AD%E6%9B%B4%E6%96%B0%EF%BC%8C%E7%94%A8%E4%BA%91%E6%95%B0%E6%8D%AE%E5%BA%93MongoDB%E5%86%85%E5%B5%8C%E6%95%B0%E7%BB%84%E7%9A%84%E5%BD%A2%E5%BC%8F%E6%9D%A5%E5%AD%98%E5%82%A8%EF%BC%8C%E4%B8%80%E6%AC%A1%E6%9F%A5%E8%AF%A2%E5%B0%B1%E8%83%BD%E5%B0%86%E8%AE%A2%E5%8D%95%E6%89%80%E6%9C%89%E7%9A%84%E5%8F%98%E6%9B%B4%E8%AF%BB%E5%8F%96%E5%87%BA%E6%9D%A5%EF%BC%8C%E6%96%B9%E4%BE%BF%E5%BF%AB%E6%8D%B7%E4%B8%94%E4%B8%80%E7%9B%AE%E4%BA%86%E7%84%B6%E3%80%82%0A3.%20%E7%A4%BE%E4%BA%A4%E5%BA%94%E7%94%A8%EF%BC%9A%E4%BD%BF%E7%94%A8%E4%BA%91%E6%95%B0%E6%8D%AE%E5%BA%93MongoDB%E5%AD%98%E5%82%A8%E7%94%A8%E6%88%B7%E5%8F%91%E8%A1%A8%E7%9A%84%E6%9C%8B%E5%8F%8B%E5%9C%88%E4%BF%A1%E6%81%AF%EF%BC%8C%E8%81%8A%E5%A4%A9%E8%AE%B0%E5%BD%95%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%AE%83%E6%8F%90%E4%BE%9B%E4%BA%86%E9%9D%9E%E5%B8%B8%E4%B8%B0%E5%AF%8C%E7%9A%84%E6%9F%A5%E8%AF%A2%EF%BC%8C%E5%B9%B6%E5%9C%A8%E5%86%99%E5%85%A5%E5%92%8C%E8%AF%BB%E5%8F%96%E6%96%B9%E9%9D%A2%E9%83%BD%E7%9B%B8%E5%AF%B9%E8%BE%83%E5%BF%AB%0A4.%20%E5%A4%A7%E6%95%B0%E5%BA%93%E5%BA%94%E7%94%A8%EF%BC%9A%E4%BD%BF%E7%94%A8%E4%BA%91%E6%95%B0%E6%8D%AE%E5%BA%93MongoDB%E9%9A%8F%E6%97%B6%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E6%8F%90%E5%8F%96%E5%88%86%E6%9E%90%EF%BC%8C%E6%8E%8C%E6%8F%A1%E8%A1%8C%E4%B8%9A%E5%8A%A8%E6%80%81%E3%80%82%0A%0A%0A%0A%23%23%23%20%E7%9B%B8%E8%BE%85%E7%9B%B8%E6%88%90%0A%0A%3E%20%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E5%92%8C%E9%9D%9E%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E6%98%AF%E7%9B%B8%E8%BE%85%E7%9B%B8%E6%88%90%E4%BA%86%0A%3E%0A%3E%20%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E5%BC%BA%E4%BA%8B%E5%8A%A1%E7%89%B9%E6%80%A7%E5%9C%A8%E9%9D%9E%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E6%98%AF%E6%B2%A1%E6%9C%89%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%80%E4%BA%9B%E5%85%B3%E9%94%AE%E7%9A%84%E6%A0%B8%E5%BF%83%E4%B8%9A%E5%8A%A1%E6%95%B0%E6%8D%AE%E8%BF%98%E6%98%AF%E8%A6%81%E5%AD%98%E5%82%A8%E5%9C%A8%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%EF%BC%8C%E6%AF%94%E5%A6%82%E7%94%A8%E6%88%B7%E7%9A%84%E8%AE%A2%E5%8D%95%EF%BC%8C%E5%B8%90%E6%88%B7%E9%87%91%E9%A2%9D%E7%AD%89%0A%3E%0A%3E%20%E5%AF%B9%E4%BA%8E%E4%B8%80%E4%BA%9B%E6%9F%A5%E8%AF%A2%E5%86%99%E5%85%A5%E9%80%9F%E5%BA%A6%E8%A6%81%E6%B1%82%E9%AB%98%E4%BD%86%E5%AF%B9%E4%BA%8B%E5%8A%A1%E8%A6%81%E6%B1%82%E4%B8%8D%E9%AB%98%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8F%AF%E4%BB%A5%E6%94%BE%E5%88%B0%E9%9D%9E%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%8E%BB%E5%AD%98%E5%82%A8%0A%0A%0A%0A%23%23%20%E5%8E%86%E5%8F%B2%0A%0A1.%202009%E5%B9%B42%E6%9C%88%EF%BC%8CMongoDB%E9%A6%96%E6%AC%A1%E5%9C%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E9%A2%86%E5%9F%9F%E4%BA%AE%E7%9B%B8%EF%BC%8C%E6%89%93%E7%A0%B4%E4%BA%86%E5%85%B3%E7%B3%BB%E6%80%A7%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%80%E7%BB%9F%E5%A4%A9%E4%B8%8B%E7%9A%84%E5%B1%80%E9%9D%A2%0A%0A2.%202010%E5%B9%B48%E6%9C%88%EF%BC%8CMongoDB1.6%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%EF%BC%8C%E6%9C%80%E5%A4%A7%E7%9A%84%E4%B8%80%E4%B8%AA%E5%8A%9F%E8%83%BD%E5%B0%B1%E6%98%AF%E6%94%AF%E6%8C%81Sharding%E8%87%AA%E5%8A%A8%E5%88%86%E7%89%87%0A%0A3.%202014%E5%B9%B412%E6%9C%88%EF%BC%8CMongoDB%203.0%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%EF%BC%8C%E7%94%B1%E4%BA%8E%E6%94%B6%E8%B4%AD%E4%BA%86WiredTiger%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E%EF%BC%8C%E5%A4%A7%E5%B9%85%E6%8F%90%E5%8D%87%E4%BA%86MongoDB%E5%86%99%E5%85%A5%E6%80%A7%E8%83%BD%0A%0A4.%202015%E5%B9%B412%E6%9C%88%EF%BC%8CMongoDB3.2%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%EF%BC%8C%E5%BC%80%E5%A7%8B%E6%94%AF%E6%8C%81%E5%85%B3%E8%81%94%E6%9F%A5%E8%AF%A2%EF%BC%8C%E6%9F%A5%E4%BB%A5%E4%B8%80%E6%AC%A1%E6%80%A7%E6%9F%A5%E8%AF%A2%E5%A4%9A%E4%B8%AAMongoDB%E9%9B%86%E5%90%88%0A%0A5.%202016%E5%B9%B4%EF%BC%8CMongoDB%E6%8E%A8%E5%87%BAAtlas%2C%20%E5%9C%A8AWS%2C%20Azure%E5%92%8CGCP%E4%B8%8A%E7%9A%84MongoDB%E6%89%98%E7%AE%A1%E6%9C%8D%E5%8A%A1%0A%0A6.%202017%E5%B9%B410%E6%9C%88%EF%BC%8CMongoDB%E6%88%90%E5%8A%9F%E5%9C%A8%E7%BA%B3%E6%96%AF%E8%BE%BE%E5%85%8B%E4%B8%8A%E5%B8%82%0A%0A7.%202018%E5%B9%B46%E6%9C%88%EF%BC%8C%20MongoDB4.0%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%8E%A8%E5%87%BAACID%E4%BA%8B%E5%8A%A1%E6%94%AF%E6%8C%81%EF%BC%8C%E6%88%90%E4%B8%BA%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%94%AF%E6%8C%81%E5%BC%BA%E4%BA%8B%E5%8A%A1%E7%9A%84NOSQL%E6%95%B0%E6%8D%AE%E5%BA%93%0A%0A%23%23%20%E5%AE%89%E8%A3%85%0A%0A%23%23%23%20%E4%BC%A0%E7%BB%9F%E5%AE%89%E8%A3%85%0A%0A%23%23%23%23%20%E4%B8%8B%E8%BD%BD%0A%0Ahttp%3A%2F%2Fmongodb.com%2Ftry%2Fdownload%2Fcommunity%0A%0A!%5B3e76cba4fdf9653451751d84b1a29995.png%5D(en-resource%3A%2F%2Fdatabase%2F1549%3A1)%0A%0A%0A%23%23%23%23%20bin%E7%9B%AE%E5%BD%95%0A%0Abin%E7%9B%AE%E5%BD%95%E7%94%A8%E6%9D%A5%E5%AD%98%E6%94%BE%E5%90%AF%E5%8A%A8%E5%92%8C%E5%85%B3%E9%97%AD%E7%9A%84%E8%84%9A%E6%9C%AC%0A%0A!%5B38fbdc029275114547b22d5e4aed0638.png%5D(en-resource%3A%2F%2Fdatabase%2F1551%3A1)%0A%0A%60%60%60shell%0Ainstall_compass%20%E6%98%AF%E6%9D%A5%E7%94%A8%E5%AE%89%E8%A3%85compass%E5%B7%A5%E5%85%B7%0Amongo%E6%98%AF%E7%94%A8%E6%9D%A5%E5%90%AF%E5%8A%A8mongodb%E5%AE%A2%E6%88%B7%E7%AB%AF%0Amongod%E6%98%AF%E7%94%A8%E6%9D%A5%E5%90%AF%E5%8A%A8mongo%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E8%84%9A%E6%9C%AC%0Amongos%E8%B7%AF%E7%94%B1%E8%84%9A%E6%9C%AC%0A%60%60%60%0A%0A%23%23%23%23%20%E5%90%AF%E5%8A%A8mongodb%0A%0A%60%60%60shell%0Amkdir%20..%2Fdatas%20..%2Flogs%0A%60%60%60%0A%0A%60%60%60%0A.%2Fmongod%20--port%3D27017%20--dbpath%3D..%2Fdata%20--logpath%3D..%2Flogs%2Fmongo.log%0A--port%20%E6%8C%87%E5%AE%9A%E6%9C%8D%E5%8A%A1%E7%9B%91%E5%90%AC%E5%95%86%E5%93%81%E5%8F%B7%E9%BB%98%E8%AE%A427017%0A--dbpath%20%20%E6%8C%87%E5%AE%9Amongodb%E6%95%B0%E6%8D%AE%E5%AD%98%E6%94%BE%E7%9B%AE%E5%BD%95%EF%BC%8C%E5%90%AF%E5%8A%A8%E6%97%B6%E7%9B%AE%E5%BD%95%E5%BF%85%E9%A1%BB%E5%AD%98%E5%9C%A8%0A--logpath%20%E6%8C%87%E5%AE%9Amongodb%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E5%AD%98%E6%94%BE%E4%BD%8D%E7%BD%AE%0A%60%60%60%0A%0A%60%60%60shell%0A.%2Fmongod%20--help%0A%60%60%60%0A%0A%23%23%23%20docker%E5%AE%89%E8%A3%85%0A%0A%E6%90%9C%E7%B4%A2mongo%0A%0A%E8%BF%9B%E5%85%A5%20mongo%0A!%5B72cd3b00b9a8e4b86487891a9cb5743c.png%5D(en-resource%3A%2F%2Fdatabase%2F1553%3A1)%0A!%5B4c55e351ecc65311a8681e595ac77e42.png%5D(en-resource%3A%2F%2Fdatabase%2F1555%3A1)%0A!%5B1b14449e40493ea39966c1f603997a2e.png%5D(en-resource%3A%2F%2Fdatabase%2F1557%3A1)%0A%0A%0A%60%60%60shell%0A%5Broot%40master%20~%5D%23%20docker%20search%20mongo%0A%5Broot%40master%20~%5D%23%20docker%20pull%20mongo%3A5.0.5%0A%5Broot%40master%20~%5D%23%20docker%20run%20-d%20--name%3D%22mongo%22%20-p%2027017%3A27017%20mongo%3A5.0.5%0A%5Broot%40master%20~%5D%23%20docker%20exec%20-it%20mongo%20%2Fbin%2Fbash%0A%60%60%60%0A%0A%60%60%60shell%0Aroot%40a4634a4f15c7%3A%2F%23%20mongo%09%20%23%23%E5%90%AF%E5%8A%A8mongdodb%0A%3E%20show%20dbs%3B%0Aadmin%20%20%200.000GB%0Aconfig%20%200.000GB%0Alocal%20%20%200.000GB%0A%3E%20exit%20%20%23%23%E5%8F%AA%E6%98%AF%E9%80%80%E5%87%BA%E5%BD%93%E5%89%8Dmongodb%E7%9A%84%E5%AE%A2%E6%88%B7%E7%AB%AF%0Abye%0Aroot%40a4634a4f15c7%3A%2F%23%20%0A%60%60%60%0A%0A%23%23%20%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%0A%0A%23%23%23%20%E5%BA%93-DataBase%0A%0A%60%60%60%0Amongodb%E4%B8%AD%E7%9A%84%E5%BA%93%E7%9A%84%E6%A6%82%E5%BF%B5%E7%B1%BB%E4%BC%BC%E4%BA%8E%E4%BC%A0%E7%BB%9F%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E5%BA%93%E7%9A%84%E6%A6%82%E5%BF%B5%EF%BC%8C%E7%94%A8%E6%9D%A5%E9%9A%94%E7%A6%BB%E4%B8%8D%E5%90%8C%E5%BA%94%E7%94%A8%E7%9A%84%E6%95%B0%E6%8D%AE%0Amongodb%E4%B8%AD%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E5%A4%9A%E4%B8%AA%E5%BA%93%EF%BC%8C%E6%AF%8F%E4%B8%80%E4%B8%AA%E5%BA%93%E9%83%BD%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E9%9B%86%E5%90%88%E5%92%8C%E6%9D%83%E9%99%90%EF%BC%8C%E4%B8%8D%E5%90%8C%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E6%94%BE%E7%BD%AE%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E6%96%87%E4%BB%B6%E4%B8%AD%0A%E9%BB%98%E8%AE%A4%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%BAtest%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8%E5%9C%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E6%8C%87%E5%AE%9A%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%AD%E3%80%82%0A%60%60%60%0A%0A%23%23%23%20%E9%9B%86%E5%90%88-Collection%0A%0A%60%60%60%0A%E9%9B%86%E5%90%88%E5%B0%B1%E6%98%AFMongoDB%E4%B8%AD%E6%96%87%E6%A1%A3%E7%BB%84%EF%BC%8C%E7%B1%BB%E4%BC%BC%E4%BA%8E%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E8%A1%A8%E7%9A%84%E6%A6%82%E5%BF%B5%0A%E9%9B%86%E5%90%88%E5%AD%98%E5%9C%A8%E4%BA%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%BA%93%E5%8F%AF%E4%BB%A5%E6%9C%89%E5%A4%9A%E4%B8%AA%E9%9B%86%E5%90%88%EF%BC%8C%E6%AF%8F%E4%B8%AA%E9%9B%86%E5%90%88%E6%B2%A1%E6%9C%89%E5%9B%BA%E5%AE%9A%E7%9A%84%E7%BB%93%E6%9E%84%EF%BC%8C%E8%BF%99%E6%84%8F%E5%91%B3%E7%9D%80%E5%8F%AF%E4%BB%A5%E5%AF%B9%E9%9B%86%E5%90%88%E6%8F%92%E5%85%A5%E4%B8%8D%E5%90%8C%E6%A0%BC%E5%BC%8F%E5%92%8C%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BD%86%E9%80%9A%E5%B8%B8%E6%83%85%E5%86%B5%E4%B8%8B%E6%8F%92%E5%85%A5%E9%9B%86%E5%90%88%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E4%BC%9A%E6%9C%89%E4%B8%80%E5%AE%9A%E7%9A%84%E5%85%B3%E8%81%94%E6%80%A7%0A%60%60%60%0A%0A%23%23%23%20%E6%96%87%E6%A1%A3-Document%0A%0A%60%60%60%0A%E6%96%87%E6%A1%A3%E6%98%AF%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E4%B8%80%E6%9D%A1%E6%9D%A1%E8%AE%B0%E5%BD%95%EF%BC%8C%E6%98%AF%E4%B8%80%E7%BB%84%E9%94%AE%E5%80%BCkey-value%E5%AF%B9%E5%8D%B3Bson.%20%0AMongoDB%E7%9A%84%E6%96%87%E6%A1%A3%E4%B8%8D%E9%9C%80%E8%A6%81%E8%AE%BE%E7%BD%AE%E7%9B%B8%E5%90%8C%E7%9A%84%E5%AD%97%E6%AE%B5%EF%BC%8C%E5%B9%B6%E4%B8%94%E7%9B%B8%E5%90%8C%E7%9A%84%E5%AD%97%E6%AE%B5%E4%B8%8D%E9%9C%80%E8%A6%81%E7%9B%B8%E5%90%8C%E7%9A%84%E7%B1%BB%E5%9E%8B%EF%BC%8C%E8%BF%99%E4%B8%8E%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E6%9C%89%E5%BE%88%E5%A4%A7%E7%9A%84%E5%8C%BA%E5%88%86%EF%BC%8C%E4%B9%9F%E6%98%AFMongoDB%E9%9D%9E%E5%B8%B8%E7%AA%81%E5%87%BA%E7%9A%84%E7%89%B9%E7%82%B9%E3%80%82%0A%60%60%60%0A%0A%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E6%96%87%E6%A1%A3%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%7B%22site%22%3A%22www.baidu.com%22%2C%20%22name%22%3A%22chris%22%7D%60%0A%0A%0A%23%23%23%20%20%E5%85%B3%E7%B3%BB%E6%80%BB%E7%BB%93%0A!%5Be85accbcc17e8b90bf69427c17ac90da.png%5D(en-resource%3A%2F%2Fdatabase%2F1559%3A1)%0A%0A%0A%23%23%23%20%E5%BA%93%E6%93%8D%E4%BD%9C%0A%0A1.%20%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%E5%BA%93%0A%0A%60show%20dbs%3B%20%7C%20show%20databases%3B%60%0A%0A%60db%60%20%E6%9F%A5%E8%AF%A2%E5%BD%93%E5%89%8D%E6%89%80%E5%9C%A8%E7%9A%84%E5%BA%93%0A%0A%60%60%60shell%0A%3E%20show%20dbs%3B%0Aadmin%20%20%200.000GB%0Aconfig%20%200.000GB%0Alocal%20%20%200.000GB%0A%3E%20db%0Atest%0A%3E%20use%20chris%0Aswitched%20to%20db%20chris%0A%3E%20show%20dbs%3B%0Aadmin%20%20%200.000GB%0Aconfig%20%200.000GB%0Alocal%20%20%200.000GB%0A%3E%20db.users.insert(%7B'name'%3A'chris'%7D)%0AWriteResult(%7B%20%22nInserted%22%20%3A%201%20%7D)%0A%3E%20show%20dbs%3B%0Aadmin%20%20%200.000GB%0Achris%20%20%200.000GB%0Aconfig%20%200.000GB%0Alocal%20%20%200.000GB%0A%60%60%60%0A%0A%60admin%60%3A%20%E4%BB%8E%E6%9D%83%E9%99%90%E7%9A%84%E8%A7%92%E5%BA%A6%E6%9D%A5%E7%9C%8B%EF%BC%8C%E8%BF%99%E4%BA%BA%E6%98%AF%60root%60%20%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%8C%E8%A6%81%E6%98%AF%E5%B0%86%E4%B8%80%E4%B8%AA%E7%94%A8%E6%88%B7%E6%B7%BB%E5%8A%A0%E5%88%B0%E8%BF%99%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%8C%E8%BF%99%E4%B8%AA%E7%94%A8%E6%88%B7%E8%87%AA%E5%8A%A8%E7%BB%A7%E6%89%BF%E6%89%80%E6%9C%89%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E6%9D%83%E9%99%90%EF%BC%8C%E4%B8%80%E4%BA%9B%E7%89%B9%E6%AE%8A%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E5%91%BD%E4%BB%A4%E4%B9%9F%E5%8F%AA%E8%83%BD%E4%BB%8E%E8%BF%99%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%90%E8%A1%8C%EF%BC%8C%E6%AF%94%E5%A6%82%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E6%95%B0%E6%8D%AE%E5%BA%93%E6%88%96%E8%80%85%E5%85%B3%E9%97%AD%E6%9C%8D%E5%8A%A1%E5%99%A8%E3%80%82%0A%0A%60local%60%3A%20%E8%BF%99%E4%B8%AA%E6%95%B0%E6%8D%AE%E6%B0%B8%E8%BF%9C%E4%B8%8D%E4%BC%9A%E8%A2%AB%E5%A4%8D%E5%88%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E5%AD%98%E5%82%A8%E9%99%90%E4%BA%8E%E6%9C%AC%E5%9C%B0%E5%8D%95%E5%8F%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E4%BB%BB%E6%84%8F%E9%9B%86%E5%90%88%0A%0A%60config%60%3A%20%E5%BD%93MongoDB%E5%88%86%E7%89%87%E8%AE%BE%E7%BD%AE%E6%97%B6%EF%BC%8Cconfig%E6%95%B0%E6%8D%AE%E5%BA%93%E5%9C%A8%E5%86%85%E9%83%A8%E4%BD%BF%E7%94%A8%EF%BC%8C%E7%94%A8%E4%BA%8E%E4%BF%9D%E5%AD%98%E5%88%86%E7%89%87%E7%9B%B8%E5%85%B3%E7%9A%84%E4%BF%A1%E6%81%AF%0A%0A%0A%0A%3E%20%E5%BD%93%E6%89%93%E5%BC%80%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%97%B6%E9%BB%98%E8%AE%A4%E8%BF%9E%E6%8E%A5%E6%98%AFtest%E5%BA%93%0A%0A%60%60%60shell%0Aroot%40a4634a4f15c7%3A%2F%23%20mongo%0AMongoDB%20shell%20version%20v5.0.5%0A%60%60%60%0A%0A2.%20%E5%88%9B%E5%BB%BA%E6%95%B0%E6%8D%AE%E5%BA%93%0A%0A%3E%20%20%E5%BD%93%E5%BA%93%E5%AD%98%E5%9C%A8%E6%97%B6%E5%88%87%E6%8D%A2%E5%BA%93%EF%BC%8C%E5%BA%93%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%97%B6%E5%88%9B%E5%BB%BA%E5%B9%B6%E4%BD%BF%E7%94%A8%E5%BA%93%EF%BC%8C%E5%BD%93%E5%BA%93%E9%87%8C%E9%9D%A2%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%E9%BB%98%E5%BF%B5%E4%B8%8D%E6%98%BE%E7%A4%BA%E8%BF%99%E4%B8%AA%E5%BA%93%0A%0A%60use%20%E6%95%B0%E6%8D%AE%E5%BA%93%E5%90%8D%E7%A7%B0%60%0A%0A3.%20%E5%88%A0%E9%99%A4%E5%BD%93%E5%89%8D%E5%BA%93%0A%0A%20%20%20%60db.dropDatabase()%3B%60%0A%0A%20%20%20%60%60%60shell%0A%20%20%20%3E%20db%0A%20%20%20chris%0A%20%20%20%3E%20db.dropDatabase()%0A%20%20%20%7B%20%22ok%22%20%3A%201%20%7D%0A%20%20%20%3E%20db%0A%20%20%20chris%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%20%E9%9B%86%E5%90%88%E6%93%8D%E4%BD%9C%0A%0A1.%20%E6%9F%A5%E7%9C%8B%E5%BA%93%E4%B8%AD%E7%9A%84%E9%9B%86%E5%90%88%0A%0A%20%20%20%60show%20collections%20%7C%20show%20tables%60%0A%0A%60%60%60shell%0A%3E%20show%20collections%3B%0Ausers%0A%3E%20show%20tables%3B%0Ausers%0A%60%60%60%0A%0A2.%20%E5%88%9B%E5%BB%BA%E9%9B%86%E5%90%88%0A%0A%20%20%20%60db.createCollection('%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0'%EF%BC%8C%5Boptions%5D)%60%0A%0A%60%60%60shell%0A%3E%20db.createCollection('users')%3B%0A%7B%0A%20%20%20%20%20%20%20%20%22ok%22%20%3A%200%2C%0A%20%20%20%20%20%20%20%20%22errmsg%22%20%3A%20%22Collection%20already%20exists.%20NS%3A%20chris.users%22%2C%0A%20%20%20%20%20%20%20%20%22code%22%20%3A%2048%2C%0A%20%20%20%20%20%20%20%20%22codeName%22%20%3A%20%22NamespaceExists%22%0A%7D%0A%3E%20db.createCollection('products')%3B%0A%7B%20%22ok%22%20%3A%201%20%7D%0A%60%60%60%0A%0A%3E%20options%3A%0A%0A%7C%20%E5%AD%97%E6%AE%B5%20%20%20%7C%20%E7%B1%BB%E5%9E%8B%20%7C%20%E6%8F%8F%E8%BF%B0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20------%20%7C%20----%20%7C%20------------------------------------------------------------%20%7C%0A%7C%20capped%20%7C%20%E5%B8%83%E5%B0%94%20%7C%20%E5%A6%82%E6%9E%9C%E4%B8%BAture%E5%BF%85%E9%A1%BB%E6%8C%87%E5%AE%9Asize%E5%8F%82%E6%95%B0%EF%BC%8C%E5%88%99%E5%88%9B%E5%BB%BA%E5%9B%BA%E5%AE%9A%E9%9B%86%E5%90%88%EF%BC%8C%E5%9B%BA%E5%AE%9A%E9%9B%86%E5%90%88%E6%98%AF%E6%8C%87%E6%9C%89%E5%9B%BA%E5%AE%9A%E5%A4%A7%E5%B0%8F%E7%9A%84%E9%9B%86%E5%90%88%EF%BC%8C%E5%BD%93%E8%BE%BE%E5%88%B0%E6%9C%80%E5%A4%A7%E5%80%BC%E6%97%B6%EF%BC%8C%E4%BC%9A%E8%87%AA%E5%8A%A8%E8%A6%86%E7%9B%96%E6%8E%89%E6%9C%80%E6%9C%80%E6%97%A9%E7%9A%84%E6%96%87%E6%A1%A3%E3%80%82%20%7C%0A%7C%20size%20%20%20%7C%20%E6%95%B0%E5%80%BC%20%7C%20%E4%B8%BA%E5%9B%BA%E5%AE%9A%E9%9B%86%E5%90%88%E6%8C%87%E5%AE%9A%E4%B8%80%E4%B8%AA%E6%9C%80%E5%A4%A7%E5%80%BC%EF%BC%8C%E5%8D%B3%E5%AD%97%E8%8A%82%E6%95%B0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20max%20%20%20%20%7C%20%E6%95%B0%E5%80%BC%20%7C%20%E6%8C%87%E5%AE%9A%E5%9B%BA%E5%AE%9A%E9%9B%86%E5%90%88%E4%B8%AD%E5%8C%85%E5%90%AB%E6%96%87%E6%A1%A3%E7%9A%84%E6%9C%80%E5%A4%A7%E6%95%B0%E9%87%8F%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%0A%3E%20%E5%BD%93%E9%9B%86%E5%90%88%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%97%B6%EF%BC%8C%E5%90%91%E9%9B%86%E5%90%88%E4%B8%AD%E6%8F%92%E5%85%A5%E6%96%87%E6%A1%A3%E4%B9%9F%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BA%E9%9B%86%E5%90%88%0A%0A3.%20%E5%88%A0%E9%99%A4%E9%9B%86%E5%90%88%0A%0A%20%20%20%60db.%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0.drop()%3B%60%0A%0A%20%20%20%60%60%60shell%0A%20%20%20db.orders.drop()%3B%0A%20%20%20%60%60%60%0A%0A%23%23%23%20%E6%96%87%E6%A1%A3%E6%93%8D%E4%BD%9C%0A%0A%0A%0Ahttps%3A%2F%2Fdocs.mongodb.com%2Fmanual%2Freference%2Fmethod%0A%0Ahttps%3A%2F%2Fwww.mongodb.com%2Fdocs%2Fv5.0%2Fcrud%2F%0A%0A%23%23%23%23%20%E6%96%87%E6%A1%A3%E6%8F%92%E5%85%A5%0A%0A%23%23%23%23%23%20%E5%8D%95%E6%9D%A1%0A%0A%60db.%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0.insert(%7Bname%3A'chris'%2Cage%3A12%7D)%60%0A%0A%23%23%23%23%23%20%E5%A4%9A%E6%9D%A1%0A%0A%60%60%60shell%0Adb.%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0.insertMany(%0A%09%5B%3Cdoc1%3E%2C%3Cdoc2%3E%5D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%09writeConcern%3A1%2C%2F%2F%E5%86%99%E5%85%A5%E7%AD%96%E7%95%A5%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA1%E5%8D%B3%E8%A6%81%E6%B1%82%E7%A1%AE%E8%AE%A4%E5%86%99%E6%93%8D%E4%BD%9C%EF%BC%8C0%E6%98%AF%E4%B8%8D%E8%A6%81%E6%B1%82%0A%20%20%20%20%09ordered%3Atrue%20%2F%2F%E6%98%AF%E5%90%A6%E6%8C%89%E9%A1%BA%E5%BA%8F%E5%86%99%E5%85%A5%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%98%AFtrue%0A%20%20%20%20%7D%0A%0Adb.users.insertMany(%5B%0A%09%7Bname%3A'John'%2C%20age%3A23%7D%2C%0A%09%7Bname%3A'Rebecca'%2C%20age%3A64%7D%0A%5D)%3B%0A%60%60%60%0A%0A%60%60%60shell%0Adb.users.insert(%5B%0A%09%7Bname%3A'Wonderful'%2C%20age%3A32%2C%20birthday%3A'2010-12-31%2021%3A23%3A21'%7D%2C%0A%09%7Bname%3A'Dave'%2C%20age%3A22%2C%20birthday%3A'2010-03-12%2011%3A27%3A11'%7D%0A%5D)%3B%0A%0A--%20%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%0ABulkWriteResult(%7B%0A%20%20%20%20%20%20%20%20%22writeErrors%22%20%3A%20%5B%20%5D%2C%0A%20%20%20%20%20%20%20%20%22writeConcernErrors%22%20%3A%20%5B%20%5D%2C%0A%20%20%20%20%20%20%20%20%22nInserted%22%20%3A%202%2C%0A%20%20%20%20%20%20%20%20%22nUpserted%22%20%3A%200%2C%0A%20%20%20%20%20%20%20%20%22nMatched%22%20%3A%200%2C%0A%20%20%20%20%20%20%20%20%22nModified%22%20%3A%200%2C%0A%20%20%20%20%20%20%20%20%22nRemoved%22%20%3A%200%2C%0A%20%20%20%20%20%20%20%20%22upserted%22%20%3A%20%5B%20%5D%0A%7D)%0A%60%60%60%0A%0A%23%23%23%23%23%20%E8%84%9A%E6%9C%AC%E6%96%B9%E5%BC%8F%0A%0A%60%60%60shell%0Afor(let%20i%3D0%3B%20i%3C10%3B%20i%2B%2B)%7B%0A%09db.users.insert(%7B_id%3Ai%2Cname%3A'Chris_'%2Bi%2Cage%3A32%2Bi%7D)%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E5%9C%A8mongodb%E4%B8%AD%E6%AF%8F%E4%B8%AA%E6%96%87%E6%A1%A3%E9%83%BD%E4%BC%9A%E6%9C%89%E4%B8%80%E4%B8%AA%60_id%60%20%E4%BD%9C%E4%B8%BA%E6%96%87%E6%A1%A3%E7%9A%84%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86%EF%BC%8C%60_id%60%E9%BB%98%E8%AE%A4%E4%BC%9A%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%89%8B%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%B0%86%E4%BD%BF%E7%94%A8%E6%89%8B%E5%8A%A8%E6%8C%87%E5%AE%9A%E7%9A%84%60_id%60%E5%80%BC%E3%80%82%0A%0A%23%23%23%23%20%E6%9F%A5%E8%AF%A2%0A%0A1.%20%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%0A%0A%20%20%20%60db.%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0.find()%3B%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%0A2.%20%E6%9D%A1%E4%BB%B6%E6%9F%A5%E8%AF%A2%0A%0A%20%20%20%60%60%60%0A%20%20%20db.%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0.find(query%2C%20projection).pretty()%3B%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20query%3A%20%60%E5%8F%AF%E9%80%89%60%EF%BC%8C%E6%8C%87%E5%AE%9A%E7%9A%84%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%0A%20%20%20%3E%0A%20%20%20%3E%20projection%EF%BC%9A%60%E5%8F%AF%E9%80%89%60%0A%20%20%20%3E%0A%20%20%20%3E%20pretty()%EF%BC%9A%E5%AF%B9%E8%B6%85%E8%BF%87%E4%B8%80%E5%AE%9A%E9%95%BF%E5%BA%A6%E7%9A%84%E6%96%87%E6%A1%A3%E8%BF%9B%E8%A1%8C%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%98%BE%E7%A4%BA%0A%20%20%20%3E%0A%0A%23%23%23%23%23%20%E5%85%B3%E7%B3%BB%E8%BF%90%E7%AE%97%E7%AC%A6%0A%0A%7C%20%E6%93%8D%E4%BD%9C%20%20%20%20%20%7C%20%E6%A0%BC%E5%BC%8F%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E4%BE%8B%E5%AD%90%20%7C%20%E7%B1%BB%E6%AF%94SQL%20%7C%0A%7C%20--------%20%7C%20------------------%20%7C%20----%20%7C%20-------%20%7C%0A%7C%20%E7%AD%89%E4%BA%8E%20%20%20%20%20%7C%20%7Bkey%3Avalue%7D%20%20%20%20%20%20%20%20%7C%20db.users.find(%7Bname%3A'chris'%7D).pretty()%3B%20%7C%20where%20name%3D'chris'%20%7C%0A%7C%20%E5%B0%8F%E4%BA%8E%20%20%20%20%20%7C%20%7Bkey%3A%7B%24lt%3Avalue%7D%7D%20%20%7Cdb.users.find(%7Bage%3A%7B%24lt%3A23%7D%7D).pretty()%3B%7C%20where%20age%3C23%20%7C%0A%7C%20%E5%B0%8F%E4%BA%8E%E7%AD%89%E4%BA%8E%20%7C%20%7Bkey%3A%7B%24lte%3Avalue%7D%7D%20%7C%20db.users.find(%7Bage%3A%7B%24lte%3A23%7D%7D).pretty()%3B%20%7C%20where%20age%3C%3D23%20%7C%0A%7C%20%E5%A4%A7%E4%BA%8E%20%20%20%20%20%7C%7Bkey%3A%7B%24gt%3Avalue%7D%7D%20%7Cdb.users.find(%7Bage%3A%7B%24gt%3A23%7D%7D).pretty()%3B%7C%20where%20age%3E23%20%7C%0A%7C%20%E5%A4%A7%E4%BA%8E%E7%AD%89%E4%BA%8E%20%7C%20%7Bkey%3A%7B%24gte%3Avalue%7D%7D%20%7Cdb.users.find(%7Bage%3A%7B%24gte%3A23%7D%7D).pretty()%3B%7C%20where%20age%3E%3D23%20%7C%0A%7C%20%E4%B8%8D%E7%AD%89%E4%BA%8E%20%20%20%7C%20%7Bkey%3A%7B%24ne%3Avalue%7D%7D%20%7C%20db.users.find(%7Bage%3A%7B%24ne%3A23%7D%7D).pretty()%3B%20%7C%20where%20age!%3D23%20%7C%0A%0A%0A%0A%23%23%23%23%23%20%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97%E7%AC%A6%0A%0A1.%20AND%0A%0A%20%20%20%60db.user.find(%7Bkey1%3Avalue1%2Ckey2%3Avalue2...%7D).pretty()%20%60%0A%0A%60%60%60shell%0Adb.users.find(%7Bname%3A'Chris'%2C%20age%3A33%7D)%20--%E6%9F%A5%E8%AF%A2%20name%3DChris%20%E5%B9%B6%E4%B8%94%20age%3D33%20%E7%9A%84%E6%96%87%E6%A1%A3%0Adb.users.find(%7Bage%3A12%2C%20age%3A%7B%24gt%3A33%7D%7D)%20--%E6%9F%A5%E8%AF%A2%20age%3D12%20%E5%B9%B6%E4%B8%94%20age%3E%3D33%20%E7%9A%84%E6%96%87%E6%A1%A3%2C%E7%9B%B8%E5%90%8C%E5%AD%97%E6%AE%B5%E5%87%BA%E7%8E%B0%E5%A4%9A%E6%AC%A1%E6%97%B6%E4%BC%9A%E4%BB%A5%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%87%BA%E7%8E%B0%E4%B8%BA%E5%87%86%0A%60%60%60%0A%0A2.%20OR%0A%0A%20%20%20%60db.users.find(%7B%0A%20%20%20%20%24or%3A%5B%0A%20%20%20%20%09%7Bkey1%3Avalue1%7D%2C%7Bkey2%3Avalue2%7D...%0A%20%20%20%20%5D%0A%20%20%20%7D)%3B%60%0A%0A%20%20%20%60%60%60json%0A%20%20%20--%E6%9F%A5%E8%AF%A2%20name%3DJohn%20%E6%88%96%E8%80%85age%3E33%20%E7%9A%84%E6%96%87%E6%A1%A3%0A%20%20%20db.users.find(%7B%0A%20%20%20%20%24or%3A%5B%0A%20%20%20%20%09%7Bname%3A'John'%7D%2C%7Bage%3A%7B%24gt%3A33%7D%7D%0A%20%20%20%20%5D%0A%20%20%20%7D)%3B%0A%20%20%20%0A%20%20%20--%E7%BB%93%E6%9E%9C%0A%20%20%20%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b35%22)%2C%20%22name%22%20%3A%20%22John%22%2C%20%22age%22%20%3A%2023%20%7D%0A%20%20%20%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b36%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%2C%20%22age%22%20%3A%2064%20%7D%0A%20%20%20%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b37%22)%2C%20%22name%22%20%3A%20%22John%22%2C%20%22age%22%20%3A%2023%20%7D%0A%20%20%20%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b38%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%2C%20%22age%22%20%3A%2064%20%7D%0A%20%20%20%7B%20%22_id%22%20%3A%209%2C%20%22name%22%20%3A%20%22Chris_9%22%2C%20%22age%22%20%3A%2041%20%7D%0A%20%20%20%7B%20%22_id%22%20%3A%20ObjectId(%22638e007512b0b293386f7153%22)%2C%20%22age%22%20%3A%2045%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%0A3.%20AND%20%E5%92%8C%20OR%E8%81%94%E5%90%88%0A%0A%20%20%20%60db.users.find(%7Bkey1%3Avalue%2C%0A%20%20%20%20%24or%3A%5B%0A%20%20%20%20%09%7Bkey1%3Avalue1%7D%2C%7Bkey2%3Avalue2%7D...%0A%20%20%20%20%5D%0A%20%20%20%7D)%3B%60%0A%0A%20%20%20%60%60%60json%0A%20%20%20--%E6%9F%A5%E8%AF%A2%20age%3E33%20%E7%9A%84%E5%B9%B6%E4%B8%94%E5%90%8D%E5%AD%97%E6%98%AF%20John%E6%88%96%E8%80%85Rebecca%20%E7%9A%84%E6%96%87%E6%A1%A3%0A%20%20%20db.users.find(%7B%0A%20%20%20%20%7Bage%3A%7B%24gt%3A33%7D%2C%0A%20%20%20%20%24or%3A%5B%0A%20%20%20%20%09%7Bname%3A'John'%7D%2C%7Bname%3A'Rebecca'%7D%0A%20%20%20%20%5D%0A%20%20%20%7D)%3B%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A%0A%23%23%23%23%23%20%20%20in%20%0A%0A%60%60%60json%0A%3E%20db.users.find(%7Bname%3A%7B%24in%3A%5B'John'%2C'Rebecca'%5D%7D%7D)%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b35%22)%2C%20%22name%22%20%3A%20%22John%22%2C%20%22age%22%20%3A%2031%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b36%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%2C%20%22age%22%20%3A%2042%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b37%22)%2C%20%22name%22%20%3A%20%22John%22%2C%20%22age%22%20%3A%2023%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b38%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%2C%20%22age%22%20%3A%2064%20%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E6%9F%A5%E8%AF%A2%0A%0A%60%60%60json%0A--%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%0Adb.users.insert(%5B%7B%20name%20%3A%20%22Ethan%22%2C%20age%20%3A%2033%2C%20birthday%20%3A%20%222020-03-12%2011%3A27%3A11%22%2C%20likes%20%3A%20%5B%20%22read%22%2C%20%22play%20toy%22%2C%20%22running%22%5D%7D%2C%0Aname%20%3A%20%22Dave%22%2C%20age%20%3A%2023%2C%20birthday%20%3A%20%222010-03-12%2011%3A27%3A11%22%2C%20likes%20%3A%20%5B%20%22read%22%2C%20%22girl%22%2C%20%22running%22%20%5D%5D)%3B%0A%0A--%E6%9F%A5%E8%AF%A2likes%E5%AD%97%E6%AE%B5%E6%9C%89running%E7%9A%84%E6%96%87%E6%A1%A3%0Adb.users.find(%7Blikes%3A%22running%22%7D)%0A%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df7174d72a1b3fad46b3a%22)%2C%20%22name%22%20%3A%20%22Dave%22%2C%20%22age%22%20%3A%2023%2C%20%22birthday%22%20%3A%20%222010-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22girl%22%2C%20%22running%22%20%5D%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22639d9d49b5512c2b26224951%22)%2C%20%22name%22%20%3A%20%22Ethan%22%2C%20%22age%22%20%3A%2033%2C%20%22birthday%22%20%3A%20%222020-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22play%20toy%22%2C%20%22running%22%20%5D%20%7D%0A%0A--%E6%9F%A5%E8%AF%A2likes%E5%AD%97%E6%AE%B5%E5%8F%AA%E6%9C%89read%E5%92%8Crunning%E7%9A%84%E6%96%87%E6%A1%A3%0Adb.users.find(%7Blikes%3A%5B%22read%22%2C%22running%22%5D%7D)%0A%0A--%E6%9F%A5%E8%AF%A2likes%E5%AD%97%E6%AE%B5%E9%95%BF%E5%BA%A6%E4%B8%BA3%E7%9A%84%E6%96%87%E6%A1%A3%0Adb.users.find(%7Blikes%3A%7B%24size%3A3%7D%7D)%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df7174d72a1b3fad46b3a%22)%2C%20%22name%22%20%3A%20%22Dave%22%2C%20%22age%22%20%3A%2023%2C%20%22birthday%22%20%3A%20%222010-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22girl%22%2C%20%22running%22%20%5D%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22639d9d49b5512c2b26224951%22)%2C%20%22name%22%20%3A%20%22Ethan%22%2C%20%22age%22%20%3A%2033%2C%20%22birthday%22%20%3A%20%222020-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22play%20toy%22%2C%20%22running%22%20%5D%20%7D%0A%60%60%60%0A%0A%23%23%23%23%23%20%20%20%E6%A8%A1%E7%B3%8A%E6%9F%A5%E8%AF%A2%0A%0A%3E%20%E5%9C%A8mongodb%E4%B8%AD%E7%9A%84%E6%A8%A1%E7%B3%8A%E6%9F%A5%E8%AF%A2%E6%98%AF%E9%80%9A%E8%BF%87%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9A%84%20%20%20%0A%0A%60%60%60json%0A--%E6%9F%A5%E8%AF%A2%E5%90%8D%E5%AD%97%E4%B8%AD%E5%8C%85%E5%90%ABChris%E7%9A%84%E6%96%87%E6%A1%A3%0Adb.users.find(%7Bname%3A%2FChris%2F%7D)%0A--%E6%9F%A5%E8%AF%A2%E5%90%8D%E5%AD%97%E4%BB%A5Chris%E5%BC%80%E5%A4%B4%E7%9A%84%E6%96%87%E6%A1%A3%0Adb.users.find(%7Bname%3A%2F%5EChris%2F%7D)%0A--%E6%9F%A5%E8%AF%A2%E7%88%B1%E5%A5%BD%E5%AD%97%E6%AE%B5%E4%B8%AD%E6%9C%89toy%E7%9A%84%E6%96%87%E6%A1%A3%0Adb.users.find(%7Blikes%3A%2Ftoy%2F%7D)%0A%7B%20%22_id%22%20%3A%20ObjectId(%22639d9d49b5512c2b26224951%22)%2C%20%22name%22%20%3A%20%22Ethan%22%2C%20%22age%22%20%3A%2033%2C%20%22birthday%22%20%3A%20%222020-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22play%20toy%22%2C%20%22running%22%20%5D%20%7D%0A%60%60%60%0A%0A%23%23%23%23%23%20%E6%8E%92%E5%BA%8F%0A%0A%3E%201%20%EF%BC%9A%20%E5%8D%87%E5%BA%8F%EF%BC%8C%20-1%20%EF%BC%9A%20%E9%99%8D%E5%BA%8F%0A%0A%60%60%60json%0A--%E6%8C%89%E5%90%8D%E5%AD%97%E9%99%8D%E5%BA%8F%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%90%8D%E5%AD%97%E7%9B%B8%E5%90%8C%E5%88%99%E6%8C%89%E5%B9%B4%E9%BE%84%E5%8D%87%E5%BA%8F%E6%8E%92%E5%88%97%0Adb.users.find().sort(%7Bname%3A-1%2Cage%3A1%7D)%0A%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b36%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%2C%20%22age%22%20%3A%2042%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b38%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%2C%20%22age%22%20%3A%2064%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b37%22)%2C%20%22name%22%20%3A%20%22John%22%2C%20%22age%22%20%3A%2023%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b35%22)%2C%20%22name%22%20%3A%20%22John%22%2C%20%22age%22%20%3A%2031%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22639d9d49b5512c2b26224951%22)%2C%20%22name%22%20%3A%20%22Ethan%22%2C%20%22age%22%20%3A%2033%2C%20%22birthday%22%20%3A%20%222020-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22play%20toy%22%2C%20%22running%22%20%5D%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df7174d72a1b3fad46b3a%22)%2C%20%22name%22%20%3A%20%22Dave%22%2C%20%22age%22%20%3A%2023%2C%20%22birthday%22%20%3A%20%222010-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22girl%22%2C%20%22running%22%20%5D%20%7D%0A%7B%20%22_id%22%20%3A%209%2C%20%22name%22%20%3A%20%22Chris_9%22%2C%20%22age%22%20%3A%2041%20%7D%0A%7B%20%22_id%22%20%3A%208%2C%20%22name%22%20%3A%20%22Chris_8%22%2C%20%22age%22%20%3A%2040%20%7D%0A%7B%20%22_id%22%20%3A%207%2C%20%22name%22%20%3A%20%22Chris_7%22%2C%20%22age%22%20%3A%2039%20%7D%0A%7B%20%22_id%22%20%3A%206%2C%20%22name%22%20%3A%20%22Chris_6%22%2C%20%22age%22%20%3A%2038%20%7D%0A%7B%20%22_id%22%20%3A%205%2C%20%22name%22%20%3A%20%22Chris_5%22%2C%20%22age%22%20%3A%2037%20%7D%0A%7B%20%22_id%22%20%3A%204%2C%20%22name%22%20%3A%20%22Chris_4%22%2C%20%22age%22%20%3A%2036%20%7D%0A%7B%20%22_id%22%20%3A%203%2C%20%22name%22%20%3A%20%22Chris_3%22%2C%20%22age%22%20%3A%2035%20%7D%0A%7B%20%22_id%22%20%3A%202%2C%20%22name%22%20%3A%20%22Chris_2%22%2C%20%22age%22%20%3A%2034%20%7D%0A%7B%20%22_id%22%20%3A%201%2C%20%22name%22%20%3A%20%22Chris_1%22%2C%20%22age%22%20%3A%2033%20%7D%0A%7B%20%22_id%22%20%3A%200%2C%20%22name%22%20%3A%20%22Chris_0%22%2C%20%22age%22%20%3A%2031%20%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20%E5%88%86%E9%A1%B5%E6%9F%A5%E8%AF%A2%0A%0A%3E%20%E7%B1%BB%E4%BC%BC%E4%BA%8Esql%E4%B8%AD%E7%9A%84%20%60limit%20start%2C%20rows%60%0A%3E%0A%3E%20start%20%E4%BB%8E%200%20%E5%BC%80%E5%A7%8B%20%3A%0A%3E%0A%3E%20%E7%AE%97%E6%B3%95%EF%BC%9A%EF%BC%88%E9%A1%B5%E6%95%B0%20-1%EF%BC%89x%20%E6%98%BE%E7%A4%BA%E6%9D%A1%E6%95%B0%0A%0A%60%60%60json%0Adb.users.find().sort(%7Bname%3A-1%2Cage%3A1%7D).skip(start).limit(rows)%3B%0A%0A--%20%E7%AC%AC1%E9%A1%B5%0Adb.users.find().sort(%7Bname%3A-1%2Cage%3A1%7D).skip(0).limit(2)%3B%0A--%20%E7%AC%AC2%E9%A1%B5%0Adb.users.find().sort(%7Bname%3A-1%2Cage%3A1%7D).skip(2).limit(2)%3B%0A--%20%E7%AC%AC3%E9%A1%B5%0Adb.users.find().sort(%7Bname%3A-1%2Cage%3A1%7D).skip(4).limit(2)%3B%0A--%20%E7%AC%AC4%E9%A1%B5%0Adb.users.find().sort(%7Bname%3A-1%2Cage%3A1%7D).skip(6).limit(2)%3B%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20%E6%80%BB%E6%9D%A1%E6%95%B0%0A%0A%3E%20%E7%B1%BB%E4%BC%BC%E4%BA%8E%20%60select%20count(*)%20from%20T%20where%20name%3D'Rebecca'%60%0A%0A%60%60%60json%0Adb.users.count()%0Adb.users.find(%7Bname%3A'Rebecca').count()%3B%0A%60%60%60%0A%0A%23%23%23%23%23%20%E5%8E%BB%E9%87%8D%0A%0A%60%60%60json%0Adb.users.distinct('age')%0A%5B%2023%2C%2031%2C%2033%2C%2034%2C%2035%2C%2036%2C%2037%2C%2038%2C%2039%2C%2040%2C%2041%2C%2042%2C%2045%2C%2064%20%5D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20%E8%BF%94%E5%9B%9E%E6%8C%87%E5%AE%9A%E5%AD%97%E6%AE%B5%0A%0A%3E%201%3A%20%E8%BF%94%E5%9B%9E%E8%AF%A5%E5%AD%97%E6%AE%B5%0A%3E%0A%3E%200%3A%E4%B8%8D%E8%BF%94%E5%9B%9E%E8%AF%A5%E5%AD%97%E6%AE%B5%0A%3E%0A%3E%20%E6%B3%A8%E6%84%8F%20%601%20%E5%92%8C%200%20%E4%B8%8D%E8%83%BD%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8%60%0A%0A%60%60%60json%0A--%E9%BB%98%E8%AE%A4%E8%BF%94%E5%9B%9E%E6%89%80%E6%9C%89%E5%AD%97%E6%AE%B5%0A%3E%20db.users.find(%7B%7D%2C%7B%7D)%3B%0A%0A--%E6%9F%A5%E8%AF%A2%E7%BB%93%E6%9E%9C%E5%8F%AA%E8%BF%94%E5%9B%9Ename%E5%AD%97%E6%AE%B5%EF%BC%8C%20%E6%B3%A8%E6%84%8F%20_id%E6%98%AF%E9%BB%98%E8%AE%A4%E9%83%BD%E8%BF%94%E5%9B%9E%E7%9A%84%EF%BC%8C%0A%3E%20db.users.find(%7B%7D%2C%7Bname%3A1%7D)%3B%0A%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b35%22)%2C%20%22name%22%20%3A%20%22John%22%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b36%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b37%22)%2C%20%22name%22%20%3A%20%22John%22%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b38%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df7174d72a1b3fad46b39%22)%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df7174d72a1b3fad46b3a%22)%2C%20%22name%22%20%3A%20%22Dave%22%20%7D%0A%7B%20%22_id%22%20%3A%200%2C%20%22name%22%20%3A%20%22Chris_0%22%20%7D%0A%7B%20%22_id%22%20%3A%201%2C%20%22name%22%20%3A%20%22Chris_1%22%20%7D%0A%7B%20%22_id%22%20%3A%202%2C%20%22name%22%20%3A%20%22Chris_2%22%20%7D%0A%7B%20%22_id%22%20%3A%203%2C%20%22name%22%20%3A%20%22Chris_3%22%20%7D%0A%7B%20%22_id%22%20%3A%204%2C%20%22name%22%20%3A%20%22Chris_4%22%20%7D%0A%7B%20%22_id%22%20%3A%205%2C%20%22name%22%20%3A%20%22Chris_5%22%20%7D%0A%7B%20%22_id%22%20%3A%206%2C%20%22name%22%20%3A%20%22Chris_6%22%20%7D%0A%7B%20%22_id%22%20%3A%207%2C%20%22name%22%20%3A%20%22Chris_7%22%20%7D%0A%7B%20%22_id%22%20%3A%208%2C%20%22name%22%20%3A%20%22Chris_8%22%20%7D%0A%7B%20%22_id%22%20%3A%209%2C%20%22name%22%20%3A%20%22Chris_9%22%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638e007512b0b293386f7153%22)%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22639d9d49b5512c2b26224951%22)%2C%20%22name%22%20%3A%20%22Ethan%22%20%7D%0A%0A--%E6%9F%A5%E8%AF%A2%E6%97%B6%E9%99%A4%E8%BF%87_id%E5%AD%97%E6%AE%B5%E5%A4%96%EF%BC%8C%E5%85%B6%E5%AE%83%E5%AD%97%E6%AE%B5%E7%9A%840%E5%92%8C1%E4%B8%8D%E8%83%BD%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8%0A%3E%20db.users.find(%7B%7D%2C%7B_id%3A1%2Cage%3A0%7D)%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b35%22)%2C%20%22name%22%20%3A%20%22John%22%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b36%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%20%7D%0A%3E%20db.users.find(%7B%7D%2C%7B_id%3A1%2Cage%3A1%7D)%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b35%22)%2C%20%22age%22%20%3A%2031%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b36%22)%2C%20%22age%22%20%3A%2042%20%7D%0A%3E%20db.users.find(%7B%7D%2C%7Bname%3A1%2Cage%3A0%7D)%0AError%3A%20error%3A%20%7B%0A%20%20%20%20%20%20%20%20%22ok%22%20%3A%200%2C%0A%20%20%20%20%20%20%20%20%22errmsg%22%20%3A%20%22Cannot%20do%20exclusion%20on%20field%20age%20in%20inclusion%20projection%22%2C%0A%20%20%20%20%20%20%20%20%22code%22%20%3A%2031254%2C%0A%20%20%20%20%20%20%20%20%22codeName%22%20%3A%20%22Location31254%22%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20%24type%0A%0A%3E%20%60%24type%60%20%E6%93%8D%E4%BD%9C%E7%AC%A6%E6%98%AF%E5%9F%BA%E4%BA%8EBson%E7%B1%BB%E5%9E%8B%E6%9D%A5%E6%A3%80%E7%B4%A2%E9%9B%86%E5%90%88%E4%B8%AD%E9%85%8D%E7%BD%AE%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%B9%B6%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%0A%3E%0A%3E%20%E5%BD%93%E6%96%87%E6%A1%A3%E4%B8%AD%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%E7%9A%84%E7%B1%BB%E5%9E%8B%E4%B8%8D%E5%90%8C%E6%97%B6%E5%8F%AF%E4%BB%A5%E7%94%A8%60%24type%60%E8%BF%9B%E8%A1%8C%E8%BF%87%E6%BB%A4%0A%3E%0A%3E%20https%3A%2F%2Fwww.mongodb.com%2Fdocs%2Fv5.0%2Freference%2Foperator%2Fquery%2Ftype%2F%23mongodb-query-op.-type%0A%3E%0A%3E%20Bson%20type%0A%3E%0A%3E%20https%3A%2F%2Fwww.mongodb.com%2Fdocs%2Fv5.0%2Freference%2Fbson-types%2F%0A%0AMongodb%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%A6%82%E4%B8%8B%0A%0A%7C%20Type%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Number%20%7C%20Alias%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Notes%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%3A-------------------------%20%7C%20%3A-----%20%7C%20%3A--------------------%20%7C%20%3A------------------------------%20%7C%0A%7C%20Double%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%201%20%20%20%20%20%20%7C%20%22double%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20mongodb%E4%B8%AD%E6%95%B0%E5%AD%97%E9%BB%98%E8%AE%A4%E9%83%BD%E6%98%AFdouble%E7%B1%BB%E5%9E%8B%20%7C%0A%7C%20String%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%202%20%20%20%20%20%20%7C%20%22string%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Object%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%203%20%20%20%20%20%20%7C%20%22object%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Array%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%204%20%20%20%20%20%20%7C%20%22array%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Binary%20data%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%205%20%20%20%20%20%20%7C%20%22binData%22%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Undefined%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%206%20%20%20%20%20%20%7C%20%22undefined%22%20%20%20%20%20%20%20%20%20%20%20%7C%20Deprecated.%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20ObjectId%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%207%20%20%20%20%20%20%7C%20%22objectId%22%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Boolean%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%208%20%20%20%20%20%20%7C%20%22bool%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Date%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%209%20%20%20%20%20%20%7C%20%22date%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Null%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%2010%20%20%20%20%20%7C%20%22null%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Regular%20Expression%20%20%20%20%20%20%20%20%20%7C%2011%20%20%20%20%20%7C%20%22regex%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20DBPointer%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%2012%20%20%20%20%20%7C%20%22dbPointer%22%20%20%20%20%20%20%20%20%20%20%20%7C%20Deprecated.%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20JavaScript%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%2013%20%20%20%20%20%7C%20%22javascript%22%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Symbol%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%2014%20%20%20%20%20%7C%20%22symbol%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Deprecated.%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20JavaScript%20code%20with%20scope%20%7C%2015%20%20%20%20%20%7C%20%22javascriptWithScope%22%20%7C%20Deprecated%20in%20MongoDB%204.4.%20%20%20%20%20%20%7C%0A%7C%2032-bit%20integer%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%2016%20%20%20%20%20%7C%20%22int%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Timestamp%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%2017%20%20%20%20%20%7C%20%22timestamp%22%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%2064-bit%20integer%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%2018%20%20%20%20%20%7C%20%22long%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Decimal128%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%2019%20%20%20%20%20%7C%20%22decimal%22%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Min%20key%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20-1%20%20%20%20%20%7C%20%22minKey%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Max%20key%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20127%20%20%20%20%7C%20%22maxKey%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%0A%0A%0A%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E7%9A%84%E5%85%B7%E4%BD%93%E7%9A%84Bson%20type%E7%B1%BB%E5%9E%8B%0A%0A%7C%20Example%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Results%20%20%20%20%7C%0A%7C%20%3A---------------------------%20%7C%20%3A---------%20%7C%0A%7C%20%60%7B%20%24type%3A%20%22a%22%20%7D%60%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%60%22string%22%60%20%7C%0A%7C%20%60%7B%20%24type%3A%20%2Fa%2F%20%7D%60%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%60%22regex%22%60%20%20%7C%0A%7C%20%60%7B%20%24type%3A%201%20%7D%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%60%22double%22%60%20%7C%0A%7C%20%60%7B%20%24type%3A%20NumberLong(627)%20%7D%60%20%7C%20%60%22long%22%60%20%20%20%7C%0A%7C%20%60%7B%20%24type%3A%20%7B%20x%3A%201%20%7D%20%7D%60%20%20%20%20%20%20%20%20%7C%20%60%22object%22%60%20%7C%0A%7C%20%60%7B%20%24type%3A%20%5B%20%5B%201%2C%202%2C%203%20%5D%20%5D%20%7D%60%20%7C%20%60%22array%22%60%20%20%7C%0A%0A%0A%0A%60%60%60json%0A--%E6%9F%A5%E8%AF%A2age%E7%B1%BB%E5%9E%8B%E4%B8%BAstring%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20db.users.find(%7Bage%3A%7B%24type%3A2%7D%7D)%0A%3E%20db.users.find(%7Bage%3A%7B%24type%3A'string'%7D%7D)%0A%0A%7B%20%22_id%22%20%3A%20ObjectId(%22639d9d49b5512c2b26224951%22)%2C%20%22name%22%20%3A%20%22Ethan%22%2C%20%22age%22%20%3A%20%223%22%2C%20%22birthday%22%20%3A%20%222020-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22play%20toy%22%2C%20%22running%22%20%5D%20%7D%0A%0A--%E6%9F%A5%E8%AF%A2age%E7%B1%BB%E5%9E%8B%E4%B8%BAdouble%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20db.users.find(%7Bage%3A%7B%24type%3A1%7D%7D)%0A%3E%20db.users.find(%7Bage%3A%7B%24type%3A'double'%7D%7D)%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b35%22)%2C%20%22name%22%20%3A%20%22John%22%2C%20%22age%22%20%3A%2031%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6d54d72a1b3fad46b36%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%2C%20%22age%22%20%3A%2042%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b37%22)%2C%20%22name%22%20%3A%20%22John%22%2C%20%22age%22%20%3A%2023%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df6fb4d72a1b3fad46b38%22)%2C%20%22name%22%20%3A%20%22Rebecca%22%2C%20%22age%22%20%3A%2064%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df7174d72a1b3fad46b39%22)%2C%20%22age%22%20%3A%2031%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df7174d72a1b3fad46b3a%22)%2C%20%22name%22%20%3A%20%22Dave%22%2C%20%22age%22%20%3A%2023%2C%20%22birthday%22%20%3A%20%222010-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22girl%22%2C%20%22running%22%20%5D%20%7D%0A%7B%20%22_id%22%20%3A%200%2C%20%22name%22%20%3A%20%22Chris_0%22%2C%20%22age%22%20%3A%2031%20%7D%0A%7B%20%22_id%22%20%3A%201%2C%20%22name%22%20%3A%20%22Chris_1%22%2C%20%22age%22%20%3A%2033%20%7D%0A%7B%20%22_id%22%20%3A%202%2C%20%22name%22%20%3A%20%22Chris_2%22%2C%20%22age%22%20%3A%2034%20%7D%0A%7B%20%22_id%22%20%3A%203%2C%20%22name%22%20%3A%20%22Chris_3%22%2C%20%22age%22%20%3A%2035%20%7D%0A%7B%20%22_id%22%20%3A%204%2C%20%22name%22%20%3A%20%22Chris_4%22%2C%20%22age%22%20%3A%2036%20%7D%0A%7B%20%22_id%22%20%3A%205%2C%20%22name%22%20%3A%20%22Chris_5%22%2C%20%22age%22%20%3A%2037%20%7D%0A%7B%20%22_id%22%20%3A%206%2C%20%22name%22%20%3A%20%22Chris_6%22%2C%20%22age%22%20%3A%2038%20%7D%0A%7B%20%22_id%22%20%3A%207%2C%20%22name%22%20%3A%20%22Chris_7%22%2C%20%22age%22%20%3A%2039%20%7D%0A%7B%20%22_id%22%20%3A%208%2C%20%22name%22%20%3A%20%22Chris_8%22%2C%20%22age%22%20%3A%2040%20%7D%0A%7B%20%22_id%22%20%3A%209%2C%20%22name%22%20%3A%20%22Chris_9%22%2C%20%22age%22%20%3A%2041%20%7D%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638e007512b0b293386f7153%22)%2C%20%22age%22%20%3A%2045%20%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%88%A0%E9%99%A4%0A%0A%60%60%60json%0Adb.%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0.remove(%0A%09%3Cquery%3E%2C%0A%09%7B%0A%09%09justOne%3A%3Cboolean%3E%2C%0A%09%09writeConcern%3A%3Cdocument%3E%0A%09%7D%0A)%0A%60%60%60%0A%0A%3E%20query%EF%BC%9A%20%60%E5%8F%AF%E9%80%89%60%EF%BC%8C%E5%88%A0%E9%99%A4%E6%96%87%E6%A1%A3%E7%9A%84%E6%9D%A1%E4%BB%B6%0A%3E%0A%3E%20justOne%EF%BC%9A%20%60%E5%8F%AF%E9%80%89%60%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AE%BE%E7%BD%AE%E6%88%90true%E6%88%961%EF%BC%8C%E5%88%99%E5%8F%AA%E5%88%A0%E9%99%A4%E4%B8%80%E4%B8%AA%E6%96%87%E6%A1%A3%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E8%AE%BE%E7%BD%AE%E6%88%96%E4%BD%BF%E7%94%A8%E9%BB%98%E8%AE%A4%E5%80%BC%60false%60%EF%BC%8C%E5%88%99%E5%88%A0%E9%99%A4%E6%89%80%E6%9C%89%E5%8C%B9%E9%85%8D%E6%9D%A1%E4%BB%B6%E7%9A%84%E6%96%87%E6%A1%A3%E3%80%82%0A%3E%0A%3E%20writeConcern%EF%BC%9A%60%E5%8F%AF%E9%80%89%60%EF%BC%8C%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E7%9A%84%E7%BA%A7%E5%88%AB%0A%0A%60%60%60json%0Adb.users.remove(%7B%7D)%20--%E5%88%A0%E9%99%A4%E6%89%80%E6%9C%89%E6%96%87%E6%A1%A3%0Adb.users.remove(%7Bname%3A'Chris'%7D)%20--%E5%88%A0%E9%99%A4%20name%3Dchris%20%E7%9A%84%E6%96%87%E6%A1%A3%0A%0A%3E%20db.users.find()%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638c28e34ce7551b9100bb94%22)%2C%20%22name%22%20%3A%20%22chris%22%20%7D%0A%0Adb.users.remove(%7B_id%3AObjectId(%22638c28e34ce7551b9100bb94%22)%7D)%3B--%E5%88%A0%E9%99%A4%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%E7%9A%84_id%E6%98%AF638c28e34ce7551b9100bb94%E7%9A%84%E6%96%87%E6%A1%A3%0A%60%60%60%0A%0A%23%23%23%23%20%E6%9B%B4%E6%96%B0%0A%0A%60%60%60json%0Adb.%E9%9B%86%E5%90%88%E5%90%8D%E7%A7%B0.update(%0A%09%3Cquery%3E%2C%0A%09%3Cupdate%3E%2C%0A%09%7B%0A%09%09upsert%3A%3Cboolean%3E%2C%0A%09%09multi%3A%3Cboolean%3E%2C%0A%09%09writeConcern%3A%3Cdocument%3E%0A%09%7D%0A)%0A%60%60%60%0A%0A%3E%20%20query%3A%20%E6%9B%B4%E6%96%B0%E6%96%87%E6%A1%A3%E7%9A%84%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%EF%BC%8C%E7%B1%BB%E5%9E%8Bsql%20update%E4%B8%ADwhere%E5%90%8E%E9%9D%A2%E7%9A%84%E6%9D%A1%E4%BB%B6%0A%3E%0A%3E%20%20update%3A%20update%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%92%8C%E4%B8%80%E4%BA%9B%E6%9B%B4%E6%96%B0%E7%9A%84%E6%93%8D%E4%BD%9C%E7%AC%A6%EF%BC%8C%E5%A6%82(%24%2C%24inc...)%E7%AD%89%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BAsql%20update%20%E4%B8%ADset%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%0A%3E%0A%3E%20upsert%3A%20%60%E5%8F%AF%E9%80%89%60%EF%BC%8C%E5%A6%82%E6%9F%A5%E6%9B%B4%E6%96%B0%E7%9A%84%E6%96%87%E6%A1%A3%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%88%99%E6%8F%92%E5%85%A5%E4%B8%80%E4%B8%AA%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA%60false%60%0A%3E%0A%3E%20multi%3A%20%60%E5%8F%AF%E9%80%89%60%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%98%AF%60false%60%EF%BC%8C%E5%8F%AA%E6%9B%B4%E6%96%B0%E6%89%BE%E5%88%B0%E7%9A%84%E7%AC%AC%E4%B8%80%E6%9D%A1%E8%AE%B0%E5%BD%95%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AE%BE%E7%BD%AE%E6%88%90true%E5%88%99%E6%9B%B4%E6%96%B0%E6%8C%89%E6%9D%A1%E4%BB%B6%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%E7%9A%84%E5%85%A8%E9%83%A8%E8%AE%B0%E5%BD%95%0A%3E%0A%3E%20writeConcern%EF%BC%9A%60%E5%8F%AF%E9%80%89%60%EF%BC%8C%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E7%9A%84%E7%BA%A7%E5%88%AB%0A%0A%60%60%60json%0A--%E4%BC%9A%E5%85%88%E5%B0%86%20age%3D32%20%E7%9A%84%E5%88%A0%E9%99%A4%E6%8E%89%EF%BC%8C%E5%86%8D%E6%8F%92%E5%85%A5%E4%B8%80%E6%9D%A1%20age%3D31%20%E7%9A%84%E6%96%B0%E8%AE%B0%E5%BD%95%0Adb.users.update(%7Bage%3A32%7D%2C%7Bage%3A31%7D)%3B%20%0A%0A--%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BF%9D%E5%AD%98%E5%8E%9F%E6%9D%A5%E7%9A%84%E8%AE%B0%E5%BD%95%E9%9C%80%E8%A6%81%E5%8A%A0%20%24set%2C%20%E6%9B%B4%E6%96%B0%E7%9A%84%E6%97%B6%E5%80%99%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%96%B0%E5%A2%9E%E5%AD%97%E6%AE%B5%0Adb.users.update(%7Bage%3A32%7D%2C%7B%24set%3A%7Bage%3A31%7D%7D)%3B%20%0Adb.users.update(%7Bname%3A'John'%7D%2C%7B%24set%3A%7Bage%3A41%7D%7D)%3B%0A%0A--%E6%9B%B4%E6%96%B0%E7%9A%84%E6%97%B6%E5%80%99%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%96%B0%E5%A2%9E%E5%AD%97%E6%AE%B5%0Adb.users.update(%7Bage%3A22%7D%2C%7B%24set%3A%7Bage%3A23%2C%20likes%3A%5B'read'%2C'girl'%2C'running'%5D%7D%7D)%3B%20%0A--%E7%BB%93%E6%9E%9C%20%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638df7174d72a1b3fad46b3a%22)%2C%20%22name%22%20%3A%20%22Dave%22%2C%20%22age%22%20%3A%2023%2C%20%22birthday%22%20%3A%20%222010-03-12%2011%3A27%3A11%22%2C%20%22likes%22%20%3A%20%5B%20%22read%22%2C%20%22girl%22%2C%20%22running%22%20%5D%20%7D%0A%0A--%E5%B0%86%20age%3D32%20%E7%9A%84%E6%89%80%E6%9C%89%E8%AE%B0%E5%BD%95%E7%9A%84age%E6%9B%B4%E6%96%B0%E4%B8%BA45%2C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E9%85%8D%E7%BD%AE%E5%88%B0%E7%9A%84%E8%AE%B0%E5%BD%95%E5%88%99%E6%8F%92%E5%85%A5%E4%B8%80%E6%9D%A1%E6%96%B0%E7%9A%84%E8%AE%B0%E5%BD%95%0Adb.users.update(%7Bage%3A32%7D%2C%7B%24set%3A%7Bage%3A45%7D%7D%2C%7Bmulti%3Atrue%2Cupsert%3Atrue%7D)%3B%20%0A--%E7%BB%93%E6%9E%9C%0AWriteResult(%7B%0A%20%20%20%20%20%20%20%20%22nMatched%22%20%3A%200%2C%0A%20%20%20%20%20%20%20%20%22nUpserted%22%20%3A%201%2C%0A%20%20%20%20%20%20%20%20%22nModified%22%20%3A%200%2C%0A%20%20%20%20%20%20%20%20%22_id%22%20%3A%20ObjectId(%22638e007512b0b293386f7153%22)%0A%7D)%0A%0A%3E%20db.users.find()%0A%7B%20%22_id%22%20%3A%20ObjectId(%22638e007512b0b293386f7153%22)%2C%20%22age%22%20%3A%2045%20%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%20%E7%B4%A2%E5%BC%95%0A%0A%3E%20https%3A%2F%2Fwww.mongodb.com%2Fdocs%2Fv5.0%2Findexes%2F%0A%0A%3E%20%E7%B4%A2%E5%BC%95%E6%98%AF%E4%B8%80%E7%A7%8D%E7%89%B9%E6%AE%8A%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%EF%BC%8C%E5%AD%98%E5%82%A8%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%98%93%E4%BA%8E%E9%81%8D%E5%8E%86%E8%AF%BB%E5%8F%96%E7%9A%84%E6%95%B0%E6%8D%AE%E9%9B%86%E5%90%88%E4%B8%AD%EF%BC%8C%E6%98%AF%E5%AF%B9%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E4%B8%80%E5%88%97%E6%88%96%E5%A4%9A%E5%88%97%E5%80%BC%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%E7%9A%84%E4%B8%80%E7%A7%8D%E7%BB%93%E6%9E%84%E3%80%82%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E7%B4%A2%E5%BC%95%EF%BC%8Cmongodb%E5%9C%A8%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE%E6%97%B6%E9%9C%80%E8%A6%81%E6%89%AB%E6%8F%8F%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E6%AF%8F%E4%B8%AA%E6%96%87%E6%A1%A3%EF%BC%8C%E5%B9%B6%E9%80%89%E5%8F%96%E9%82%A3%E4%BA%9B%E7%AC%A6%E5%90%88%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%E7%9A%84%E8%AE%B0%E5%BD%95%EF%BC%8C%E8%BF%99%E7%A7%8D%E6%89%AB%E6%8F%8F%E5%85%A8%E9%9B%86%E5%90%88%E7%9A%84%E6%9F%A5%E8%AF%A2%E6%95%88%E7%8E%87%E6%98%AF%E9%9D%9E%E5%B8%B8%E4%BD%8E%E7%9A%84%EF%BC%8C%E7%89%B9%E5%88%AB%E6%98%AF%E5%9C%A8%E5%A4%84%E7%90%86%E5%A4%A7%E9%87%8F%E6%95%B0%E6%8D%AE%E6%97%B6%E3%80%82%0A%3E%0A%3E%20mongodb%E5%9C%A8%E9%9B%86%E5%90%88%E5%B1%82%E9%9D%A2%E4%B8%8A%E5%AE%9A%E4%B9%89%E4%BA%86%E7%B4%A2%E5%BC%95%EF%BC%8C%E5%B9%B6%E6%94%AF%E6%8C%81%E5%AF%B9mongodb%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E4%BB%BB%E4%BD%95%E5%AD%97%E6%AE%B5%E6%88%96%E6%96%87%E6%A1%A3%E7%9A%84%E5%AD%90%E5%AD%97%E6%AE%B5%E8%BF%9B%E8%A1%8C%E7%B4%A2%E5%BC%95%E3%80%82%0A%0A%3E%20%E9%BB%98%E8%AE%A4%60_id%60%E7%B4%A2%E5%BC%95%EF%BC%9A%20%E5%9C%A8%E5%88%9B%E5%BB%BA%E9%9B%86%E5%90%88%E6%97%B6%EF%BC%8Cmongodb%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%9C%A8%60_id%60%E5%AD%97%E6%AE%B5%E4%B8%8A%E5%88%9B%E5%BB%BA%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95.%20%60_id%60%E5%AD%97%E6%AE%B5%E9%98%B2%E6%AD%A2%E5%86%99%E5%85%A5%E4%B8%A4%E4%B8%AA%C2%B7%20%60_id%60%20%E4%B8%80%E6%A0%B7%E7%9A%84%E6%96%87%E6%A1%A3%EF%BC%8C%E5%B9%B6%E4%B8%94%60_id%60%E4%B8%8A%E7%9A%84%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%E6%98%AF%E4%B8%8D%E8%83%BD%E5%88%A0%E9%99%A4%E7%9A%84%0A%0A%0A%0A%E5%8E%9F%E7%90%86%0A%0A%0A%23%23%23%23%20%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%0A%0A%60%60%60json%0A--key%E5%80%BC%E4%B8%BA%E4%BD%A0%E8%A6%81%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%E7%9A%84%E5%AD%97%E6%AE%B5%EF%BC%8C%201%3A%E6%8C%87%E5%AE%9A%E6%8C%89%E5%8D%87%E5%BA%8F%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%EF%BC%8C-1%3A%E6%8C%87%E5%AE%9A%E6%8C%89%E9%99%8D%E5%BA%8F%E6%9D%A5%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%0Adb.users.createIndex(keys%2C%20options)%0A%0A--%E5%9C%A8%E5%AD%97%E6%AE%B5name%E5%92%8Cage%E5%AD%97%E6%AE%B5%E4%B8%8A%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%EF%BC%8C%E5%9C%A8name%E5%AD%97%E6%AE%B5%E5%8D%87%E5%BA%8F%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%EF%BC%8C%E5%BD%93age%E5%AD%97%E6%AE%B5%E7%9B%B8%E5%90%8C%E6%97%B6%EF%BC%8C%E5%86%8D%E5%9C%A8age%E5%AD%97%E6%AE%B5%E6%8C%89%E9%99%8D%E5%BA%8F%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%0Adb.users.createIndex(%7Bname%3A1%2C%20age%3A-1%7D)%0A%0A--%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%E6%97%B6%2C%E6%8C%87%E5%AE%9A%E7%B4%A2%E5%BC%95%E5%90%8D%E7%A7%B0%E4%B8%BA%20name_age_inx%EF%BC%8C%E4%B8%94%E4%B8%BA%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%0A%3E%20db.users.createIndex(%7Bname%3A1%2C%20age%3A-1%7D%2C%7Bname%3A'name_age_inx'%2C%20unique%3Atrue%7D)%3B%0A%7B%0A%20%20%20%20%20%20%20%20%22numIndexesBefore%22%20%3A%201%2C%0A%20%20%20%20%20%20%20%20%22numIndexesAfter%22%20%3A%202%2C%0A%20%20%20%20%20%20%20%20%22createdCollectionAutomatically%22%20%3A%20false%2C%0A%20%20%20%20%20%20%20%20%22ok%22%20%3A%201%0A%7D%0A%3E%20db.users.getIndexes()%0A%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22v%22%20%3A%202%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22key%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22_id%22%20%3A%201%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%20%3A%20%22_id_%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22v%22%20%3A%202%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22key%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%20%3A%201%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22age%22%20%3A%20-1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%20%3A%20%22name_age_inx%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22unique%22%20%3A%20true%0A%20%20%20%20%20%20%20%20%7D%0A%5D%0A%0A--%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%E6%97%B6%2C%E6%8C%87%E5%AE%9A%E7%B4%A2%E5%BC%95%E5%90%8D%E7%A7%B0%E4%B8%BA%EF%BC%8C%E4%B8%94%E6%8C%87%E5%AE%9A%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%E4%B8%BA10%E7%A7%92%0A%3E%20db.users.createIndex(%7Bname%3A1%7D%2C%7BexpireAfterSeconds%3A10%7D)%0A%7B%0A%20%20%20%20%20%20%20%20%22numIndexesBefore%22%20%3A%202%2C%0A%20%20%20%20%20%20%20%20%22numIndexesAfter%22%20%3A%203%2C%0A%20%20%20%20%20%20%20%20%22createdCollectionAutomatically%22%20%3A%20false%2C%0A%20%20%20%20%20%20%20%20%22ok%22%20%3A%201%0A%7D%0A%0A%3E%20db.users.getIndexes()%0A%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22v%22%20%3A%202%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22key%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22_id%22%20%3A%201%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%20%3A%20%22_id_%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22v%22%20%3A%202%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22key%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%20%3A%201%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22age%22%20%3A%20-1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%20%3A%20%22name_age_inx%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22unique%22%20%3A%20true%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22v%22%20%3A%202%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22key%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%20%3A%201%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%20%3A%20%22name_1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22expireAfterSeconds%22%20%3A%2010%0A%20%20%20%20%20%20%20%20%7D%0A%5D%0A%60%60%60%0A%0A%0A%0A%7C%20Parameter%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20type%20%20%20%20%20%20%20%20%20%20%7C%20Desc%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20---------------------%20%7C%20-------------%20%7C%20------------------------------------------------------------%20%7C%0A%7C%20%60background%60%20%20%20%20%20%20%20%20%20%20%7C%20Booelean%20%20%20%20%20%20%7C%20%E3%80%90%E5%8F%AF%E9%80%89%E3%80%91%E9%BB%98%E8%AE%A4%E4%B8%BA%60false%60%2C%20%20%E7%B4%A2%E5%BC%95%E5%88%9B%E5%BB%BA%E6%97%B6%E4%BC%9A%E9%98%BB%E5%A1%9E%E5%85%B6%E5%AE%83%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E5%90%8E%E5%8F%B0%E5%88%9B%E5%BB%BA%E3%80%82%20%7C%0A%7C%20%60unique%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Boolean%20%20%20%20%20%20%20%7C%20%E3%80%90%E5%8F%AF%E9%80%89%E3%80%91%E9%BB%98%E8%AE%A4%E4%B8%BA%60false%60%2C%20%20%E6%98%AF%E5%90%A6%E5%88%9B%E5%BB%BA%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%60name%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20String%20%20%20%20%20%20%20%20%7C%20%E3%80%90%E5%8F%AF%E9%80%89%E3%80%91%E7%B4%A2%E5%BC%95%E5%90%8D%E7%A7%B0%2C%20%20%E5%A6%82%E6%9E%9C%E4%B8%8D%E6%8C%87%E5%AE%9A%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%8C%89%E7%85%A7%E5%AD%97%E6%AE%B5%E5%90%8D%E7%A7%B0%2B%E6%8E%92%E5%BA%8F%E9%A1%BA%E5%BA%8F%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E5%90%8D%E7%A7%B0%20%7C%0A%7C%20%60expireAftertSeconds%60%20%7C%20Integer%20%20%20%20%20%20%20%7C%20%E3%80%90%E5%8F%AF%E9%80%89%E3%80%91%E7%B4%A2%E5%BC%95%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%2C%20%E5%8D%95%E4%BD%8D%E4%B8%BA%E7%A7%92%EF%BC%8C%E5%8F%AA%E8%83%BD%E6%8C%87%E5%AE%9A%E5%9C%A8%E5%8D%95%E5%AD%97%E6%AE%B5%E7%B4%A2%E5%BC%95%E7%9A%84%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%20%7C%0A%7C%20%60v%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20index%20version%20%7C%20%E7%B4%A2%E5%BC%95%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%8F%96%E5%86%B3%E4%BA%8Emongodb%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%E6%97%B6%E8%BF%90%E8%A1%8C%E7%9A%84%E7%89%88%E6%9C%AC%20%20%20%20%20%20%20%20%20%20%7C%0A%0A%0A%0A%23%23%23%23%20%E6%9F%A5%E8%AF%A2%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E7%B4%A2%E5%BC%95%0A%0A%60%60%60json%0A--%E6%9F%A5%E8%AF%A2%E4%B8%80%E4%B8%AA%E9%9B%86%E5%90%88%E9%87%8C%E9%9D%A2%E7%9A%84%E7%B4%A2%E5%BC%95%0A%3E%20db.users.getIndexes()%0A%5B%20%7B%20%22v%22%20%3A%202%2C%20%22key%22%20%3A%20%7B%20%22_id%22%20%3A%201%20%7D%2C%20%22name%22%20%3A%20%22_id_%22%20%7D%20%5D%0A%0A--%E6%9F%A5%E8%AF%A2%E9%9B%86%E5%90%88%E7%B4%A2%E5%BC%95%E5%A4%A7%E5%B0%8F%0Adb.users.totalIndexSize()%0A36864%20--%E5%AD%97%E8%8A%82%0A%60%60%60%0A%0A%23%23%23%23%20%E5%88%A0%E9%99%A4%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E7%B4%A2%E5%BC%95%0A%0A%60%60%60json%0A--%E5%88%A0%E9%99%A4%E9%9B%86%E5%90%88%E4%B8%AD%E6%89%80%E6%9C%89%E7%9A%84%E7%B4%A2%E5%BC%95%0Adb.users.dropIndexes()%0A%0A--%E5%88%A0%E9%99%A4%E9%9B%86%E5%90%88%E4%B8%AD%E5%90%8D%E7%A7%B0%E4%B8%BA'name_index'%E7%9A%84%E7%B4%A2%E5%BC%95%0Adb.users.dropIndex('name_index')%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%A4%8D%E5%90%88%E7%B4%A2%E5%BC%95%0A%0A%3E%20%E5%A4%8D%E5%90%88%E7%B4%A2%E5%BC%95%E7%94%9F%E6%95%88%E5%92%8Cmysql%E4%B8%80%E6%A0%B7%EF%BC%8C%E9%80%82%E7%94%A8%E5%B7%A6%E5%8C%85%E5%90%AB%E5%8E%9F%E5%88%99%EF%BC%8C%20%0A%0Ahttps%3A%2F%2Fdocs.mongodb.com%2Fmanual%2Ftutorial%2Fsort-results-with-indexes%2F%23std-lable-sort-on-multiple-fields%0A%0A%60%60%60json%0Aif%20the%20sort%20keys%20correspond%20to%20the%20index%20keys%20or%20an%20index%20prefix%2C%20MongoDB%20can%20use%20the%20index%20to%20sort%20the%20query%20results.%20A%20prefix%20of%20a%20compound%20index%20is%20a%20subset%20that%20consists%20of%20one%20or%20more%20keys%20at%20the%20start%20of%20the%20index%20key%20pattern.%0A%0AFor%20example%2C%20create%20a%20compound%20index%20on%20the%20data%20collection%3A%0A%0Adb.data.createIndex(%20%7B%20a%3A1%2C%20b%3A%201%2C%20c%3A%201%2C%20d%3A%201%20%7D%20)%0A%0AThen%2C%20the%20following%20are%20prefixes%20for%20that%20index%3A%0A%0A%7B%20a%3A%201%20%7D%0A%7B%20a%3A%201%2C%20b%3A%201%20%7D%0A%7B%20a%3A%201%2C%20b%3A%201%2C%20c%3A%201%20%7D%0A%7B%20a%3A%201%2C%20b%3A%201%2C%20c%3A%201%2C%20d%3A%201%20%7D%0A%60%60%60%0A%0A%3E%20b%20a%20c%20d%20%E4%B9%9F%E6%98%AF%E5%8F%AF%E4%BB%A5%E8%B5%B0%E5%A4%8D%E5%90%88%E7%B4%A2%E5%BC%95%E7%9A%84%E5%90%8C%EF%BC%8C%20%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E6%A3%80%E7%B4%A2%E7%9A%84%E5%AD%97%E6%AE%B5%E5%8C%85%E5%90%AB%E5%A4%8D%E5%90%88%E7%B4%A2%E5%BC%95%E7%9A%84%E5%85%A8%E9%83%A8%E5%AD%97%E6%AE%B5%E4%BD%86%E6%98%AF%E9%A1%BA%E5%BA%8F%E4%B8%8D%E5%90%8C%EF%BC%8C%E5%BC%95%E6%93%8E%E4%BC%9A%E8%87%AA%E5%8A%A8%E4%BC%98%E5%8C%96%E6%9D%A5%E4%BD%BF%E7%94%A8%E5%A4%8D%E5%90%88%E7%B4%A2%E5%BC%95%0A%0A%3E%20mongodb%E4%B8%AD%E6%8E%92%E5%BA%8F%E4%B9%9F%E6%98%AF%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E7%B4%A2%E5%BC%95%E7%9A%84%0A%3E%0A%3E%20The%20following%20query%20and%20sort%20operations%20use%20the%20index%20prefixes%20to%20sort%20the%20results.%20These%20operations%20do%20not%20need%20to%20sort%20the%20result%20set%20in%20memory.%0A%0A%7C%20Example%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Index%20Prefix%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%3A---------------------------------------------------------%20%7C%20%3A---------------------%20%7C%0A%7C%20%60db.data.find().sort(%20%7B%20a%3A%201%20%7D%20)%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%60%7B%20a%3A%201%20%7D%60%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%60db.data.find().sort(%20%7B%20a%3A%20-1%20%7D%20)%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%60%7B%20a%3A%201%20%7D%60%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%60db.data.find().sort(%20%7B%20a%3A%201%2C%20b%3A%201%20%7D%20)%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%60%7B%20a%3A%201%2C%20b%3A%201%20%7D%60%20%20%20%20%20%20%20%7C%0A%7C%20%60db.data.find().sort(%20%7B%20a%3A%20-1%2C%20b%3A%20-1%20%7D%20)%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%60%7B%20a%3A%201%2C%20b%3A%201%20%7D%60%20%20%20%20%20%20%20%7C%0A%7C%20%60db.data.find().sort(%20%7B%20a%3A%201%2C%20b%3A%201%2C%20c%3A%201%20%7D%20)%60%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%60%7B%20a%3A%201%2C%20b%3A%201%2C%20c%3A%201%20%7D%60%20%7C%0A%7C%20%60db.data.find(%20%7B%20a%3A%20%7B%20%24gt%3A%204%20%7D%20%7D%20).sort(%20%7B%20a%3A%201%2C%20b%3A%201%20%7D%20)%60%20%7C%20%60%7B%20a%3A%201%2C%20b%3A%201%20%7D%60%20%20%20%20%20%20%20%7C%0A%0A%0A%0A%23%23%23%20%E8%81%9A%E5%90%88%E6%9F%A5%E8%AF%A2%0A%0A%3E%20mongodb%E4%B8%AD%E7%9A%84%E8%81%9A%E5%90%88%E4%B8%BB%E8%A6%81%E7%94%A8%E4%BA%8E%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E7%BB%9F%E8%AE%A1%E5%B9%B3%E5%9D%87%E5%80%BC%EF%BC%8C%E6%B1%82%E5%92%8C%E7%AD%89%EF%BC%8C%E5%B9%B6%E8%BF%94%E5%9B%9E%E8%AE%A1%E7%AE%97%E5%90%8E%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%9C%EF%BC%8C%E7%B1%BB%E4%BC%BC%E4%BA%8Emysql%E4%B8%AD%E7%9A%84count()%0A%0A

import

创建时间:2022/12/11 23:11
更新时间:2022/12/17 17:23
作者:Chris

1

2

3

4

package com.chris.cloud.importer.bean;

public interface ServiceInterface {
    void test();
}

package com.chris.cloud.importer.bean.impl;
import com.chris.cloud.importer.bean.ServiceInterface;

public class ServiceA implements ServiceInterface {
    public ServiceA() {
        System.out.println("new service A");
    }

    @Override
    public void test() {
        System.out.println("ServiceA");
    }
}


package com.chris.cloud.importer.bean.impl;

import com.chris.cloud.importer.bean.ServiceInterface;

public class ServiceB implements ServiceInterface {
    public ServiceB() {
        System.out.println("new service B");
    }

    @Override
    public void test() {
        System.out.println("ServiceB");
    }
}



package com.chris.cloud.importer.bean.impl;

import cn.hutool.json.JSONUtil;
import com.chris.cloud.importer.bean.impl.ServiceB;
import com.chris.cloud.importer.config.ConfigB;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

@Slf4j
@SuppressWarnings({"NullableProblems"})
public class ServiceImportSelector implements ImportSelector {
    /**
     * 通过AnnotationMetadata里面的属性,动态加载类。AnnotationMetadata是Import注解所在的类属性(如果所在类是注解类,则延伸至应用这个注解类的非注解类为止)
     *
     * @param importingClassMetadata com.chris.cloud.importer.config.ConfigA
     * @return 返回要加载的@Configuation或者具体Bean类的全限定名的String数组
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //可以是@Configuration注解修饰的类,也可以是具体的Bean类的全限定名称
        String[] beanClzNames = new String[]{ConfigB.class.getName()/*, ServiceB.class.getName()*/};
        log.info("beanClzNames:{}", JSONUtil.toJsonStr(beanClzNames));

        return beanClzNames;
    }
}


package com.chris.cloud.importer.bean.impl;

import com.chris.cloud.importer.bean.EnableImportService;
import com.chris.cloud.importer.utils.ImportUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.type.AnnotationMetadata;

import java.util.Map;
import java.util.Set;

@Slf4j
@SuppressWarnings({"NullableProblems"})
public class ServiceImportSelector2 implements ImportSelector {
    /**
     * 通过AnnotationMetadata里面的属性,动态加载类。AnnotationMetadata是Import注解所在的类属性(如果所在类是注解类,则延伸至应用这个注解类的非注解类为止)
     *
     * @param importingClassMetadata com.chris.cloud.importer.config.ConfigA
     * @return 返回要加载的@Configuation或者具体Bean类的全限定名的String数组
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        MergedAnnotations annotations = importingClassMetadata.getAnnotations();
        Set<String> annotationTypes = importingClassMetadata.getAnnotationTypes();
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableImportService.class.getName());
        Map<String, Object> annoMap = importingClassMetadata.getAnnotationAttributes(EnableImportService.class.getName(), true);

        return ImportUtil.getClzNames(annoMap);
    }
}


package com.chris.cloud.importer.bean;

import com.chris.cloud.importer.bean.impl.ServiceImportSelector2;
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import(ServiceImportSelector2.class)
@SuppressWarnings({"rawtypes"})
public @interface EnableImportService {
    Class[] clz_names();
}


public class User1 {
    private String name;
}

public class User2 {
    private String name;
}




package com.chris.cloud.importer.config;

import com.chris.cloud.importer.bean.EnableImportService;
import com.chris.cloud.importer.bean.ServiceInterface;
import com.chris.cloud.importer.bean.impl.ServiceA;
import com.chris.cloud.importer.bean.impl.ServiceB;
import com.chris.cloud.importer.bean.impl.ServiceImportSelector;
import com.chris.cloud.importer.bean.impl.User1;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Import(ConfigB.class)

//Spring 4.2之后,@Import可以直接指定实体类,加载这个类定义到context中, @Import(ServiceB.class),就会生成ServiceBBean到容器上下文中
//@Import(ServiceB.class)

//通过mportSelector实现动态加载,需要返回要加载的@Configuation或者具体Bean类的全限定名的String数组
//@Import(ServiceImportSelector.class)

//@EnableImportService(clz_names = {ConfigB.class})
@Configuration
@Slf4j
public class ConfigA {

    ConfigA() {
        log.info("begin get configA");
    }

    @Bean
    public Object getUser1() {
        log.info("begin get User1");
        return new User1();
    }

    @Bean
    @ConditionalOnMissingBean
    public ServiceInterface getServiceA() {
        log.info("begin get service A");
        return new ServiceA();
    }
}


package com.chris.cloud.importer.config;

import com.chris.cloud.importer.bean.impl.ServiceB;
import com.chris.cloud.importer.bean.ServiceInterface;
import com.chris.cloud.importer.bean.impl.User2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
public class ConfigB {
    ConfigB() {
        log.info("begin get configB");
    }

    @Bean
    public Object getUser2() {
        log.info("begin get User2");
        return new User2();
    }

    @Bean
    @ConditionalOnMissingBean
    public ServiceInterface getServiceB() {
        log.info("begin get service B");
        return new ServiceB();
    }
}


package com.chris.cloud;

@SpringBootTest(classes = Cloud2022Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
@Slf4j
public class ImportTest implements ApplicationContextAware {

    private ApplicationContext applicationContext;


    @Test
    public void test2() {
//        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigA.class);
        ServiceInterface bean = this.applicationContext.getBean(ServiceInterface.class);
        bean.test();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}


%0A%0A%5B1%5D(https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F147025312)%0A%5B2%5D(https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F453432519)%0A%5B3%5D(https%3A%2F%2Fwww.zhihu.com%2Fquestion%2F428542278)%0A%5B4%5D(https%3A%2F%2Fblog.csdn.net%2Fgongsenlin341%2Farticle%2Fdetails%2F113281596)%0A%0A%0A%60%60%60java%0Apackage%20com.chris.cloud.importer.bean%3B%0A%0Apublic%20interface%20ServiceInterface%20%7B%0A%20%20%20%20void%20test()%3B%0A%7D%0A%0Apackage%20com.chris.cloud.importer.bean.impl%3B%0Aimport%20com.chris.cloud.importer.bean.ServiceInterface%3B%0A%0Apublic%20class%20ServiceA%20implements%20ServiceInterface%20%7B%0A%20%20%20%20public%20ServiceA()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22new%20service%20A%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20test()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22ServiceA%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%0Apackage%20com.chris.cloud.importer.bean.impl%3B%0A%0Aimport%20com.chris.cloud.importer.bean.ServiceInterface%3B%0A%0Apublic%20class%20ServiceB%20implements%20ServiceInterface%20%7B%0A%20%20%20%20public%20ServiceB()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22new%20service%20B%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20test()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22ServiceB%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%0A%0Apackage%20com.chris.cloud.importer.bean.impl%3B%0A%0Aimport%20cn.hutool.json.JSONUtil%3B%0Aimport%20com.chris.cloud.importer.bean.impl.ServiceB%3B%0Aimport%20com.chris.cloud.importer.config.ConfigB%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.context.annotation.ImportSelector%3B%0Aimport%20org.springframework.core.type.AnnotationMetadata%3B%0A%0A%40Slf4j%0A%40SuppressWarnings(%7B%22NullableProblems%22%7D)%0Apublic%20class%20ServiceImportSelector%20implements%20ImportSelector%20%7B%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E9%80%9A%E8%BF%87AnnotationMetadata%E9%87%8C%E9%9D%A2%E7%9A%84%E5%B1%9E%E6%80%A7%EF%BC%8C%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD%E7%B1%BB%E3%80%82AnnotationMetadata%E6%98%AFImport%E6%B3%A8%E8%A7%A3%E6%89%80%E5%9C%A8%E7%9A%84%E7%B1%BB%E5%B1%9E%E6%80%A7%EF%BC%88%E5%A6%82%E6%9E%9C%E6%89%80%E5%9C%A8%E7%B1%BB%E6%98%AF%E6%B3%A8%E8%A7%A3%E7%B1%BB%EF%BC%8C%E5%88%99%E5%BB%B6%E4%BC%B8%E8%87%B3%E5%BA%94%E7%94%A8%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E7%B1%BB%E7%9A%84%E9%9D%9E%E6%B3%A8%E8%A7%A3%E7%B1%BB%E4%B8%BA%E6%AD%A2%EF%BC%89%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%40param%20importingClassMetadata%20com.chris.cloud.importer.config.ConfigA%0A%20%20%20%20%20*%20%40return%20%E8%BF%94%E5%9B%9E%E8%A6%81%E5%8A%A0%E8%BD%BD%E7%9A%84%40Configuation%E6%88%96%E8%80%85%E5%85%B7%E4%BD%93Bean%E7%B1%BB%E7%9A%84%E5%85%A8%E9%99%90%E5%AE%9A%E5%90%8D%E7%9A%84String%E6%95%B0%E7%BB%84%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20String%5B%5D%20selectImports(AnnotationMetadata%20importingClassMetadata)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E5%8F%AF%E4%BB%A5%E6%98%AF%40Configuration%E6%B3%A8%E8%A7%A3%E4%BF%AE%E9%A5%B0%E7%9A%84%E7%B1%BB%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%85%B7%E4%BD%93%E7%9A%84Bean%E7%B1%BB%E7%9A%84%E5%85%A8%E9%99%90%E5%AE%9A%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20String%5B%5D%20beanClzNames%20%3D%20new%20String%5B%5D%7BConfigB.class.getName()%2F*%2C%20ServiceB.class.getName()*%2F%7D%3B%0A%20%20%20%20%20%20%20%20log.info(%22beanClzNames%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(beanClzNames))%3B%0A%0A%20%20%20%20%20%20%20%20return%20beanClzNames%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%0Apackage%20com.chris.cloud.importer.bean.impl%3B%0A%0Aimport%20com.chris.cloud.importer.bean.EnableImportService%3B%0Aimport%20com.chris.cloud.importer.utils.ImportUtil%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.context.annotation.ImportSelector%3B%0Aimport%20org.springframework.core.annotation.MergedAnnotations%3B%0Aimport%20org.springframework.core.type.AnnotationMetadata%3B%0A%0Aimport%20java.util.Map%3B%0Aimport%20java.util.Set%3B%0A%0A%40Slf4j%0A%40SuppressWarnings(%7B%22NullableProblems%22%7D)%0Apublic%20class%20ServiceImportSelector2%20implements%20ImportSelector%20%7B%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E9%80%9A%E8%BF%87AnnotationMetadata%E9%87%8C%E9%9D%A2%E7%9A%84%E5%B1%9E%E6%80%A7%EF%BC%8C%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD%E7%B1%BB%E3%80%82AnnotationMetadata%E6%98%AFImport%E6%B3%A8%E8%A7%A3%E6%89%80%E5%9C%A8%E7%9A%84%E7%B1%BB%E5%B1%9E%E6%80%A7%EF%BC%88%E5%A6%82%E6%9E%9C%E6%89%80%E5%9C%A8%E7%B1%BB%E6%98%AF%E6%B3%A8%E8%A7%A3%E7%B1%BB%EF%BC%8C%E5%88%99%E5%BB%B6%E4%BC%B8%E8%87%B3%E5%BA%94%E7%94%A8%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E7%B1%BB%E7%9A%84%E9%9D%9E%E6%B3%A8%E8%A7%A3%E7%B1%BB%E4%B8%BA%E6%AD%A2%EF%BC%89%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%40param%20importingClassMetadata%20com.chris.cloud.importer.config.ConfigA%0A%20%20%20%20%20*%20%40return%20%E8%BF%94%E5%9B%9E%E8%A6%81%E5%8A%A0%E8%BD%BD%E7%9A%84%40Configuation%E6%88%96%E8%80%85%E5%85%B7%E4%BD%93Bean%E7%B1%BB%E7%9A%84%E5%85%A8%E9%99%90%E5%AE%9A%E5%90%8D%E7%9A%84String%E6%95%B0%E7%BB%84%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20String%5B%5D%20selectImports(AnnotationMetadata%20importingClassMetadata)%20%7B%0A%20%20%20%20%20%20%20%20MergedAnnotations%20annotations%20%3D%20importingClassMetadata.getAnnotations()%3B%0A%20%20%20%20%20%20%20%20Set%3CString%3E%20annotationTypes%20%3D%20importingClassMetadata.getAnnotationTypes()%3B%0A%20%20%20%20%20%20%20%20Map%3CString%2C%20Object%3E%20annotationAttributes%20%3D%20importingClassMetadata.getAnnotationAttributes(EnableImportService.class.getName())%3B%0A%20%20%20%20%20%20%20%20Map%3CString%2C%20Object%3E%20annoMap%20%3D%20importingClassMetadata.getAnnotationAttributes(EnableImportService.class.getName()%2C%20true)%3B%0A%0A%20%20%20%20%20%20%20%20return%20ImportUtil.getClzNames(annoMap)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%0Apackage%20com.chris.cloud.importer.bean%3B%0A%0Aimport%20com.chris.cloud.importer.bean.impl.ServiceImportSelector2%3B%0Aimport%20org.springframework.context.annotation.Import%3B%0A%0Aimport%20java.lang.annotation.*%3B%0A%0A%40Retention(RetentionPolicy.RUNTIME)%0A%40Documented%0A%40Target(ElementType.TYPE)%0A%40Import(ServiceImportSelector2.class)%0A%40SuppressWarnings(%7B%22rawtypes%22%7D)%0Apublic%20%40interface%20EnableImportService%20%7B%0A%20%20%20%20Class%5B%5D%20clz_names()%3B%0A%7D%0A%0A%0Apublic%20class%20User1%20%7B%0A%20%20%20%20private%20String%20name%3B%0A%7D%0A%0Apublic%20class%20User2%20%7B%0A%20%20%20%20private%20String%20name%3B%0A%7D%0A%0A%0A%0A%0Apackage%20com.chris.cloud.importer.config%3B%0A%0Aimport%20com.chris.cloud.importer.bean.EnableImportService%3B%0Aimport%20com.chris.cloud.importer.bean.ServiceInterface%3B%0Aimport%20com.chris.cloud.importer.bean.impl.ServiceA%3B%0Aimport%20com.chris.cloud.importer.bean.impl.ServiceB%3B%0Aimport%20com.chris.cloud.importer.bean.impl.ServiceImportSelector%3B%0Aimport%20com.chris.cloud.importer.bean.impl.User1%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean%3B%0Aimport%20org.springframework.context.annotation.Bean%3B%0Aimport%20org.springframework.context.annotation.Configuration%3B%0Aimport%20org.springframework.context.annotation.Import%3B%0A%0A%40Import(ConfigB.class)%0A%0A%2F%2FSpring%204.2%E4%B9%8B%E5%90%8E%EF%BC%8C%40Import%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E6%8C%87%E5%AE%9A%E5%AE%9E%E4%BD%93%E7%B1%BB%EF%BC%8C%E5%8A%A0%E8%BD%BD%E8%BF%99%E4%B8%AA%E7%B1%BB%E5%AE%9A%E4%B9%89%E5%88%B0context%E4%B8%AD%2C%20%40Import(ServiceB.class)%EF%BC%8C%E5%B0%B1%E4%BC%9A%E7%94%9F%E6%88%90ServiceB%E7%9A%84Bean%E5%88%B0%E5%AE%B9%E5%99%A8%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%0A%2F%2F%40Import(ServiceB.class)%0A%0A%2F%2F%E9%80%9A%E8%BF%87mportSelector%E5%AE%9E%E7%8E%B0%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD%EF%BC%8C%E9%9C%80%E8%A6%81%E8%BF%94%E5%9B%9E%E8%A6%81%E5%8A%A0%E8%BD%BD%E7%9A%84%40Configuation%E6%88%96%E8%80%85%E5%85%B7%E4%BD%93Bean%E7%B1%BB%E7%9A%84%E5%85%A8%E9%99%90%E5%AE%9A%E5%90%8D%E7%9A%84String%E6%95%B0%E7%BB%84%0A%2F%2F%40Import(ServiceImportSelector.class)%0A%0A%2F%2F%40EnableImportService(clz_names%20%3D%20%7BConfigB.class%7D)%0A%40Configuration%0A%40Slf4j%0Apublic%20class%20ConfigA%20%7B%0A%0A%20%20%20%20ConfigA()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20get%20configA%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20Object%20getUser1()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20get%20User1%22)%3B%0A%20%20%20%20%20%20%20%20return%20new%20User1()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20%40ConditionalOnMissingBean%0A%20%20%20%20public%20ServiceInterface%20getServiceA()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20get%20service%20A%22)%3B%0A%20%20%20%20%20%20%20%20return%20new%20ServiceA()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%0Apackage%20com.chris.cloud.importer.config%3B%0A%0Aimport%20com.chris.cloud.importer.bean.impl.ServiceB%3B%0Aimport%20com.chris.cloud.importer.bean.ServiceInterface%3B%0Aimport%20com.chris.cloud.importer.bean.impl.User2%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean%3B%0Aimport%20org.springframework.context.annotation.Bean%3B%0Aimport%20org.springframework.context.annotation.Configuration%3B%0A%0A%40Slf4j%0Apublic%20class%20ConfigB%20%7B%0A%20%20%20%20ConfigB()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20get%20configB%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20Object%20getUser2()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20get%20User2%22)%3B%0A%20%20%20%20%20%20%20%20return%20new%20User2()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20%40ConditionalOnMissingBean%0A%20%20%20%20public%20ServiceInterface%20getServiceB()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20get%20service%20B%22)%3B%0A%20%20%20%20%20%20%20%20return%20new%20ServiceB()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%0Apackage%20com.chris.cloud%3B%0A%0A%40SpringBootTest(classes%20%3D%20Cloud2022Application.class)%0A%40RunWith(SpringJUnit4ClassRunner.class)%0A%40Slf4j%0Apublic%20class%20ImportTest%20implements%20ApplicationContextAware%20%7B%0A%0A%20%20%20%20private%20ApplicationContext%20applicationContext%3B%0A%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test2()%20%7B%0A%2F%2F%20%20%20%20%20%20%20%20AnnotationConfigApplicationContext%20applicationContext%20%3D%20new%20AnnotationConfigApplicationContext(ConfigA.class)%3B%0A%20%20%20%20%20%20%20%20ServiceInterface%20bean%20%3D%20this.applicationContext.getBean(ServiceInterface.class)%3B%0A%20%20%20%20%20%20%20%20bean.test()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20setApplicationContext(ApplicationContext%20applicationContext)%20throws%20BeansException%20%7B%0A%20%20%20%20%20%20%20%20this.applicationContext%20%3D%20applicationContext%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%0A%60%60%60

annotation

创建时间:2020/9/2 15:43
更新时间:2022/12/14 23:11
作者:Chris
来源:https://blog.csdn.net/forezp/article/details/84313907

1.常见注解

1.1 @Autowired

按 byType 自动注入
@Autowired默认按类型装配(这个注解是属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,
如:@Autowired(required=false),如果我们想使用名称装配可以结合@Qualifier注解进行使用

@Autowired()
@Qualifier("baseDao")
private BaseDao baseDao;

1.1.@Resource

默认按 byName 自动注入
默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配

@Resource(name="baseDao")
private BaseDao baseDao;

@Resource 装配顺序

    1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
    1. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到,再根据类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常则抛出异常
    1. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到会抛出异常,找到多个,会根据默认取字段名进行名称匹配,匹配不到则报错。
    1. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

1.3 @Qualifier注解

@Autowired是根据类型进行自动装配的。

  1. 如果当Spring上下文中存在不止一个UserDao类型的bean时,就会抛出BeanCreationException异常;
@Autowired  
@Qualifier("userServiceImpl")  
public IUserService userService;

@Autowired   
public void setUserDao(@Qualifier("userDao") UserDao userDao) {   
    this.userDao = userDao;   
}  

这样Spring会找到id为userServiceImpl和userDao的bean进行装配。

  1. 如果Spring上下文中不存在UserDao类型的bean,也会抛出BeanCreationException异常。
@Autowired(required = false)   
public IUserService userService  

1.4 定义Bean

1.4.1 @Controller

定义控制层Bean,如Action

@Controller
@Controller("Bean的名称")
1.4.1.@Service

定义业务层Bean

@Service          
@Service("Bean的名称")
1.4.3 @Repository

定义DAO层Bean

@Repository   
@Repository("Bean的名称")
1.4.4 @Component

定义Bean, 不好归类时使用.

1.4.5 @Configuration

使用注解@Configuration,告诉Spring容器这是一个配置类.
@Bean:给容器中添加组件,以方法名作为组件的id。返回类型为组件类型,返回的值,就是组件在容器中的实例

@Configuration
public class ConfigProxyBeanMethods {

    @Bean
    public User getUser01() {
        return new User();
    }

    @Bean
    public Pet getPet01() {
        return new Pet();
    }

    /*@Bean("oh baby")
    public Pet getPet01() {
        return new Pet();
    }*/
}
/**
     * 2022-12-14 22:18:00.558  INFO 5604 --- [           main] com.chris.cloud.ConfigProxyTest          : bean name :getUser01
     * 2022-12-14 22:18:00.558  INFO 5604 --- [           main] com.chris.cloud.ConfigProxyTest          : bean name :getPet01
     * <p>
     * <p>
     * 2022-12-14 22:20:24.551  INFO 11480 --- [           main] com.chris.cloud.ConfigProxyTest          : bean name :getUser01
     * 2022-12-14 22:20:24.551  INFO 11480 --- [           main] com.chris.cloud.ConfigProxyTest          : bean name :oh baby
     */
    @Test
    public void test1() {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            log.info("bean name :{}", beanDefinitionName);
        }
    }

proxyBeanMethods = false

@Configuration(proxyBeanMethods = false)
public class ConfigProxyBeanMethods {

    @Bean
    public User getUser01() {
        return new User();
    }

    @Bean
    public Pet getPet01() {
        return new Pet();
    }

    /*@Bean("oh baby")
    public Pet getPet01() {
        return new Pet();
    }*/
}

/**
 * proxyBeanMethods,默认为true
 * 容器中注册的组件默认是单实例的
 * 在向容器中注册组件时,会在容器中查找有没有该组件。如果有,则取该组件用于保证单实例,如果没有再注册一个新的组件。
 * 2022-12-14 23:06:00.966  INFO 17044 --- [           main] com.chris.cloud.ConfigProxyTest          : user01.equals(user02): true
 * 2022-12-14 23:06:00.967  INFO 17044 --- [           main] com.chris.cloud.ConfigProxyTest          : user01 == user02 : true
 * 2022-12-14 23:06:00.967  INFO 17044 --- [           main] com.chris.cloud.ConfigProxyTest          : getUser01 == user01: true
 * <p>
 * proxyBeanMethods 改为false
 *
 * 2022-12-14 23:05:21.110  INFO 4244 --- [           main] com.chris.cloud.ConfigProxyTest          : user01.equals(user02): true
 * 2022-12-14 23:05:21.110  INFO 4244 --- [           main] com.chris.cloud.ConfigProxyTest          : user01 == user02 : true
 * 2022-12-14 23:05:21.110  INFO 4244 --- [           main] com.chris.cloud.ConfigProxyTest          : getUser01 == user01: false
 */
@Test
public void test2() {
    ConfigProxyBeanMethods bean = applicationContext.getBean(ConfigProxyBeanMethods.class);
    User getUser01 = bean.getUser01();

    User user01 = applicationContext.getBean("getUser01", User.class);
    User user02 = applicationContext.getBean("getUser01", User.class);

    log.info("user01.equals(user02): {}", user01.equals(user02));
    log.info("user01 == user02 : {}", user01 == user02);
    log.info("getUser01 == user01: {}", getUser01 == user01);

}

1.5 @Scope("prototype")

定义Bean的作用域和生命过程

@Scope("prototype")
值有:singleton,prototype,request,session,globalSession

1.6 @PostConstruct

相当于init-method , 使用在方法上,当Bean初始化时执行。

1.7 @PreDestroy

相当于destory-method,使用在方法上,当Bean销毁时执行。

%5Btoc%5D%0A%0A%0A%23%23%201.%E5%B8%B8%E8%A7%81%E6%B3%A8%E8%A7%A3%0A%0A%23%23%23%23%201.1%20%40Autowired%20%0A%3E%20%E6%8C%89%20byType%20%E8%87%AA%E5%8A%A8%E6%B3%A8%E5%85%A5%0A%3E%20%40Autowired%E9%BB%98%E8%AE%A4%E6%8C%89%E7%B1%BB%E5%9E%8B%E8%A3%85%E9%85%8D%EF%BC%88%60%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E6%98%AF%E5%B1%9E%E4%BA%8Espring%E7%9A%84%60%EF%BC%89%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5%E4%B8%8B%E5%BF%85%E9%A1%BB%E8%A6%81%E6%B1%82%E4%BE%9D%E8%B5%96%E5%AF%B9%E8%B1%A1%E5%BF%85%E9%A1%BB%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%A6%81%E5%85%81%E8%AE%B8null%E5%80%BC%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%AE%BE%E7%BD%AE%E5%AE%83%E7%9A%84required%E5%B1%9E%E6%80%A7%E4%B8%BAfalse%EF%BC%8C%0A%3E%20%E5%A6%82%EF%BC%9A%60%40Autowired(required%3Dfalse)%20%60%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%88%91%E4%BB%AC%E6%83%B3%E4%BD%BF%E7%94%A8%E5%90%8D%E7%A7%B0%E8%A3%85%E9%85%8D%E5%8F%AF%E4%BB%A5%E7%BB%93%E5%90%88%40Qualifier%E6%B3%A8%E8%A7%A3%E8%BF%9B%E8%A1%8C%E4%BD%BF%E7%94%A8%0A%0A%60%60%60java%0A%40Autowired()%0A%40Qualifier(%22baseDao%22)%0Aprivate%20BaseDao%20baseDao%3B%0A%60%60%60%0A%0A%23%23%23%23%201.1.%40Resource%20%0A%3E%20%E9%BB%98%E8%AE%A4%E6%8C%89%20byName%20%E8%87%AA%E5%8A%A8%E6%B3%A8%E5%85%A5%0A%3E%20%E9%BB%98%E8%AE%A4%E6%8C%89%E7%85%A7%E5%90%8D%E7%A7%B0%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D%EF%BC%8C%E5%90%8D%E7%A7%B0%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87name%E5%B1%9E%E6%80%A7%E8%BF%9B%E8%A1%8C%E6%8C%87%E5%AE%9A%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E6%8C%87%E5%AE%9Aname%E5%B1%9E%E6%80%A7%EF%BC%8C%E5%BD%93%E6%B3%A8%E8%A7%A3%E5%86%99%E5%9C%A8%E5%AD%97%E6%AE%B5%E4%B8%8A%E6%97%B6%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%8F%96%E5%AD%97%E6%AE%B5%E5%90%8D%E8%BF%9B%E8%A1%8C%E5%AE%89%E8%A3%85%E5%90%8D%E7%A7%B0%E6%9F%A5%E6%89%BE%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B3%A8%E8%A7%A3%E5%86%99%E5%9C%A8setter%E6%96%B9%E6%B3%95%E4%B8%8A%E9%BB%98%E8%AE%A4%E5%8F%96%E5%B1%9E%E6%80%A7%E5%90%8D%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D%0A%0A%60%60%60java%0A%40Resource(name%3D%22baseDao%22)%0Aprivate%20BaseDao%20baseDao%3B%0A%60%60%60%0A%0A%3E%20%60%40Resource%20%E8%A3%85%E9%85%8D%E9%A1%BA%E5%BA%8F%60%0A%3E-%201.%20%E5%A6%82%E6%9E%9C%E5%90%8C%E6%97%B6%E6%8C%87%E5%AE%9A%E4%BA%86name%E5%92%8Ctype%EF%BC%8C%E5%88%99%E4%BB%8ESpring%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E6%89%BE%E5%88%B0%E5%94%AF%E4%B8%80%E5%8C%B9%E9%85%8D%E7%9A%84bean%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D%EF%BC%8C%E6%89%BE%E4%B8%8D%E5%88%B0%E5%88%99%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%0A%3E-%202.%20%E5%A6%82%E6%9E%9C%E6%8C%87%E5%AE%9A%E4%BA%86name%EF%BC%8C%E5%88%99%E4%BB%8E%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E6%9F%A5%E6%89%BE%E5%90%8D%E7%A7%B0%EF%BC%88id%EF%BC%89%E5%8C%B9%E9%85%8D%E7%9A%84bean%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D%EF%BC%8C%E6%89%BE%E4%B8%8D%E5%88%B0%EF%BC%8C%E5%86%8D%E6%A0%B9%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%8C%B9%E9%85%8D%E7%9A%84%E5%94%AF%E4%B8%80bean%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D%EF%BC%8C%E6%89%BE%E4%B8%8D%E5%88%B0%E6%88%96%E8%80%85%E6%89%BE%E5%88%B0%E5%A4%9A%E4%B8%AA%EF%BC%8C%E9%83%BD%E4%BC%9A%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E5%88%99%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%0A%3E-%203.%20%E5%A6%82%E6%9E%9C%E6%8C%87%E5%AE%9A%E4%BA%86type%EF%BC%8C%E5%88%99%E4%BB%8E%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E6%89%BE%E5%88%B0%E7%B1%BB%E5%9E%8B%E5%8C%B9%E9%85%8D%E7%9A%84%E5%94%AF%E4%B8%80bean%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D%EF%BC%8C%E6%89%BE%E4%B8%8D%E5%88%B0%E4%BC%9A%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%EF%BC%8C%E6%89%BE%E5%88%B0%E5%A4%9A%E4%B8%AA%EF%BC%8C%E4%BC%9A%E6%A0%B9%E6%8D%AE%E9%BB%98%E8%AE%A4%E5%8F%96%E5%AD%97%E6%AE%B5%E5%90%8D%E8%BF%9B%E8%A1%8C%E5%90%8D%E7%A7%B0%E5%8C%B9%E9%85%8D%EF%BC%8C%E5%8C%B9%E9%85%8D%E4%B8%8D%E5%88%B0%E5%88%99%E6%8A%A5%E9%94%99%E3%80%82%0A%3E-%204.%20%E5%A6%82%E6%9E%9C%E6%97%A2%E6%B2%A1%E6%9C%89%E6%8C%87%E5%AE%9Aname%EF%BC%8C%E5%8F%88%E6%B2%A1%E6%9C%89%E6%8C%87%E5%AE%9Atype%EF%BC%8C%E5%88%99%E8%87%AA%E5%8A%A8%E6%8C%89%E7%85%A7byName%E6%96%B9%E5%BC%8F%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D%EF%BC%9B%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%8C%B9%E9%85%8D%EF%BC%8C%E5%88%99%E5%9B%9E%E9%80%80%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%8E%9F%E5%A7%8B%E7%B1%BB%E5%9E%8B%E8%BF%9B%E8%A1%8C%E5%8C%B9%E9%85%8D%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%8C%B9%E9%85%8D%E5%88%99%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%EF%BC%9B%0A%0A%23%23%23%23%201.3%20%40Qualifier%E6%B3%A8%E8%A7%A3%0A%0A%3E%20%40Autowired%E6%98%AF%E6%A0%B9%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BF%9B%E8%A1%8C%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%E7%9A%84%E3%80%82%0A%3E%201.%20%E5%A6%82%E6%9E%9C%E5%BD%93Spring%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E5%AD%98%E5%9C%A8%E4%B8%8D%E6%AD%A2%E4%B8%80%E4%B8%AAUserDao%E7%B1%BB%E5%9E%8B%E7%9A%84bean%E6%97%B6%EF%BC%8C%E5%B0%B1%E4%BC%9A%E6%8A%9B%E5%87%BABeanCreationException%E5%BC%82%E5%B8%B8%3B%0A%0A%60%60%60java%0A%40Autowired%20%20%0A%40Qualifier(%22userServiceImpl%22)%20%20%0Apublic%20IUserService%20userService%3B%0A%0A%40Autowired%20%20%20%0Apublic%20void%20setUserDao(%40Qualifier(%22userDao%22)%20UserDao%20userDao)%20%7B%20%20%20%0A%20%20%20%20this.userDao%20%3D%20userDao%3B%20%20%20%0A%7D%20%20%0A%60%60%60%0A%3E%20%20%E8%BF%99%E6%A0%B7Spring%E4%BC%9A%E6%89%BE%E5%88%B0id%E4%B8%BAuserServiceImpl%E5%92%8CuserDao%E7%9A%84bean%E8%BF%9B%E8%A1%8C%E8%A3%85%E9%85%8D%E3%80%82%0A%0A%3E%201.%20%E5%A6%82%E6%9E%9CSpring%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E4%B8%8D%E5%AD%98%E5%9C%A8UserDao%E7%B1%BB%E5%9E%8B%E7%9A%84bean%EF%BC%8C%E4%B9%9F%E4%BC%9A%E6%8A%9B%E5%87%BABeanCreationException%E5%BC%82%E5%B8%B8%E3%80%82%0A%0A%60%60%60java%0A%40Autowired(required%20%3D%20false)%20%20%20%0Apublic%20IUserService%20userService%20%20%0A%60%60%60%0A%0A%23%23%23%23%201.4%20%E5%AE%9A%E4%B9%89Bean%0A%23%23%23%23%23%201.4.1%20%40Controller%0A%3E%20%E5%AE%9A%E4%B9%89%E6%8E%A7%E5%88%B6%E5%B1%82Bean%2C%E5%A6%82Action%0A%0A%60%60%60java%0A%40Controller%0A%40Controller(%22Bean%E7%9A%84%E5%90%8D%E7%A7%B0%22)%0A%60%60%60%0A%0A%23%23%23%23%23%201.4.1.%40Service%0A%3E%20%E5%AE%9A%E4%B9%89%E4%B8%9A%E5%8A%A1%E5%B1%82Bean%0A%60%60%60java%0A%40Service%20%20%20%20%20%20%20%20%20%20%0A%40Service(%22Bean%E7%9A%84%E5%90%8D%E7%A7%B0%22)%0A%60%60%60%0A%0A%23%23%23%23%23%201.4.3%20%40Repository%0A%3E%20%E5%AE%9A%E4%B9%89DAO%E5%B1%82Bean%0A%60%60%60java%0A%40Repository%20%20%20%0A%40Repository(%22Bean%E7%9A%84%E5%90%8D%E7%A7%B0%22)%0A%60%60%60%0A%0A%23%23%23%23%23%201.4.4%20%40Component%20%20%0A%3E%20%E5%AE%9A%E4%B9%89Bean%2C%20%E4%B8%8D%E5%A5%BD%E5%BD%92%E7%B1%BB%E6%97%B6%E4%BD%BF%E7%94%A8.%0A%0A%23%23%23%23%23%201.4.5%20%40Configuration%20%20%0A%3E%20%E4%BD%BF%E7%94%A8%E6%B3%A8%E8%A7%A3%40Configuration%EF%BC%8C%E5%91%8A%E8%AF%89Spring%E5%AE%B9%E5%99%A8%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB.%0A%3E%20%40Bean%EF%BC%9A%E7%BB%99%E5%AE%B9%E5%99%A8%E4%B8%AD%E6%B7%BB%E5%8A%A0%E7%BB%84%E4%BB%B6%EF%BC%8C%E4%BB%A5%E6%96%B9%E6%B3%95%E5%90%8D%E4%BD%9C%E4%B8%BA%E7%BB%84%E4%BB%B6%E7%9A%84id%E3%80%82%E8%BF%94%E5%9B%9E%E7%B1%BB%E5%9E%8B%E4%B8%BA%E7%BB%84%E4%BB%B6%E7%B1%BB%E5%9E%8B%EF%BC%8C%E8%BF%94%E5%9B%9E%E7%9A%84%E5%80%BC%EF%BC%8C%E5%B0%B1%E6%98%AF%E7%BB%84%E4%BB%B6%E5%9C%A8%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84%E5%AE%9E%E4%BE%8B%0A%0A%60%60%60java%0A%40Configuration%0Apublic%20class%20ConfigProxyBeanMethods%20%7B%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20User%20getUser01()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20User()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20Pet%20getPet01()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20Pet()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F*%40Bean(%22oh%20baby%22)%0A%20%20%20%20public%20Pet%20getPet01()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20Pet()%3B%0A%20%20%20%20%7D*%2F%0A%7D%0A%2F**%0A%20%20%20%20%20*%202022-12-14%2022%3A18%3A00.558%20%20INFO%205604%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20bean%20name%20%3AgetUser01%0A%20%20%20%20%20*%202022-12-14%2022%3A18%3A00.558%20%20INFO%205604%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20bean%20name%20%3AgetPet01%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%202022-12-14%2022%3A20%3A24.551%20%20INFO%2011480%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20bean%20name%20%3AgetUser01%0A%20%20%20%20%20*%202022-12-14%2022%3A20%3A24.551%20%20INFO%2011480%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20bean%20name%20%3Aoh%20baby%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test1()%20%7B%0A%20%20%20%20%20%20%20%20String%5B%5D%20beanDefinitionNames%20%3D%20applicationContext.getBeanDefinitionNames()%3B%0A%20%20%20%20%20%20%20%20for%20(String%20beanDefinitionName%20%3A%20beanDefinitionNames)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22bean%20name%20%3A%7B%7D%22%2C%20beanDefinitionName)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%60%60%60%0A%0A%3E%20%60proxyBeanMethods%20%3D%20false%60%0A%0A%60%60%60java%0A%40Configuration(proxyBeanMethods%20%3D%20false)%0Apublic%20class%20ConfigProxyBeanMethods%20%7B%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20User%20getUser01()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20User()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20Pet%20getPet01()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20Pet()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F*%40Bean(%22oh%20baby%22)%0A%20%20%20%20public%20Pet%20getPet01()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20Pet()%3B%0A%20%20%20%20%7D*%2F%0A%7D%0A%0A%2F**%0A%20*%20proxyBeanMethods%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20*%20%E5%AE%B9%E5%99%A8%E4%B8%AD%E6%B3%A8%E5%86%8C%E7%9A%84%E7%BB%84%E4%BB%B6%E9%BB%98%E8%AE%A4%E6%98%AF%E5%8D%95%E5%AE%9E%E4%BE%8B%E7%9A%84%0A%20*%20%E5%9C%A8%E5%90%91%E5%AE%B9%E5%99%A8%E4%B8%AD%E6%B3%A8%E5%86%8C%E7%BB%84%E4%BB%B6%E6%97%B6%EF%BC%8C%E4%BC%9A%E5%9C%A8%E5%AE%B9%E5%99%A8%E4%B8%AD%E6%9F%A5%E6%89%BE%E6%9C%89%E6%B2%A1%E6%9C%89%E8%AF%A5%E7%BB%84%E4%BB%B6%E3%80%82%E5%A6%82%E6%9E%9C%E6%9C%89%EF%BC%8C%E5%88%99%E5%8F%96%E8%AF%A5%E7%BB%84%E4%BB%B6%E7%94%A8%E4%BA%8E%E4%BF%9D%E8%AF%81%E5%8D%95%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%86%8D%E6%B3%A8%E5%86%8C%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E7%BB%84%E4%BB%B6%E3%80%82%0A%20*%202022-12-14%2023%3A06%3A00.966%20%20INFO%2017044%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20user01.equals(user02)%3A%20true%0A%20*%202022-12-14%2023%3A06%3A00.967%20%20INFO%2017044%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20user01%20%3D%3D%20user02%20%3A%20true%0A%20*%202022-12-14%2023%3A06%3A00.967%20%20INFO%2017044%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20getUser01%20%3D%3D%20user01%3A%20true%0A%20*%20%3Cp%3E%0A%20*%20proxyBeanMethods%20%E6%94%B9%E4%B8%BAfalse%0A%20*%0A%20*%202022-12-14%2023%3A05%3A21.110%20%20INFO%204244%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20user01.equals(user02)%3A%20true%0A%20*%202022-12-14%2023%3A05%3A21.110%20%20INFO%204244%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20user01%20%3D%3D%20user02%20%3A%20true%0A%20*%202022-12-14%2023%3A05%3A21.110%20%20INFO%204244%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20com.chris.cloud.ConfigProxyTest%20%20%20%20%20%20%20%20%20%20%3A%20getUser01%20%3D%3D%20user01%3A%20false%0A%20*%2F%0A%40Test%0Apublic%20void%20test2()%20%7B%0A%20%20%20%20ConfigProxyBeanMethods%20bean%20%3D%20applicationContext.getBean(ConfigProxyBeanMethods.class)%3B%0A%20%20%20%20User%20getUser01%20%3D%20bean.getUser01()%3B%0A%0A%20%20%20%20User%20user01%20%3D%20applicationContext.getBean(%22getUser01%22%2C%20User.class)%3B%0A%20%20%20%20User%20user02%20%3D%20applicationContext.getBean(%22getUser01%22%2C%20User.class)%3B%0A%0A%20%20%20%20log.info(%22user01.equals(user02)%3A%20%7B%7D%22%2C%20user01.equals(user02))%3B%0A%20%20%20%20log.info(%22user01%20%3D%3D%20user02%20%3A%20%7B%7D%22%2C%20user01%20%3D%3D%20user02)%3B%0A%20%20%20%20log.info(%22getUser01%20%3D%3D%20user01%3A%20%7B%7D%22%2C%20getUser01%20%3D%3D%20user01)%3B%0A%0A%7D%0A%60%60%60%0A%0A%0A%23%23%23%23%201.5%20%40Scope(%22prototype%22)%0A%3E%20%E5%AE%9A%E4%B9%89Bean%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E7%94%9F%E5%91%BD%E8%BF%87%E7%A8%8B%0A%0A%60%60%60%0A%40Scope(%22prototype%22)%0A%E5%80%BC%E6%9C%89%3Asingleton%2Cprototype%2Crequest%2Csession%2CglobalSession%0A%60%60%60%0A%0A%23%23%23%23%201.6%20%40PostConstruct%20%0A%3E%20%E7%9B%B8%E5%BD%93%E4%BA%8E%60init-method%60%20%2C%20%E4%BD%BF%E7%94%A8%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%8A%EF%BC%8C%E5%BD%93Bean%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%E6%89%A7%E8%A1%8C%E3%80%82%0A%0A%23%23%23%23%201.7%20%40PreDestroy%20%0A%3E%20%E7%9B%B8%E5%BD%93%E4%BA%8E%60destory-method%60%EF%BC%8C%E4%BD%BF%E7%94%A8%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%8A%EF%BC%8C%E5%BD%93Bean%E9%94%80%E6%AF%81%E6%97%B6%E6%89%A7%E8%A1%8C%E3%80%82%0A%0A%0A%0A

springboot annotation

创建时间:2020/9/8 11:23
更新时间:2022/12/11 10:14
作者:Chris
来源:https://blog.csdn.net/sqlgao22/article/details/96476754

2. @ConfigurationProperties

告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
prefix = "xxx":配置文件中哪个下面的所有属性进行一一映射
只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;

@ConfigurationProperties(prefix = "xxx")默认从全局配置文件中获取值;
@Component
@ConfigurationProperties(prefix = "async.executor.thread")
@Data
public class ThreadPoolConfigBean {
    private int corePoolSize;
    private int maxPoolSize;
    private int queueCapacity;
    private String namePrefix;
}

3. @EnableConfigurationProperties

@EnableConfigurationProperties 注解的作用是:使使用 @ConfigurationProperties 注解的类生效.

如果一个配置类只配置@ConfigurationProperties 注解,而没有使用@Component,那么在IOC容器中是获取不到properties 配置文件转化的bean。说白了 @EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了一次注入。

@Configuration
@EnableConfigurationProperties(ThreadPoolConfigBean.class)
public class ExecutorConfig {
    @Resource
    private ThreadPoolConfigBean configBean;

4. @ConfigurationPropertiesScan

可以用来替换@EnableConfigurationProperties,配置在主启动类上对项目中的属性配
置类统一扫描后生成bean放到容器中

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
@MapperScan("com.chris.mybatisplus.dao.mapper")
@ConfigurationPropertiesScan("com.chris.mybatisplus.config")
@EnableAsync
public class MybatisPlusMain {
    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusMain.class, args);
    }
}

6. @ConfigurationOnXXX

/** 这里加了@ConditionalOnBean注解,就代表如果city存在才实例化people*/ 
@Bean 
@ConditionalOnBean(name = "city")
public People (City city) { //这里如果city实体没有成功注入 这里就会报空指针  
    city.setCityCode(301701); 
    return new People("小小", 3, city); 
}
@Conditional({WindowsCondition.class})
@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)

当前上下文中不存在TeamTalkService对象时,才会实例化一个TeamTalkService Bean

@Bean
@ConditionalOnMissingBean(TeamTalkService.class)
public TeamTalkService teamTalkService() {    
    return new TeamTalkService(prefix, appId, secret);
}

7. @ConditionalOnProperty

Spring Boot通过@ConditionalOnProperty来控制Configuration是否生效
通过其两个属性name以及havingValue来实现的,其中name用来从application.properties中读取某个属性值。
如果该值为空,则返回false;
如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。
如果返回值为false,则该configuration不生效;为true则生效。

//控制某个configuration是否生效

@Configuration 
@ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true", 
matchIfMissing=false) 
public class FilterConfig { 
// prefix 为配置文件中的前缀, 
// name 为配置的名字 
// havingValue 是与配置的值对比值,当两个值相同返回true,配置类生效. 
// matchIfMissing 缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错

@Bean 
public FilterRegistrationBean getFilterRegistration() { 
      FilterRegistrationBean filterRegistration = new FilterRegistrationBean(new LoginFilter());
      filterRegistration.addUrlPatterns("/*"); 
      return filterRegistration; }
 }

配置文件中的代码

filter.loginFilter=true
%5Btoc%5D%0A%0A%23%23%23%23%202.%20%40ConfigurationProperties%0A%3E%20%E5%91%8A%E8%AF%89SpringBoot%E5%B0%86%E6%9C%AC%E7%B1%BB%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E5%B1%9E%E6%80%A7%E5%92%8C%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9B%B8%E5%85%B3%E7%9A%84%E9%85%8D%E7%BD%AE%E8%BF%9B%E8%A1%8C%E7%BB%91%E5%AE%9A%EF%BC%9B%0Aprefix%C2%A0%3D%C2%A0%22xxx%22%EF%BC%9A%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E5%93%AA%E4%B8%AA%E4%B8%8B%E9%9D%A2%E7%9A%84%E6%89%80%E6%9C%89%E5%B1%9E%E6%80%A7%E8%BF%9B%E8%A1%8C%E4%B8%80%E4%B8%80%E6%98%A0%E5%B0%84%0A%E5%8F%AA%E6%9C%89%E8%BF%99%E4%B8%AA%E7%BB%84%E4%BB%B6%E6%98%AF%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84%E7%BB%84%E4%BB%B6%EF%BC%8C%E6%89%8D%E8%83%BD%E5%AE%B9%E5%99%A8%E6%8F%90%E4%BE%9B%E7%9A%84%40ConfigurationProperties%E5%8A%9F%E8%83%BD%EF%BC%9B%0A%60%60%60%0A%40ConfigurationProperties(prefix%C2%A0%3D%C2%A0%22xxx%22)%E9%BB%98%E8%AE%A4%E4%BB%8E%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%80%BC%EF%BC%9B%0A%60%60%60%0A%60%60%60java%0A%40Component%0A%40ConfigurationProperties(prefix%20%3D%20%22async.executor.thread%22)%0A%40Data%0Apublic%20class%20ThreadPoolConfigBean%20%7B%0A%20%20%20%20private%20int%20corePoolSize%3B%0A%20%20%20%20private%20int%20maxPoolSize%3B%0A%20%20%20%20private%20int%20queueCapacity%3B%0A%20%20%20%20private%20String%20namePrefix%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%203.%20%40EnableConfigurationProperties%0A%0A%60%40EnableConfigurationProperties%60%20%E6%B3%A8%E8%A7%A3%E7%9A%84%E4%BD%9C%E7%94%A8%E6%98%AF%EF%BC%9A%E4%BD%BF%E4%BD%BF%E7%94%A8%20%60%40ConfigurationProperties%60%20%E6%B3%A8%E8%A7%A3%E7%9A%84%E7%B1%BB%E7%94%9F%E6%95%88.%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%E5%8F%AA%E9%85%8D%E7%BD%AE%60%40ConfigurationProperties%60%20%E6%B3%A8%E8%A7%A3%EF%BC%8C%E8%80%8C%E6%B2%A1%E6%9C%89%E4%BD%BF%E7%94%A8%60%40Component%60%EF%BC%8C%E9%82%A3%E4%B9%88%E5%9C%A8IOC%E5%AE%B9%E5%99%A8%E4%B8%AD%E6%98%AF%E8%8E%B7%E5%8F%96%E4%B8%8D%E5%88%B0properties%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%BD%AC%E5%8C%96%E7%9A%84bean%E3%80%82%E8%AF%B4%E7%99%BD%E4%BA%86%20%40EnableConfigurationProperties%20%E7%9B%B8%E5%BD%93%E4%BA%8E%E6%8A%8A%E4%BD%BF%E7%94%A8%20%20%40ConfigurationProperties%20%E7%9A%84%E7%B1%BB%E8%BF%9B%E8%A1%8C%E4%BA%86%E4%B8%80%E6%AC%A1%E6%B3%A8%E5%85%A5%E3%80%82%0A%0A%60%60%60java%0A%40Configuration%0A%40EnableConfigurationProperties(ThreadPoolConfigBean.class)%0Apublic%20class%20ExecutorConfig%20%7B%0A%20%20%20%20%40Resource%0A%20%20%20%20private%20ThreadPoolConfigBean%20configBean%3B%0A%0A%60%60%60%0A%0A%23%23%23%23%204.%20%40ConfigurationPropertiesScan%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E6%9B%BF%E6%8D%A2%40EnableConfigurationProperties%EF%BC%8C%E9%85%8D%E7%BD%AE%E5%9C%A8%E4%B8%BB%E5%90%AF%E5%8A%A8%E7%B1%BB%E4%B8%8A%E5%AF%B9%E9%A1%B9%E7%9B%AE%E4%B8%AD%E7%9A%84%E5%B1%9E%E6%80%A7%E9%85%8D%0A%3E%20%E7%BD%AE%E7%B1%BB%E7%BB%9F%E4%B8%80%E6%89%AB%E6%8F%8F%E5%90%8E%E7%94%9F%E6%88%90bean%E6%94%BE%E5%88%B0%E5%AE%B9%E5%99%A8%E4%B8%AD%0A%0A%60%60%60java%0A%40SpringBootApplication(exclude%20%3D%20DruidDataSourceAutoConfigure.class)%0A%40MapperScan(%22com.chris.mybatisplus.dao.mapper%22)%0A%40ConfigurationPropertiesScan(%22com.chris.mybatisplus.config%22)%0A%40EnableAsync%0Apublic%20class%20MybatisPlusMain%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20SpringApplication.run(MybatisPlusMain.class%2C%20args)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%206.%20%40ConfigurationOnXXX%0A%60%60%60%20java%0A%2F**%20%E8%BF%99%E9%87%8C%E5%8A%A0%E4%BA%86%40ConditionalOnBean%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%B0%B1%E4%BB%A3%E8%A1%A8%E5%A6%82%E6%9E%9Ccity%E5%AD%98%E5%9C%A8%E6%89%8D%E5%AE%9E%E4%BE%8B%E5%8C%96people*%2F%20%0A%40Bean%20%0A%40ConditionalOnBean(name%20%3D%20%22city%22)%0Apublic%20People%20(City%20city)%20%7B%20%2F%2F%E8%BF%99%E9%87%8C%E5%A6%82%E6%9E%9Ccity%E5%AE%9E%E4%BD%93%E6%B2%A1%E6%9C%89%E6%88%90%E5%8A%9F%E6%B3%A8%E5%85%A5%20%E8%BF%99%E9%87%8C%E5%B0%B1%E4%BC%9A%E6%8A%A5%E7%A9%BA%E6%8C%87%E9%92%88%20%20%0A%20%20%20%20city.setCityCode(301701)%3B%20%0A%20%20%20%20return%20new%20People(%22%E5%B0%8F%E5%B0%8F%22%2C%203%2C%20city)%3B%20%0A%7D%0A%60%60%60%0A%60%60%60java%0A%40Conditional(%7BWindowsCondition.class%7D)%0A%40ConditionalOnBean%EF%BC%88%E4%BB%85%E4%BB%85%E5%9C%A8%E5%BD%93%E5%89%8D%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E5%AD%98%E5%9C%A8%E6%9F%90%E4%B8%AA%E5%AF%B9%E8%B1%A1%E6%97%B6%EF%BC%8C%E6%89%8D%E4%BC%9A%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%80%E4%B8%AABean%EF%BC%89%0A%40ConditionalOnClass%EF%BC%88%E6%9F%90%E4%B8%AAclass%E4%BD%8D%E4%BA%8E%E7%B1%BB%E8%B7%AF%E5%BE%84%E4%B8%8A%EF%BC%8C%E6%89%8D%E4%BC%9A%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%80%E4%B8%AABean%EF%BC%89%0A%40ConditionalOnExpression%EF%BC%88%E5%BD%93%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%BAtrue%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E6%89%8D%E4%BC%9A%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%80%E4%B8%AABean%EF%BC%89%0A%40ConditionalOnMissingBean%EF%BC%88%E4%BB%85%E4%BB%85%E5%9C%A8%E5%BD%93%E5%89%8D%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%9F%90%E4%B8%AA%E5%AF%B9%E8%B1%A1%E6%97%B6%EF%BC%8C%E6%89%8D%E4%BC%9A%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%80%E4%B8%AABean%EF%BC%89%0A%40ConditionalOnMissingClass%EF%BC%88%E6%9F%90%E4%B8%AAclass%E7%B1%BB%E8%B7%AF%E5%BE%84%E4%B8%8A%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E6%89%8D%E4%BC%9A%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%80%E4%B8%AABean%EF%BC%89%0A%40ConditionalOnNotWebApplication%EF%BC%88%E4%B8%8D%E6%98%AFweb%E5%BA%94%E7%94%A8%EF%BC%89%0A%60%60%60%0A%0A%3E%20%E5%BD%93%E5%89%8D%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E4%B8%8D%E5%AD%98%E5%9C%A8TeamTalkService%E5%AF%B9%E8%B1%A1%E6%97%B6%EF%BC%8C%E6%89%8D%E4%BC%9A%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%80%E4%B8%AATeamTalkService%20Bean%0A%60%60%60java%0A%40Bean%0A%40ConditionalOnMissingBean(TeamTalkService.class)%0Apublic%20TeamTalkService%20teamTalkService()%20%7B%C2%A0%C2%A0%C2%A0%20%0A%20%20%20%20return%20new%20TeamTalkService(prefix%2C%20appId%2C%20secret)%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%207.%20%40ConditionalOnProperty%0ASpring%20Boot%E9%80%9A%E8%BF%87%40ConditionalOnProperty%E6%9D%A5%E6%8E%A7%E5%88%B6Configuration%E6%98%AF%E5%90%A6%E7%94%9F%E6%95%88%0A%E9%80%9A%E8%BF%87%E5%85%B6%E4%B8%A4%E4%B8%AA%E5%B1%9E%E6%80%A7name%E4%BB%A5%E5%8F%8AhavingValue%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8C%E5%85%B6%E4%B8%ADname%E7%94%A8%E6%9D%A5%E4%BB%8Eapplication.properties%E4%B8%AD%E8%AF%BB%E5%8F%96%E6%9F%90%E4%B8%AA%E5%B1%9E%E6%80%A7%E5%80%BC%E3%80%82%0A%E5%A6%82%E6%9E%9C%E8%AF%A5%E5%80%BC%E4%B8%BA%E7%A9%BA%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9Efalse%3B%0A%E5%A6%82%E6%9E%9C%E5%80%BC%E4%B8%8D%E4%B8%BA%E7%A9%BA%EF%BC%8C%E5%88%99%E5%B0%86%E8%AF%A5%E5%80%BC%E4%B8%8EhavingValue%E6%8C%87%E5%AE%9A%E7%9A%84%E5%80%BC%E8%BF%9B%E8%A1%8C%E6%AF%94%E8%BE%83%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%80%E6%A0%B7%E5%88%99%E8%BF%94%E5%9B%9Etrue%3B%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9Efalse%E3%80%82%0A%E5%A6%82%E6%9E%9C%E8%BF%94%E5%9B%9E%E5%80%BC%E4%B8%BAfalse%EF%BC%8C%E5%88%99%E8%AF%A5configuration%E4%B8%8D%E7%94%9F%E6%95%88%EF%BC%9B%E4%B8%BAtrue%E5%88%99%E7%94%9F%E6%95%88%E3%80%82%0A%0A%60%60%60java%0A%2F%2F%E6%8E%A7%E5%88%B6%E6%9F%90%E4%B8%AAconfiguration%E6%98%AF%E5%90%A6%E7%94%9F%E6%95%88%0A%0A%40Configuration%20%0A%40ConditionalOnProperty(prefix%20%3D%20%22filter%22%2Cname%20%3D%20%22loginFilter%22%2ChavingValue%20%3D%20%22true%22%2C%20%0AmatchIfMissing%3Dfalse)%20%0Apublic%20class%20FilterConfig%20%7B%20%0A%2F%2F%20prefix%20%E4%B8%BA%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E5%89%8D%E7%BC%80%2C%20%0A%2F%2F%20name%20%E4%B8%BA%E9%85%8D%E7%BD%AE%E7%9A%84%E5%90%8D%E5%AD%97%20%0A%2F%2F%20havingValue%20%E6%98%AF%E4%B8%8E%E9%85%8D%E7%BD%AE%E7%9A%84%E5%80%BC%E5%AF%B9%E6%AF%94%E5%80%BC%2C%E5%BD%93%E4%B8%A4%E4%B8%AA%E5%80%BC%E7%9B%B8%E5%90%8C%E8%BF%94%E5%9B%9Etrue%2C%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%94%9F%E6%95%88.%20%0A%2F%2F%20matchIfMissing%20%E7%BC%BA%E5%B0%91%E8%AF%A5property%E6%97%B6%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E5%8A%A0%E8%BD%BD%E3%80%82%E5%A6%82%E6%9E%9C%E4%B8%BAtrue%EF%BC%8C%E6%B2%A1%E6%9C%89%E8%AF%A5property%E4%B9%9F%E4%BC%9A%E6%AD%A3%E5%B8%B8%E5%8A%A0%E8%BD%BD%EF%BC%9B%E5%8F%8D%E4%B9%8B%E6%8A%A5%E9%94%99%0A%0A%40Bean%20%0Apublic%20FilterRegistrationBean%20getFilterRegistration()%20%7B%20%0A%20%20%20%20%20%20FilterRegistrationBean%20filterRegistration%20%3D%20new%20FilterRegistrationBean(new%20LoginFilter())%3B%0A%20%20%20%20%20%20filterRegistration.addUrlPatterns(%22%2F*%22)%3B%20%0A%20%20%20%20%20%20return%20filterRegistration%3B%20%7D%0A%20%7D%0A%60%60%60%0A%0A%0A%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E4%BB%A3%E7%A0%81%0A%60%60%60%0Afilter.loginFilter%3Dtrue%0A%60%60%60

Spring依赖注入方式

创建时间:2022/5/10 19:00
更新时间:2022/12/11 9:51
作者:Chris

1 控制反转IOC

IOC 的核心就是原先创建一个对象,我们需要自己直接通过 new 来创建,而 IOC 就相当于有人帮们创建好了对象,需要使用的时候直接去拿就行

IOC 主要有两种实现方式:
DL(Dependency Lookup):依赖查找
DI(Dependency Inject):依赖注入

1.1 依赖查找

DL(Dependency Lookup)

容器帮我们创建好了对象,我们需要使用的时候自己再主动去容器中查找

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application-context.xml");
Object bean = applicationContext.getBean("object");

1.2 依赖注入

DI(Dependency Inject)

依赖注入相比较依赖查找又是一种优化,也就是我们不需要自己去查找,只需要告诉容器当前需要注入的对象,容器就会自动将创建好的对象进行注入(赋值)

1.2.1 三种常规注入方式

1. 基于属性注入
@Service
public class UserService {
    @Autowired
    private Wolf1Bean wolf1Bean;//通过属性注入
}
2. 基于 setter 方法
@Service
public class UserService {
    private Wolf3Bean wolf3Bean;
    
    @Autowired  //通过setter方法实现注入
    public void setWolf3Bean(Wolf3Bean wolf3Bean) {
        this.wolf3Bean = wolf3Bean;
    }
}
3. 注入基于构造器注入
@Service
public class UserService {
  private Wolf2Bean wolf2Bean;
    
    @Autowired //通过构造器注入
    public UserService(Wolf2Bean wolf2Bean) {
        this.wolf2Bean = wolf2Bean;
    }
}

1.2.2 接口注入

假如我们想要注入一个接口,而当前接口又有多个实现类,那么这时候就会报错,因为 Spring 无法知道到底应该注入哪一个实现类。

比如我们上面的三个类全部实现同一个接口 IWolf,那么这时候直接使用常规的,不带任何注解元数据的注入方式来注入接口 IWolf。

@Autowired
private IWolf iWolf;

解决思路主要有以下 5 种:

  1. 通过配置文件和 @ConditionalOnProperty 注解实现

    配置文件中配置了lonely.wolf=test1

@Component
@ConditionalOnProperty(name = "lonely.wolf",havingValue = "test1")
public class Wolf1Bean implements IWolf{
}

这种配置方式,编译器可能还是会提示有多个 Bean,但是只要我们确保每个实现类的条件不一致,就可以正常使用。

  1. 通过其他 @Condition 条件注解
@ConditionalOnBean:当存在某一个 Bean 时,初始化此类到容器。
@ConditionalOnClass:当存在某一个类时,初始化此类的容器。
@ConditionalOnMissingBean:当不存在某一个 Bean 时,初始化此类到容器。
@ConditionalOnMissingClass:当不存在某一个类时,初始化此类到容器。
  1. 通过 @Resource 注解动态获取

只会注入 BeanName 为 wolf1Bean 的实现类

@Component
public class InterfaceInject {
    @Resource(name = "wolf1Bean")
    private IWolf iWolf;
}
  1. 通过集合注入

可以通过集合的方式一次性注入接口的所有实现类
这两种形式都会将 IWolf 中所有的实现类注入集合中。
如果使用的是 List 集合,那么我们可以取出来再通过 instanceof 关键字来判定类型;
通过 Map 集合注入的话,Spring 会将 Bean 的名称默认类名首字母小写作为key来存储,这样我们就可以在需要的时候动态获取自己想要的实现类。

@Component
public class InterfaceInject {
    @Autowired
    List<IWolf> list;

    @Autowired
    private Map<String,IWolf> map;
}
  1. @Primary 注解实现默认注入

在其中某一个实现类上加上@Primary注解来表示当有多个 Bean 满足条件时,优先注入当前带有@Primary注解的 Bean

@Component
@Primary
public class Wolf1Bean implements IWolf{
}

2. 手动获取Bean的方式

2.1.直接注入

@Component
public class InterfaceInject {
    //注入
    @Autowired
    private ApplicationContext applicationContext;

    public Object getBean(){
        //获取bean
        return applicationContext.getBean("wolf2.ean");
    }
}

2.2 通过 ApplicationContextAware 接口获取

通过实现ApplicationContextAware接口来获取ApplicationContext对象,从而获取 Bean。
需要注意的是,实现ApplicationContextAware接口的类也需要加上注解,以便交给 Spring 统一管理(这种方式也是项目中使用比较多的一种方式)

@Component
public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    /**
     * 通过名称获取bean
     */
    public static <T> T getBeanByName(String beanName){
        return (T) applicationContext.getBean(beanName);
    }
    /**
     * 通过类型获取bean
     */
    public static <T>T getBeanByType(Class<T> clazz){
        return (T) applicationContext.getBean(clazz);
    }
}
Wolf2Bean wolf2Bean = SpringContextUtil.getBeanByName("wolf2Bean");
Wolf3Bean wolf3Bean = SpringContextUtil.getBeanByType(Wolf3Bean.class);

2.3 通过 ApplicationObjectSupport 和 WebApplicationObjectSupport 获取

这两个对象中,WebApplicationObjectSupport继承了ApplicationObjectSupport,所以并无实质的区别。

@Component
public class SpringUtil extends /*WebApplicationObjectSupport*/ ApplicationObjectSupport {
    private static ApplicationContext applicationContext = null;

    public static <T>T getBean(String beanName){
        return (T) applicationContext.getBean(beanName);
    }

    @PostConstruct
    public void init(){
        applicationContext = super.getApplicationContext();
    }
}

//有了工具类,在方法中就可以直接调用了:
@RestController
@RequestMapping("/hello")
@Qualifier
public class HelloController {
    @GetMapping("/bean3")
    public Object getBean3(){
        Wolf2.ean wolf2.ean = SpringUtil.getBean("wolf2.ean");
        return wolf2.ean.toString();
    }
}

2.4 通过 HttpServletRequest 获取

通过HttpServletRequest对象,再结合 Spring 自身提供的工具类WebApplicationContextUtils也可以获取到ApplicationContext对象,
而HttpServletRequest对象可以主动获取(如下 getBean2 方法),也可以被动获取(如下 getBean2.方法):

@RestController
@RequestMapping("/hello")
@Qualifier
public class HelloController {

    @GetMapping("/bean2.)
    public Object getBean2.HttpServletRequest request){
        //直接通过方法中的HttpServletRequest对象
        ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        Wolf2.ean wolf2.ean = (Wolf2.ean)applicationContext.getBean("wolf2.ean");

        return wolf2.ean.toString();
    }

    @GetMapping("/bean2")
    public Object getBean2(){
        //手动获取request对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());

        Wolf2Bean wolf2Bean = (Wolf2Bean)applicationContext.getBean("wolf2Bean");
        return wolf2Bean.toString();
    }
}
%5BTOC%5D%0A%0A%23%23%201%20%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%ACIOC%0A%0A%3E%20IOC%20%E7%9A%84%E6%A0%B8%E5%BF%83%E5%B0%B1%E6%98%AF%E5%8E%9F%E5%85%88%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%EF%BC%8C%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E8%87%AA%E5%B7%B1%E7%9B%B4%E6%8E%A5%E9%80%9A%E8%BF%87%20%60new%60%20%E6%9D%A5%E5%88%9B%E5%BB%BA%EF%BC%8C%E8%80%8C%20IOC%20%E5%B0%B1%E7%9B%B8%E5%BD%93%E4%BA%8E%E6%9C%89%E4%BA%BA%E5%B8%AE%E4%BB%AC%E5%88%9B%E5%BB%BA%E5%A5%BD%E4%BA%86%E5%AF%B9%E8%B1%A1%EF%BC%8C%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E7%9A%84%E6%97%B6%E5%80%99%E7%9B%B4%E6%8E%A5%E5%8E%BB%E6%8B%BF%E5%B0%B1%E8%A1%8C%0A%0A%3E%20IOC%20%E4%B8%BB%E8%A6%81%E6%9C%89%E4%B8%A4%E7%A7%8D%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F%EF%BC%9A%0A%3E%20DL%EF%BC%88Dependency%20Lookup%EF%BC%89%EF%BC%9A%E4%BE%9D%E8%B5%96%E6%9F%A5%E6%89%BE%0A%3E%20DI%EF%BC%88Dependency%20Inject%EF%BC%89%EF%BC%9A%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%0A%0A%23%23%23%201.1%20%E4%BE%9D%E8%B5%96%E6%9F%A5%E6%89%BE%0A%0A%3E%20DL%EF%BC%88Dependency%20Lookup%EF%BC%89%0A%3E%0A%3E%20%20%E5%AE%B9%E5%99%A8%E5%B8%AE%E6%88%91%E4%BB%AC%E5%88%9B%E5%BB%BA%E5%A5%BD%E4%BA%86%E5%AF%B9%E8%B1%A1%EF%BC%8C%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E7%9A%84%E6%97%B6%E5%80%99%E8%87%AA%E5%B7%B1%E5%86%8D%E4%B8%BB%E5%8A%A8%E5%8E%BB%E5%AE%B9%E5%99%A8%E4%B8%AD%E6%9F%A5%E6%89%BE%0A%0A%60%60%60java%0AApplicationContext%20applicationContext%20%3D%20new%20ClassPathXmlApplicationContext(%22%2Fapplication-context.xml%22)%3B%0AObject%20bean%20%3D%20applicationContext.getBean(%22object%22)%3B%0A%60%60%60%0A%0A%0A%23%23%23%201.2%20%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%0A%0A%3E%20DI%EF%BC%88Dependency%20Inject%EF%BC%89%0A%3E%0A%3E%20%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E7%9B%B8%E6%AF%94%E8%BE%83%E4%BE%9D%E8%B5%96%E6%9F%A5%E6%89%BE%E5%8F%88%E6%98%AF%E4%B8%80%E7%A7%8D%E4%BC%98%E5%8C%96%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%88%91%E4%BB%AC%E4%B8%8D%E9%9C%80%E8%A6%81%E8%87%AA%E5%B7%B1%E5%8E%BB%E6%9F%A5%E6%89%BE%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E5%91%8A%E8%AF%89%E5%AE%B9%E5%99%A8%E5%BD%93%E5%89%8D%E9%9C%80%E8%A6%81%E6%B3%A8%E5%85%A5%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%AE%B9%E5%99%A8%E5%B0%B1%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%B0%86%E5%88%9B%E5%BB%BA%E5%A5%BD%E7%9A%84%E5%AF%B9%E8%B1%A1%E8%BF%9B%E8%A1%8C%E6%B3%A8%E5%85%A5%EF%BC%88%E8%B5%8B%E5%80%BC%EF%BC%89%0A%0A%23%23%23%23%201.2.1%20%E4%B8%89%E7%A7%8D%E5%B8%B8%E8%A7%84%E6%B3%A8%E5%85%A5%E6%96%B9%E5%BC%8F%0A%0A%23%23%23%23%23%201.%20%20%E5%9F%BA%E4%BA%8E%E5%B1%9E%E6%80%A7%E6%B3%A8%E5%85%A5%0A%0A%60%60%60java%0A%40Service%0Apublic%20class%20UserService%20%7B%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20Wolf1Bean%20wolf1Bean%3B%2F%2F%E9%80%9A%E8%BF%87%E5%B1%9E%E6%80%A7%E6%B3%A8%E5%85%A5%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%202.%20%20%E5%9F%BA%E4%BA%8E%20setter%20%E6%96%B9%E6%B3%95%0A%0A%60%60%60java%0A%40Service%0Apublic%20class%20UserService%20%7B%0A%20%20%20%20private%20Wolf3Bean%20wolf3Bean%3B%0A%20%20%20%20%0A%20%20%20%20%40Autowired%20%20%2F%2F%E9%80%9A%E8%BF%87setter%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0%E6%B3%A8%E5%85%A5%0A%20%20%20%20public%20void%20setWolf3Bean(Wolf3Bean%20wolf3Bean)%20%7B%0A%20%20%20%20%20%20%20%20this.wolf3Bean%20%3D%20wolf3Bean%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%203.%20%E6%B3%A8%E5%85%A5%E5%9F%BA%E4%BA%8E%E6%9E%84%E9%80%A0%E5%99%A8%E6%B3%A8%E5%85%A5%0A%0A%60%60%60java%0A%40Service%0Apublic%20class%20UserService%20%7B%0A%20%20private%20Wolf2Bean%20wolf2Bean%3B%0A%20%20%20%20%0A%20%20%20%20%40Autowired%20%2F%2F%E9%80%9A%E8%BF%87%E6%9E%84%E9%80%A0%E5%99%A8%E6%B3%A8%E5%85%A5%0A%20%20%20%20public%20UserService(Wolf2Bean%20wolf2Bean)%20%7B%0A%20%20%20%20%20%20%20%20this.wolf2Bean%20%3D%20wolf2Bean%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%201.2.2%20%E6%8E%A5%E5%8F%A3%E6%B3%A8%E5%85%A5%0A%0A%3E%20%E5%81%87%E5%A6%82%E6%88%91%E4%BB%AC%E6%83%B3%E8%A6%81%E6%B3%A8%E5%85%A5%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%EF%BC%8C%E8%80%8C%E5%BD%93%E5%89%8D%E6%8E%A5%E5%8F%A3%E5%8F%88%E6%9C%89%E5%A4%9A%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%B1%BB%EF%BC%8C%E9%82%A3%E4%B9%88%E8%BF%99%E6%97%B6%E5%80%99%E5%B0%B1%E4%BC%9A%E6%8A%A5%E9%94%99%EF%BC%8C%E5%9B%A0%E4%B8%BA%20Spring%20%E6%97%A0%E6%B3%95%E7%9F%A5%E9%81%93%E5%88%B0%E5%BA%95%E5%BA%94%E8%AF%A5%E6%B3%A8%E5%85%A5%E5%93%AA%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%B1%BB%E3%80%82%0A%3E%0A%3E%20%E6%AF%94%E5%A6%82%E6%88%91%E4%BB%AC%E4%B8%8A%E9%9D%A2%E7%9A%84%E4%B8%89%E4%B8%AA%E7%B1%BB%E5%85%A8%E9%83%A8%E5%AE%9E%E7%8E%B0%E5%90%8C%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%20IWolf%EF%BC%8C%E9%82%A3%E4%B9%88%E8%BF%99%E6%97%B6%E5%80%99%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E5%B8%B8%E8%A7%84%E7%9A%84%EF%BC%8C%E4%B8%8D%E5%B8%A6%E4%BB%BB%E4%BD%95%E6%B3%A8%E8%A7%A3%E5%85%83%E6%95%B0%E6%8D%AE%E7%9A%84%E6%B3%A8%E5%85%A5%E6%96%B9%E5%BC%8F%E6%9D%A5%E6%B3%A8%E5%85%A5%E6%8E%A5%E5%8F%A3%20IWolf%E3%80%82%0A%0A%60%60%60java%0A%40Autowired%0Aprivate%20IWolf%20iWolf%3B%0A%60%60%60%0A%0A%3E%20%E8%A7%A3%E5%86%B3%E6%80%9D%E8%B7%AF%E4%B8%BB%E8%A6%81%E6%9C%89%E4%BB%A5%E4%B8%8B%205%20%E7%A7%8D%EF%BC%9A%0A%0A1.%20**%E9%80%9A%E8%BF%87%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%92%8C%20%40ConditionalOnProperty%20%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0**%0A%0A%20%20%20%3E%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E9%85%8D%E7%BD%AE%E4%BA%86%60lonely.wolf%3Dtest1%60%0A%0A%60%60%60%0A%40Component%0A%40ConditionalOnProperty(name%20%3D%20%22lonely.wolf%22%2ChavingValue%20%3D%20%22test1%22)%0Apublic%20class%20Wolf1Bean%20implements%20IWolf%7B%0A%7D%0A%60%60%60%0A%0A%3E%20%E8%BF%99%E7%A7%8D%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F%EF%BC%8C%E7%BC%96%E8%AF%91%E5%99%A8%E5%8F%AF%E8%83%BD%E8%BF%98%E6%98%AF%E4%BC%9A%E6%8F%90%E7%A4%BA%E6%9C%89%E5%A4%9A%E4%B8%AA%20Bean%EF%BC%8C%E4%BD%86%E6%98%AF%E5%8F%AA%E8%A6%81%E6%88%91%E4%BB%AC%E7%A1%AE%E4%BF%9D%E6%AF%8F%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%B1%BB%E7%9A%84%E6%9D%A1%E4%BB%B6%E4%B8%8D%E4%B8%80%E8%87%B4%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E6%AD%A3%E5%B8%B8%E4%BD%BF%E7%94%A8%E3%80%82%0A%0A2.%20**%E9%80%9A%E8%BF%87%E5%85%B6%E4%BB%96%20%40Condition%20%E6%9D%A1%E4%BB%B6%E6%B3%A8%E8%A7%A3**%0A%0A%60%60%60java%0A%40ConditionalOnBean%EF%BC%9A%E5%BD%93%E5%AD%98%E5%9C%A8%E6%9F%90%E4%B8%80%E4%B8%AA%20Bean%20%E6%97%B6%EF%BC%8C%E5%88%9D%E5%A7%8B%E5%8C%96%E6%AD%A4%E7%B1%BB%E5%88%B0%E5%AE%B9%E5%99%A8%E3%80%82%0A%40ConditionalOnClass%EF%BC%9A%E5%BD%93%E5%AD%98%E5%9C%A8%E6%9F%90%E4%B8%80%E4%B8%AA%E7%B1%BB%E6%97%B6%EF%BC%8C%E5%88%9D%E5%A7%8B%E5%8C%96%E6%AD%A4%E7%B1%BB%E7%9A%84%E5%AE%B9%E5%99%A8%E3%80%82%0A%40ConditionalOnMissingBean%EF%BC%9A%E5%BD%93%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%9F%90%E4%B8%80%E4%B8%AA%20Bean%20%E6%97%B6%EF%BC%8C%E5%88%9D%E5%A7%8B%E5%8C%96%E6%AD%A4%E7%B1%BB%E5%88%B0%E5%AE%B9%E5%99%A8%E3%80%82%0A%40ConditionalOnMissingClass%EF%BC%9A%E5%BD%93%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%9F%90%E4%B8%80%E4%B8%AA%E7%B1%BB%E6%97%B6%EF%BC%8C%E5%88%9D%E5%A7%8B%E5%8C%96%E6%AD%A4%E7%B1%BB%E5%88%B0%E5%AE%B9%E5%99%A8%E3%80%82%0A%60%60%60%0A%0A3.%20**%E9%80%9A%E8%BF%87%20%40Resource%20%E6%B3%A8%E8%A7%A3%E5%8A%A8%E6%80%81%E8%8E%B7%E5%8F%96**%0A%0A%3E%20%E5%8F%AA%E4%BC%9A%E6%B3%A8%E5%85%A5%20BeanName%20%E4%B8%BA%20wolf1Bean%20%E7%9A%84%E5%AE%9E%E7%8E%B0%E7%B1%BB%0A%0A%60%60%60java%0A%40Component%0Apublic%20class%20InterfaceInject%20%7B%0A%20%20%20%20%40Resource(name%20%3D%20%22wolf1Bean%22)%0A%20%20%20%20private%20IWolf%20iWolf%3B%0A%7D%0A%60%60%60%0A%0A4.%20**%E9%80%9A%E8%BF%87%E9%9B%86%E5%90%88%E6%B3%A8%E5%85%A5**%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E9%9B%86%E5%90%88%E7%9A%84%E6%96%B9%E5%BC%8F%E4%B8%80%E6%AC%A1%E6%80%A7%E6%B3%A8%E5%85%A5%E6%8E%A5%E5%8F%A3%E7%9A%84%E6%89%80%E6%9C%89%E5%AE%9E%E7%8E%B0%E7%B1%BB%0A%3E%20%E8%BF%99%E4%B8%A4%E7%A7%8D%E5%BD%A2%E5%BC%8F%E9%83%BD%E4%BC%9A%E5%B0%86%20IWolf%20%E4%B8%AD%E6%89%80%E6%9C%89%E7%9A%84%E5%AE%9E%E7%8E%B0%E7%B1%BB%E6%B3%A8%E5%85%A5%E9%9B%86%E5%90%88%E4%B8%AD%E3%80%82%0A%3E%20%E5%A6%82%E6%9E%9C%E4%BD%BF%E7%94%A8%E7%9A%84%E6%98%AF%20List%20%E9%9B%86%E5%90%88%EF%BC%8C%E9%82%A3%E4%B9%88%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E5%8F%96%E5%87%BA%E6%9D%A5%E5%86%8D%E9%80%9A%E8%BF%87%20%60instanceof%60%20%E5%85%B3%E9%94%AE%E5%AD%97%E6%9D%A5%E5%88%A4%E5%AE%9A%E7%B1%BB%E5%9E%8B%EF%BC%9B%0A%3E%20%E9%80%9A%E8%BF%87%20Map%20%E9%9B%86%E5%90%88%E6%B3%A8%E5%85%A5%E7%9A%84%E8%AF%9D%EF%BC%8CSpring%20%E4%BC%9A%E5%B0%86%20Bean%20%E7%9A%84%E5%90%8D%E7%A7%B0%60%E9%BB%98%E8%AE%A4%E7%B1%BB%E5%90%8D%E9%A6%96%E5%AD%97%E6%AF%8D%E5%B0%8F%E5%86%99%60%E4%BD%9C%E4%B8%BAkey%E6%9D%A5%E5%AD%98%E5%82%A8%EF%BC%8C%E8%BF%99%E6%A0%B7%E6%88%91%E4%BB%AC%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%9C%A8%E9%9C%80%E8%A6%81%E7%9A%84%E6%97%B6%E5%80%99%E5%8A%A8%E6%80%81%E8%8E%B7%E5%8F%96%E8%87%AA%E5%B7%B1%E6%83%B3%E8%A6%81%E7%9A%84%E5%AE%9E%E7%8E%B0%E7%B1%BB%E3%80%82%0A%0A%60%60%60java%0A%40Component%0Apublic%20class%20InterfaceInject%20%7B%0A%20%20%20%20%40Autowired%0A%20%20%20%20List%3CIWolf%3E%20list%3B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20Map%3CString%2CIWolf%3E%20map%3B%0A%7D%0A%60%60%60%0A%0A5.%20**%40Primary%20%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0%E9%BB%98%E8%AE%A4%E6%B3%A8%E5%85%A5**%0A%3E%20%E5%9C%A8%E5%85%B6%E4%B8%AD%E6%9F%90%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%B1%BB%E4%B8%8A%E5%8A%A0%E4%B8%8A%60%40Primary%60%E6%B3%A8%E8%A7%A3%E6%9D%A5%E8%A1%A8%E7%A4%BA%E5%BD%93%E6%9C%89%E5%A4%9A%E4%B8%AA%20Bean%20%E6%BB%A1%E8%B6%B3%E6%9D%A1%E4%BB%B6%E6%97%B6%EF%BC%8C%E4%BC%98%E5%85%88%E6%B3%A8%E5%85%A5%E5%BD%93%E5%89%8D%E5%B8%A6%E6%9C%89%60%40Primary%60%E6%B3%A8%E8%A7%A3%E7%9A%84%20Bean%0A%0A%60%60%60java%0A%40Component%0A%40Primary%0Apublic%20class%20Wolf1Bean%20implements%20IWolf%7B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%202.%20%E6%89%8B%E5%8A%A8%E8%8E%B7%E5%8F%96Bean%E7%9A%84%E6%96%B9%E5%BC%8F%0A%23%23%23%23%202.1.%E7%9B%B4%E6%8E%A5%E6%B3%A8%E5%85%A5%0A%60%60%60java%0A%40Component%0Apublic%20class%20InterfaceInject%20%7B%0A%20%20%20%20%2F%2F%E6%B3%A8%E5%85%A5%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20ApplicationContext%20applicationContext%3B%0A%0A%20%20%20%20public%20Object%20getBean()%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E8%8E%B7%E5%8F%96bean%0A%20%20%20%20%20%20%20%20return%20applicationContext.getBean(%22wolf2.ean%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%23%23%23%23%202.2%20%E9%80%9A%E8%BF%87%20ApplicationContextAware%20%E6%8E%A5%E5%8F%A3%E8%8E%B7%E5%8F%96%0A%3E%20%E9%80%9A%E8%BF%87%E5%AE%9E%E7%8E%B0ApplicationContextAware%E6%8E%A5%E5%8F%A3%E6%9D%A5%E8%8E%B7%E5%8F%96ApplicationContext%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BB%8E%E8%80%8C%E8%8E%B7%E5%8F%96%20Bean%E3%80%82%0A%3E%20%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%EF%BC%8C%E5%AE%9E%E7%8E%B0ApplicationContextAware%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%E4%B9%9F%E9%9C%80%E8%A6%81%E5%8A%A0%E4%B8%8A%E6%B3%A8%E8%A7%A3%EF%BC%8C%E4%BB%A5%E4%BE%BF%E4%BA%A4%E7%BB%99%20Spring%20%E7%BB%9F%E4%B8%80%E7%AE%A1%E7%90%86%EF%BC%88%E8%BF%99%E7%A7%8D%E6%96%B9%E5%BC%8F%E4%B9%9F%E6%98%AF%E9%A1%B9%E7%9B%AE%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%AF%94%E8%BE%83%E5%A4%9A%E7%9A%84%E4%B8%80%E7%A7%8D%E6%96%B9%E5%BC%8F%EF%BC%89%0A%60%60%60java%0A%40Component%0Apublic%20class%20SpringContextUtil%20implements%20ApplicationContextAware%20%7B%0A%20%20%20%20private%20static%20ApplicationContext%20applicationContext%20%3D%20null%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20setApplicationContext(ApplicationContext%20applicationContext)%20throws%20BeansException%20%7B%0A%20%20%20%20%20%20%20%20this.applicationContext%20%3D%20applicationContext%3B%0A%20%20%20%20%7D%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E9%80%9A%E8%BF%87%E5%90%8D%E7%A7%B0%E8%8E%B7%E5%8F%96bean%0A%20%20%20%20%20*%2F%0A%20%20%20%20public%20static%20%3CT%3E%20T%20getBeanByName(String%20beanName)%7B%0A%20%20%20%20%20%20%20%20return%20(T)%20applicationContext.getBean(beanName)%3B%0A%20%20%20%20%7D%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E9%80%9A%E8%BF%87%E7%B1%BB%E5%9E%8B%E8%8E%B7%E5%8F%96bean%0A%20%20%20%20%20*%2F%0A%20%20%20%20public%20static%20%3CT%3ET%20getBeanByType(Class%3CT%3E%20clazz)%7B%0A%20%20%20%20%20%20%20%20return%20(T)%20applicationContext.getBean(clazz)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0AWolf2Bean%20wolf2Bean%20%3D%20SpringContextUtil.getBeanByName(%22wolf2Bean%22)%3B%0AWolf3Bean%20wolf3Bean%20%3D%20SpringContextUtil.getBeanByType(Wolf3Bean.class)%3B%0A%60%60%60%0A%0A%23%23%23%23%202.3%20%E9%80%9A%E8%BF%87%20ApplicationObjectSupport%20%E5%92%8C%20WebApplicationObjectSupport%20%E8%8E%B7%E5%8F%96%0A%3E%20%E8%BF%99%E4%B8%A4%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%B8%AD%EF%BC%8CWebApplicationObjectSupport%E7%BB%A7%E6%89%BF%E4%BA%86ApplicationObjectSupport%EF%BC%8C%E6%89%80%E4%BB%A5%E5%B9%B6%E6%97%A0%E5%AE%9E%E8%B4%A8%E7%9A%84%E5%8C%BA%E5%88%AB%E3%80%82%0A%0A%60%60%60java%0A%40Component%0Apublic%20class%20SpringUtil%20extends%20%2F*WebApplicationObjectSupport*%2F%20ApplicationObjectSupport%20%7B%0A%20%20%20%20private%20static%20ApplicationContext%20applicationContext%20%3D%20null%3B%0A%0A%20%20%20%20public%20static%20%3CT%3ET%20getBean(String%20beanName)%7B%0A%20%20%20%20%20%20%20%20return%20(T)%20applicationContext.getBean(beanName)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40PostConstruct%0A%20%20%20%20public%20void%20init()%7B%0A%20%20%20%20%20%20%20%20applicationContext%20%3D%20super.getApplicationContext()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2F%E6%9C%89%E4%BA%86%E5%B7%A5%E5%85%B7%E7%B1%BB%EF%BC%8C%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%AD%E5%B0%B1%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E8%B0%83%E7%94%A8%E4%BA%86%EF%BC%9A%0A%40RestController%0A%40RequestMapping(%22%2Fhello%22)%0A%40Qualifier%0Apublic%20class%20HelloController%20%7B%0A%20%20%20%20%40GetMapping(%22%2Fbean3%22)%0A%20%20%20%20public%20Object%20getBean3()%7B%0A%20%20%20%20%20%20%20%20Wolf2.ean%20wolf2.ean%20%3D%20SpringUtil.getBean(%22wolf2.ean%22)%3B%0A%20%20%20%20%20%20%20%20return%20wolf2.ean.toString()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202.4%20%E9%80%9A%E8%BF%87%20HttpServletRequest%20%E8%8E%B7%E5%8F%96%0A%3E%20%E9%80%9A%E8%BF%87HttpServletRequest%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%86%8D%E7%BB%93%E5%90%88%20Spring%20%E8%87%AA%E8%BA%AB%E6%8F%90%E4%BE%9B%E7%9A%84%E5%B7%A5%E5%85%B7%E7%B1%BB%60WebApplicationContextUtils%60%E4%B9%9F%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%8F%96%E5%88%B0ApplicationContext%E5%AF%B9%E8%B1%A1%EF%BC%8C%0A%3E%20%E8%80%8CHttpServletRequest%E5%AF%B9%E8%B1%A1%E5%8F%AF%E4%BB%A5%E4%B8%BB%E5%8A%A8%E8%8E%B7%E5%8F%96%EF%BC%88%E5%A6%82%E4%B8%8B%20getBean2%20%E6%96%B9%E6%B3%95%EF%BC%89%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%EF%BC%88%E5%A6%82%E4%B8%8B%20getBean2.%E6%96%B9%E6%B3%95%EF%BC%89%EF%BC%9A%0A%0A%60%60%60java%0A%40RestController%0A%40RequestMapping(%22%2Fhello%22)%0A%40Qualifier%0Apublic%20class%20HelloController%20%7B%0A%0A%20%20%20%20%40GetMapping(%22%2Fbean2.)%0A%20%20%20%20public%20Object%20getBean2.HttpServletRequest%20request)%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E7%9B%B4%E6%8E%A5%E9%80%9A%E8%BF%87%E6%96%B9%E6%B3%95%E4%B8%AD%E7%9A%84HttpServletRequest%E5%AF%B9%E8%B1%A1%0A%20%20%20%20%20%20%20%20ApplicationContext%20applicationContext%20%3D%20WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext())%3B%0A%20%20%20%20%20%20%20%20Wolf2.ean%20wolf2.ean%20%3D%20(Wolf2.ean)applicationContext.getBean(%22wolf2.ean%22)%3B%0A%0A%20%20%20%20%20%20%20%20return%20wolf2.ean.toString()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40GetMapping(%22%2Fbean2%22)%0A%20%20%20%20public%20Object%20getBean2()%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E6%89%8B%E5%8A%A8%E8%8E%B7%E5%8F%96request%E5%AF%B9%E8%B1%A1%0A%20%20%20%20%20%20%20%20HttpServletRequest%20request%20%3D%20((ServletRequestAttributes)%20RequestContextHolder.getRequestAttributes()).getRequest()%3B%0A%20%20%20%20%20%20%20%20ApplicationContext%20applicationContext%20%3D%20WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext())%3B%0A%0A%20%20%20%20%20%20%20%20Wolf2Bean%20wolf2Bean%20%3D%20(Wolf2Bean)applicationContext.getBean(%22wolf2Bean%22)%3B%0A%20%20%20%20%20%20%20%20return%20wolf2Bean.toString()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A

Maven常见问题

创建时间:2020/9/2 15:31
更新时间:2022/12/8 22:40
作者:Chris
来源:https://blog.csdn.net/u010406047/article/details/110878472

1.查看依赖

mvn dependency:tree
mvn dependency:tree -Dverbose -Dincludes=commons-collections

idea 可以安装 maven helper 插件

2. maven-surefire-plugin

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
    	<skipTests>true</skipTests>
    </configuration>
</plugin>

3. 添加aliyun镜像

D:\apache-maven-3.6.3\conf\settings.xml

  <mirror> 
      <id>alimaven</id> 
      <name>aliyun maven</name> 
      <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> 
      <mirrorOf>central</mirrorOf> 
    </mirror>

4. spring-boot-maven-plugin

简述

spring-boot-maven-plugin是spring boot提供的maven打包插件。可打直接可运行的jar包或war包。

官网

https://docs.spring.io/spring-boot/docs/2.2.1.RELEASE/maven-plugin/

GoalDescription
spring-boot:build-infoGenerate a build-info.properties file based the content of the current MavenProject.
spring-boot:helpDisplay help information on spring-boot-maven-plugin. Call mvn spring-boot:help -Ddetail=true -Dgoal= to display parameter details.
spring-boot:repackageRepackages existing JAR and WAR archives so that they can be executed from the command line using java -jar. With layout=NONE can also be used simply to package a JAR with nested dependencies (and no main class, so not executable).
spring-boot:runRun an executable archive application.
spring-boot:startStart a spring application. Contrary to the run goal, this does not block and allows other goal to operate on the application. This goal is typically used in integration test scenario where the application is started before a test suite and stopped after.
spring-boot:stopStop a spring application that has been started by the "start" goal. Typically invoked once a test suite has completed.

打包:repackage
打包主要使用的是repackage goal,它是spring-boot-starter-parent为插件设置的默认goal。这个goal绑定在maven的 package生命周期上,完整命令为mvn package spring-boot:repackage。在 mvn package 执行打包之后,repackage 再次打包生成可执行的 jar包或war包.

5. 打源码包

<!-- 打源码包 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>3.2.1</version>
    <executions>
        <execution>
            <id>attach-sources</id>
            <phase>verify</phase>
            <goals>
                <goal>jar-no-fork</goal>
            </goals>
        </execution>
    </executions>
</plugin>
%5BTOC%5D%0A%0A%23%23%201.%E6%9F%A5%E7%9C%8B%E4%BE%9D%E8%B5%96%0A%0A%60%60%60%0Amvn%20dependency%3Atree%0A%60%60%60%0A%0A%60%60%60%0Amvn%20dependency%3Atree%20-Dverbose%20-Dincludes%3Dcommons-collections%0A%60%60%60%0A%0A%3E%20idea%20%E5%8F%AF%E4%BB%A5%E5%AE%89%E8%A3%85%20maven%20helper%20%E6%8F%92%E4%BB%B6%0A%0A%0A%0A%23%23%202.%20maven-surefire-plugin%0A%0AFailed%20to%20execute%20goal%20org.apache.maven.plugins%3Amaven-surefire-plugin%3A2.12.4%3Atest%0A%0A%60%60%60xml%0A%3Cplugin%3E%0A%20%20%20%20%3CgroupId%3Eorg.apache.maven.plugins%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Emaven-surefire-plugin%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E3.0.0-M5%3C%2Fversion%3E%0A%20%20%20%20%3Cconfiguration%3E%0A%20%20%20%20%09%3CskipTests%3Etrue%3C%2FskipTests%3E%0A%20%20%20%20%3C%2Fconfiguration%3E%0A%3C%2Fplugin%3E%0A%60%60%60%0A%0A%0A%23%23%203.%20%E6%B7%BB%E5%8A%A0aliyun%E9%95%9C%E5%83%8F%0A%3E%20D%3A%5Capache-maven-3.6.3%5Cconf%5Csettings.xml%0A%60%60%60%0A%20%20%3Cmirror%3E%20%0A%20%20%20%20%20%20%3Cid%3Ealimaven%3C%2Fid%3E%20%0A%20%20%20%20%20%20%3Cname%3Ealiyun%20maven%3C%2Fname%3E%20%0A%20%20%20%20%20%20%3Curl%3Ehttp%3A%2F%2Fmaven.aliyun.com%2Fnexus%2Fcontent%2Frepositories%2Fcentral%2F%3C%2Furl%3E%20%0A%20%20%20%20%20%20%3CmirrorOf%3Ecentral%3C%2FmirrorOf%3E%20%0A%20%20%20%20%3C%2Fmirror%3E%0A%60%60%60%0A%0A%23%23%204.%20spring-boot-maven-plugin%0A%23%23%23%20%E7%AE%80%E8%BF%B0%0A%3E%20%5Bspring-boot-maven-plugin%E6%98%AFspring%20boot%E6%8F%90%E4%BE%9B%E7%9A%84maven%E6%89%93%E5%8C%85%E6%8F%92%E4%BB%B6%E3%80%82%E5%8F%AF%E6%89%93%E7%9B%B4%E6%8E%A5%E5%8F%AF%E8%BF%90%E8%A1%8C%E7%9A%84jar%E5%8C%85%E6%88%96war%E5%8C%85%E3%80%82%5D(https%3A%2F%2Fblog.csdn.net%2Fu010406047%2Farticle%2Fdetails%2F110878472)%0A%0A%0A%23%23%23%20%E5%AE%98%E7%BD%91%0A%3E%20https%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.2.1.RELEASE%2Fmaven-plugin%2F%0A%0A%0A%7C%20Goal%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Description%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20------------------------------------------------------------%20%7C%20------------------------------------------------------------%20%7C%0A%7C%20%5Bspring-boot%3Abuild-info%5D(https%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.2.1.RELEASE%2Fmaven-plugin%2Fbuild-info-mojo.html)%20%7C%20Generate%20a%20%60build-info.properties%60%20file%20based%20the%20content%20of%20the%20current%20%60MavenProject%60.%20%7C%0A%7C%20%5Bspring-boot%3Ahelp%5D(https%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.2.1.RELEASE%2Fmaven-plugin%2Fhelp-mojo.html)%20%7C%20Display%20help%20information%20on%20spring-boot-maven-plugin.%20Call%20%60mvn%20spring-boot%3Ahelp%20-Ddetail%3Dtrue%20-Dgoal%3D%60%20to%20display%20parameter%20details.%20%7C%0A%7C%20%5Bspring-boot%3Arepackage%5D(https%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.2.1.RELEASE%2Fmaven-plugin%2Frepackage-mojo.html)%20%7C%20Repackages%20existing%20JAR%20and%20WAR%20archives%20so%20that%20they%20can%20be%20executed%20from%20the%20command%20line%20using%20java%20-jar.%20With%20%60layout%3DNONE%60%20can%20also%20be%20used%20simply%20to%20package%20a%20JAR%20with%20nested%20dependencies%20(and%20no%20main%20class%2C%20so%20not%20executable).%20%7C%0A%7C%20%5Bspring-boot%3Arun%5D(https%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.2.1.RELEASE%2Fmaven-plugin%2Frun-mojo.html)%20%7C%20Run%20an%20executable%20archive%20application.%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%5Bspring-boot%3Astart%5D(https%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.2.1.RELEASE%2Fmaven-plugin%2Fstart-mojo.html)%20%7C%20Start%20a%20spring%20application.%20Contrary%20to%20the%20%60run%60%20goal%2C%20this%20does%20not%20block%20and%20allows%20other%20goal%20to%20operate%20on%20the%20application.%20This%20goal%20is%20typically%20used%20in%20integration%20test%20scenario%20where%20the%20application%20is%20started%20before%20a%20test%20suite%20and%20stopped%20after.%20%7C%0A%7C%20%5Bspring-boot%3Astop%5D(https%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.2.1.RELEASE%2Fmaven-plugin%2Fstop-mojo.html)%20%7C%20Stop%20a%20spring%20application%20that%20has%20been%20started%20by%20the%20%22start%22%20goal.%20Typically%20invoked%20once%20a%20test%20suite%20has%20completed.%20%7C%0A%0A%0A%3E%20%60%E6%89%93%E5%8C%85%EF%BC%9Arepackage%60%0A%3E%20%E6%89%93%E5%8C%85%E4%B8%BB%E8%A6%81%E4%BD%BF%E7%94%A8%E7%9A%84%E6%98%AFrepackage%20goal%EF%BC%8C%E5%AE%83%E6%98%AFspring-boot-starter-parent%E4%B8%BA%E6%8F%92%E4%BB%B6%E8%AE%BE%E7%BD%AE%E7%9A%84%E9%BB%98%E8%AE%A4goal%E3%80%82%E8%BF%99%E4%B8%AAgoal%E7%BB%91%E5%AE%9A%E5%9C%A8maven%E7%9A%84%20package%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E4%B8%8A%EF%BC%8C%E5%AE%8C%E6%95%B4%E5%91%BD%E4%BB%A4%E4%B8%BAmvn%20package%20spring-boot%3Arepackage%E3%80%82%E5%9C%A8%20mvn%20package%20%E6%89%A7%E8%A1%8C%E6%89%93%E5%8C%85%E4%B9%8B%E5%90%8E%EF%BC%8Crepackage%20%E5%86%8D%E6%AC%A1%E6%89%93%E5%8C%85%E7%94%9F%E6%88%90%E5%8F%AF%E6%89%A7%E8%A1%8C%E7%9A%84%20jar%E5%8C%85%E6%88%96war%E5%8C%85.%0A%0A%23%23%205.%20%E6%89%93%E6%BA%90%E7%A0%81%E5%8C%85%0A%60%60%60xml%0A%3C!--%20%E6%89%93%E6%BA%90%E7%A0%81%E5%8C%85%20--%3E%0A%3Cplugin%3E%0A%20%20%20%20%3CgroupId%3Eorg.apache.maven.plugins%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Emaven-source-plugin%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E3.2.1%3C%2Fversion%3E%0A%20%20%20%20%3Cexecutions%3E%0A%20%20%20%20%20%20%20%20%3Cexecution%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cid%3Eattach-sources%3C%2Fid%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cphase%3Everify%3C%2Fphase%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cgoals%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cgoal%3Ejar-no-fork%3C%2Fgoal%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fgoals%3E%0A%20%20%20%20%20%20%20%20%3C%2Fexecution%3E%0A%20%20%20%20%3C%2Fexecutions%3E%0A%3C%2Fplugin%3E%0A%60%60%60

maven中的scope总结

创建时间:2022/5/26 17:29
更新时间:2022/12/8 21:54
作者:Chris
来源:https://blog.csdn.net/qgnczmnmn/article/details/118050472

Maven中的scope主要有以下6种,接下来分别介绍下这几种Scope:

1. compile

不声明scope元素的情况下的 默认值
compile表示被依赖包需要参与当前项目的编译,包括后续的测试运行周期也参与其中,是一个比较强的依赖;
打包的时候通常需要包含进去。

2. provided

provided 类型的scope只会在项目的编译,测试阶段起作用;

可以认为在目标容器中已经提供了这个依赖,无需在提供,但是在编写代码或者编译时可能会用到这个依赖;

依赖不会被打入到项目jar包中

说到provided,这里就要说到<dependency>下的子标签<optional> ,如果一个依赖的<optional> 设置为true,则该依赖在打包的时候不会被打进jar包,同时不会通过依赖传递传递到依赖该项目的工程;
例如:x依赖B,B由依赖于A(x->B->A),则A中设置<optional> 为true的依赖不会被传递到x中。

这两者的区别在于:
1、<optional>为true 表示某个依赖可选,该依赖是否使用都不会影响服务运行;
2、provided的<scope>在目标容器中已经提供了这个依赖,无需在提供

3. runtime

runtime 与 compile 比较相似,区别在于runtime 跳过了编译阶段,打包的时候通常需要包含进去。

4. test

在一般的编译和运行时都不需要,它们只有在测试编译测试运行阶段可用,

不会被打包到项目jar包中

同时如果项目A依赖于项目B,项目B中的test作用域下的依赖不会被继承。

5. system

表示使用本地系统路径下的jar包,需要和一个systemPath一起使用,如下:

<dependency>
	<groupId>xxxx</groupId>
	<artifactId>xxx</artifactId>
	<systemPath>${basedir}/lib/xxxxx.jar</systemPath>
	<scope>system</scope>
	<version>1.4.12</version>
</dependency>

6. import

import 只能在pom文件的<dependencyManagement>中使用,从而引入其他的pom文件中引入依赖,

如:在Spring boot 项目的POM文件中,我们可以通过在POM文件中继承 Spring-boot-starter-parent来引用Spring boot默认依赖的jar包,如下:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.0.1.BUILD-SNAPSHOT</version>
</parent>

但是,通过上面的parent继承的方法,只能继承一个 spring-boot-start-parent。
实际开发中,用户很可能需要继承自己公司的标准parent配置,这个时候可以使用 scope=import 来实现多继承。代码如下:

<dependencyManagement>
     <dependencies>
         <dependency>
             <!-- Import dependency management from Spring Boot -->
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-dependencies</artifactId>
             <version>2.0.1.BUILD-SNAPSHOT</version>
             <type>pom</type>
             <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

通过上面方式,就可以获取spring-boot-dependencies.2.0.1.BUILD-SNAPSHOT.pom文件中dependencyManagement配置的jar包依赖。
如果要继承多个,可以在dependencyManagement中添加,如:

<dependencyManagement>
     <dependencies>
         <!-- Override Spring Data release train provided by Spring Boot -->
         <dependency>
             <groupId>org.springframework.data</groupId>
             <artifactId>spring-data-releasetrain</artifactId>
             <version>Fowler-SR2</version>
             <type>pom</type>
             <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.0.1.BUILD-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
%5Btoc%5D%0A%0A%0AMaven%E4%B8%AD%E7%9A%84scope%E4%B8%BB%E8%A6%81%E6%9C%89%E4%BB%A5%E4%B8%8B6%E7%A7%8D%EF%BC%8C%E6%8E%A5%E4%B8%8B%E6%9D%A5%E5%88%86%E5%88%AB%E4%BB%8B%E7%BB%8D%E4%B8%8B%E8%BF%99%E5%87%A0%E7%A7%8DScope%EF%BC%9A%0A%0A%23%23%23%23%201.%20compile%0A%0A%3E%20%E4%B8%8D%E5%A3%B0%E6%98%8Escope%E5%85%83%E7%B4%A0%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E7%9A%84%20**%E9%BB%98%E8%AE%A4%E5%80%BC**%EF%BC%9B%0A%3E%20compile%E8%A1%A8%E7%A4%BA%E8%A2%AB%E4%BE%9D%E8%B5%96%E5%8C%85%E9%9C%80%E8%A6%81%E5%8F%82%E4%B8%8E%E5%BD%93%E5%89%8D%E9%A1%B9%E7%9B%AE%E7%9A%84%60%E7%BC%96%E8%AF%91%60%EF%BC%8C%E5%8C%85%E6%8B%AC%E5%90%8E%E7%BB%AD%E7%9A%84%60%E6%B5%8B%E8%AF%95%60%EF%BC%8C%60%E8%BF%90%E8%A1%8C%E5%91%A8%E6%9C%9F%60%E4%B9%9F%E5%8F%82%E4%B8%8E%E5%85%B6%E4%B8%AD%EF%BC%8C%E6%98%AF%E4%B8%80%E4%B8%AA%E6%AF%94%E8%BE%83%E5%BC%BA%E7%9A%84%E4%BE%9D%E8%B5%96%EF%BC%9B%0A%3E%20%E6%89%93%E5%8C%85%E7%9A%84%E6%97%B6%E5%80%99%E9%80%9A%E5%B8%B8%E9%9C%80%E8%A6%81%E5%8C%85%E5%90%AB%E8%BF%9B%E5%8E%BB%E3%80%82%0A%0A%23%23%23%23%202.%20provided%0A%0A%3E%20provided%20%E7%B1%BB%E5%9E%8B%E7%9A%84scope%E5%8F%AA%E4%BC%9A%E5%9C%A8%E9%A1%B9%E7%9B%AE%E7%9A%84%60%E7%BC%96%E8%AF%91%EF%BC%8C%E6%B5%8B%E8%AF%95%60%E9%98%B6%E6%AE%B5%E8%B5%B7%E4%BD%9C%E7%94%A8%EF%BC%9B%0A%3E%0A%3E%20%E5%8F%AF%E4%BB%A5%E8%AE%A4%E4%B8%BA%E5%9C%A8%E7%9B%AE%E6%A0%87%E5%AE%B9%E5%99%A8%E4%B8%AD%E5%B7%B2%E7%BB%8F%E6%8F%90%E4%BE%9B%E4%BA%86%E8%BF%99%E4%B8%AA%E4%BE%9D%E8%B5%96%EF%BC%8C%E6%97%A0%E9%9C%80%E5%9C%A8%E6%8F%90%E4%BE%9B%EF%BC%8C%E4%BD%86%E6%98%AF%E5%9C%A8%E7%BC%96%E5%86%99%E4%BB%A3%E7%A0%81%E6%88%96%E8%80%85%E7%BC%96%E8%AF%91%E6%97%B6%E5%8F%AF%E8%83%BD%E4%BC%9A%E7%94%A8%E5%88%B0%E8%BF%99%E4%B8%AA%E4%BE%9D%E8%B5%96%EF%BC%9B%0A%3E%0A%3E%20%60%E4%BE%9D%E8%B5%96%E4%B8%8D%E4%BC%9A%E8%A2%AB%E6%89%93%E5%85%A5%E5%88%B0%E9%A1%B9%E7%9B%AEjar%E5%8C%85%E4%B8%AD%60%0A%0A%60%60%60%0A%E8%AF%B4%E5%88%B0provided%EF%BC%8C%E8%BF%99%E9%87%8C%E5%B0%B1%E8%A6%81%E8%AF%B4%E5%88%B0%3Cdependency%3E%E4%B8%8B%E7%9A%84%E5%AD%90%E6%A0%87%E7%AD%BE%3Coptional%3E%20%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E4%BE%9D%E8%B5%96%E7%9A%84%3Coptional%3E%20%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%EF%BC%8C%E5%88%99%E8%AF%A5%E4%BE%9D%E8%B5%96%E5%9C%A8%E6%89%93%E5%8C%85%E7%9A%84%E6%97%B6%E5%80%99%E4%B8%8D%E4%BC%9A%E8%A2%AB%E6%89%93%E8%BF%9Bjar%E5%8C%85%EF%BC%8C%E5%90%8C%E6%97%B6%E4%B8%8D%E4%BC%9A%E9%80%9A%E8%BF%87%E4%BE%9D%E8%B5%96%E4%BC%A0%E9%80%92%E4%BC%A0%E9%80%92%E5%88%B0%E4%BE%9D%E8%B5%96%E8%AF%A5%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%B7%A5%E7%A8%8B%EF%BC%9B%0A%E4%BE%8B%E5%A6%82%EF%BC%9Ax%E4%BE%9D%E8%B5%96B%EF%BC%8CB%E7%94%B1%E4%BE%9D%E8%B5%96%E4%BA%8EA%EF%BC%88x-%3EB-%3EA%EF%BC%89%EF%BC%8C%E5%88%99A%E4%B8%AD%E8%AE%BE%E7%BD%AE%3Coptional%3E%20%E4%B8%BAtrue%E7%9A%84%E4%BE%9D%E8%B5%96%E4%B8%8D%E4%BC%9A%E8%A2%AB%E4%BC%A0%E9%80%92%E5%88%B0x%E4%B8%AD%E3%80%82%0A%0A%E8%BF%99%E4%B8%A4%E8%80%85%E7%9A%84%E5%8C%BA%E5%88%AB%E5%9C%A8%E4%BA%8E%EF%BC%9A%0A1%E3%80%81%3Coptional%3E%E4%B8%BAtrue%20%E8%A1%A8%E7%A4%BA%E6%9F%90%E4%B8%AA%E4%BE%9D%E8%B5%96%E5%8F%AF%E9%80%89%EF%BC%8C%E8%AF%A5%E4%BE%9D%E8%B5%96%E6%98%AF%E5%90%A6%E4%BD%BF%E7%94%A8%E9%83%BD%E4%B8%8D%E4%BC%9A%E5%BD%B1%E5%93%8D%E6%9C%8D%E5%8A%A1%E8%BF%90%E8%A1%8C%EF%BC%9B%0A2%E3%80%81provided%E7%9A%84%3Cscope%3E%E5%9C%A8%E7%9B%AE%E6%A0%87%E5%AE%B9%E5%99%A8%E4%B8%AD%E5%B7%B2%E7%BB%8F%E6%8F%90%E4%BE%9B%E4%BA%86%E8%BF%99%E4%B8%AA%E4%BE%9D%E8%B5%96%EF%BC%8C%E6%97%A0%E9%9C%80%E5%9C%A8%E6%8F%90%E4%BE%9B%0A%60%60%60%0A%0A%23%23%23%23%203.%20runtime%0A%0A%3E%20runtime%20%E4%B8%8E%20compile%20%E6%AF%94%E8%BE%83%E7%9B%B8%E4%BC%BC%EF%BC%8C%E5%8C%BA%E5%88%AB%E5%9C%A8%E4%BA%8E%60runtime%60%20%E8%B7%B3%E8%BF%87%E4%BA%86%60%E7%BC%96%E8%AF%91%60%E9%98%B6%E6%AE%B5%EF%BC%8C%E6%89%93%E5%8C%85%E7%9A%84%E6%97%B6%E5%80%99%E9%80%9A%E5%B8%B8%E9%9C%80%E8%A6%81%E5%8C%85%E5%90%AB%E8%BF%9B%E5%8E%BB%E3%80%82%0A%0A%23%23%23%23%204.%20test%0A%0A%3E%20%E5%9C%A8%E4%B8%80%E8%88%AC%E7%9A%84%E7%BC%96%E8%AF%91%E5%92%8C%E8%BF%90%E8%A1%8C%E6%97%B6%E9%83%BD%E4%B8%8D%E9%9C%80%E8%A6%81%EF%BC%8C%E5%AE%83%E4%BB%AC%E5%8F%AA%E6%9C%89%E5%9C%A8%60%E6%B5%8B%E8%AF%95%E7%BC%96%E8%AF%91%60%E5%92%8C%60%E6%B5%8B%E8%AF%95%E8%BF%90%E8%A1%8C%60%E9%98%B6%E6%AE%B5%E5%8F%AF%E7%94%A8%EF%BC%8C%0A%3E%0A%3E%20%60%E4%B8%8D%E4%BC%9A%E8%A2%AB%E6%89%93%E5%8C%85%E5%88%B0%E9%A1%B9%E7%9B%AEjar%E5%8C%85%E4%B8%AD%60%EF%BC%8C%0A%3E%0A%3E%20%E5%90%8C%E6%97%B6%E5%A6%82%E6%9E%9C%E9%A1%B9%E7%9B%AEA%E4%BE%9D%E8%B5%96%E4%BA%8E%E9%A1%B9%E7%9B%AEB%EF%BC%8C%E9%A1%B9%E7%9B%AEB%E4%B8%AD%E7%9A%84%60test%60%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8B%E7%9A%84%E4%BE%9D%E8%B5%96%E4%B8%8D%E4%BC%9A%E8%A2%AB%E7%BB%A7%E6%89%BF%E3%80%82%0A%0A%0A%23%23%23%23%20%205.%20system%0A%3E%20%E8%A1%A8%E7%A4%BA%E4%BD%BF%E7%94%A8%E6%9C%AC%E5%9C%B0%E7%B3%BB%E7%BB%9F%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%9A%84jar%E5%8C%85%EF%BC%8C%E9%9C%80%E8%A6%81%E5%92%8C%E4%B8%80%E4%B8%AAsystemPath%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60xml%0A%3Cdependency%3E%0A%09%3CgroupId%3Exxxx%3C%2FgroupId%3E%0A%09%3CartifactId%3Exxx%3C%2FartifactId%3E%0A%09%3CsystemPath%3E%24%7Bbasedir%7D%2Flib%2Fxxxxx.jar%3C%2FsystemPath%3E%0A%09%3Cscope%3Esystem%3C%2Fscope%3E%0A%09%3Cversion%3E1.4.12%3C%2Fversion%3E%0A%3C%2Fdependency%3E%0A%60%60%60%0A%0A%23%23%23%23%206.%20import%0A%0A%3E%20import%20%E5%8F%AA%E8%83%BD%E5%9C%A8pom%E6%96%87%E4%BB%B6%E7%9A%84%60%3CdependencyManagement%3E%60%E4%B8%AD%E4%BD%BF%E7%94%A8%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%BC%95%E5%85%A5%E5%85%B6%E4%BB%96%E7%9A%84pom%E6%96%87%E4%BB%B6%E4%B8%AD%E5%BC%95%E5%85%A5%E4%BE%9D%E8%B5%96%EF%BC%8C%0A%3E%0A%3E%20%E5%A6%82%EF%BC%9A%E5%9C%A8Spring%20boot%20%E9%A1%B9%E7%9B%AE%E7%9A%84POM%E6%96%87%E4%BB%B6%E4%B8%AD%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%9C%A8POM%E6%96%87%E4%BB%B6%E4%B8%AD%E7%BB%A7%E6%89%BF%20Spring-boot-starter-parent%E6%9D%A5%E5%BC%95%E7%94%A8Spring%20boot%E9%BB%98%E8%AE%A4%E4%BE%9D%E8%B5%96%E7%9A%84jar%E5%8C%85%EF%BC%8C%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60xml%0A%3Cparent%3E%0A%09%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%09%3CartifactId%3Espring-boot-starter-parent%3C%2FartifactId%3E%0A%09%3Cversion%3E2.0.1.BUILD-SNAPSHOT%3C%2Fversion%3E%0A%3C%2Fparent%3E%0A%60%60%60%0A%0A%3E%20%E4%BD%86%E6%98%AF%EF%BC%8C%E9%80%9A%E8%BF%87%E4%B8%8A%E9%9D%A2%E7%9A%84parent%E7%BB%A7%E6%89%BF%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8F%AA%E8%83%BD%E7%BB%A7%E6%89%BF%E4%B8%80%E4%B8%AA%20spring-boot-start-parent%E3%80%82%0A%3E%20%E5%AE%9E%E9%99%85%E5%BC%80%E5%8F%91%E4%B8%AD%EF%BC%8C%E7%94%A8%E6%88%B7%E5%BE%88%E5%8F%AF%E8%83%BD%E9%9C%80%E8%A6%81%E7%BB%A7%E6%89%BF%E8%87%AA%E5%B7%B1%E5%85%AC%E5%8F%B8%E7%9A%84%E6%A0%87%E5%87%86parent%E9%85%8D%E7%BD%AE%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%97%B6%E5%80%99%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20scope%3Dimport%20%E6%9D%A5%E5%AE%9E%E7%8E%B0%E5%A4%9A%E7%BB%A7%E6%89%BF%E3%80%82%E4%BB%A3%E7%A0%81%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60xml%0A%3CdependencyManagement%3E%0A%20%20%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%20Import%20dependency%20management%20from%20Spring%20Boot%20--%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-dependencies%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E2.0.1.BUILD-SNAPSHOT%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctype%3Epom%3C%2Ftype%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eimport%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%3C%2Fdependencies%3E%0A%3C%2FdependencyManagement%3E%0A%0A%60%60%60%0A%0A%3E%20%E9%80%9A%E8%BF%87%E4%B8%8A%E9%9D%A2%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%8F%96spring-boot-dependencies.2.0.1.BUILD-SNAPSHOT.pom%E6%96%87%E4%BB%B6%E4%B8%ADdependencyManagement%E9%85%8D%E7%BD%AE%E7%9A%84jar%E5%8C%85%E4%BE%9D%E8%B5%96%E3%80%82%0A%3E%20%E5%A6%82%E6%9E%9C%E8%A6%81%E7%BB%A7%E6%89%BF%E5%A4%9A%E4%B8%AA%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%9C%A8dependencyManagement%E4%B8%AD%E6%B7%BB%E5%8A%A0%EF%BC%8C%E5%A6%82%EF%BC%9A%0A%60%60%60xml%0A%3CdependencyManagement%3E%0A%20%20%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%20%20%3C!--%20Override%20Spring%20Data%20release%20train%20provided%20by%20Spring%20Boot%20--%3E%0A%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.data%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-data-releasetrain%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3EFowler-SR2%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctype%3Epom%3C%2Ftype%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eimport%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-dependencies%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E2.0.1.BUILD-SNAPSHOT%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Ctype%3Epom%3C%2Ftype%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eimport%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%3C%2Fdependencies%3E%0A%3C%2FdependencyManagement%3E%0A%60%60%60%0A%0A

Guava

创建时间:2022/12/7 23:16
更新时间:2022/12/8 12:19
作者:Chris

1. Cache

package com.chris.guava.cache;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class CacheTest {

    /**
     * 通过CacheBuilder类构建一个缓存对象,CacheBuilder类采用builder设计模式,它的每个方法都返回CacheBuilder本身,直到build方法被调用
     */
    @Test
    public void test1() {
        Cache<String, String> cache = CacheBuilder.newBuilder().build();
        cache.put("word", "Hello Guava Cache");
        System.out.println(cache.getIfPresent("word"));
    }

    /**
     * 设置最大存储
     * Guava Cache可以在构建缓存对象时指定缓存所能够存储的最大记录数量。
     * 当Cache中的记录数量达到最大值后,再调用put方法向其中添加对象,Guava会先从当前缓存的对象记录中选择一条删除掉,腾出空间后,再将新的对象存储到Cache中。
     * 第一个值:null
     * 第二个值:value2
     * 第三个值:value3
     */
    @Test
    public void test2() {
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(2)
                .build();
        cache.put("key1", "value1");
        cache.put("key2", "value2");
        cache.put("key3", "value3");
        System.out.println("第一个值:" + cache.getIfPresent("key1"));
        System.out.println("第二个值:" + cache.getIfPresent("key2"));
        System.out.println("第三个值:" + cache.getIfPresent("key3"));
    }

    /**
     * 设置过期时间
     * <p>
     * 可以通过CacheBuilder类的expireAfterAccess和expireAfterWrite两个方法为缓存中的对象指定过期时间
     * 使用CacheBuilder构建的缓存不会“自动”执行清理和逐出值,也不会在值到期后立即执行或逐出任何类型。
     * 相反,它在写入操作期间执行少量维护,或者在写入很少的情况下偶尔执行读取操作。
     * 其中,expireAfterWrite方法指定对象被写入到缓存后多久过期,expireAfterAccess方法指定对象多久没有被访问后过期。
     * <p>
     * 第1次取到key1的值为:value1
     * 第2次取到key1的值为:value1
     * 第3次取到key1的值为:value1
     * 第4次取到key1的值为:null
     * 第5次取到key1的值为:null
     */
    @Test
    public void test3() throws InterruptedException {
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(2)
                .expireAfterWrite(3, TimeUnit.SECONDS)
                .build();
        cache.put("key1", "value1");
        int time = 1;
        while (time <= 5) {
            System.out.println("第" + time++ + "次取到key1的值为:" + cache.getIfPresent("key1"));
            Thread.sleep(1000);
        }
    }

    /**
     * 通过CacheBuilder的expireAfterAccess方法,指定如果Cache中存储的对象超过3秒没有被访问,就会过期。
     * while中的代码每sleep一段时间,就会访问一次Cache中存储的对象key1;每次访问key1之后,下次sleep的时间会加长一秒。
     * 也可以同时用expireAfterAccess和expireAfterWrite方法指定过期时间,这时只要对象满足两者中的一个条件,就会被自动过期删除。
     * <p>
     * 睡眠1秒后取到key1的值为:value1
     * 睡眠2秒后取到key1的值为:value1
     * 睡眠3秒后取到key1的值为:null
     * 睡眠4秒后取到key1的值为:null
     * 睡眠5秒后取到key1的值为:null
     */
    @Test
    public void test4() throws InterruptedException {
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(2)
                .expireAfterAccess(3, TimeUnit.SECONDS)
                .build();
        cache.put("key1", "value1");
        int time = 1;
        while (time <= 5) {
            Thread.sleep(time * 1000L);
            System.out.println("睡眠" + time++ + "秒后取到key1的值为:" + cache.getIfPresent("key1"));
        }
    }


    /**
     * 显示清除缓存
     * <p>
     * 调用Cache的invalidateAll或invalidate方法,可以显示删除Cache中的记录。
     * invalidate方法一次只能删除Cache中一个记录,接收的参数是要删除记录的key。
     * invalidateAll方法可以批量删除Cache中的记录;当没有传任何参数时,invalidateAll方法将清除Cache中的全部记录。
     * <p>
     * cache size:4
     * invalidate key1 cache size:3
     * invalidate key2 key3 cache size:1
     * invalidate all cache size:0
     * null
     * null
     * null
     */
    @Test
    public void test5() {
        Cache<String, String> cache = CacheBuilder.newBuilder().build();
        cache.put("key1", "value1");
        cache.put("key2", "value2");
        cache.put("key3", "value3");
        cache.put("key4", "value4");
        System.out.println("cache size:" + cache.size());
        cache.invalidate("key1");
        System.out.println("invalidate key1 cache size:" + cache.size());
        List<String> list = new ArrayList<>();
        list.add("key2");
        list.add("key3");
        cache.invalidateAll(list);  //批量清除list中全部key对应的记录
        System.out.println("invalidate key2 key3 cache size:" + cache.size());
        cache.invalidateAll();
        System.out.println("invalidate all cache size:" + cache.size());
        System.out.println(cache.getIfPresent("key1"));
        System.out.println(cache.getIfPresent("key2"));
        System.out.println(cache.getIfPresent("key3"));
    }

    /**
     * 移除动作监听器
     * <p>
     * 可以为Cache对象添加一个移除监听器。这样,当有记录被删除时,可以感知到这个事件
     * <p>
     * 这个存在问题,当内存数据清理掉时候,RemovalListener不会触发
     * 因为
     * Guava并不保证在过期时间到了之后立刻删除该key,如果你此时去访问这这个key,它会检测是否过期,过期则移除.
     * 所以过期时间到了之后你去访问这个key会显示这个key已经移除,但是你如果不做任何操作,那么这个key还在内存中。
     * <p>
     * [key1:value1] is removed!
     * [key2:value2] is removed!
     * [key3:value3] is removed!
     * [key4:value4] is removed!
     * [key5:value5] is removed!
     */
    @Test
    public void test6() {
        RemovalListener<String, String> listener = new RemovalListener<String, String>() {
            public void onRemoval(RemovalNotification<String, String> notification) {
                System.out.println("[" + notification.getKey() + ":" + notification.getValue() + "] is removed!");
            }
        };
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(3)
                .removalListener(listener)
                .build();
        cache.put("key1", "value1");
        cache.put("key2", "value2");
        cache.put("key3", "value3");
        cache.put("key4", "value4");
        cache.put("key5", "value5");
        cache.put("key6", "value6");
        cache.put("key7", "value7");
        cache.put("key8", "value8");
    }


    private static final Cache<String, String> cache = CacheBuilder.newBuilder()
            .maximumSize(3)
            .build();

    /**
     * 自动加载
     * <p>
     * Cache的get方法有两个参数,第一个参数是从Cache中获取记录的key,第二个记录是一个Callable对象。
     * 当缓存中已经存在key对应的记录时,get方法直接返回key对应的记录。如果缓存中不包含key对应的记录,Guava会启动一个线程执行Callable对象中的call方法.
     * call方法的返回值会作为“key对应的值”被存储到缓存中,并且被get方法返回。
     * <p>
     * 有两个线程共享同一个Cache对象,两个线程同时调用get方法获取同一个key对应的值。由于key对应的值不存在,所以两个线程都在get方法处阻塞。
     * 此处在call方法中调用Thread.sleep(1000),模拟程序从外存加载数据的时间消耗。
     * 虽然是两个线程同时调用get方法,但只有一个get方法中的Callable会被执行(只打印出load1或者load2)。
     * Guava可以保证当有多个线程同时访问Cache中的一个key时,如果key对应的记录不存在,Guava只会启动一个线程执行get方法中Callable参数对应的任务,加载数据存到缓存。
     * 当加载完数据后,任何线程中的get方法都会获取到key对应的值。
     * <p>
     * thread1
     * thread2
     * load2
     * thread1 auto load by Callable 2
     * thread2 auto load by Callable 2
     */
    @Test
    public void test7() throws InterruptedException {
        new Thread(() -> {
            System.out.println("thread1");
            try {
                String value = cache.get("key", () -> {
                    System.out.println("load1"); //加载数据线程执行标志
                    Thread.sleep(1000); //模拟加载时间
                    return "auto load by Callable 1";
                });
                System.out.println("thread1 " + value);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            System.out.println("thread2");
            try {
                String value = cache.get("key", () -> {
                    System.out.println("load2"); //加载数据线程执行标志
                    Thread.sleep(1000); //模拟加载时间
                    return "auto load by Callable 2";
                });
                System.out.println("thread2 " + value);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }).start();

        TimeUnit.SECONDS.sleep(5);
    }

    /**
     * 统计信息
     * <p>
     * 可以对Cache的命中率、加载数据时间等信息进行统计。
     * 在构建Cache对象时,通过CacheBuilder的recordStats方法,可以开启统计信息的开关。
     * 开关开启后,Cache会自动对缓存的各种操作进行统计,调用Cache的stats方法可以查看统计后的信息。
     */
    @Test
    public void test8() {
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(3)
                .recordStats() //开启统计信息开关
                .build();
        cache.put("key1", "value1");
        cache.put("key2", "value2");
        cache.put("key3", "value3");
        cache.put("key4", "value4");
        cache.getIfPresent("key1");
        cache.getIfPresent("key2");
        cache.getIfPresent("key3");
        cache.getIfPresent("key4");
        cache.getIfPresent("key5");
        cache.getIfPresent("key6");
        System.out.println(cache.stats()); //获取统计信息
    }

}

1. LoadingCache

@Data
@AllArgsConstructor
class Customer {
  private Integer id;
  
  private String firstName;
}

/**
 * @Auther Chris Lee
 * @Date 1/3/2019 10:50
 * @Description LoadingCache是Cache的子接口,相比较于Cache,当从LoadingCache中读取一个指定key的记录时,如果该记录不存在,则LoadingCache可以自动执行加载数据到缓存的操作.
 * 在调用CacheBuilder的build方法时必须传递一个CacheLoader类型的参数,CacheLoader的load方法需要我们提供具体实现。
 * 当调用LoadingCache的get方法时,如果缓存不存在对应key的记录,则CacheLoader中的load方法会被自动调用从外存加载数据,“load方法的返回值”会作为“key对应的value”存储到LoadingCache中,并从get方法返回。
 */
public enum CustomerCacheProvider {
    INSTANCE;

    private final LoadingCache<Integer, Customer> customerCache;

    CustomerCacheProvider() {
        CacheLoader<Integer, Customer> cacheLoader = new CacheLoader<Integer, Customer>() {
            @Override
            public Customer load(Integer id) {
                return CustomerRepo.findById(id);
            }
        };
        customerCache = CacheBuilder.newBuilder().maximumSize(100).expireAfterWrite(2, TimeUnit.SECONDS).build(cacheLoader);
    }

    public LoadingCache<Integer, Customer> getCustomerCache() {
        return customerCache;
    }
}
/**
 * @Auther Chris Lee
 * @Date 1/3/2019 10:45
 * @Description
 */
class CustomerRepo {
    private static final Map<Integer, Customer> customers = new HashMap<>();

    static {
        // add data
        Customer customer1 = new Customer(1, "Jhon");
        Customer customer2 = new Customer(2, "James");
        Customer customer3 = new Customer(3, "Mark");

        customers.put(1, customer1);
        customers.put(2, customer2);
        customers.put(3, customer3);
    }

    public static Customer findById(Integer id) {
        System.out.printf("find %s in Repo \n", id);
        if (customers.containsKey(id)) {
            return customers.get(id);
        }
        return null;
    }
}
/**
 * @Auther Chris Lee
 * @Date 1/3/2019 10:52
 * @Description https://blog.csdn.net/qq_38567039/article/details/126488902
 */
public class Main {

    /**
     * 与构建Cache类型的对象类似,LoadingCache类型的对象也是通过CacheBuilder进行构建。
     * 不同的是,在调用CacheBuilder的build方法时,必须传递一个CacheLoader类型的参数,CacheLoader的load方法需要我们提供具体实现。
     * 当调用LoadingCache的get方法时,如果缓存不存在对应key的记录,则CacheLoader中的load方法会被自动调用从外存加载数据,
     * “load方法的返回值”会作为“key对应的value”存储到LoadingCache中,并从get方法返回。
     */
    @Test
    public void test1() {
        LoadingCache<Integer, Customer> cutomerCache = CustomerCacheProvider.INSTANCE.getCustomerCache();
        /*
         * V get(K key) : This will either return an already cached value, or else use the cache's CacheLoader to atomically
         * load a new value into the cache
         */
        try {
            System.out.println("Cache size : " + cutomerCache.size());
            System.out.println("Get Customer 1 : " + cutomerCache.get(1).getFirstName());
            System.out.println("Cache size : " + cutomerCache.size());
            TimeUnit.SECONDS.sleep(3);
            System.out.println("Get Customer 1 : " + cutomerCache.get(1).getFirstName());
            System.out.println("Get Customer 3 : " + cutomerCache.get(3).getFirstName());
            System.out.println("Cache size : " + cutomerCache.size());
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}
%5Btoc%5D%0A%0A%23%23%201.%20Cache%0A%0A%60%60%60java%0Apackage%20com.chris.guava.cache%3B%0A%0Aimport%20com.google.common.cache.Cache%3B%0Aimport%20com.google.common.cache.CacheBuilder%3B%0Aimport%20com.google.common.cache.RemovalListener%3B%0Aimport%20com.google.common.cache.RemovalNotification%3B%0Aimport%20org.junit.Test%3B%0A%0Aimport%20java.util.ArrayList%3B%0Aimport%20java.util.List%3B%0Aimport%20java.util.concurrent.Callable%3B%0Aimport%20java.util.concurrent.ExecutionException%3B%0Aimport%20java.util.concurrent.TimeUnit%3B%0A%0Apublic%20class%20CacheTest%20%7B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E9%80%9A%E8%BF%87CacheBuilder%E7%B1%BB%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%BC%93%E5%AD%98%E5%AF%B9%E8%B1%A1%EF%BC%8CCacheBuilder%E7%B1%BB%E9%87%87%E7%94%A8builder%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%AE%83%E7%9A%84%E6%AF%8F%E4%B8%AA%E6%96%B9%E6%B3%95%E9%83%BD%E8%BF%94%E5%9B%9ECacheBuilder%E6%9C%AC%E8%BA%AB%EF%BC%8C%E7%9B%B4%E5%88%B0build%E6%96%B9%E6%B3%95%E8%A2%AB%E8%B0%83%E7%94%A8%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test1()%20%7B%0A%20%20%20%20%20%20%20%20Cache%3CString%2C%20String%3E%20cache%20%3D%20CacheBuilder.newBuilder().build()%3B%0A%20%20%20%20%20%20%20%20cache.put(%22word%22%2C%20%22Hello%20Guava%20Cache%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(cache.getIfPresent(%22word%22))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%AE%BE%E7%BD%AE%E6%9C%80%E5%A4%A7%E5%AD%98%E5%82%A8%0A%20%20%20%20%20*%20Guava%20Cache%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%9E%84%E5%BB%BA%E7%BC%93%E5%AD%98%E5%AF%B9%E8%B1%A1%E6%97%B6%E6%8C%87%E5%AE%9A%E7%BC%93%E5%AD%98%E6%89%80%E8%83%BD%E5%A4%9F%E5%AD%98%E5%82%A8%E7%9A%84%E6%9C%80%E5%A4%A7%E8%AE%B0%E5%BD%95%E6%95%B0%E9%87%8F%E3%80%82%0A%20%20%20%20%20*%20%E5%BD%93Cache%E4%B8%AD%E7%9A%84%E8%AE%B0%E5%BD%95%E6%95%B0%E9%87%8F%E8%BE%BE%E5%88%B0%E6%9C%80%E5%A4%A7%E5%80%BC%E5%90%8E%EF%BC%8C%E5%86%8D%E8%B0%83%E7%94%A8put%E6%96%B9%E6%B3%95%E5%90%91%E5%85%B6%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%AF%B9%E8%B1%A1%EF%BC%8CGuava%E4%BC%9A%E5%85%88%E4%BB%8E%E5%BD%93%E5%89%8D%E7%BC%93%E5%AD%98%E7%9A%84%E5%AF%B9%E8%B1%A1%E8%AE%B0%E5%BD%95%E4%B8%AD%E9%80%89%E6%8B%A9%E4%B8%80%E6%9D%A1%E5%88%A0%E9%99%A4%E6%8E%89%EF%BC%8C%E8%85%BE%E5%87%BA%E7%A9%BA%E9%97%B4%E5%90%8E%EF%BC%8C%E5%86%8D%E5%B0%86%E6%96%B0%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8%E5%88%B0Cache%E4%B8%AD%E3%80%82%0A%20%20%20%20%20*%20%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%80%BC%EF%BC%9Anull%0A%20%20%20%20%20*%20%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%80%BC%EF%BC%9Avalue2%0A%20%20%20%20%20*%20%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%80%BC%EF%BC%9Avalue3%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test2()%20%7B%0A%20%20%20%20%20%20%20%20Cache%3CString%2C%20String%3E%20cache%20%3D%20CacheBuilder.newBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.maximumSize(2)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key1%22%2C%20%22value1%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key2%22%2C%20%22value2%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key3%22%2C%20%22value3%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%80%BC%EF%BC%9A%22%20%2B%20cache.getIfPresent(%22key1%22))%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%80%BC%EF%BC%9A%22%20%2B%20cache.getIfPresent(%22key2%22))%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%80%BC%EF%BC%9A%22%20%2B%20cache.getIfPresent(%22key3%22))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%AE%BE%E7%BD%AE%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87CacheBuilder%E7%B1%BB%E7%9A%84expireAfterAccess%E5%92%8CexpireAfterWrite%E4%B8%A4%E4%B8%AA%E6%96%B9%E6%B3%95%E4%B8%BA%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%8C%87%E5%AE%9A%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%0A%20%20%20%20%20*%20%E4%BD%BF%E7%94%A8CacheBuilder%E6%9E%84%E5%BB%BA%E7%9A%84%E7%BC%93%E5%AD%98%E4%B8%8D%E4%BC%9A%E2%80%9C%E8%87%AA%E5%8A%A8%E2%80%9D%E6%89%A7%E8%A1%8C%E6%B8%85%E7%90%86%E5%92%8C%E9%80%90%E5%87%BA%E5%80%BC%EF%BC%8C%E4%B9%9F%E4%B8%8D%E4%BC%9A%E5%9C%A8%E5%80%BC%E5%88%B0%E6%9C%9F%E5%90%8E%E7%AB%8B%E5%8D%B3%E6%89%A7%E8%A1%8C%E6%88%96%E9%80%90%E5%87%BA%E4%BB%BB%E4%BD%95%E7%B1%BB%E5%9E%8B%E3%80%82%0A%20%20%20%20%20*%20%E7%9B%B8%E5%8F%8D%EF%BC%8C%E5%AE%83%E5%9C%A8%E5%86%99%E5%85%A5%E6%93%8D%E4%BD%9C%E6%9C%9F%E9%97%B4%E6%89%A7%E8%A1%8C%E5%B0%91%E9%87%8F%E7%BB%B4%E6%8A%A4%EF%BC%8C%E6%88%96%E8%80%85%E5%9C%A8%E5%86%99%E5%85%A5%E5%BE%88%E5%B0%91%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E5%81%B6%E5%B0%94%E6%89%A7%E8%A1%8C%E8%AF%BB%E5%8F%96%E6%93%8D%E4%BD%9C%E3%80%82%0A%20%20%20%20%20*%20%E5%85%B6%E4%B8%AD%EF%BC%8CexpireAfterWrite%E6%96%B9%E6%B3%95%E6%8C%87%E5%AE%9A%E5%AF%B9%E8%B1%A1%E8%A2%AB%E5%86%99%E5%85%A5%E5%88%B0%E7%BC%93%E5%AD%98%E5%90%8E%E5%A4%9A%E4%B9%85%E8%BF%87%E6%9C%9F%EF%BC%8CexpireAfterAccess%E6%96%B9%E6%B3%95%E6%8C%87%E5%AE%9A%E5%AF%B9%E8%B1%A1%E5%A4%9A%E4%B9%85%E6%B2%A1%E6%9C%89%E8%A2%AB%E8%AE%BF%E9%97%AE%E5%90%8E%E8%BF%87%E6%9C%9F%E3%80%82%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%E7%AC%AC1%E6%AC%A1%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Avalue1%0A%20%20%20%20%20*%20%E7%AC%AC2%E6%AC%A1%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Avalue1%0A%20%20%20%20%20*%20%E7%AC%AC3%E6%AC%A1%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Avalue1%0A%20%20%20%20%20*%20%E7%AC%AC4%E6%AC%A1%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Anull%0A%20%20%20%20%20*%20%E7%AC%AC5%E6%AC%A1%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Anull%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test3()%20throws%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20Cache%3CString%2C%20String%3E%20cache%20%3D%20CacheBuilder.newBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.maximumSize(2)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.expireAfterWrite(3%2C%20TimeUnit.SECONDS)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key1%22%2C%20%22value1%22)%3B%0A%20%20%20%20%20%20%20%20int%20time%20%3D%201%3B%0A%20%20%20%20%20%20%20%20while%20(time%20%3C%3D%205)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%AC%AC%22%20%2B%20time%2B%2B%20%2B%20%22%E6%AC%A1%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9A%22%20%2B%20cache.getIfPresent(%22key1%22))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(1000)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E9%80%9A%E8%BF%87CacheBuilder%E7%9A%84expireAfterAccess%E6%96%B9%E6%B3%95%EF%BC%8C%E6%8C%87%E5%AE%9A%E5%A6%82%E6%9E%9CCache%E4%B8%AD%E5%AD%98%E5%82%A8%E7%9A%84%E5%AF%B9%E8%B1%A1%E8%B6%85%E8%BF%873%E7%A7%92%E6%B2%A1%E6%9C%89%E8%A2%AB%E8%AE%BF%E9%97%AE%EF%BC%8C%E5%B0%B1%E4%BC%9A%E8%BF%87%E6%9C%9F%E3%80%82%0A%20%20%20%20%20*%20while%E4%B8%AD%E7%9A%84%E4%BB%A3%E7%A0%81%E6%AF%8Fsleep%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%EF%BC%8C%E5%B0%B1%E4%BC%9A%E8%AE%BF%E9%97%AE%E4%B8%80%E6%AC%A1Cache%E4%B8%AD%E5%AD%98%E5%82%A8%E7%9A%84%E5%AF%B9%E8%B1%A1key1%EF%BC%9B%E6%AF%8F%E6%AC%A1%E8%AE%BF%E9%97%AEkey1%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%B8%8B%E6%AC%A1sleep%E7%9A%84%E6%97%B6%E9%97%B4%E4%BC%9A%E5%8A%A0%E9%95%BF%E4%B8%80%E7%A7%92%E3%80%82%0A%20%20%20%20%20*%20%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E7%94%A8expireAfterAccess%E5%92%8CexpireAfterWrite%E6%96%B9%E6%B3%95%E6%8C%87%E5%AE%9A%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%EF%BC%8C%E8%BF%99%E6%97%B6%E5%8F%AA%E8%A6%81%E5%AF%B9%E8%B1%A1%E6%BB%A1%E8%B6%B3%E4%B8%A4%E8%80%85%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AA%E6%9D%A1%E4%BB%B6%EF%BC%8C%E5%B0%B1%E4%BC%9A%E8%A2%AB%E8%87%AA%E5%8A%A8%E8%BF%87%E6%9C%9F%E5%88%A0%E9%99%A4%E3%80%82%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%E7%9D%A1%E7%9C%A01%E7%A7%92%E5%90%8E%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Avalue1%0A%20%20%20%20%20*%20%E7%9D%A1%E7%9C%A02%E7%A7%92%E5%90%8E%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Avalue1%0A%20%20%20%20%20*%20%E7%9D%A1%E7%9C%A03%E7%A7%92%E5%90%8E%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Anull%0A%20%20%20%20%20*%20%E7%9D%A1%E7%9C%A04%E7%A7%92%E5%90%8E%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Anull%0A%20%20%20%20%20*%20%E7%9D%A1%E7%9C%A05%E7%A7%92%E5%90%8E%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9Anull%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test4()%20throws%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20Cache%3CString%2C%20String%3E%20cache%20%3D%20CacheBuilder.newBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.maximumSize(2)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.expireAfterAccess(3%2C%20TimeUnit.SECONDS)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key1%22%2C%20%22value1%22)%3B%0A%20%20%20%20%20%20%20%20int%20time%20%3D%201%3B%0A%20%20%20%20%20%20%20%20while%20(time%20%3C%3D%205)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(time%20*%201000L)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%9D%A1%E7%9C%A0%22%20%2B%20time%2B%2B%20%2B%20%22%E7%A7%92%E5%90%8E%E5%8F%96%E5%88%B0key1%E7%9A%84%E5%80%BC%E4%B8%BA%EF%BC%9A%22%20%2B%20cache.getIfPresent(%22key1%22))%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%98%BE%E7%A4%BA%E6%B8%85%E9%99%A4%E7%BC%93%E5%AD%98%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%E8%B0%83%E7%94%A8Cache%E7%9A%84invalidateAll%E6%88%96invalidate%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%98%BE%E7%A4%BA%E5%88%A0%E9%99%A4Cache%E4%B8%AD%E7%9A%84%E8%AE%B0%E5%BD%95%E3%80%82%0A%20%20%20%20%20*%20invalidate%E6%96%B9%E6%B3%95%E4%B8%80%E6%AC%A1%E5%8F%AA%E8%83%BD%E5%88%A0%E9%99%A4Cache%E4%B8%AD%E4%B8%80%E4%B8%AA%E8%AE%B0%E5%BD%95%EF%BC%8C%E6%8E%A5%E6%94%B6%E7%9A%84%E5%8F%82%E6%95%B0%E6%98%AF%E8%A6%81%E5%88%A0%E9%99%A4%E8%AE%B0%E5%BD%95%E7%9A%84key%E3%80%82%0A%20%20%20%20%20*%20invalidateAll%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E6%89%B9%E9%87%8F%E5%88%A0%E9%99%A4Cache%E4%B8%AD%E7%9A%84%E8%AE%B0%E5%BD%95%EF%BC%9B%E5%BD%93%E6%B2%A1%E6%9C%89%E4%BC%A0%E4%BB%BB%E4%BD%95%E5%8F%82%E6%95%B0%E6%97%B6%EF%BC%8CinvalidateAll%E6%96%B9%E6%B3%95%E5%B0%86%E6%B8%85%E9%99%A4Cache%E4%B8%AD%E7%9A%84%E5%85%A8%E9%83%A8%E8%AE%B0%E5%BD%95%E3%80%82%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20cache%20size%3A4%0A%20%20%20%20%20*%20invalidate%20key1%20cache%20size%3A3%0A%20%20%20%20%20*%20invalidate%20key2%20key3%20cache%20size%3A1%0A%20%20%20%20%20*%20invalidate%20all%20cache%20size%3A0%0A%20%20%20%20%20*%20null%0A%20%20%20%20%20*%20null%0A%20%20%20%20%20*%20null%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test5()%20%7B%0A%20%20%20%20%20%20%20%20Cache%3CString%2C%20String%3E%20cache%20%3D%20CacheBuilder.newBuilder().build()%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key1%22%2C%20%22value1%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key2%22%2C%20%22value2%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key3%22%2C%20%22value3%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key4%22%2C%20%22value4%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22cache%20size%3A%22%20%2B%20cache.size())%3B%0A%20%20%20%20%20%20%20%20cache.invalidate(%22key1%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22invalidate%20key1%20cache%20size%3A%22%20%2B%20cache.size())%3B%0A%20%20%20%20%20%20%20%20List%3CString%3E%20list%20%3D%20new%20ArrayList%3C%3E()%3B%0A%20%20%20%20%20%20%20%20list.add(%22key2%22)%3B%0A%20%20%20%20%20%20%20%20list.add(%22key3%22)%3B%0A%20%20%20%20%20%20%20%20cache.invalidateAll(list)%3B%20%20%2F%2F%E6%89%B9%E9%87%8F%E6%B8%85%E9%99%A4list%E4%B8%AD%E5%85%A8%E9%83%A8key%E5%AF%B9%E5%BA%94%E7%9A%84%E8%AE%B0%E5%BD%95%0A%20%20%20%20%20%20%20%20System.out.println(%22invalidate%20key2%20key3%20cache%20size%3A%22%20%2B%20cache.size())%3B%0A%20%20%20%20%20%20%20%20cache.invalidateAll()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22invalidate%20all%20cache%20size%3A%22%20%2B%20cache.size())%3B%0A%20%20%20%20%20%20%20%20System.out.println(cache.getIfPresent(%22key1%22))%3B%0A%20%20%20%20%20%20%20%20System.out.println(cache.getIfPresent(%22key2%22))%3B%0A%20%20%20%20%20%20%20%20System.out.println(cache.getIfPresent(%22key3%22))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E7%A7%BB%E9%99%A4%E5%8A%A8%E4%BD%9C%E7%9B%91%E5%90%AC%E5%99%A8%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%E5%8F%AF%E4%BB%A5%E4%B8%BACache%E5%AF%B9%E8%B1%A1%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E7%A7%BB%E9%99%A4%E7%9B%91%E5%90%AC%E5%99%A8%E3%80%82%E8%BF%99%E6%A0%B7%EF%BC%8C%E5%BD%93%E6%9C%89%E8%AE%B0%E5%BD%95%E8%A2%AB%E5%88%A0%E9%99%A4%E6%97%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%84%9F%E7%9F%A5%E5%88%B0%E8%BF%99%E4%B8%AA%E4%BA%8B%E4%BB%B6%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%E8%BF%99%E4%B8%AA%E5%AD%98%E5%9C%A8%E9%97%AE%E9%A2%98%2C%E5%BD%93%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE%E6%B8%85%E7%90%86%E6%8E%89%E6%97%B6%E5%80%99%2CRemovalListener%E4%B8%8D%E4%BC%9A%E8%A7%A6%E5%8F%91%0A%20%20%20%20%20*%20%E5%9B%A0%E4%B8%BA%0A%20%20%20%20%20*%20Guava%E5%B9%B6%E4%B8%8D%E4%BF%9D%E8%AF%81%E5%9C%A8%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%E5%88%B0%E4%BA%86%E4%B9%8B%E5%90%8E%E7%AB%8B%E5%88%BB%E5%88%A0%E9%99%A4%E8%AF%A5key%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%BD%A0%E6%AD%A4%E6%97%B6%E5%8E%BB%E8%AE%BF%E9%97%AE%E8%BF%99%E8%BF%99%E4%B8%AAkey%EF%BC%8C%E5%AE%83%E4%BC%9A%E6%A3%80%E6%B5%8B%E6%98%AF%E5%90%A6%E8%BF%87%E6%9C%9F%EF%BC%8C%E8%BF%87%E6%9C%9F%E5%88%99%E7%A7%BB%E9%99%A4.%0A%20%20%20%20%20*%20%E6%89%80%E4%BB%A5%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%E5%88%B0%E4%BA%86%E4%B9%8B%E5%90%8E%E4%BD%A0%E5%8E%BB%E8%AE%BF%E9%97%AE%E8%BF%99%E4%B8%AAkey%E4%BC%9A%E6%98%BE%E7%A4%BA%E8%BF%99%E4%B8%AAkey%E5%B7%B2%E7%BB%8F%E7%A7%BB%E9%99%A4%EF%BC%8C%E4%BD%86%E6%98%AF%E4%BD%A0%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%81%9A%E4%BB%BB%E4%BD%95%E6%93%8D%E4%BD%9C%EF%BC%8C%E9%82%A3%E4%B9%88%E8%BF%99%E4%B8%AAkey%E8%BF%98%E5%9C%A8%E5%86%85%E5%AD%98%E4%B8%AD%E3%80%82%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%5Bkey1%3Avalue1%5D%20is%20removed!%0A%20%20%20%20%20*%20%5Bkey2%3Avalue2%5D%20is%20removed!%0A%20%20%20%20%20*%20%5Bkey3%3Avalue3%5D%20is%20removed!%0A%20%20%20%20%20*%20%5Bkey4%3Avalue4%5D%20is%20removed!%0A%20%20%20%20%20*%20%5Bkey5%3Avalue5%5D%20is%20removed!%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test6()%20%7B%0A%20%20%20%20%20%20%20%20RemovalListener%3CString%2C%20String%3E%20listener%20%3D%20new%20RemovalListener%3CString%2C%20String%3E()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20public%20void%20onRemoval(RemovalNotification%3CString%2C%20String%3E%20notification)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%5B%22%20%2B%20notification.getKey()%20%2B%20%22%3A%22%20%2B%20notification.getValue()%20%2B%20%22%5D%20is%20removed!%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20Cache%3CString%2C%20String%3E%20cache%20%3D%20CacheBuilder.newBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.maximumSize(3)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.removalListener(listener)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key1%22%2C%20%22value1%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key2%22%2C%20%22value2%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key3%22%2C%20%22value3%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key4%22%2C%20%22value4%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key5%22%2C%20%22value5%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key6%22%2C%20%22value6%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key7%22%2C%20%22value7%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key8%22%2C%20%22value8%22)%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20private%20static%20final%20Cache%3CString%2C%20String%3E%20cache%20%3D%20CacheBuilder.newBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20.maximumSize(3)%0A%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%87%AA%E5%8A%A8%E5%8A%A0%E8%BD%BD%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20Cache%E7%9A%84get%E6%96%B9%E6%B3%95%E6%9C%89%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%E6%98%AF%E4%BB%8ECache%E4%B8%AD%E8%8E%B7%E5%8F%96%E8%AE%B0%E5%BD%95%E7%9A%84key%EF%BC%8C%E7%AC%AC%E4%BA%8C%E4%B8%AA%E8%AE%B0%E5%BD%95%E6%98%AF%E4%B8%80%E4%B8%AACallable%E5%AF%B9%E8%B1%A1%E3%80%82%0A%20%20%20%20%20*%20%E5%BD%93%E7%BC%93%E5%AD%98%E4%B8%AD%E5%B7%B2%E7%BB%8F%E5%AD%98%E5%9C%A8key%E5%AF%B9%E5%BA%94%E7%9A%84%E8%AE%B0%E5%BD%95%E6%97%B6%EF%BC%8Cget%E6%96%B9%E6%B3%95%E7%9B%B4%E6%8E%A5%E8%BF%94%E5%9B%9Ekey%E5%AF%B9%E5%BA%94%E7%9A%84%E8%AE%B0%E5%BD%95%E3%80%82%E5%A6%82%E6%9E%9C%E7%BC%93%E5%AD%98%E4%B8%AD%E4%B8%8D%E5%8C%85%E5%90%ABkey%E5%AF%B9%E5%BA%94%E7%9A%84%E8%AE%B0%E5%BD%95%EF%BC%8CGuava%E4%BC%9A%E5%90%AF%E5%8A%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8CCallable%E5%AF%B9%E8%B1%A1%E4%B8%AD%E7%9A%84call%E6%96%B9%E6%B3%95.%0A%20%20%20%20%20*%20call%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E4%BC%9A%E4%BD%9C%E4%B8%BA%E2%80%9Ckey%E5%AF%B9%E5%BA%94%E7%9A%84%E5%80%BC%E2%80%9D%E8%A2%AB%E5%AD%98%E5%82%A8%E5%88%B0%E7%BC%93%E5%AD%98%E4%B8%AD%EF%BC%8C%E5%B9%B6%E4%B8%94%E8%A2%ABget%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E3%80%82%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%E6%9C%89%E4%B8%A4%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%85%B1%E4%BA%AB%E5%90%8C%E4%B8%80%E4%B8%AACache%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%B8%A4%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%97%B6%E8%B0%83%E7%94%A8get%E6%96%B9%E6%B3%95%E8%8E%B7%E5%8F%96%E5%90%8C%E4%B8%80%E4%B8%AAkey%E5%AF%B9%E5%BA%94%E7%9A%84%E5%80%BC%E3%80%82%E7%94%B1%E4%BA%8Ekey%E5%AF%B9%E5%BA%94%E7%9A%84%E5%80%BC%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%A4%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%83%BD%E5%9C%A8get%E6%96%B9%E6%B3%95%E5%A4%84%E9%98%BB%E5%A1%9E%E3%80%82%0A%20%20%20%20%20*%20%E6%AD%A4%E5%A4%84%E5%9C%A8call%E6%96%B9%E6%B3%95%E4%B8%AD%E8%B0%83%E7%94%A8Thread.sleep(1000)%EF%BC%8C%E6%A8%A1%E6%8B%9F%E7%A8%8B%E5%BA%8F%E4%BB%8E%E5%A4%96%E5%AD%98%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%E7%9A%84%E6%97%B6%E9%97%B4%E6%B6%88%E8%80%97%E3%80%82%0A%20%20%20%20%20*%20%E8%99%BD%E7%84%B6%E6%98%AF%E4%B8%A4%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%97%B6%E8%B0%83%E7%94%A8get%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BD%86%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AAget%E6%96%B9%E6%B3%95%E4%B8%AD%E7%9A%84Callable%E4%BC%9A%E8%A2%AB%E6%89%A7%E8%A1%8C(%E5%8F%AA%E6%89%93%E5%8D%B0%E5%87%BAload1%E6%88%96%E8%80%85load2)%E3%80%82%0A%20%20%20%20%20*%20Guava%E5%8F%AF%E4%BB%A5%E4%BF%9D%E8%AF%81%E5%BD%93%E6%9C%89%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%97%B6%E8%AE%BF%E9%97%AECache%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AAkey%E6%97%B6%EF%BC%8C%E5%A6%82%E6%9E%9Ckey%E5%AF%B9%E5%BA%94%E7%9A%84%E8%AE%B0%E5%BD%95%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8CGuava%E5%8F%AA%E4%BC%9A%E5%90%AF%E5%8A%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8Cget%E6%96%B9%E6%B3%95%E4%B8%ADCallable%E5%8F%82%E6%95%B0%E5%AF%B9%E5%BA%94%E7%9A%84%E4%BB%BB%E5%8A%A1%EF%BC%8C%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%E5%AD%98%E5%88%B0%E7%BC%93%E5%AD%98%E3%80%82%0A%20%20%20%20%20*%20%E5%BD%93%E5%8A%A0%E8%BD%BD%E5%AE%8C%E6%95%B0%E6%8D%AE%E5%90%8E%EF%BC%8C%E4%BB%BB%E4%BD%95%E7%BA%BF%E7%A8%8B%E4%B8%AD%E7%9A%84get%E6%96%B9%E6%B3%95%E9%83%BD%E4%BC%9A%E8%8E%B7%E5%8F%96%E5%88%B0key%E5%AF%B9%E5%BA%94%E7%9A%84%E5%80%BC%E3%80%82%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20thread1%0A%20%20%20%20%20*%20thread2%0A%20%20%20%20%20*%20load2%0A%20%20%20%20%20*%20thread1%20auto%20load%20by%20Callable%202%0A%20%20%20%20%20*%20thread2%20auto%20load%20by%20Callable%202%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test7()%20throws%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread1%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20value%20%3D%20cache.get(%22key%22%2C%20()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22load1%22)%3B%20%2F%2F%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E6%A0%87%E5%BF%97%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(1000)%3B%20%2F%2F%E6%A8%A1%E6%8B%9F%E5%8A%A0%E8%BD%BD%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%22auto%20load%20by%20Callable%201%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread1%20%22%20%2B%20value)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(ExecutionException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D).start()%3B%0A%0A%20%20%20%20%20%20%20%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread2%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20value%20%3D%20cache.get(%22key%22%2C%20()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22load2%22)%3B%20%2F%2F%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E6%A0%87%E5%BF%97%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(1000)%3B%20%2F%2F%E6%A8%A1%E6%8B%9F%E5%8A%A0%E8%BD%BD%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%22auto%20load%20by%20Callable%202%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread2%20%22%20%2B%20value)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(ExecutionException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D).start()%3B%0A%0A%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(5)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20%E5%8F%AF%E4%BB%A5%E5%AF%B9Cache%E7%9A%84%E5%91%BD%E4%B8%AD%E7%8E%87%E3%80%81%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%E6%97%B6%E9%97%B4%E7%AD%89%E4%BF%A1%E6%81%AF%E8%BF%9B%E8%A1%8C%E7%BB%9F%E8%AE%A1%E3%80%82%0A%20%20%20%20%20*%20%E5%9C%A8%E6%9E%84%E5%BB%BACache%E5%AF%B9%E8%B1%A1%E6%97%B6%EF%BC%8C%E9%80%9A%E8%BF%87CacheBuilder%E7%9A%84recordStats%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%BC%80%E5%90%AF%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF%E7%9A%84%E5%BC%80%E5%85%B3%E3%80%82%0A%20%20%20%20%20*%20%E5%BC%80%E5%85%B3%E5%BC%80%E5%90%AF%E5%90%8E%EF%BC%8CCache%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%AF%B9%E7%BC%93%E5%AD%98%E7%9A%84%E5%90%84%E7%A7%8D%E6%93%8D%E4%BD%9C%E8%BF%9B%E8%A1%8C%E7%BB%9F%E8%AE%A1%EF%BC%8C%E8%B0%83%E7%94%A8Cache%E7%9A%84stats%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E6%9F%A5%E7%9C%8B%E7%BB%9F%E8%AE%A1%E5%90%8E%E7%9A%84%E4%BF%A1%E6%81%AF%E3%80%82%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test8()%20%7B%0A%20%20%20%20%20%20%20%20Cache%3CString%2C%20String%3E%20cache%20%3D%20CacheBuilder.newBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.maximumSize(3)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.recordStats()%20%2F%2F%E5%BC%80%E5%90%AF%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF%E5%BC%80%E5%85%B3%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key1%22%2C%20%22value1%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key2%22%2C%20%22value2%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key3%22%2C%20%22value3%22)%3B%0A%20%20%20%20%20%20%20%20cache.put(%22key4%22%2C%20%22value4%22)%3B%0A%20%20%20%20%20%20%20%20cache.getIfPresent(%22key1%22)%3B%0A%20%20%20%20%20%20%20%20cache.getIfPresent(%22key2%22)%3B%0A%20%20%20%20%20%20%20%20cache.getIfPresent(%22key3%22)%3B%0A%20%20%20%20%20%20%20%20cache.getIfPresent(%22key4%22)%3B%0A%20%20%20%20%20%20%20%20cache.getIfPresent(%22key5%22)%3B%0A%20%20%20%20%20%20%20%20cache.getIfPresent(%22key6%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(cache.stats())%3B%20%2F%2F%E8%8E%B7%E5%8F%96%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF%0A%20%20%20%20%7D%0A%0A%7D%0A%0A%60%60%60%0A%0A%23%23%201.%20LoadingCache%0A%0A%60%60%60java%0A%40Data%0A%40AllArgsConstructor%0Aclass%20Customer%20%7B%0A%20%20private%20Integer%20id%3B%0A%20%20%0A%20%20private%20String%20firstName%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%0A%2F**%0A%20*%20%40Auther%20Chris%20Lee%0A%20*%20%40Date%201%2F3%2F2019%2010%3A50%0A%20*%20%40Description%20LoadingCache%E6%98%AFCache%E7%9A%84%E5%AD%90%E6%8E%A5%E5%8F%A3%EF%BC%8C%E7%9B%B8%E6%AF%94%E8%BE%83%E4%BA%8ECache%EF%BC%8C%E5%BD%93%E4%BB%8ELoadingCache%E4%B8%AD%E8%AF%BB%E5%8F%96%E4%B8%80%E4%B8%AA%E6%8C%87%E5%AE%9Akey%E7%9A%84%E8%AE%B0%E5%BD%95%E6%97%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AF%A5%E8%AE%B0%E5%BD%95%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%88%99LoadingCache%E5%8F%AF%E4%BB%A5%E8%87%AA%E5%8A%A8%E6%89%A7%E8%A1%8C%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%E5%88%B0%E7%BC%93%E5%AD%98%E7%9A%84%E6%93%8D%E4%BD%9C.%0A%20*%20%E5%9C%A8%E8%B0%83%E7%94%A8CacheBuilder%E7%9A%84build%E6%96%B9%E6%B3%95%E6%97%B6%E5%BF%85%E9%A1%BB%E4%BC%A0%E9%80%92%E4%B8%80%E4%B8%AACacheLoader%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%8CCacheLoader%E7%9A%84load%E6%96%B9%E6%B3%95%E9%9C%80%E8%A6%81%E6%88%91%E4%BB%AC%E6%8F%90%E4%BE%9B%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0%E3%80%82%0A%20*%20%E5%BD%93%E8%B0%83%E7%94%A8LoadingCache%E7%9A%84get%E6%96%B9%E6%B3%95%E6%97%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%BC%93%E5%AD%98%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%AF%B9%E5%BA%94key%E7%9A%84%E8%AE%B0%E5%BD%95%EF%BC%8C%E5%88%99CacheLoader%E4%B8%AD%E7%9A%84load%E6%96%B9%E6%B3%95%E4%BC%9A%E8%A2%AB%E8%87%AA%E5%8A%A8%E8%B0%83%E7%94%A8%E4%BB%8E%E5%A4%96%E5%AD%98%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%EF%BC%8C%E2%80%9Cload%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E2%80%9D%E4%BC%9A%E4%BD%9C%E4%B8%BA%E2%80%9Ckey%E5%AF%B9%E5%BA%94%E7%9A%84value%E2%80%9D%E5%AD%98%E5%82%A8%E5%88%B0LoadingCache%E4%B8%AD%EF%BC%8C%E5%B9%B6%E4%BB%8Eget%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E3%80%82%0A%20*%2F%0Apublic%20enum%20CustomerCacheProvider%20%7B%0A%20%20%20%20INSTANCE%3B%0A%0A%20%20%20%20private%20final%20LoadingCache%3CInteger%2C%20Customer%3E%20customerCache%3B%0A%0A%20%20%20%20CustomerCacheProvider()%20%7B%0A%20%20%20%20%20%20%20%20CacheLoader%3CInteger%2C%20Customer%3E%20cacheLoader%20%3D%20new%20CacheLoader%3CInteger%2C%20Customer%3E()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20%20public%20Customer%20load(Integer%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20CustomerRepo.findById(id)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20customerCache%20%3D%20CacheBuilder.newBuilder().maximumSize(100).expireAfterWrite(2%2C%20TimeUnit.SECONDS).build(cacheLoader)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20LoadingCache%3CInteger%2C%20Customer%3E%20getCustomerCache()%20%7B%0A%20%20%20%20%20%20%20%20return%20customerCache%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%2F**%0A%20*%20%40Auther%20Chris%20Lee%0A%20*%20%40Date%201%2F3%2F2019%2010%3A45%0A%20*%20%40Description%0A%20*%2F%0Aclass%20CustomerRepo%20%7B%0A%20%20%20%20private%20static%20final%20Map%3CInteger%2C%20Customer%3E%20customers%20%3D%20new%20HashMap%3C%3E()%3B%0A%0A%20%20%20%20static%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20add%20data%0A%20%20%20%20%20%20%20%20Customer%20customer1%20%3D%20new%20Customer(1%2C%20%22Jhon%22)%3B%0A%20%20%20%20%20%20%20%20Customer%20customer2%20%3D%20new%20Customer(2%2C%20%22James%22)%3B%0A%20%20%20%20%20%20%20%20Customer%20customer3%20%3D%20new%20Customer(3%2C%20%22Mark%22)%3B%0A%0A%20%20%20%20%20%20%20%20customers.put(1%2C%20customer1)%3B%0A%20%20%20%20%20%20%20%20customers.put(2%2C%20customer2)%3B%0A%20%20%20%20%20%20%20%20customers.put(3%2C%20customer3)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20static%20Customer%20findById(Integer%20id)%20%7B%0A%20%20%20%20%20%20%20%20System.out.printf(%22find%20%25s%20in%20Repo%20%5Cn%22%2C%20id)%3B%0A%20%20%20%20%20%20%20%20if%20(customers.containsKey(id))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20customers.get(id)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%2F**%0A%20*%20%40Auther%20Chris%20Lee%0A%20*%20%40Date%201%2F3%2F2019%2010%3A52%0A%20*%20%40Description%20https%3A%2F%2Fblog.csdn.net%2Fqq_38567039%2Farticle%2Fdetails%2F126488902%0A%20*%2F%0Apublic%20class%20Main%20%7B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E4%B8%8E%E6%9E%84%E5%BB%BACache%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%AF%B9%E8%B1%A1%E7%B1%BB%E4%BC%BC%EF%BC%8CLoadingCache%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%AF%B9%E8%B1%A1%E4%B9%9F%E6%98%AF%E9%80%9A%E8%BF%87CacheBuilder%E8%BF%9B%E8%A1%8C%E6%9E%84%E5%BB%BA%E3%80%82%0A%20%20%20%20%20*%20%E4%B8%8D%E5%90%8C%E7%9A%84%E6%98%AF%EF%BC%8C%E5%9C%A8%E8%B0%83%E7%94%A8CacheBuilder%E7%9A%84build%E6%96%B9%E6%B3%95%E6%97%B6%EF%BC%8C%E5%BF%85%E9%A1%BB%E4%BC%A0%E9%80%92%E4%B8%80%E4%B8%AACacheLoader%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%8CCacheLoader%E7%9A%84load%E6%96%B9%E6%B3%95%E9%9C%80%E8%A6%81%E6%88%91%E4%BB%AC%E6%8F%90%E4%BE%9B%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0%E3%80%82%0A%20%20%20%20%20*%20%E5%BD%93%E8%B0%83%E7%94%A8LoadingCache%E7%9A%84get%E6%96%B9%E6%B3%95%E6%97%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%BC%93%E5%AD%98%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%AF%B9%E5%BA%94key%E7%9A%84%E8%AE%B0%E5%BD%95%EF%BC%8C%E5%88%99CacheLoader%E4%B8%AD%E7%9A%84load%E6%96%B9%E6%B3%95%E4%BC%9A%E8%A2%AB%E8%87%AA%E5%8A%A8%E8%B0%83%E7%94%A8%E4%BB%8E%E5%A4%96%E5%AD%98%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%EF%BC%8C%0A%20%20%20%20%20*%20%E2%80%9Cload%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E2%80%9D%E4%BC%9A%E4%BD%9C%E4%B8%BA%E2%80%9Ckey%E5%AF%B9%E5%BA%94%E7%9A%84value%E2%80%9D%E5%AD%98%E5%82%A8%E5%88%B0LoadingCache%E4%B8%AD%EF%BC%8C%E5%B9%B6%E4%BB%8Eget%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E3%80%82%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test1()%20%7B%0A%20%20%20%20%20%20%20%20LoadingCache%3CInteger%2C%20Customer%3E%20cutomerCache%20%3D%20CustomerCacheProvider.INSTANCE.getCustomerCache()%3B%0A%20%20%20%20%20%20%20%20%2F*%0A%20%20%20%20%20%20%20%20%20*%20V%20get(K%20key)%20%3A%20This%20will%20either%20return%20an%20already%20cached%20value%2C%20or%20else%20use%20the%20cache's%20CacheLoader%20to%20atomically%0A%20%20%20%20%20%20%20%20%20*%20load%20a%20new%20value%20into%20the%20cache%0A%20%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22Cache%20size%20%3A%20%22%20%2B%20cutomerCache.size())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22Get%20Customer%201%20%3A%20%22%20%2B%20cutomerCache.get(1).getFirstName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22Cache%20size%20%3A%20%22%20%2B%20cutomerCache.size())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(3)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22Get%20Customer%201%20%3A%20%22%20%2B%20cutomerCache.get(1).getFirstName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22Get%20Customer%203%20%3A%20%22%20%2B%20cutomerCache.get(3).getFirstName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22Cache%20size%20%3A%20%22%20%2B%20cutomerCache.size())%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(ExecutionException%20%7C%20InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60

Type类型详解

创建时间:2022/12/6 22:54
更新时间:2022/12/6 23:06
作者:Chris
来源:https://blog.csdn.net/m0_63989537/article/details/124640643

1. Type 简述

Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedType)、数组类型(GenericArrayType)、类型变量(TypeVariable)、基本类型(Class);

- 原始类型,不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;
- 参数化类型,就是我们平常所用到的泛型List、Map;
- 数组类型,并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[] ;
- 基本类型,也就是我们所说的java的基本类型,即int,float,double等

2. ParameterizedType

Type的直接子接口ParameterizedType: 是参数化类型,即泛型,类似List、Map<Integer, String>、List<? extends Number>带有类型参数的类型,也可以是自定义的.

public interface ParameterizedType extends Type {
    // 获取泛型的类型,比如 Map<Integer,String> 获取的是 Integer和String
    Type[] getActualTypeArguments();

    // 获取<> 前面的类型,比如 Map<Integer,String> 获取的是Map
    Type getRawType();

     // For example, if this type is {@code O<T>.I<S>}, return a representation of {@code O<T>}.
    Type getOwnerType();
}

@Data
public class Person {
    List<Integer> integerList;
    Map<String, Integer> belongs;
}

/**
 * integerList 属性的原生类型为 interface java.util.List, 参数类型有:class java.lang.Integer
 * belongs 属性的原生类型为 interface java.util.Map, 参数类型有:class java.lang.String class java.lang.Integer
 */
@Test
public void test1() {
    Class<Person> clz = Person.class;
    Field[] declaredFields = clz.getDeclaredFields();
    Arrays.stream(declaredFields).forEach(field -> {
        if (field.getGenericType() instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
            System.out.printf("%s 属性的原生类型为 %s, 参数类型有:", field.getName(), parameterizedType.getRawType());
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    });
}

3. TypeVariable

TypeVariable是各种类型变量的公共父接口,就是泛型里面的类似T、E。
在这需要强调的是,TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型

public interface GenericDeclaration extends AnnotatedElement {
    /**
     * 返回的泛型变量数组代表了泛型声明的内容,TypeVariable类型就是定义泛型变量的。
     */
    public TypeVariable<?>[] getTypeParameters();
}

GenericDeclaration 有三个直接子类 Class, Construtor, Method,也就是说只能在这几种对象上进行范型变量的声明(定义)。
GenericDeclaration的接口方法getTypeParameters用来逐个获取该GenericDeclaration的范型变量声明.

public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    /**
     * 获得该类型变量的上限(上边界),若无显式定义(extends),默认为Object,类型变量的上限可能不止一个,因为可以用&符号限定多个(这其中有且只能有一个为类或抽象类,且必须放在extends后的第一个,即若有多个上边界,则第一个&后必为接口)
     * 比如 xxxClass<K extends List & Serialize>,则返回 List和Serialize
    */
    Type[] getBounds();

    /**
     *  获取的是在哪个类上进行的泛型声明,在如上的例子中,返回的是xxxClass
     * @since 1.5
     */
    D getGenericDeclaration();

    /**
     *  同样是上面的例子,返回 K, 也就是泛型类型声明时写的名字
     */
    String getName();

    /**
     * 
     * @since 1.8
     */
     AnnotatedType[] getAnnotatedBounds();
}

public class TestType<K extends List & Serializable, V> {

}

/**
 * [java.util.List, java.io.Serializable]
 * K
 * class com.chris.reflect.type.bean.TestType
 * -----------------
 * [java.lang.Object]
 * V
 * class com.chris.reflect.type.bean.TestType
 * -----------------
 */
@Test
public void test2() {
    TypeVariable[] v = TestType.class.getTypeParameters();

    for (TypeVariable t : v) {
        System.out.println(Arrays.stream(t.getBounds()).map(Type::getTypeName).collect(Collectors.toList()));
        System.out.println(t.getName());
        System.out.println(t.getGenericDeclaration());
        System.out.println("-----------------");
    }
}
%5Btoc%5D%0A%0A%23%23%201.%20Type%20%E7%AE%80%E8%BF%B0%0A%3E%20Type%E4%BD%93%E7%B3%BB%E4%B8%AD%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8C%85%E6%8B%AC%EF%BC%9A%E5%8E%9F%E5%A7%8B%E7%B1%BB%E5%9E%8B(Class)%E3%80%81%E5%8F%82%E6%95%B0%E5%8C%96%E7%B1%BB%E5%9E%8B(ParameterizedType)%E3%80%81%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B(GenericArrayType)%E3%80%81%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F(TypeVariable)%E3%80%81%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B(Class)%3B%0A%60%60%60%0A-%20%E5%8E%9F%E5%A7%8B%E7%B1%BB%E5%9E%8B%EF%BC%8C%E4%B8%8D%E4%BB%85%E4%BB%85%E5%8C%85%E5%90%AB%E6%88%91%E4%BB%AC%E5%B9%B3%E5%B8%B8%E6%89%80%E6%8C%87%E7%9A%84%E7%B1%BB%EF%BC%8C%E8%BF%98%E5%8C%85%E6%8B%AC%E6%9E%9A%E4%B8%BE%E3%80%81%E6%95%B0%E7%BB%84%E3%80%81%E6%B3%A8%E8%A7%A3%E7%AD%89%EF%BC%9B%0A-%20%E5%8F%82%E6%95%B0%E5%8C%96%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%B0%B1%E6%98%AF%E6%88%91%E4%BB%AC%E5%B9%B3%E5%B8%B8%E6%89%80%E7%94%A8%E5%88%B0%E7%9A%84%E6%B3%9B%E5%9E%8BList%E3%80%81Map%EF%BC%9B%0A-%20%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%B9%B6%E4%B8%8D%E6%98%AF%E6%88%91%E4%BB%AC%E5%B7%A5%E4%BD%9C%E4%B8%AD%E6%89%80%E4%BD%BF%E7%94%A8%E7%9A%84%E6%95%B0%E7%BB%84String%5B%5D%20%E3%80%81byte%5B%5D%EF%BC%8C%E8%80%8C%E6%98%AF%E5%B8%A6%E6%9C%89%E6%B3%9B%E5%9E%8B%E7%9A%84%E6%95%B0%E7%BB%84%EF%BC%8C%E5%8D%B3T%5B%5D%20%EF%BC%9B%0A-%20%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%88%91%E4%BB%AC%E6%89%80%E8%AF%B4%E7%9A%84java%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%8D%B3int%2Cfloat%2Cdouble%E7%AD%89%0A%60%60%60%0A%0A%23%23%202.%20ParameterizedType%0A%3E%20Type%E7%9A%84%E7%9B%B4%E6%8E%A5%E5%AD%90%E6%8E%A5%E5%8F%A3ParameterizedType%EF%BC%9A%20%E6%98%AF%E5%8F%82%E6%95%B0%E5%8C%96%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%8D%B3%E6%B3%9B%E5%9E%8B%EF%BC%8C%E7%B1%BB%E4%BC%BCList%E3%80%81Map%3CInteger%2C%20String%3E%E3%80%81List%3C%3F%20extends%20Number%3E%E5%B8%A6%E6%9C%89%E7%B1%BB%E5%9E%8B%E5%8F%82%E6%95%B0%E7%9A%84%E7%B1%BB%E5%9E%8B%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%98%AF%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84.%0A%0A%60%60%60java%0Apublic%20interface%20ParameterizedType%20extends%20Type%20%7B%0A%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%E6%B3%9B%E5%9E%8B%E7%9A%84%E7%B1%BB%E5%9E%8B%2C%E6%AF%94%E5%A6%82%20Map%3CInteger%2CString%3E%20%E8%8E%B7%E5%8F%96%E7%9A%84%E6%98%AF%20Integer%E5%92%8CString%0A%20%20%20%20Type%5B%5D%20getActualTypeArguments()%3B%0A%0A%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%3C%3E%20%E5%89%8D%E9%9D%A2%E7%9A%84%E7%B1%BB%E5%9E%8B%2C%E6%AF%94%E5%A6%82%20Map%3CInteger%2CString%3E%20%E8%8E%B7%E5%8F%96%E7%9A%84%E6%98%AFMap%0A%20%20%20%20Type%20getRawType()%3B%0A%0A%20%20%20%20%20%2F%2F%20For%20example%2C%20if%20this%20type%20is%20%7B%40code%20O%3CT%3E.I%3CS%3E%7D%2C%20return%20a%20representation%20of%20%7B%40code%20O%3CT%3E%7D.%0A%20%20%20%20Type%20getOwnerType()%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%0A%40Data%0Apublic%20class%20Person%20%7B%0A%20%20%20%20List%3CInteger%3E%20integerList%3B%0A%20%20%20%20Map%3CString%2C%20Integer%3E%20belongs%3B%0A%7D%0A%0A%2F**%0A%20*%20integerList%20%E5%B1%9E%E6%80%A7%E7%9A%84%E5%8E%9F%E7%94%9F%E7%B1%BB%E5%9E%8B%E4%B8%BA%20interface%20java.util.List%2C%20%E5%8F%82%E6%95%B0%E7%B1%BB%E5%9E%8B%E6%9C%89%3Aclass%20java.lang.Integer%0A%20*%20belongs%20%E5%B1%9E%E6%80%A7%E7%9A%84%E5%8E%9F%E7%94%9F%E7%B1%BB%E5%9E%8B%E4%B8%BA%20interface%20java.util.Map%2C%20%E5%8F%82%E6%95%B0%E7%B1%BB%E5%9E%8B%E6%9C%89%3Aclass%20java.lang.String%20class%20java.lang.Integer%0A%20*%2F%0A%40Test%0Apublic%20void%20test1()%20%7B%0A%20%20%20%20Class%3CPerson%3E%20clz%20%3D%20Person.class%3B%0A%20%20%20%20Field%5B%5D%20declaredFields%20%3D%20clz.getDeclaredFields()%3B%0A%20%20%20%20Arrays.stream(declaredFields).forEach(field%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20if%20(field.getGenericType()%20instanceof%20ParameterizedType)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20ParameterizedType%20parameterizedType%20%3D%20(ParameterizedType)%20field.getGenericType()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.printf(%22%25s%20%E5%B1%9E%E6%80%A7%E7%9A%84%E5%8E%9F%E7%94%9F%E7%B1%BB%E5%9E%8B%E4%B8%BA%20%25s%2C%20%E5%8F%82%E6%95%B0%E7%B1%BB%E5%9E%8B%E6%9C%89%3A%22%2C%20field.getName()%2C%20parameterizedType.getRawType())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Type%5B%5D%20actualTypeArguments%20%3D%20parameterizedType.getActualTypeArguments()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(Type%20actualTypeArgument%20%3A%20actualTypeArguments)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(actualTypeArgument)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D)%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%203.%20TypeVariable%0A%3E%20TypeVariable%E6%98%AF%E5%90%84%E7%A7%8D%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E7%9A%84%E5%85%AC%E5%85%B1%E7%88%B6%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%B0%B1%E6%98%AF%E6%B3%9B%E5%9E%8B%E9%87%8C%E9%9D%A2%E7%9A%84%E7%B1%BB%E4%BC%BCT%E3%80%81E%E3%80%82%0A%3E%20%E5%9C%A8%E8%BF%99%E9%9C%80%E8%A6%81%E5%BC%BA%E8%B0%83%E7%9A%84%E6%98%AF%EF%BC%8CTypeVariable%E4%BB%A3%E8%A1%A8%E7%9D%80%E6%B3%9B%E5%9E%8B%E4%B8%AD%E7%9A%84%E5%8F%98%E9%87%8F%EF%BC%8C%E8%80%8CParameterizedType%E5%88%99%E4%BB%A3%E8%A1%A8%E6%95%B4%E4%B8%AA%E6%B3%9B%E5%9E%8B%0A%0A%60%60%60java%0Apublic%20interface%20GenericDeclaration%20extends%20AnnotatedElement%20%7B%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%BF%94%E5%9B%9E%E7%9A%84%E6%B3%9B%E5%9E%8B%E5%8F%98%E9%87%8F%E6%95%B0%E7%BB%84%E4%BB%A3%E8%A1%A8%E4%BA%86%E6%B3%9B%E5%9E%8B%E5%A3%B0%E6%98%8E%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8CTypeVariable%E7%B1%BB%E5%9E%8B%E5%B0%B1%E6%98%AF%E5%AE%9A%E4%B9%89%E6%B3%9B%E5%9E%8B%E5%8F%98%E9%87%8F%E7%9A%84%E3%80%82%0A%20%20%20%20%20*%2F%0A%20%20%20%20public%20TypeVariable%3C%3F%3E%5B%5D%20getTypeParameters()%3B%0A%7D%0A%60%60%60%0A%0A%3E%20GenericDeclaration%20%E6%9C%89%E4%B8%89%E4%B8%AA%E7%9B%B4%E6%8E%A5%E5%AD%90%E7%B1%BB%20%60Class%2C%20Construtor%2C%20Method%60%2C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%E5%8F%AA%E8%83%BD%E5%9C%A8%E8%BF%99%E5%87%A0%E7%A7%8D%E5%AF%B9%E8%B1%A1%E4%B8%8A%E8%BF%9B%E8%A1%8C%E8%8C%83%E5%9E%8B%E5%8F%98%E9%87%8F%E7%9A%84%E5%A3%B0%E6%98%8E%EF%BC%88%E5%AE%9A%E4%B9%89%EF%BC%89%E3%80%82%0A%3E%20GenericDeclaration%E7%9A%84%E6%8E%A5%E5%8F%A3%E6%96%B9%E6%B3%95getTypeParameters%E7%94%A8%E6%9D%A5%E9%80%90%E4%B8%AA%E8%8E%B7%E5%8F%96%E8%AF%A5GenericDeclaration%E7%9A%84%E8%8C%83%E5%9E%8B%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E.%0A%0A%60%60%60java%0Apublic%20interface%20TypeVariable%3CD%20extends%20GenericDeclaration%3E%20extends%20Type%2C%20AnnotatedElement%20%7B%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%8E%B7%E5%BE%97%E8%AF%A5%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E7%9A%84%E4%B8%8A%E9%99%90%EF%BC%88%E4%B8%8A%E8%BE%B9%E7%95%8C%EF%BC%89%EF%BC%8C%E8%8B%A5%E6%97%A0%E6%98%BE%E5%BC%8F%E5%AE%9A%E4%B9%89%EF%BC%88extends%EF%BC%89%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAObject%EF%BC%8C%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E7%9A%84%E4%B8%8A%E9%99%90%E5%8F%AF%E8%83%BD%E4%B8%8D%E6%AD%A2%E4%B8%80%E4%B8%AA%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%8F%AF%E4%BB%A5%E7%94%A8%26%E7%AC%A6%E5%8F%B7%E9%99%90%E5%AE%9A%E5%A4%9A%E4%B8%AA%EF%BC%88%E8%BF%99%E5%85%B6%E4%B8%AD%E6%9C%89%E4%B8%94%E5%8F%AA%E8%83%BD%E6%9C%89%E4%B8%80%E4%B8%AA%E4%B8%BA%E7%B1%BB%E6%88%96%E6%8A%BD%E8%B1%A1%E7%B1%BB%EF%BC%8C%E4%B8%94%E5%BF%85%E9%A1%BB%E6%94%BE%E5%9C%A8extends%E5%90%8E%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%EF%BC%8C%E5%8D%B3%E8%8B%A5%E6%9C%89%E5%A4%9A%E4%B8%AA%E4%B8%8A%E8%BE%B9%E7%95%8C%EF%BC%8C%E5%88%99%E7%AC%AC%E4%B8%80%E4%B8%AA%26%E5%90%8E%E5%BF%85%E4%B8%BA%E6%8E%A5%E5%8F%A3%EF%BC%89%0A%20%20%20%20%20*%20%E6%AF%94%E5%A6%82%20xxxClass%3CK%20extends%20List%20%26%20Serialize%3E%2C%E5%88%99%E8%BF%94%E5%9B%9E%20List%E5%92%8CSerialize%0A%20%20%20%20*%2F%0A%20%20%20%20Type%5B%5D%20getBounds()%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%20%E8%8E%B7%E5%8F%96%E7%9A%84%E6%98%AF%E5%9C%A8%E5%93%AA%E4%B8%AA%E7%B1%BB%E4%B8%8A%E8%BF%9B%E8%A1%8C%E7%9A%84%E6%B3%9B%E5%9E%8B%E5%A3%B0%E6%98%8E%2C%E5%9C%A8%E5%A6%82%E4%B8%8A%E7%9A%84%E4%BE%8B%E5%AD%90%E4%B8%AD%2C%E8%BF%94%E5%9B%9E%E7%9A%84%E6%98%AFxxxClass%0A%20%20%20%20%20*%20%40since%201.5%0A%20%20%20%20%20*%2F%0A%20%20%20%20D%20getGenericDeclaration()%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%20%E5%90%8C%E6%A0%B7%E6%98%AF%E4%B8%8A%E9%9D%A2%E7%9A%84%E4%BE%8B%E5%AD%90%2C%E8%BF%94%E5%9B%9E%20K%2C%20%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%B3%9B%E5%9E%8B%E7%B1%BB%E5%9E%8B%E5%A3%B0%E6%98%8E%E6%97%B6%E5%86%99%E7%9A%84%E5%90%8D%E5%AD%97%0A%20%20%20%20%20*%2F%0A%20%20%20%20String%20getName()%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%0A%20%20%20%20%20*%20%40since%201.8%0A%20%20%20%20%20*%2F%0A%20%20%20%20%20AnnotatedType%5B%5D%20getAnnotatedBounds()%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%0Apublic%20class%20TestType%3CK%20extends%20List%20%26%20Serializable%2C%20V%3E%20%7B%0A%0A%7D%0A%0A%2F**%0A%20*%20%5Bjava.util.List%2C%20java.io.Serializable%5D%0A%20*%20K%0A%20*%20class%20com.chris.reflect.type.bean.TestType%0A%20*%20-----------------%0A%20*%20%5Bjava.lang.Object%5D%0A%20*%20V%0A%20*%20class%20com.chris.reflect.type.bean.TestType%0A%20*%20-----------------%0A%20*%2F%0A%40Test%0Apublic%20void%20test2()%20%7B%0A%20%20%20%20TypeVariable%5B%5D%20v%20%3D%20TestType.class.getTypeParameters()%3B%0A%0A%20%20%20%20for%20(TypeVariable%20t%20%3A%20v)%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(Arrays.stream(t.getBounds()).map(Type%3A%3AgetTypeName).collect(Collectors.toList()))%3B%0A%20%20%20%20%20%20%20%20System.out.println(t.getName())%3B%0A%20%20%20%20%20%20%20%20System.out.println(t.getGenericDeclaration())%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22-----------------%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60

Typora快捷键

创建时间:2020/9/2 16:15
更新时间:2023/8/6 11:22
作者:Chris
来源:https://blog.csdn.net/qusikao/article/details/126737400

Typora快捷键

https://www.cnblogs.com/hongdada/p/9776547.html
偏好设置->打开高级设置->conf.user.json文件

 "keyBinding": {
    // "Always on Top": "Ctrl+Shift+P"
	"Always on Top": "Ctrl+Shift+P",  
    "Code Fences": "Alt+z",  
    "Ordered List":"Ctrl+Alt+o",  
    "Unordered List": "Ctrl+Alt+u"  
  },

新增字体

Microsoft YaHe
font-size: 14px

#write {
  max-
  margin: 0 auto;
  padding: 20px 30px 160px;
}

编辑器自适应屏幕宽度

https://blog.csdn.net/qusikao/article/details/126737400

偏好设置,外观,打开主题文件夹
选择使用中的主题
将max-width的值调整为94%,意思是在全屏状态下编辑器窗口宽度会自动占用94%的宽度。

#write {
  max-width: 94%;
  margin: 0 auto;
  padding: 20px 30px 160px;
}

对于高阶版用户可能还会调整源文件编辑器宽度,依然是调整对应主题的css文件,代码如下:

#typora-source .CodeMirror-lines{
   max-width: 94%;
}
%5Btoc%5D%0A%23%23%20**Typora%E5%BF%AB%E6%8D%B7%E9%94%AE**%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fhongdada%2Fp%2F9776547.html%0A%E5%81%8F%E5%A5%BD%E8%AE%BE%E7%BD%AE-%3E%E6%89%93%E5%BC%80%E9%AB%98%E7%BA%A7%E8%AE%BE%E7%BD%AE-%3Econf.user.json%E6%96%87%E4%BB%B6%0A%60%60%60%0A%20%22keyBinding%22%3A%20%7B%0A%20%20%20%20%2F%2F%20%22Always%20on%20Top%22%3A%20%22Ctrl%2BShift%2BP%22%0A%09%22Always%20on%20Top%22%3A%20%22Ctrl%2BShift%2BP%22%2C%20%20%0A%20%20%20%20%22Code%20Fences%22%3A%20%22Alt%2Bz%22%2C%20%20%0A%20%20%20%20%22Ordered%20List%22%3A%22Ctrl%2BAlt%2Bo%22%2C%20%20%0A%20%20%20%20%22Unordered%20List%22%3A%20%22Ctrl%2BAlt%2Bu%22%20%20%0A%20%20%7D%2C%0A%60%60%60%0A%0A%0A%23%23%20**%E6%96%B0%E5%A2%9E%E5%AD%97%E4%BD%93**%0AMicrosoft%20YaHe%0Afont-size%3A%2014px%0A%0A%0A!%5B5b3d5ad46262dca700bb5a27675c0470.png%5D(en-resource%3A%2F%2Fdatabase%2F605%3A1)%0A%0A%0A%60%60%60%0A%23write%20%7B%0A%20%20max-width%3A%20860px%3B%0A%20%20margin%3A%200%20auto%3B%0A%20%20padding%3A%2020px%2030px%20160px%3B%0A%7D%0A%60%60%60%0A%0A%23%23%20**%E7%BC%96%E8%BE%91%E5%99%A8%E8%87%AA%E9%80%82%E5%BA%94%E5%B1%8F%E5%B9%95%E5%AE%BD%E5%BA%A6**%0Ahttps%3A%2F%2Fblog.csdn.net%2Fqusikao%2Farticle%2Fdetails%2F126737400%0A%3E%20%E5%81%8F%E5%A5%BD%E8%AE%BE%E7%BD%AE%EF%BC%8C%E5%A4%96%E8%A7%82%EF%BC%8C%E6%89%93%E5%BC%80%E4%B8%BB%E9%A2%98%E6%96%87%E4%BB%B6%E5%A4%B9%0A%3E%20%E9%80%89%E6%8B%A9%E4%BD%BF%E7%94%A8%E4%B8%AD%E7%9A%84%E4%B8%BB%E9%A2%98%0A%3E%20%E5%B0%86max-width%E7%9A%84%E5%80%BC%E8%B0%83%E6%95%B4%E4%B8%BA94%25%EF%BC%8C%E6%84%8F%E6%80%9D%E6%98%AF%E5%9C%A8%E5%85%A8%E5%B1%8F%E7%8A%B6%E6%80%81%E4%B8%8B%E7%BC%96%E8%BE%91%E5%99%A8%E7%AA%97%E5%8F%A3%E5%AE%BD%E5%BA%A6%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%8D%A0%E7%94%A894%25%E7%9A%84%E5%AE%BD%E5%BA%A6%E3%80%82%0A%0A%60%60%60%0A%23write%20%7B%0A%20%20max-width%3A%2094%25%3B%0A%20%20margin%3A%200%20auto%3B%0A%20%20padding%3A%2020px%2030px%20160px%3B%0A%7D%0A%60%60%60%0A%3E%20%E5%AF%B9%E4%BA%8E%E9%AB%98%E9%98%B6%E7%89%88%E7%94%A8%E6%88%B7%E5%8F%AF%E8%83%BD%E8%BF%98%E4%BC%9A%E8%B0%83%E6%95%B4%E6%BA%90%E6%96%87%E4%BB%B6%E7%BC%96%E8%BE%91%E5%99%A8%E5%AE%BD%E5%BA%A6%EF%BC%8C%E4%BE%9D%E7%84%B6%E6%98%AF%E8%B0%83%E6%95%B4%E5%AF%B9%E5%BA%94%E4%B8%BB%E9%A2%98%E7%9A%84css%E6%96%87%E4%BB%B6%EF%BC%8C%E4%BB%A3%E7%A0%81%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60%0A%23typora-source%20.CodeMirror-lines%7B%0A%20%20%20max-width%3A%2094%25%3B%0A%7D%0A%60%60%60%0A

docker

创建时间:2021/12/29 15:18
更新时间:2022/12/3 12:56
作者:Chris
来源:https://blog.csdn.net/IT_heima/article/details/124058108

Docker

1 概述

1.1 是什么

基于Go语言实现的云开源项目
Docker的主要目标是:Build,Ship and Run any app, anywhere

1.2 解决了什么问题

解决了运行环境和配置问题软件容器,方便做系统集成并有助于整体发布的容器虚拟化技术

1.3 能干什么

更轻量:

基于容器的虚拟化,仅包含业务运行所需要的runtime环境[root用户权限,进程空间,用户空间和网络空间]
CentOS、Ubuntu基础镜像仅170M,这宿主机可部署100~1000个容器

更高效:

一次构建,随处运行
更快速高效的交付和部署系统
降低运维成本,更便捷的升级和扩容

1.4 三要素

镜像
容器
仓库

1.4.1 镜像image

镜像就是模板,可以用来创建Docker容器,一个镜像可以创建很多个容器

1.4.2 容器container

容器是用镜像创建的运行实例

1.4.3 仓库Repository

集中存放镜像文件的场所
仓库分为公开仓库和私有仓库
最大的公开仓库是 DockerHub https://hub.docker.com/
国内的公开仓库有阿里和网易

1.4.3 底层原理

1.4.3.1 是如何工作的

Docker是一个CS结构的系统,Docker守护进程运行在主机上,然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器

2 安装

2.1 去哪下

官网:

http://www.docker.com
http://www.docker-cn.com

2.2 前提

Docker运行在CentOS7上要求系统版本为64位,内核版本为3.10以上
Docker运行在CentOS6.5上要求系统版本为64位,内核版本为2.6.32-431或以上

[root@master ~]# uname -r
3.10.0-1127.el7.x86_64

2.3 CentOS7 安装Docker

https://docs.docker.com/install/linux/docker-ce/centos

卸载老版本

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

安装仓库

sudo yum install -y yum-utils
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

查看可用docker版本

yum list docker-ce --showduplicates | sort -r

安装指定版本

yum install docker-ce-19.03.8 docker-ce-cli-19.03.8 containerd.io

启动docker

systemctl start docker

2.4 阿里云镜像加速

https://dev.aliyun.com/search.html

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json
{
  "registry-mirrors": ["https://96rbv7qx.mirror.aliyuncs.com"]
}

sudo systemctl daemon-reload
sudo systemctl restart docker

docker run hello-world

[root@master ~]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete 
Digest: sha256:f2266cbfc127c960fd30e76b7c792dc23b588c0db76233517e1891a4e357d519
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

3 常用命令

3.1 帮助命令

描述命令
查看版本docker version
docker信息汇总docker info
帮助命令docker --help

3.2 镜像命令

3.2.1 查询本地镜像

描述命令
列出本地镜像docker images
列出本地所有镜像包括是间映像层docker image -a
只显示镜像IDdocker image -q
显示镜像的摘要信息docker image --digests
显示完整的镜像信息docker image --no-trunc
[root@master ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              d1165f221234        6 weeks ago         13.3kB

REPOSITORY:镜像仓库源
TAG:镜像的标签
IMAGE ID:镜像ID
CREATED:镜像创建时间
SIZE:镜像大小

如查不你指定一个镜像的标签,docker默认使用hello-world:latest镜像

3.2.2 查询远程镜像

STARS:点赞数
OFFICIAL:官方版本

描述命令
从[https://hub.docker.com]上查询镜像信息docker search image-name
列出收藏数不小于30的镜像docker search -s 30 image-name
显示完整的镜像信息docker search --no-trunc image-name
只列出automated的镜像docker search --automated image-name

3.2.3 拉取远程镜像

描述命令
摘取远程镜像到本地,不加版本默认拉取最新版本docker pull elasticsearch

3.2.4 删除镜像

描述命令
删除本地镜像,不加版本默认删除最新版本docker rmi elasticsearch
删除多个本地镜像,不加版本默认删除最新版本docker rmi elasticsearch nginx
强制删除本地镜像,不加版本默认删除最新版本docker rmi -f elasticsearch
强制删除本地所有镜像,不加版本默认删除最新版本docker rmi -f $(docker images -q)

3.2.5 生成镜像

描述命令
提交容器副本使之成为一个新的镜像docker commit

docker commit -m="信息描述" -a="作者" 容器ID 要创建的目标镜像:[标签名]

[root@master ~]# docker commit -m "tomcat without doc" -a "chris" 3b7146c6590e christomcat:1.0
[root@master ~]# docker run -it -p 8888:8080 christomcat:1.0

3.3 容器命令

3.3.1 新建并启动容器

描述命令
新建并启动容器docker run [OPTIONS] (image-name|id) [COMMAND] [ARG...]
--name="指定新的容器名称"docker run --name 指定新的容器名称 (image-name|id)
以交互方式运行容器通常与-t并用docker run -i (image-name|id)
为容器重新分配一个伪输入终端docker run -t (image-name|id)
随机端口映射docker run -P (image-name
指定端口映射,有四种形式docker run -p (image-name|id)
1docker run -p ip:hostPort:containPort (image-name|id)
2docker run -p ip::containPort (image-name|id)
3docker run -p hostPort:containPort (image-name|id)
4docker run -p containPort (image-name|id)
以守护的方启动容器docker run -d (image-name|id)

docker run -it --name="es0422" elasticsearch /bin/bash
docker run -d centos
docker run -it -p 8080:8080 tomcat /bin/bash

3.3.2 列出所有正在运行的容器

描述命令
所有正在运行的容器docker ps [OPTIONS]
列出正在运行的和历史上运行过的容器docker ps -a
列出最近创建的容器docker ps -l
列出最近3个创建的容器docker ps -n 3
静默模式,只显示容器编号docker ps -q
不截断输出docker ps --no-trunc

3.3.3 退出正在运行的容器

描述命令
停止容器并退出exit
退出但不停止容器ctrl+p+q

3.3.4 启动停止容器

描述命令
启动容器docker start (container-name|id)
重新启动容器docker restart (container-name|id)
停止容器docker stop (container-name|id)
强制停止容器docker kill (container-name|id)

3.3.5 删除容器

描述命令
删除已停止的容器docker rm (container-name|id)
强制删除容器无论容器是否已停止docker rm (container-name|id)
一次性删除多个容器docker rm -f $(docker ps -aq)
一次性删除多个容器docker ps -aq | xargs docker rm

3.3.6 查看容器日志

docker run -d centos /bin/sh -c "while true; do echo hello zzyy;sleep 2;done"

[root@master docker]# docker run -d centos /bin/sh -c "while true; do echo hello zzyy;sleep 2;done"
9b5688f06fc2c4a52721e6dbcbba94062915211bbfaceb9473b8d3bfced736ce
[root@master ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
9b5688f06fc2        centos              "/bin/sh -c 'while t…"   5 seconds ago       Up 2 seconds                            wonderful_goldwasser

docker logs -f -t --tail 3 9b5688f06fc2
-f: 打印最新的日志
-t: 加入时间戳
--tail: 显示最后多少条

[root@master ~]# docker logs -f -t --tail  3 9b5688f06fc2
2021-04-22T13:39:23.793299808Z hello zzyy
2021-04-22T13:39:25.804149907Z hello zzyy
2021-04-22T13:39:27.815085938Z hello zzyy
2021-04-22T13:39:29.826784950Z hello zzyy

3.3.7 容器内命令

描述命令
查看容器内的进程docker -ps
查看容器内的细节docker inspect id

3.3.8 进入运行中的容器并以命令交互

描述命令
进入容器正在执行的终端docker attach id
进入容器内docker exec -it id /bin/bash
在容器外操作执行命令docker exec -it id ls -l /tmp
  1. 进入当前容器后开启一个新的终端,可以在里面操作。(常用)
    docker exec
  2. 进入容器正在执行某个命令的终端,不能在里面操作;多个窗口同时attach到同一个容器时,所有窗口同步显示;当某个窗口因命令阻塞,其他窗口也无法操作
    docker attach
[root@master docker]# docker attach 013c88f998bd
[root@013c88f998bd /]# ls -l /tmp
total 8
-rwx------. 1 root root 701 Dec  4 17:37 ks-script-esd4my7v
-rwx------. 1 root root 671 Dec  4 17:37 ks-script-eusq_sc5


[root@master ~]# docker exec 013c88f998bd ls -l /tmp
total 8
-rwx------. 1 root root 701 Dec  4 17:37 ks-script-esd4my7v
-rwx------. 1 root root 671 Dec  4 17:37 ks-script-eusq_sc5

3.3.9 copy文件

容器停止后容器里面之前改动的数据就会消失
docker cp id:/容器内路径 宿主机路径
docker cp id:/tmp/yum.log /root

4 镜像

4.1 是什么

联合文件系统(UnionFS), 是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时将不同的目录挂载到同一个虚拟文件下

4.2 加载原理

bootfs(boot file system):主要包含bootloader和kernel,bootloader主要是引导加载kernel,linux启动时会先加载bootfs,在Docker镜像的最底层就是bootfs,这一层与linux是一样的,当bootfs加载完成之后整个内核就都在内存中,此时内存的使用权就由bootfs转交给内核,同时系统也会卸载掉bootfs。

rootfs(root file system):在bootfs之上包含了典型的linux系统中的/dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu或CentOS

为什么我们安装的CentOS要好几个G,但是docker里面的CentOS却只有200M
对于不同的linux发行版本bootfs是一致的,rootfs会有差别,对于一个精简的OS,可以共用系统的bootfs并提供自己的rootfs

tomcat镜像里面的分层结构

4.3 特点

Docker镜像都是只读的
当容器启动时,当容器启动时当一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下叫作“镜像层”

5 数据卷

5.1 是什么

docker容器产生的数据,如果不通过docker commit生成新的镜像,当容器删除之后,数据就会消失
容器数据卷就是用来保存docker容器中的数据
卷是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但是不属于UnionFS,因此能绕过UnionFS提供一些用于持久存储或共享数据的特性
卷的设计目的就是数据持久化,完全独立于容器的生命周期,因此docker不会在容器删除时删除挂载的数据卷

5.2 特点

1. 数据卷可以在容器之间共享或重用数据
2. 数据卷中的更改可以直接生效
3. 数据卷中的更改不会包含在镜像的更新中
4. 数据卷的生命周期一直持续到没有容器使用它为止

5.3 容器内添加数据卷

5.3.1 直接命令添加

docker run -it -v /宿主机目录绝对路径:容器内目录[权限:ro] 镜像名或ID
docker run -it -v /mydataVolume":/dataVolumeContainer: centos
在目录不存在的情况会自动创建目录, 如果创建添加权限:ro, 表示容器里面的数据卷只读但不能修改

# docker inspect 250d8813d860
"HostConfig": {
            "Binds": [
                "/mydataVolume:/dataVolumeContainer:"
            ],
}

"Mounts": [
            {
                "Type": "bind",
                "Source": "/mydataVolume",
                "Destination": "/dataVolumeContainer",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

[root@master ~]# docker run -it -v /mydataVolume:/dataVolumeContainer: centos
[root@250d8813d860 /]# ls
bin  dataVolumeContainer  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

[root@master /]# ll
total 24
lrwxrwxrwx.   1 root root    7 Dec 24 11:26 bin -> usr/bin
dr-xr-xr-x.   5 root root 4096 Dec 24 11:48 boot
drwxr-xr-x.  20 root root 3300 Apr 23 15:29 dev
drwxr-xr-x. 141 root root 8192 Apr 23 15:29 etc
drwxr-xr-x.   3 root root   19 Dec 24 11:53 home
lrwxrwxrwx.   1 root root    7 Dec 24 11:26 lib -> usr/lib
lrwxrwxrwx.   1 root root    9 Dec 24 11:26 lib64 -> usr/lib64
drwxr-xr-x.   2 root root    6 Apr 11  2018 media
drwxr-xr-x.   2 root root    6 Apr 11  2018 mnt
drwxr-xr-x.   2 root root    6 Apr 25 10:15 mydataVolume
drwxr-xr-x.   4 root root   34 Apr 22 13:49 opt
dr-xr-xr-x. 256 root root    0 Apr 23 15:28 proc
dr-xr-x---.   6 root root 4096 Apr 23 15:29 root
drwxr-xr-x.  43 root root 1340 Apr 25 06:35 run
lrwxrwxrwx.   1 root root    8 Dec 24 11:26 sbin -> usr/sbin
drwxr-xr-x.   2 root root    6 Apr 11  2018 srv
dr-xr-xr-x.  13 root root    0 Apr 23 15:28 sys
drwxrwxrwt.  22 root root 4096 Apr 25 10:15 tmp
drwxr-xr-x.  13 root root  155 Dec 24 11:26 usr
drwxr-xr-x.  20 root root  282 Dec 24 11:50 var

备注
Docker挂载主机目录Docker访问出现 cann't open directory.:Permission denied
解决办法在挂载目录后增加 --privileged true 参数即可
[root@master ~]# docker run -it -v /mydataVolume:/dataVolumeContainer: --privileged true centos

5.3.2 DockerFile添加

  1. 新建dockerfile
mkdir mydocker  
cd mydocker  
vi dockerfile
写入如下命令

From centos
VOLUME ["/dataVolumeContainer01","/dataVolumeContainer02"]
CMD echo "finished,------success"
CMD /bin/bash
  1. 生成镜像

docker build -f /mydocker/dockerfile -t chris/centos .
在当前目录下根据指定的dockerfile生成命名空间为chris镜像名称为centos的镜像

[root@master mydocker]# docker build -f /mydocker/dockerfile -t chris/centos .
Sending build context to Docker daemon  2.048kB
Step 1/4 : From centos
 ---> 300e315adb2f
Step 2/4 : VOLUME ["/dataVolumeContainer01","/dataVolumeContainer02"]
 ---> Running in 3a2ba255152a
Removing intermediate container 3a2ba255152a
 ---> 9522ef03e277
Step 3/4 : CMD echo "finished,------success"
 ---> Running in b6c0a82df0ad
Removing intermediate container b6c0a82df0ad
 ---> 7dff01de54a6
Step 4/4 : CMD /bin/bash
 ---> Running in af67b3613d42
Removing intermediate container af67b3613d42
 ---> f975da2854b7
Successfully built f975da2854b7
Successfully tagged chris/centos:latest

[root@master /]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
chris/centos        latest              f975da2854b7        3 minutes ago       209MB
  1. 创建容器
[root@master ~]# docker run -it chris/centos /bin/bash
[root@22f74a27ccb0 /]# ls -l
total 0
lrwxrwxrwx.   1 root root   7 Nov  3 15:22 bin -> usr/bin
drwxr-xr-x.   2 root root   6 Apr 25 03:20 dataVolumeContainer01
drwxr-xr-x.   2 root root   6 Apr 25 03:20 dataVolumeContainer02
drwxr-xr-x.   5 root root 360 Apr 25 03:20 dev
drwxr-xr-x.   1 root root  66 Apr 25 03:20 etc
drwxr-xr-x.   2 root root   6 Nov  3 15:22 home
lrwxrwxrwx.   1 root root   7 Nov  3 15:22 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 Nov  3 15:22 lib64 -> usr/lib64
drwx------.   2 root root   6 Dec  4 17:37 lost+found
drwxr-xr-x.   2 root root   6 Nov  3 15:22 media
drwxr-xr-x.   2 root root   6 Nov  3 15:22 mnt
drwxr-xr-x.   2 root root   6 Nov  3 15:22 opt
dr-xr-xr-x. 258 root root   0 Apr 25 03:20 proc
dr-xr-x---.   2 root root 162 Dec  4 17:37 root
drwxr-xr-x.  11 root root 163 Dec  4 17:37 run
lrwxrwxrwx.   1 root root   8 Nov  3 15:22 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 Nov  3 15:22 srv
dr-xr-xr-x.  13 root root   0 Apr 23 07:28 sys
drwxrwxrwt.   7 root root 145 Dec  4 17:37 tmp
drwxr-xr-x.  12 root root 144 Dec  4 17:37 usr
drwxr-xr-x.  20 root root 262 Dec  4 17:37 var

在数据卷中创建文件

[root@22f74a27ccb0 /]# cd dataVolumeContainer01
[root@22f74a27ccb0 dataVolumeContainer01]# vi container.txt

查看数据卷在容器和宿主机之间的路径关联关系

[root@master ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
22f74a27ccb0        chris/centos        "/bin/bash"         16 minutes ago      Up 16 minutes                                stupefied_cannon
692aee0e4bfe        christomcat:1.0     "catalina.sh run"   42 hours ago        Up 42 hours         0.0.0.0:8888->8080/tcp   epic_roentgen
3b7146c6590e        tomcat              "catalina.sh run"   43 hours ago        Up 43 hours         0.0.0.0:8088->8080/tcp   tomcat2
[root@master ~]# docker inspect 22f74a27ccb0
"Mounts": [
            {
                "Type": "volume",
                "Name": "f893623ee2039a23c820361dda8b45a164dc9a6a3e4329d30533ea6a73ad36e9",
                "Source": "/var/lib/docker/volumes/f893623ee2039a23c820361dda8b45a164dc9a6a3e4329d30533ea6a73ad36e9/_data",
                "Destination": "/dataVolumeContainer01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "feb81fb00529025525f7b27c20edc417eced5ce517cdf73c754343e943af50ba",
                "Source": "/var/lib/docker/volumes/feb81fb00529025525f7b27c20edc417eced5ce517cdf73c754343e943af50ba/_data",
                "Destination": "/dataVolumeContainer02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]
[root@master ~]# cd /var/lib/docker/volumes/f893623ee2039a23c820361dda8b45a164dc9a6a3e4329d30533ea6a73ad36e9/_data
[root@master _data]# ll
total 4
-rw-r--r--. 1 root root 29 Apr 25 11:36 container.txt
        

5.4 数据卷容器

命名的容器挂载数据卷,其它容器通过挂载这个父容器实现数据共享,挂载数据卷的容器称之为数据卷容器
容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止

[root@master _data]# docker run -it --name dc01 chris/centos
[root@ca18f7f9d24c /]# cd dataVolumeContainer02
[root@ca18f7f9d24c dataVolumeContainer02]# touch dc01_add.txt

[root@master ~]# docker run -it --volumes-from dc01 --name dc02 chris/centos
[root@defe4e49519f /]# ls
bin  dataVolumeContainer01  dataVolumeContainer02  dev	etc  home  lib	lib64  lost+found  media  mnt  opt  proc  root	run  sbin  srv	sys  tmp  usr  var
[root@defe4e49519f /]# cd dataVolumeContainer0
[root@defe4e49519f dataVolumeContainer02]# ls
dc01_add.txt  

6 DockerFile

6.1 是什么

DockerFile是用来构建Docker镜像的构建文件,是由一系列的命令和参数组成的脚本。

6.2 构建三步骤

  1. 编写DockerFile
  2. 构建Docker镜像
  3. 运行

6.3 DockerFile的解析过程

6.3.1 DockerFile的内容基础知识

  1. 每个保留字命令必须为大写字母并且后面至少跟一个参数
  2. 指令按从上到下顺序执行
  3. #表示注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交

6.3.2 DockerFile执行流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指定并对容器作出修改
  3. 执行类似docker commit 的操作提交一个新的镜像层
  4. docker基于则提交的镜像再运行一个新的容器
  5. 执行DockerFile中的下一条指令,直到所有的指令都被执行完成。

DockerFile是软件的原材料
Docker镜像是软件的交付物
Docker容器可以看成是软件的运行态
DockerFile面向开发,Docker镜像成为软件的交付标准,Docker容器则涉及部署到运维,三者缺一不可

6.4 指令

命令描述
FROM基础镜像,当前镜像是基于哪个镜像的
MAINTAINER作者及其邮箱
RUN容器构建时需要运行的linux命令
EXPOSE容器运行时对外暴露的端口号
WORKDIR进入容器运行后的目录,如果没有指定就是根目录
ENV在构建镜像的过程中设置环境变量
ADD将宿主机的文件拷贝进镜像且ADD命令会自动处理URL和解压TAR压缩包
COPY类似ADD,将文件或目录拷贝到镜像中,将从构建上下文目录中<源路径>的文件/目录复制到新的一层镜像内的<目标路径>位置 COPY SRC DEST
VOLUME指定数据卷,用于数据共享和持久化
CMD指定一个容器启动时需要运行的命令,DockerFile中可以有多个CMD指令,但是只有最后一个生效,CMD会被docker run之后的参数替换
ENTRYPOINT和CMD一样,指定一个容器启动时需要运行的命令,但是ENTRYPOINT只会追加,不会覆盖之前的命令
ONBUILD当构建一个被继承的DockerFile时运行命令,父镜像在被子继承后父镜像的ONBUILD被触发

6.5. 案例

6.5.1 Base镜像(scratch)

DockerHub中有99%的镜像都是通过在Base镜像中安装或配置需要软件构建出来的

6.5.2 自定义镜像(mycentos)

  1. 编写dockerfile
cd /mydocker
vi dockerfile_mycentos

FROM centos
ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "success -------"
CMD /bin/bash

  1. 构建
[root@master mydocker]# docker build -f dockerfile_mycentos -t chris/mycentos .
Sending build context to Docker daemon  2.048kB
Step 1/9 : FROM centos
 ---> 300e315adb2f
Step 2/9 : ENV MYPATH /usr/local
 ---> Running in 2949185ee980
Removing intermediate container 2949185ee980
 ---> 0f46cb36876f
Step 3/9 : WORKDIR $MYPATH
 ---> Running in fe888cab4aa9
Removing intermediate container fe888cab4aa9
 ---> 64d820bebb93
Step 4/9 : RUN yum -y install vim
 ---> Running in 96061faccf00
......

 ---> be8b79c33752
Step 6/9 : EXPOSE 80
 ---> Running in b2d74036a236
Removing intermediate container b2d74036a236
 ---> b7b067e37daa
Step 7/9 : CMD echo $MYPATH
 ---> Running in 1532b91d6170
Removing intermediate container 1532b91d6170
 ---> d4370aa3b2ff
Step 8/9 : CMD echo "success -------ok"
 ---> Running in 0fe95c30e852
Removing intermediate container 0fe95c30e852
 ---> 6c3800d76c3c
Step 9/9 : CMD /bin/bash
 ---> Running in 3a47cc176453
Removing intermediate container 3a47cc176453
 ---> eee12504217a
Successfully built eee12504217a
Successfully tagged chris/mycentos:latest
[root@master mydocker]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
chris/mycentos      latest              eee12504217a        2 minutes ago       291MB
tomcat              latest              c0e850d7b9bb        8 days ago          667MB
hello-world         latest              d1165f221234        8 weeks ago         13.3kB
centos              latest              300e315adb2f        4 months ago        209MB
  1. 运行
[root@master mydocker]# docker run -it --name centos02 chris/mycentos
[root@960bafdfce5e local]# pwd
/usr/local
  1. 列出镜像的变更历史

docker history 镜像名|ID
从下往上查看镜像的生成历史

[root@master chris]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
chris/mycentos      latest              eee12504217a        15 minutes ago      291MB
tomcat              latest              c0e850d7b9bb        8 days ago          667MB
hello-world         latest              d1165f221234        8 weeks ago         13.3kB
centos              latest              300e315adb2f        4 months ago        209MB
[root@master chris]# docker history chris/mycentos
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
eee12504217a        15 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B                  
6c3800d76c3c        15 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
d4370aa3b2ff        15 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
b7b067e37daa        15 minutes ago      /bin/sh -c #(nop)  EXPOSE 80                    0B                  
be8b79c33752        15 minutes ago      /bin/sh -c yum -y install net-tools             23.4MB              
7b1c6d927962        16 minutes ago      /bin/sh -c yum -y install vim                   58.1MB              
64d820bebb93        16 minutes ago      /bin/sh -c #(nop) WORKDIR /usr/local            0B                  
0f46cb36876f        16 minutes ago      /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B                  
300e315adb2f        4 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           4 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           4 months ago        /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7…   209MB               
[root@master chris]# 

6.5.3 CMD和ENTRYPOINT的区别

CMD 指的是下列表里面的COMMAND

[root@master chris]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
960bafdfce5e        chris/mycentos      "/bin/sh -c /bin/bash"   15 minutes ago      Up 15 minutes       80/tcp              centos02
8034e792d331        centos              "/bin/bash"              26 minutes ago      Up 26 minutes                           centos01

[root@master chris]# docker run -it --name tomcat02 -p 8888:8080  tomcat
[root@master chris]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
6b0b3c209535        tomcat              "catalina.sh run"   5 seconds ago       Up 4 seconds        0.0.0.0:8888->8080/tcp   tomcat02

在后面加 ls -l命令后,新增的tomcat03容器并没有启动

[root@master chris]# docker run -it --name tomcat03 -p 8088:8080  tomcat ls -l
total 128
-rw-r--r--. 1 root root 18984 Mar 30 10:29 BUILDING.txt
-rw-r--r--. 1 root root  5587 Mar 30 10:29 CONTRIBUTING.md
-rw-r--r--. 1 root root 57092 Mar 30 10:29 LICENSE
-rw-r--r--. 1 root root  2333 Mar 30 10:29 NOTICE
-rw-r--r--. 1 root root  3257 Mar 30 10:29 README.md
-rw-r--r--. 1 root root  6898 Mar 30 10:29 RELEASE-NOTES
-rw-r--r--. 1 root root 16507 Mar 30 10:29 RUNNING.txt
drwxr-xr-x. 2 root root  4096 Apr 22 23:10 bin
drwxr-xr-x. 2 root root   238 Mar 30 10:29 conf
drwxr-xr-x. 2 root root  4096 Apr 22 23:09 lib
drwxrwxrwx. 2 root root     6 Mar 30 10:29 logs
drwxr-xr-x. 2 root root   134 Apr 22 23:10 native-jni-lib
drwxrwxrwx. 2 root root    30 Apr 22 23:09 temp
drwxr-xr-x. 2 root root     6 Apr 22 23:09 webapps
drwxr-xr-x. 7 root root    81 Mar 30 10:29 webapps.dist
drwxrwxrwx. 2 root root     6 Mar 30 10:29 work

[root@master chris]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                    NAMES
81cbfbd01279        tomcat              "ls -l"                  6 seconds ago       Exited (0) 5 seconds ago                             tomcat03

原因:tomcat dockerfile 最后一行的CMD命令被 docker run 后面的 ls -l 替换掉

EXPOSE 8080
CMD ["catalina.sh", "run"]
[root@master]# cd /mydocker
[root@master]# vi myip01
FROM centos
RUN yum -y install curl
CMD ["curl","-s","http://www.ip.cn"]

[root@master mydocker]# docker build -f myip01 -t myip01:1.0 .
[root@master mydocker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myip01              1.0                 0ea4cc5030b2        7 seconds ago       243MB
[root@master]# cd /mydocker
[root@master]# vi myip02
FROM centos
RUN yum -y install curl
ENTRYPOINT ["curl","-s","http://www.ip.cn"]

[root@master mydocker]# docker build -f myip02 -t myip02:1.0 .
Sending build context to Docker daemon  4.096kB
Step 1/3 : FROM centos
 ---> 300e315adb2f
Step 2/3 : RUN yum -y install curl
 ---> Using cache
 ---> 552703ee39c9
Step 3/3 : ENTRYPOINT ["curl","-s","http://www.ip.cn"]
 ---> Running in 0dbc34763358
Removing intermediate container 0dbc34763358
 ---> a8f738d4a45a
Successfully built a8f738d4a45a
Successfully tagged myip02:1.0

6.5.4 ONBUILD

[root@master]# cd /mydocker
[root@master mydocker]# vi myip02_father

FROM centos
RUN yum -y install curl
ENTRYPOINT ["curl","-s","cip.cc"]
ONBUILD RUN echo "myip02_father image onbuild-----ok"

[root@master mydocker]# docker build -f myip02_father -t myip02_father:1.0 .
Sending build context to Docker daemon   5.12kB
Step 1/3 : FROM centos
 ---> 300e315adb2f
Step 2/3 : RUN yum -y install curl
 ---> Using cache
 ---> 552703ee39c9
Step 3/3 : ENTRYPOINT ["curl","-s","http://www.ip.cn"]
 ---> Using cache
 ---> a8f738d4a45a
Successfully built a8f738d4a45a
Successfully tagged myip02_father:1.0
[root@master mydocker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myip02_father       1.0                 a8f738d4a45a        3 minutes ago       243MB
[root@master]# cd /mydocker
[root@master mydocker]# vi myip02_kid
FROM myip02_father:1.0
RUN yum -y install curl
ENTRYPOINT ["curl","-s","cip.cc"]

[root@master mydocker]# docker build -f myip02_kid -t myip02_kid:1.0 .
Sending build context to Docker daemon  6.144kB
Step 1/3 : FROM myip02_father:1.0
# Executing 1 build trigger
 ---> Running in 61b5fd1fece7
myip02_father image onbuild-----ok
Removing intermediate container 61b5fd1fece7
 ---> 4d14bc2d40e8
Step 2/3 : RUN yum -y install curl
 ---> Running in e328e5961d4f
Last metadata expiration check: 0:08:57 ago on Sun May  2 01:54:21 2021.
Package curl-7.61.1-14.el8_3.1.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
Removing intermediate container e328e5961d4f
 ---> e44a48f55d44
Step 3/3 : ENTRYPOINT ["curl","-s","cip.cc"]
 ---> Running in d5e81a13e501
Removing intermediate container d5e81a13e501
 ---> df8fa730dfe4
Successfully built df8fa730dfe4
Successfully tagged myip02_kid:1.0

6.5.5 自定义tomcat9

  1. 创建目录
mkdir -p /mydocker/christomcat9
  1. 创建文件
[root@master]# cd /mydocker/christomcat9
[root@master chrisTomcat9]# touch c.txt
[root@master chrisTomcat9]# cp /opt/jdk-8u191-linux-x64.tar.gz .
[root@master chrisTomcat9]# cp /opt/apache-tomcat-9.0.38.tar.gz .
[root@master chrisTomcat9]# touch Dockerfile

FROM         centos
MAINTAINER    chris<lilunlogic@163.com>
#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt
#把java与tomcat添加到容器中
ADD jdk-8u191-linux-x64.tar.gz  /usr/local/
ADD apache-tomcat-9.0.38.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_191
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.38
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.38
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE  8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.38/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-9.0.38/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-9.0.38/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.38/bin/logs/catalina.out
  1. 构建
[root@master chrisTomcat9]# docker build -t christomcat9 .
[root@master opt]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
christomcat9        latest              a02261dc7206        8 minutes ago       680MB

  1. 运行
[root@master]# docker run -d -p 9080:8080 --name christomcat9 -v /mydocker/tomcat9/test:/usr/local/apache-tomcat-9.0.38/webapps/test -v /mydocker/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.38/logs --privileged=true christomcat9

[root@master]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
b2d9623ad57d        christomcat9        "/bin/sh -c '/usr/lo…"   7 seconds ago       Up 6 seconds        0.0.0.0:9080->8080/tcp   christomcat9

[root@master]# docker exec -it christomcat9 java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

7 将镜像上传到阿里云

  1. 创建镜像仓库

https://cr.console.aliyun.com/cn-hangzhou/instance/repositories
命名空间:chris0716
仓库名称:mydocker


  1. 上传镜像
$ sudo docker login --username=lilunlogic@163.com registry.cn-hangzhou.aliyuncs.com
$ pwd:Lilun215+

$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker:[阿里云上显示的镜像版本号]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker:[阿里云上显示的镜像版本号]

[root@master chris]# docker images
REPOSITORY                                             TAG                 IMAGE ID            CREATED             SIZE
christomcat9                                           latest              de6f4c6c9bcb        17 hours ago        680MB
registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker   1.0                 de6f4c6c9bcb        17 hours ago        680MB
[root@master chris]# docker rmi registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker:1.0
Untagged: registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker:1.0
Untagged: registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker@sha256:9ed6c267619595e22642c02a585bc75600d685cd7d93b4ea5c46c6292b30efd3
[root@master chris]# docker pull registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker:1.0
1.0: Pulling from chris0716/mydocker
Digest: sha256:9ed6c267619595e22642c02a585bc75600d685cd7d93b4ea5c46c6292b30efd3
Status: Downloaded newer image for registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker:1.0
registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker:1.0
[root@master chris]# docker images
REPOSITORY                                             TAG                 IMAGE ID            CREATED             SIZE
christomcat9                                           latest              de6f4c6c9bcb        17 hours ago        680MB
registry.cn-hangzhou.aliyuncs.com/chris0716/mydocker   1.0                 de6f4c6c9bcb        17 hours ago        680MB

%5Btoc%5D%0A%23%20Docker%0A%23%23%201%20%E6%A6%82%E8%BF%B0%0A%23%23%23%201.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20%E5%9F%BA%E4%BA%8EGo%E8%AF%AD%E8%A8%80%E5%AE%9E%E7%8E%B0%E7%9A%84%E4%BA%91%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%20%20%0A%3E%20Docker%E7%9A%84%E4%B8%BB%E8%A6%81%E7%9B%AE%E6%A0%87%E6%98%AF%EF%BC%9ABuild%2CShip%20and%20Run%20any%20app%2C%20anywhere%0A%0A%23%23%23%201.2%20%E8%A7%A3%E5%86%B3%E4%BA%86%E4%BB%80%E4%B9%88%E9%97%AE%E9%A2%98%0A%3E%20%E8%A7%A3%E5%86%B3%E4%BA%86%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E5%92%8C%E9%85%8D%E7%BD%AE%E9%97%AE%E9%A2%98%E8%BD%AF%E4%BB%B6%E5%AE%B9%E5%99%A8%EF%BC%8C%E6%96%B9%E4%BE%BF%E5%81%9A%E7%B3%BB%E7%BB%9F%E9%9B%86%E6%88%90%E5%B9%B6%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%95%B4%E4%BD%93%E5%8F%91%E5%B8%83%E7%9A%84%E5%AE%B9%E5%99%A8%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF%0A%0A%0A%23%23%23%201.3%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%E6%9B%B4%E8%BD%BB%E9%87%8F%EF%BC%9A%0A%3E%20%E5%9F%BA%E4%BA%8E%E5%AE%B9%E5%99%A8%E7%9A%84%E8%99%9A%E6%8B%9F%E5%8C%96%EF%BC%8C%E4%BB%85%E5%8C%85%E5%90%AB%E4%B8%9A%E5%8A%A1%E8%BF%90%E8%A1%8C%E6%89%80%E9%9C%80%E8%A6%81%E7%9A%84runtime%E7%8E%AF%E5%A2%83%5Broot%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%EF%BC%8C%E8%BF%9B%E7%A8%8B%E7%A9%BA%E9%97%B4%EF%BC%8C%E7%94%A8%E6%88%B7%E7%A9%BA%E9%97%B4%E5%92%8C%E7%BD%91%E7%BB%9C%E7%A9%BA%E9%97%B4%5D%20%20%0ACentOS%E3%80%81Ubuntu%E5%9F%BA%E7%A1%80%E9%95%9C%E5%83%8F%E4%BB%85170M%EF%BC%8C%E8%BF%99%E5%AE%BF%E4%B8%BB%E6%9C%BA%E5%8F%AF%E9%83%A8%E7%BD%B2100~1000%E4%B8%AA%E5%AE%B9%E5%99%A8%20%20%0A%0A%E6%9B%B4%E9%AB%98%E6%95%88%EF%BC%9A%0A%3E%20%E4%B8%80%E6%AC%A1%E6%9E%84%E5%BB%BA%EF%BC%8C%E9%9A%8F%E5%A4%84%E8%BF%90%E8%A1%8C%20%20%0A%3E%20%E6%9B%B4%E5%BF%AB%E9%80%9F%E9%AB%98%E6%95%88%E7%9A%84%E4%BA%A4%E4%BB%98%E5%92%8C%E9%83%A8%E7%BD%B2%E7%B3%BB%E7%BB%9F%20%20%0A%3E%20%E9%99%8D%E4%BD%8E%E8%BF%90%E7%BB%B4%E6%88%90%E6%9C%AC%EF%BC%8C%E6%9B%B4%E4%BE%BF%E6%8D%B7%E7%9A%84%E5%8D%87%E7%BA%A7%E5%92%8C%E6%89%A9%E5%AE%B9%0A%0A%23%23%23%201.4%20%E4%B8%89%E8%A6%81%E7%B4%A0%0A%3E%20%E9%95%9C%E5%83%8F%20%20%0A%3E%20%E5%AE%B9%E5%99%A8%20%20%0A%3E%20%E4%BB%93%E5%BA%93%20%20%0A%23%23%23%23%201.4.1%20%E9%95%9C%E5%83%8Fimage%0A%3E%20%E9%95%9C%E5%83%8F%E5%B0%B1%E6%98%AF%E6%A8%A1%E6%9D%BF%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E5%88%9B%E5%BB%BADocker%E5%AE%B9%E5%99%A8%EF%BC%8C%E4%B8%80%E4%B8%AA%E9%95%9C%E5%83%8F%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E5%BE%88%E5%A4%9A%E4%B8%AA%E5%AE%B9%E5%99%A8%0A%23%23%23%23%201.4.2%20%E5%AE%B9%E5%99%A8container%0A%3E%20%E5%AE%B9%E5%99%A8%E6%98%AF%E7%94%A8%E9%95%9C%E5%83%8F%E5%88%9B%E5%BB%BA%E7%9A%84%E8%BF%90%E8%A1%8C%E5%AE%9E%E4%BE%8B%0A%23%23%23%23%201.4.3%20%E4%BB%93%E5%BA%93Repository%0A%3E%E9%9B%86%E4%B8%AD%E5%AD%98%E6%94%BE%E9%95%9C%E5%83%8F%E6%96%87%E4%BB%B6%E7%9A%84%E5%9C%BA%E6%89%80%20%20%0A%E4%BB%93%E5%BA%93%E5%88%86%E4%B8%BA%E5%85%AC%E5%BC%80%E4%BB%93%E5%BA%93%E5%92%8C%E7%A7%81%E6%9C%89%E4%BB%93%E5%BA%93%20%20%0A%E6%9C%80%E5%A4%A7%E7%9A%84%E5%85%AC%E5%BC%80%E4%BB%93%E5%BA%93%E6%98%AF%20%60DockerHub%60%20https%3A%2F%2Fhub.docker.com%2F%0A%E5%9B%BD%E5%86%85%E7%9A%84%E5%85%AC%E5%BC%80%E4%BB%93%E5%BA%93%E6%9C%89%E9%98%BF%E9%87%8C%E5%92%8C%E7%BD%91%E6%98%93%0A%23%23%23%23%201.4.3%20%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86%0A%23%23%23%23%23%20%201.4.3.1%20%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84%0A%3E%20Docker%E6%98%AF%E4%B8%80%E4%B8%AACS%E7%BB%93%E6%9E%84%E7%9A%84%E7%B3%BB%E7%BB%9F%EF%BC%8CDocker%E5%AE%88%E6%8A%A4%E8%BF%9B%E7%A8%8B%E8%BF%90%E8%A1%8C%E5%9C%A8%E4%B8%BB%E6%9C%BA%E4%B8%8A%EF%BC%8C%E7%84%B6%E5%90%8E%E9%80%9A%E8%BF%87Socket%E8%BF%9E%E6%8E%A5%E4%BB%8E%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%BF%E9%97%AE%EF%BC%8C%E5%AE%88%E6%8A%A4%E8%BF%9B%E7%A8%8B%E4%BB%8E%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%8E%A5%E5%8F%97%E5%91%BD%E4%BB%A4%E5%B9%B6%E7%AE%A1%E7%90%86%E8%BF%90%E8%A1%8C%E5%9C%A8%E4%B8%BB%E6%9C%BA%E4%B8%8A%E7%9A%84%E5%AE%B9%E5%99%A8%0A%0A!%5Bb22231b84fb2a34e6c4871e141f5eec6.png%5D(en-resource%3A%2F%2Fdatabase%2F970%3A1)%0A%0A%0A%23%23%202%20%E5%AE%89%E8%A3%85%0A%23%23%23%202.1%20%E5%8E%BB%E5%93%AA%E4%B8%8B%0A%E5%AE%98%E7%BD%91%EF%BC%9A%0A%3E%20http%3A%2F%2Fwww.docker.com%20%20%0A%3E%20http%3A%2F%2Fwww.docker-cn.com%20%20%0A%23%23%23%202.2%20%E5%89%8D%E6%8F%90%0A%3E%20Docker%E8%BF%90%E8%A1%8C%E5%9C%A8CentOS7%E4%B8%8A%E8%A6%81%E6%B1%82%E7%B3%BB%E7%BB%9F%E7%89%88%E6%9C%AC%E4%B8%BA64%E4%BD%8D%EF%BC%8C%E5%86%85%E6%A0%B8%E7%89%88%E6%9C%AC%E4%B8%BA3.10%E4%BB%A5%E4%B8%8A%20%20%0A%3E%20Docker%E8%BF%90%E8%A1%8C%E5%9C%A8CentOS6.5%E4%B8%8A%E8%A6%81%E6%B1%82%E7%B3%BB%E7%BB%9F%E7%89%88%E6%9C%AC%E4%B8%BA64%E4%BD%8D%EF%BC%8C%E5%86%85%E6%A0%B8%E7%89%88%E6%9C%AC%E4%B8%BA2.6.32-431%E6%88%96%E4%BB%A5%E4%B8%8A%0A%0A%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20uname%20-r%0A3.10.0-1127.el7.x86_64%0A%60%60%60%0A%0A%0A%0A%0A%23%23%23%202.3%20CentOS7%20%E5%AE%89%E8%A3%85Docker%0A%0Ahttps%3A%2F%2Fdocs.docker.com%2Finstall%2Flinux%2Fdocker-ce%2Fcentos%20%20%0A%0A%3E%20%E5%8D%B8%E8%BD%BD%E8%80%81%E7%89%88%E6%9C%AC%0A%60%60%60%0Asudo%20yum%20remove%20docker%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20docker-client%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20docker-client-latest%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20docker-common%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20docker-latest%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20docker-latest-logrotate%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20docker-logrotate%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20docker-engine%0A%60%60%60%0A%3E%20%E5%AE%89%E8%A3%85%E4%BB%93%E5%BA%93%0A%60%60%60%0Asudo%20yum%20install%20-y%20yum-utils%0Asudo%20yum-config-manager%20%5C%0A%20%20%20%20--add-repo%20%5C%0A%20%20%20%20https%3A%2F%2Fdownload.docker.com%2Flinux%2Fcentos%2Fdocker-ce.repo%0A%60%60%60%0A%0A%0A%3E%20%E6%9F%A5%E7%9C%8B%E5%8F%AF%E7%94%A8docker%E7%89%88%E6%9C%AC%0A%0A%60%60%60%0Ayum%20list%20docker-ce%20--showduplicates%20%7C%20sort%20-r%0A%60%60%60%0A%3E%20%E5%AE%89%E8%A3%85%E6%8C%87%E5%AE%9A%E7%89%88%E6%9C%AC%0A%60%60%60%0Ayum%20install%20docker-ce-19.03.8%20docker-ce-cli-19.03.8%20containerd.io%0A%60%60%60%0A%3E%20%E5%90%AF%E5%8A%A8docker%0A%60%60%60%0Asystemctl%20start%20docker%0A%60%60%60%0A!%5B53d3d9f9271d9d527143f4689cc7c15a.png%5D(en-resource%3A%2F%2Fdatabase%2F971%3A1)%0A%0A%0A%0A%23%23%23%202.4%20%E9%98%BF%E9%87%8C%E4%BA%91%E9%95%9C%E5%83%8F%E5%8A%A0%E9%80%9F%0A%3E%20https%3A%2F%2Fdev.aliyun.com%2Fsearch.html%0A%0A!%5B829dbe4d9a767a2c0245861df5cf8ff7.png%5D(en-resource%3A%2F%2Fdatabase%2F972%3A1)%0A%0A%0A%60%60%60%0Asudo%20mkdir%20-p%20%2Fetc%2Fdocker%0Asudo%20tee%20%2Fetc%2Fdocker%2Fdaemon.json%0A%7B%0A%20%20%22registry-mirrors%22%3A%20%5B%22https%3A%2F%2F96rbv7qx.mirror.aliyuncs.com%22%5D%0A%7D%0A%0Asudo%20systemctl%20daemon-reload%0Asudo%20systemctl%20restart%20docker%0A%60%60%60%0A%0A%0A%3E%20docker%20run%20hello-world%0A%0A%60%60%60shell%0A%5Broot%40master%20~%5D%23%20docker%20run%20hello-world%0AUnable%20to%20find%20image%20'hello-world%3Alatest'%20locally%0Alatest%3A%20Pulling%20from%20library%2Fhello-world%0Ab8dfde127a29%3A%20Pull%20complete%20%0ADigest%3A%20sha256%3Af2266cbfc127c960fd30e76b7c792dc23b588c0db76233517e1891a4e357d519%0AStatus%3A%20Downloaded%20newer%20image%20for%20hello-world%3Alatest%0A%0AHello%20from%20Docker!%0AThis%20message%20shows%20that%20your%20installation%20appears%20to%20be%20working%20correctly.%0A%0ATo%20generate%20this%20message%2C%20Docker%20took%20the%20following%20steps%3A%0A%201.%20The%20Docker%20client%20contacted%20the%20Docker%20daemon.%0A%202.%20The%20Docker%20daemon%20pulled%20the%20%22hello-world%22%20image%20from%20the%20Docker%20Hub.%0A%20%20%20%20(amd64)%0A%203.%20The%20Docker%20daemon%20created%20a%20new%20container%20from%20that%20image%20which%20runs%20the%0A%20%20%20%20executable%20that%20produces%20the%20output%20you%20are%20currently%20reading.%0A%204.%20The%20Docker%20daemon%20streamed%20that%20output%20to%20the%20Docker%20client%2C%20which%20sent%20it%0A%20%20%20%20to%20your%20terminal.%0A%0ATo%20try%20something%20more%20ambitious%2C%20you%20can%20run%20an%20Ubuntu%20container%20with%3A%0A%20%24%20docker%20run%20-it%20ubuntu%20bash%0A%0AShare%20images%2C%20automate%20workflows%2C%20and%20more%20with%20a%20free%20Docker%20ID%3A%0A%20https%3A%2F%2Fhub.docker.com%2F%0A%0AFor%20more%20examples%20and%20ideas%2C%20visit%3A%0A%20https%3A%2F%2Fdocs.docker.com%2Fget-started%2F%0A%0A%60%60%60%0A%0A%23%23%203%20%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%0A%23%23%23%203.1%20%E5%B8%AE%E5%8A%A9%E5%91%BD%E4%BB%A4%0A%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E6%9F%A5%E7%9C%8B%E7%89%88%E6%9C%AC%20%7C%20docker%20version%0Adocker%E4%BF%A1%E6%81%AF%E6%B1%87%E6%80%BB%20%20%20%20%7C%20docker%20info%20%0A%E5%B8%AE%E5%8A%A9%E5%91%BD%E4%BB%A4%20%7C%20docker%20--help%0A%0A%23%23%23%203.2%20%E9%95%9C%E5%83%8F%E5%91%BD%E4%BB%A4%0A%23%23%23%23%203.2.1%20%E6%9F%A5%E8%AF%A2%E6%9C%AC%E5%9C%B0%E9%95%9C%E5%83%8F%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E5%88%97%E5%87%BA%E6%9C%AC%E5%9C%B0%E9%95%9C%E5%83%8F%20%7C%20docker%20images%0A%E5%88%97%E5%87%BA%E6%9C%AC%E5%9C%B0%E6%89%80%E6%9C%89%E9%95%9C%E5%83%8F%E5%8C%85%E6%8B%AC%E6%98%AF%E9%97%B4%E6%98%A0%E5%83%8F%E5%B1%82%20%7C%20docker%20image%20-a%0A%E5%8F%AA%E6%98%BE%E7%A4%BA%E9%95%9C%E5%83%8FID%20%7C%20docker%20image%20-q%0A%E6%98%BE%E7%A4%BA%E9%95%9C%E5%83%8F%E7%9A%84%E6%91%98%E8%A6%81%E4%BF%A1%E6%81%AF%20%7C%20docker%20image%20--digests%0A%E6%98%BE%E7%A4%BA%E5%AE%8C%E6%95%B4%E7%9A%84%E9%95%9C%E5%83%8F%E4%BF%A1%E6%81%AF%20%7C%20docker%20image%20--no-trunc%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20docker%20images%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Ahello-world%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20d1165f221234%20%20%20%20%20%20%20%206%20weeks%20ago%20%20%20%20%20%20%20%20%2013.3kB%0A%60%60%60%0A%3E%20REPOSITORY%3A%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%BA%90%20%20%0A%3E%20TAG%3A%E9%95%9C%E5%83%8F%E7%9A%84%E6%A0%87%E7%AD%BE%20%20%0A%3E%20IMAGE%20ID%3A%E9%95%9C%E5%83%8FID%20%20%0A%3E%20CREATED%3A%E9%95%9C%E5%83%8F%E5%88%9B%E5%BB%BA%E6%97%B6%E9%97%B4%20%20%0A%3E%20SIZE%3A%E9%95%9C%E5%83%8F%E5%A4%A7%E5%B0%8F%20%20%0A%0A%3E%20%E5%A6%82%E6%9F%A5%E4%B8%8D%E4%BD%A0%E6%8C%87%E5%AE%9A%E4%B8%80%E4%B8%AA%E9%95%9C%E5%83%8F%E7%9A%84%E6%A0%87%E7%AD%BE%EF%BC%8Cdocker%E9%BB%98%E8%AE%A4%E4%BD%BF%E7%94%A8hello-world%3Alatest%E9%95%9C%E5%83%8F%0A%0A%0A%23%23%23%23%203.2.2%20%E6%9F%A5%E8%AF%A2%E8%BF%9C%E7%A8%8B%E9%95%9C%E5%83%8F%0A%0A!%5B0be4f133e7cffd5f5bb30d88ebae9d51.png%5D(en-resource%3A%2F%2Fdatabase%2F973%3A1)%0A%0A%3E%20STARS%3A%E7%82%B9%E8%B5%9E%E6%95%B0%20%20%0A%3E%20OFFICIAL%EF%BC%9A%E5%AE%98%E6%96%B9%E7%89%88%E6%9C%AC%0A%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%20%0A---%7C---%0A%E4%BB%8E%5Bhttps%3A%2F%2Fhub.docker.com%5D%E4%B8%8A%E6%9F%A5%E8%AF%A2%E9%95%9C%E5%83%8F%E4%BF%A1%E6%81%AF%20%20%20%7C%20docker%20search%20image-name%20%20%0A%E5%88%97%E5%87%BA%E6%94%B6%E8%97%8F%E6%95%B0%E4%B8%8D%E5%B0%8F%E4%BA%8E30%E7%9A%84%E9%95%9C%E5%83%8F%20%7C%20docker%20search%20-s%2030%20image-name%0A%E6%98%BE%E7%A4%BA%E5%AE%8C%E6%95%B4%E7%9A%84%E9%95%9C%E5%83%8F%E4%BF%A1%E6%81%AF%20%20%20%20%20%20%20%7C%20docker%20search%20--no-trunc%20image-name%0A%E5%8F%AA%E5%88%97%E5%87%BAautomated%E7%9A%84%E9%95%9C%E5%83%8F%20%20%20%20%7C%20docker%20search%20--automated%20image-name%0A%0A%23%23%23%23%203.2.3%20%E6%8B%89%E5%8F%96%E8%BF%9C%E7%A8%8B%E9%95%9C%E5%83%8F%0A%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E6%91%98%E5%8F%96%E8%BF%9C%E7%A8%8B%E9%95%9C%E5%83%8F%E5%88%B0%E6%9C%AC%E5%9C%B0%EF%BC%8C%E4%B8%8D%E5%8A%A0%E7%89%88%E6%9C%AC%E9%BB%98%E8%AE%A4%E6%8B%89%E5%8F%96%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC%20%20%7C%20docker%20pull%20elasticsearch%0A%0A%0A%23%23%23%23%203.2.4%20%E5%88%A0%E9%99%A4%E9%95%9C%E5%83%8F%0A%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E5%88%A0%E9%99%A4%E6%9C%AC%E5%9C%B0%E9%95%9C%E5%83%8F%EF%BC%8C%E4%B8%8D%E5%8A%A0%E7%89%88%E6%9C%AC%E9%BB%98%E8%AE%A4%E5%88%A0%E9%99%A4%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC%20%20%7C%20docker%20rmi%20elasticsearch%0A%E5%88%A0%E9%99%A4%E5%A4%9A%E4%B8%AA%E6%9C%AC%E5%9C%B0%E9%95%9C%E5%83%8F%EF%BC%8C%E4%B8%8D%E5%8A%A0%E7%89%88%E6%9C%AC%E9%BB%98%E8%AE%A4%E5%88%A0%E9%99%A4%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC%20%20%7C%20docker%20rmi%20elasticsearch%20nginx%0A%E5%BC%BA%E5%88%B6%E5%88%A0%E9%99%A4%E6%9C%AC%E5%9C%B0%E9%95%9C%E5%83%8F%EF%BC%8C%E4%B8%8D%E5%8A%A0%E7%89%88%E6%9C%AC%E9%BB%98%E8%AE%A4%E5%88%A0%E9%99%A4%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC%20%20%7C%20docker%20rmi%20-f%20elasticsearch%0A%E5%BC%BA%E5%88%B6%E5%88%A0%E9%99%A4%E6%9C%AC%E5%9C%B0%E6%89%80%E6%9C%89%E9%95%9C%E5%83%8F%EF%BC%8C%E4%B8%8D%E5%8A%A0%E7%89%88%E6%9C%AC%E9%BB%98%E8%AE%A4%E5%88%A0%E9%99%A4%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC%20%20%7C%20docker%20rmi%20-f%20%24(docker%20images%20-q)%0A%0A%23%23%23%23%203.2.5%20%E7%94%9F%E6%88%90%E9%95%9C%E5%83%8F%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E6%8F%90%E4%BA%A4%E5%AE%B9%E5%99%A8%E5%89%AF%E6%9C%AC%E4%BD%BF%E4%B9%8B%E6%88%90%E4%B8%BA%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E9%95%9C%E5%83%8F%20%7C%20docker%20commit%0A%0A%3E%20docker%20commit%20-m%3D%22%E4%BF%A1%E6%81%AF%E6%8F%8F%E8%BF%B0%22%20-a%3D%22%E4%BD%9C%E8%80%85%22%20%E5%AE%B9%E5%99%A8ID%20%E8%A6%81%E5%88%9B%E5%BB%BA%E7%9A%84%E7%9B%AE%E6%A0%87%E9%95%9C%E5%83%8F%3A%5B%E6%A0%87%E7%AD%BE%E5%90%8D%5D%20%20%0A%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20docker%20commit%20-m%20%22tomcat%20without%20doc%22%20-a%20%22chris%22%203b7146c6590e%20christomcat%3A1.0%0A%5Broot%40master%20~%5D%23%20docker%20run%20-it%20-p%208888%3A8080%20christomcat%3A1.0%0A%60%60%60%0A%0A%0A%0A%23%23%23%203.3%20%E5%AE%B9%E5%99%A8%E5%91%BD%E4%BB%A4%0A%23%23%23%23%203.3.1%20%E6%96%B0%E5%BB%BA%E5%B9%B6%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8%0A%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E6%96%B0%E5%BB%BA%E5%B9%B6%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8%20%7C%20docker%20run%20%5BOPTIONS%5D%20(image-name%5C%7Cid)%20%5BCOMMAND%5D%20%5BARG...%5D%0A--name%3D%22%E6%8C%87%E5%AE%9A%E6%96%B0%E7%9A%84%E5%AE%B9%E5%99%A8%E5%90%8D%E7%A7%B0%22%20%20%7C%20docker%20run%20--name%20%E6%8C%87%E5%AE%9A%E6%96%B0%E7%9A%84%E5%AE%B9%E5%99%A8%E5%90%8D%E7%A7%B0%20(image-name%5C%7Cid)%20%0A%E4%BB%A5%E4%BA%A4%E4%BA%92%E6%96%B9%E5%BC%8F%E8%BF%90%E8%A1%8C%E5%AE%B9%E5%99%A8%E9%80%9A%E5%B8%B8%E4%B8%8E-t%E5%B9%B6%E7%94%A8%20%20%7C%20docker%20run%20-i%20%20(image-name%5C%7Cid)%0A%E4%B8%BA%E5%AE%B9%E5%99%A8%E9%87%8D%E6%96%B0%E5%88%86%E9%85%8D%E4%B8%80%E4%B8%AA%E4%BC%AA%E8%BE%93%E5%85%A5%E7%BB%88%E7%AB%AF%20%20%7C%20docker%20run%20-t%20%20(image-name%5C%7Cid)%0A%E9%9A%8F%E6%9C%BA%E7%AB%AF%E5%8F%A3%E6%98%A0%E5%B0%84%20%20%7C%20docker%20run%20-P%20%20(image-name%7Cid)%0A%E6%8C%87%E5%AE%9A%E7%AB%AF%E5%8F%A3%E6%98%A0%E5%B0%84%EF%BC%8C%E6%9C%89%E5%9B%9B%E7%A7%8D%E5%BD%A2%E5%BC%8F%20%20%7C%20docker%20run%20-p%20%20(image-name%5C%7Cid)%0A1%20%20%7C%20docker%20run%20-p%20%20ip%3AhostPort%3AcontainPort%20(image-name%5C%7Cid)%0A2%20%20%7C%20docker%20run%20-p%20%20ip%3A%3AcontainPort%20(image-name%5C%7Cid)%0A3%20%20%7C%20docker%20run%20-p%20%20hostPort%3AcontainPort%20(image-name%5C%7Cid)%0A4%20%20%7C%20docker%20run%20-p%20%20containPort%20(image-name%5C%7Cid)%0A%E4%BB%A5%E5%AE%88%E6%8A%A4%E7%9A%84%E6%96%B9%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8%20%20%7C%20docker%20run%20-d%20(image-name%5C%7Cid)%0A%0A%0A%3E%20docker%20run%20-it%20--name%3D%22es0422%22%20elasticsearch%20%20%2Fbin%2Fbash%0A%3E%20docker%20run%20-d%20centos%0A%3E%20docker%20run%20-it%20-p%208080%3A8080%20tomcat%20%2Fbin%2Fbash%0A%0A!%5B9a7afbb70adcc10810448c019bd2460d.png%5D(en-resource%3A%2F%2Fdatabase%2F1465%3A1)%0A%0A%0A%23%23%23%23%203.3.2%20%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84%E5%AE%B9%E5%99%A8%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E6%89%80%E6%9C%89%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84%E5%AE%B9%E5%99%A8%20%7C%20docker%20ps%20%5BOPTIONS%5D%0A%E5%88%97%E5%87%BA%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84%E5%92%8C%E5%8E%86%E5%8F%B2%E4%B8%8A%E8%BF%90%E8%A1%8C%E8%BF%87%E7%9A%84%E5%AE%B9%E5%99%A8%20%7C%20docker%20ps%20-a%0A%E5%88%97%E5%87%BA%E6%9C%80%E8%BF%91%E5%88%9B%E5%BB%BA%E7%9A%84%E5%AE%B9%E5%99%A8%20%7C%20docker%20ps%20-l%0A%E5%88%97%E5%87%BA%E6%9C%80%E8%BF%913%E4%B8%AA%E5%88%9B%E5%BB%BA%E7%9A%84%E5%AE%B9%E5%99%A8%20%7C%20docker%20ps%20-n%203%0A%E9%9D%99%E9%BB%98%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%8F%AA%E6%98%BE%E7%A4%BA%E5%AE%B9%E5%99%A8%E7%BC%96%E5%8F%B7%20%7C%20docker%20ps%20-q%0A%E4%B8%8D%E6%88%AA%E6%96%AD%E8%BE%93%E5%87%BA%20%7C%20docker%20ps%20--no-trunc%0A%0A%23%23%23%23%203.3.3%20%E9%80%80%E5%87%BA%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84%E5%AE%B9%E5%99%A8%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E5%81%9C%E6%AD%A2%E5%AE%B9%E5%99%A8%E5%B9%B6%E9%80%80%E5%87%BA%20%7C%20exit%0A%E9%80%80%E5%87%BA%E4%BD%86%E4%B8%8D%E5%81%9C%E6%AD%A2%E5%AE%B9%E5%99%A8%20%7C%20ctrl%2Bp%2Bq%0A%0A%23%23%23%23%203.3.4%20%E5%90%AF%E5%8A%A8%E5%81%9C%E6%AD%A2%E5%AE%B9%E5%99%A8%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8%20%7C%20docker%20start%20(container-name%5C%7Cid)%0A%E9%87%8D%E6%96%B0%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8%20%7C%20docker%20restart%20(container-name%5C%7Cid)%0A%E5%81%9C%E6%AD%A2%E5%AE%B9%E5%99%A8%20%7C%20docker%20stop%20(container-name%5C%7Cid)%0A%E5%BC%BA%E5%88%B6%E5%81%9C%E6%AD%A2%E5%AE%B9%E5%99%A8%20%7C%20docker%20kill%20(container-name%5C%7Cid)%0A%0A%23%23%23%23%203.3.5%20%E5%88%A0%E9%99%A4%E5%AE%B9%E5%99%A8%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E5%88%A0%E9%99%A4%E5%B7%B2%E5%81%9C%E6%AD%A2%E7%9A%84%E5%AE%B9%E5%99%A8%20%7C%20docker%20rm%20(container-name%5C%7Cid)%0A%E5%BC%BA%E5%88%B6%E5%88%A0%E9%99%A4%E5%AE%B9%E5%99%A8%E6%97%A0%E8%AE%BA%E5%AE%B9%E5%99%A8%E6%98%AF%E5%90%A6%E5%B7%B2%E5%81%9C%E6%AD%A2%20%7C%20docker%20rm%20(container-name%5C%7Cid)%0A%E4%B8%80%E6%AC%A1%E6%80%A7%E5%88%A0%E9%99%A4%E5%A4%9A%E4%B8%AA%E5%AE%B9%E5%99%A8%20%7C%20docker%20rm%20-f%20%24(docker%20ps%20-aq)%0A%E4%B8%80%E6%AC%A1%E6%80%A7%E5%88%A0%E9%99%A4%E5%A4%9A%E4%B8%AA%E5%AE%B9%E5%99%A8%20%7C%20docker%20ps%20-aq%20%5C%7C%20xargs%20docker%20rm%0A%0A%23%23%23%23%203.3.6%20%E6%9F%A5%E7%9C%8B%E5%AE%B9%E5%99%A8%E6%97%A5%E5%BF%97%0A%0A%3E%20docker%20run%20-d%20centos%20%2Fbin%2Fsh%20-c%20%22while%20true%3B%20do%20echo%20hello%20zzyy%3Bsleep%202%3Bdone%22%0A%0A%60%60%60%0A%5Broot%40master%20docker%5D%23%20docker%20run%20-d%20centos%20%2Fbin%2Fsh%20-c%20%22while%20true%3B%20do%20echo%20hello%20zzyy%3Bsleep%202%3Bdone%22%0A9b5688f06fc2c4a52721e6dbcbba94062915211bbfaceb9473b8d3bfced736ce%0A%5Broot%40master%20~%5D%23%20docker%20ps%20-a%0ACONTAINER%20ID%20%20%20%20%20%20%20%20IMAGE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20COMMAND%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20STATUS%20%20%20%20%20%20%20%20%20%20%20%20%20%20PORTS%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NAMES%0A9b5688f06fc2%20%20%20%20%20%20%20%20centos%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%2Fbin%2Fsh%20-c%20'while%20t%E2%80%A6%22%20%20%205%20seconds%20ago%20%20%20%20%20%20%20Up%202%20seconds%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20wonderful_goldwasser%0A%60%60%60%0A%0A%3E%20docker%20logs%20-f%20-t%20--tail%203%209b5688f06fc2%20%20%0A%3E%20-f%3A%20%E6%89%93%E5%8D%B0%E6%9C%80%E6%96%B0%E7%9A%84%E6%97%A5%E5%BF%97%20%20%0A%3E%20-t%3A%20%E5%8A%A0%E5%85%A5%E6%97%B6%E9%97%B4%E6%88%B3%20%20%0A%3E%20--tail%3A%20%E6%98%BE%E7%A4%BA%E6%9C%80%E5%90%8E%E5%A4%9A%E5%B0%91%E6%9D%A1%20%20%0A%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20docker%20logs%20-f%20-t%20--tail%20%203%209b5688f06fc2%0A2021-04-22T13%3A39%3A23.793299808Z%20hello%20zzyy%0A2021-04-22T13%3A39%3A25.804149907Z%20hello%20zzyy%0A2021-04-22T13%3A39%3A27.815085938Z%20hello%20zzyy%0A2021-04-22T13%3A39%3A29.826784950Z%20hello%20zzyy%0A%60%60%60%0A%23%23%23%23%203.3.7%20%E5%AE%B9%E5%99%A8%E5%86%85%E5%91%BD%E4%BB%A4%0A%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E6%9F%A5%E7%9C%8B%E5%AE%B9%E5%99%A8%E5%86%85%E7%9A%84%E8%BF%9B%E7%A8%8B%20%7C%20docker%20-ps%0A%E6%9F%A5%E7%9C%8B%E5%AE%B9%E5%99%A8%E5%86%85%E7%9A%84%E7%BB%86%E8%8A%82%20%7C%20docker%20inspect%20id%0A%20%0A%23%23%23%23%203.3.8%20%E8%BF%9B%E5%85%A5%E8%BF%90%E8%A1%8C%E4%B8%AD%E7%9A%84%E5%AE%B9%E5%99%A8%E5%B9%B6%E4%BB%A5%E5%91%BD%E4%BB%A4%E4%BA%A4%E4%BA%92%0A%E6%8F%8F%E8%BF%B0%20%7C%20%E5%91%BD%E4%BB%A4%0A---%7C---%0A%E8%BF%9B%E5%85%A5%E5%AE%B9%E5%99%A8%E6%AD%A3%E5%9C%A8%E6%89%A7%E8%A1%8C%E7%9A%84%E7%BB%88%E7%AB%AF%20%7C%20docker%20attach%20id%0A%E8%BF%9B%E5%85%A5%E5%AE%B9%E5%99%A8%E5%86%85%20%7C%20docker%20exec%20-it%20id%20%2Fbin%2Fbash%0A%E5%9C%A8%E5%AE%B9%E5%99%A8%E5%A4%96%E6%93%8D%E4%BD%9C%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%20%7C%20docker%20exec%20-it%20id%20ls%20-l%20%2Ftmp%0A%0A%3E%201.%20%E8%BF%9B%E5%85%A5%E5%BD%93%E5%89%8D%E5%AE%B9%E5%99%A8%E5%90%8E%E5%BC%80%E5%90%AF%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E7%BB%88%E7%AB%AF%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%9C%A8%E9%87%8C%E9%9D%A2%E6%93%8D%E4%BD%9C%E3%80%82%EF%BC%88%E5%B8%B8%E7%94%A8%EF%BC%89%0Adocker%20exec%0A%3E%202.%20%E8%BF%9B%E5%85%A5%E5%AE%B9%E5%99%A8%E6%AD%A3%E5%9C%A8%E6%89%A7%E8%A1%8C%E6%9F%90%E4%B8%AA%E5%91%BD%E4%BB%A4%E7%9A%84%E7%BB%88%E7%AB%AF%EF%BC%8C%E4%B8%8D%E8%83%BD%E5%9C%A8%E9%87%8C%E9%9D%A2%E6%93%8D%E4%BD%9C%EF%BC%9B%E5%A4%9A%E4%B8%AA%E7%AA%97%E5%8F%A3%E5%90%8C%E6%97%B6attach%E5%88%B0%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AE%B9%E5%99%A8%E6%97%B6%EF%BC%8C%E6%89%80%E6%9C%89%E7%AA%97%E5%8F%A3%E5%90%8C%E6%AD%A5%E6%98%BE%E7%A4%BA%EF%BC%9B%E5%BD%93%E6%9F%90%E4%B8%AA%E7%AA%97%E5%8F%A3%E5%9B%A0%E5%91%BD%E4%BB%A4%E9%98%BB%E5%A1%9E%EF%BC%8C%E5%85%B6%E4%BB%96%E7%AA%97%E5%8F%A3%E4%B9%9F%E6%97%A0%E6%B3%95%E6%93%8D%E4%BD%9C%0Adocker%20attach%0A%0A%60%60%60%0A%5Broot%40master%20docker%5D%23%20docker%20attach%20013c88f998bd%0A%5Broot%40013c88f998bd%20%2F%5D%23%20ls%20-l%20%2Ftmp%0Atotal%208%0A-rwx------.%201%20root%20root%20701%20Dec%20%204%2017%3A37%20ks-script-esd4my7v%0A-rwx------.%201%20root%20root%20671%20Dec%20%204%2017%3A37%20ks-script-eusq_sc5%0A%0A%0A%5Broot%40master%20~%5D%23%20docker%20exec%20013c88f998bd%20ls%20-l%20%2Ftmp%0Atotal%208%0A-rwx------.%201%20root%20root%20701%20Dec%20%204%2017%3A37%20ks-script-esd4my7v%0A-rwx------.%201%20root%20root%20671%20Dec%20%204%2017%3A37%20ks-script-eusq_sc5%0A%60%60%60%0A%0A%23%23%23%23%203.3.9%20copy%E6%96%87%E4%BB%B6%0A%3E%20%E5%AE%B9%E5%99%A8%E5%81%9C%E6%AD%A2%E5%90%8E%E5%AE%B9%E5%99%A8%E9%87%8C%E9%9D%A2%E4%B9%8B%E5%89%8D%E6%94%B9%E5%8A%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E5%B0%B1%E4%BC%9A%E6%B6%88%E5%A4%B1%20%20%0A%3E%20docker%20cp%20id%3A%2F%E5%AE%B9%E5%99%A8%E5%86%85%E8%B7%AF%E5%BE%84%20%E5%AE%BF%E4%B8%BB%E6%9C%BA%E8%B7%AF%E5%BE%84%20%20%0A%3E%20docker%20cp%20id%3A%2Ftmp%2Fyum.log%20%2Froot%20%20%0A%0A%23%23%204%20%E9%95%9C%E5%83%8F%0A%23%23%23%204.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20%E8%81%94%E5%90%88%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F(UnionFS)%EF%BC%8C%20%E6%98%AF%E4%B8%80%E7%A7%8D%E5%88%86%E5%B1%82%EF%BC%8C%E8%BD%BB%E9%87%8F%E7%BA%A7%E5%B9%B6%E4%B8%94%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%EF%BC%8C%E5%AE%83%E6%94%AF%E6%8C%81%E5%AF%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E7%9A%84**%E4%BF%AE%E6%94%B9%E4%BD%9C%E4%B8%BA%E4%B8%80%E6%AC%A1%E6%8F%90%E4%BA%A4%E6%9D%A5%E4%B8%80%E5%B1%82%E5%B1%82%E7%9A%84%E5%8F%A0%E5%8A%A0**%EF%BC%8C%E5%90%8C%E6%97%B6%E5%B0%86%E4%B8%8D%E5%90%8C%E7%9A%84%E7%9B%AE%E5%BD%95%E6%8C%82%E8%BD%BD%E5%88%B0%E5%90%8C%E4%B8%80%E4%B8%AA%E8%99%9A%E6%8B%9F%E6%96%87%E4%BB%B6%E4%B8%8B%0A%0A%23%23%23%204.2%20%E5%8A%A0%E8%BD%BD%E5%8E%9F%E7%90%86%0A%3E%20bootfs(boot%20file%20system)%EF%BC%9A%E4%B8%BB%E8%A6%81%E5%8C%85%E5%90%ABbootloader%E5%92%8Ckernel%EF%BC%8Cbootloader%E4%B8%BB%E8%A6%81%E6%98%AF%E5%BC%95%E5%AF%BC%E5%8A%A0%E8%BD%BDkernel%EF%BC%8Clinux%E5%90%AF%E5%8A%A8%E6%97%B6%E4%BC%9A%E5%85%88%E5%8A%A0%E8%BD%BDbootfs%EF%BC%8C%E5%9C%A8Docker%E9%95%9C%E5%83%8F%E7%9A%84%E6%9C%80%E5%BA%95%E5%B1%82%E5%B0%B1%E6%98%AFbootfs%2C%E8%BF%99%E4%B8%80%E5%B1%82%E4%B8%8Elinux%E6%98%AF%E4%B8%80%E6%A0%B7%E7%9A%84%EF%BC%8C%E5%BD%93bootfs%E5%8A%A0%E8%BD%BD%E5%AE%8C%E6%88%90%E4%B9%8B%E5%90%8E%E6%95%B4%E4%B8%AA%E5%86%85%E6%A0%B8%E5%B0%B1%E9%83%BD%E5%9C%A8%E5%86%85%E5%AD%98%E4%B8%AD%EF%BC%8C%E6%AD%A4%E6%97%B6%E5%86%85%E5%AD%98%E7%9A%84%E4%BD%BF%E7%94%A8%E6%9D%83%E5%B0%B1%E7%94%B1bootfs%E8%BD%AC%E4%BA%A4%E7%BB%99%E5%86%85%E6%A0%B8%EF%BC%8C%E5%90%8C%E6%97%B6%E7%B3%BB%E7%BB%9F%E4%B9%9F%E4%BC%9A%E5%8D%B8%E8%BD%BD%E6%8E%89bootfs%E3%80%82%0A%0A%3E%20rootfs(root%20file%20system)%EF%BC%9A%E5%9C%A8bootfs%E4%B9%8B%E4%B8%8A%E5%8C%85%E5%90%AB%E4%BA%86%E5%85%B8%E5%9E%8B%E7%9A%84linux%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%2Fdev%2C%2Fproc%2C%2Fbin%2C%2Fetc%20%E7%AD%89%E6%A0%87%E5%87%86%E7%9B%AE%E5%BD%95%E5%92%8C%E6%96%87%E4%BB%B6%E3%80%82rootfs%E5%B0%B1%E6%98%AF%E5%90%84%E7%A7%8D%E4%B8%8D%E5%90%8C%E7%9A%84%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%8F%91%E8%A1%8C%E7%89%88%EF%BC%8C%E6%AF%94%E5%A6%82Ubuntu%E6%88%96CentOS%0A%0A%3E%20%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E4%BB%AC%E5%AE%89%E8%A3%85%E7%9A%84CentOS%E8%A6%81%E5%A5%BD%E5%87%A0%E4%B8%AAG%2C%E4%BD%86%E6%98%AFdocker%E9%87%8C%E9%9D%A2%E7%9A%84CentOS%E5%8D%B4%E5%8F%AA%E6%9C%89200M%0A%3E%20%E5%AF%B9%E4%BA%8E%E4%B8%8D%E5%90%8C%E7%9A%84linux%E5%8F%91%E8%A1%8C%E7%89%88%E6%9C%ACbootfs%E6%98%AF%E4%B8%80%E8%87%B4%E7%9A%84%EF%BC%8Crootfs%E4%BC%9A%E6%9C%89%E5%B7%AE%E5%88%AB%EF%BC%8C%E5%AF%B9%E4%BA%8E%E4%B8%80%E4%B8%AA%E7%B2%BE%E7%AE%80%E7%9A%84OS%2C%E5%8F%AF%E4%BB%A5%E5%85%B1%E7%94%A8%E7%B3%BB%E7%BB%9F%E7%9A%84bootfs%E5%B9%B6%E6%8F%90%E4%BE%9B%E8%87%AA%E5%B7%B1%E7%9A%84rootfs%0A%0A%3E%20tomcat%E9%95%9C%E5%83%8F%E9%87%8C%E9%9D%A2%E7%9A%84%E5%88%86%E5%B1%82%E7%BB%93%E6%9E%84%0A%0A!%5Bimage%5D(29FFD2AAA4CF4DE9B8A2F76E60DF93F9)%20%0A%0A%23%23%23%204.3%20%E7%89%B9%E7%82%B9%0A%3E%20Docker%E9%95%9C%E5%83%8F%E9%83%BD%E6%98%AF%E5%8F%AA%E8%AF%BB%E7%9A%84%0A%3E%20%E5%BD%93%E5%AE%B9%E5%99%A8%E5%90%AF%E5%8A%A8%E6%97%B6%EF%BC%8C%E5%BD%93%E5%AE%B9%E5%99%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E5%BD%93%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E5%8F%AF%E5%86%99%E5%B1%82%E8%A2%AB%E5%8A%A0%E8%BD%BD%E5%88%B0%E9%95%9C%E5%83%8F%E7%9A%84%E9%A1%B6%E9%83%A8%E3%80%82%E8%BF%99%E4%B8%80%E5%B1%82%E9%80%9A%E5%B8%B8%E8%A2%AB%E7%A7%B0%E4%BD%9C%E2%80%9C%E5%AE%B9%E5%99%A8%E5%B1%82%E2%80%9D%EF%BC%8C%E2%80%9C%E5%AE%B9%E5%99%A8%E5%B1%82%E2%80%9D%E4%B9%8B%E4%B8%8B%E5%8F%AB%E4%BD%9C%E2%80%9C%E9%95%9C%E5%83%8F%E5%B1%82%E2%80%9D%0A%0A%23%23%205%20%E6%95%B0%E6%8D%AE%E5%8D%B7%0A%23%23%23%205.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20docker%E5%AE%B9%E5%99%A8%E4%BA%A7%E7%94%9F%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E9%80%9A%E8%BF%87docker%20commit%E7%94%9F%E6%88%90%E6%96%B0%E7%9A%84%E9%95%9C%E5%83%8F%EF%BC%8C%E5%BD%93%E5%AE%B9%E5%99%A8%E5%88%A0%E9%99%A4%E4%B9%8B%E5%90%8E%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%B0%B1%E4%BC%9A%E6%B6%88%E5%A4%B1%20%20%0A%3E%20%E5%AE%B9%E5%99%A8%E6%95%B0%E6%8D%AE%E5%8D%B7%E5%B0%B1%E6%98%AF%E7%94%A8%E6%9D%A5%E4%BF%9D%E5%AD%98docker%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%20%20%0A%3E%20%E5%8D%B7%E6%98%AF%E7%9B%AE%E5%BD%95%E6%88%96%E6%96%87%E4%BB%B6%EF%BC%8C%E5%AD%98%E5%9C%A8%E4%BA%8E%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E5%AE%B9%E5%99%A8%E4%B8%AD%EF%BC%8C%E7%94%B1docker%E6%8C%82%E8%BD%BD%E5%88%B0%E5%AE%B9%E5%99%A8%EF%BC%8C%E4%BD%86%E6%98%AF%E4%B8%8D%E5%B1%9E%E4%BA%8EUnionFS%2C%E5%9B%A0%E6%AD%A4%E8%83%BD%E7%BB%95%E8%BF%87UnionFS%E6%8F%90%E4%BE%9B%E4%B8%80%E4%BA%9B%E7%94%A8%E4%BA%8E%E6%8C%81%E4%B9%85%E5%AD%98%E5%82%A8%E6%88%96%E5%85%B1%E4%BA%AB%E6%95%B0%E6%8D%AE%E7%9A%84%E7%89%B9%E6%80%A7%20%20%0A%3E%20%E5%8D%B7%E7%9A%84%E8%AE%BE%E8%AE%A1%E7%9B%AE%E7%9A%84%E5%B0%B1%E6%98%AF%E6%95%B0%E6%8D%AE%E6%8C%81%E4%B9%85%E5%8C%96%EF%BC%8C%E5%AE%8C%E5%85%A8%E7%8B%AC%E7%AB%8B%E4%BA%8E%E5%AE%B9%E5%99%A8%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%EF%BC%8C%E5%9B%A0%E6%AD%A4docker%E4%B8%8D%E4%BC%9A%E5%9C%A8%E5%AE%B9%E5%99%A8%E5%88%A0%E9%99%A4%E6%97%B6%E5%88%A0%E9%99%A4%E6%8C%82%E8%BD%BD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8D%B7%0A%0A%23%23%23%205.2%20%E7%89%B9%E7%82%B9%0A%60%60%60%0A1.%20%E6%95%B0%E6%8D%AE%E5%8D%B7%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%AE%B9%E5%99%A8%E4%B9%8B%E9%97%B4%E5%85%B1%E4%BA%AB%E6%88%96%E9%87%8D%E7%94%A8%E6%95%B0%E6%8D%AE%0A2.%20%E6%95%B0%E6%8D%AE%E5%8D%B7%E4%B8%AD%E7%9A%84%E6%9B%B4%E6%94%B9%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E7%94%9F%E6%95%88%0A3.%20%E6%95%B0%E6%8D%AE%E5%8D%B7%E4%B8%AD%E7%9A%84%E6%9B%B4%E6%94%B9%E4%B8%8D%E4%BC%9A%E5%8C%85%E5%90%AB%E5%9C%A8%E9%95%9C%E5%83%8F%E7%9A%84%E6%9B%B4%E6%96%B0%E4%B8%AD%0A4.%20%E6%95%B0%E6%8D%AE%E5%8D%B7%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E4%B8%80%E7%9B%B4%E6%8C%81%E7%BB%AD%E5%88%B0%E6%B2%A1%E6%9C%89%E5%AE%B9%E5%99%A8%E4%BD%BF%E7%94%A8%E5%AE%83%E4%B8%BA%E6%AD%A2%0A%60%60%60%0A%0A%23%23%23%205.3%20%E5%AE%B9%E5%99%A8%E5%86%85%E6%B7%BB%E5%8A%A0%E6%95%B0%E6%8D%AE%E5%8D%B7%0A%23%23%23%23%205.3.1%20%E7%9B%B4%E6%8E%A5%E5%91%BD%E4%BB%A4%E6%B7%BB%E5%8A%A0%0A%3E%20docker%20run%20-it%20-v%20%2F%E5%AE%BF%E4%B8%BB%E6%9C%BA%E7%9B%AE%E5%BD%95%E7%BB%9D%E5%AF%B9%E8%B7%AF%E5%BE%84%3A%E5%AE%B9%E5%99%A8%E5%86%85%E7%9B%AE%E5%BD%95%5B%E6%9D%83%E9%99%90%3Aro%5D%20%E9%95%9C%E5%83%8F%E5%90%8D%E6%88%96ID%20%20%0A%3E%20docker%20run%20-it%20-v%20%2FmydataVolume%22%3A%2FdataVolumeContainer%3A%20centos%20%20%0A%3E%20%E5%9C%A8%E7%9B%AE%E5%BD%95%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%9A%84%E6%83%85%E5%86%B5%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BA%E7%9B%AE%E5%BD%95%EF%BC%8C%20%E5%A6%82%E6%9E%9C%E5%88%9B%E5%BB%BA%E6%B7%BB%E5%8A%A0%E6%9D%83%E9%99%90%3Aro%EF%BC%8C%20%E8%A1%A8%E7%A4%BA%E5%AE%B9%E5%99%A8%E9%87%8C%E9%9D%A2%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8D%B7%E5%8F%AA%E8%AF%BB%E4%BD%86%E4%B8%8D%E8%83%BD%E4%BF%AE%E6%94%B9%0A%0A%0A%60%60%60%0A%23%20docker%20inspect%20250d8813d860%0A%22HostConfig%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Binds%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%2FmydataVolume%3A%2FdataVolumeContainer%3A%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%7D%0A%0A%22Mounts%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Type%22%3A%20%22bind%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Source%22%3A%20%22%2FmydataVolume%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Destination%22%3A%20%22%2FdataVolumeContainer%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Mode%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22RW%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Propagation%22%3A%20%22rprivate%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%0A%60%60%60%0A%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20docker%20run%20-it%20-v%20%2FmydataVolume%3A%2FdataVolumeContainer%3A%20centos%0A%5Broot%40250d8813d860%20%2F%5D%23%20ls%0Abin%20%20dataVolumeContainer%20%20dev%20%20etc%20%20home%20%20lib%20%20lib64%20%20lost%2Bfound%20%20media%20%20mnt%20%20opt%20%20proc%20%20root%20%20run%20%20sbin%20%20srv%20%20sys%20%20tmp%20%20usr%20%20var%0A%0A%60%60%60%0A%0A%60%60%60%0A%5Broot%40master%20%2F%5D%23%20ll%0Atotal%2024%0Alrwxrwxrwx.%20%20%201%20root%20root%20%20%20%207%20Dec%2024%2011%3A26%20bin%20-%3E%20usr%2Fbin%0Adr-xr-xr-x.%20%20%205%20root%20root%204096%20Dec%2024%2011%3A48%20boot%0Adrwxr-xr-x.%20%2020%20root%20root%203300%20Apr%2023%2015%3A29%20dev%0Adrwxr-xr-x.%20141%20root%20root%208192%20Apr%2023%2015%3A29%20etc%0Adrwxr-xr-x.%20%20%203%20root%20root%20%20%2019%20Dec%2024%2011%3A53%20home%0Alrwxrwxrwx.%20%20%201%20root%20root%20%20%20%207%20Dec%2024%2011%3A26%20lib%20-%3E%20usr%2Flib%0Alrwxrwxrwx.%20%20%201%20root%20root%20%20%20%209%20Dec%2024%2011%3A26%20lib64%20-%3E%20usr%2Flib64%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%20%206%20Apr%2011%20%202018%20media%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%20%206%20Apr%2011%20%202018%20mnt%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%20%206%20Apr%2025%2010%3A15%20mydataVolume%0Adrwxr-xr-x.%20%20%204%20root%20root%20%20%2034%20Apr%2022%2013%3A49%20opt%0Adr-xr-xr-x.%20256%20root%20root%20%20%20%200%20Apr%2023%2015%3A28%20proc%0Adr-xr-x---.%20%20%206%20root%20root%204096%20Apr%2023%2015%3A29%20root%0Adrwxr-xr-x.%20%2043%20root%20root%201340%20Apr%2025%2006%3A35%20run%0Alrwxrwxrwx.%20%20%201%20root%20root%20%20%20%208%20Dec%2024%2011%3A26%20sbin%20-%3E%20usr%2Fsbin%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%20%206%20Apr%2011%20%202018%20srv%0Adr-xr-xr-x.%20%2013%20root%20root%20%20%20%200%20Apr%2023%2015%3A28%20sys%0Adrwxrwxrwt.%20%2022%20root%20root%204096%20Apr%2025%2010%3A15%20tmp%0Adrwxr-xr-x.%20%2013%20root%20root%20%20155%20Dec%2024%2011%3A26%20usr%0Adrwxr-xr-x.%20%2020%20root%20root%20%20282%20Dec%2024%2011%3A50%20var%0A%60%60%60%0A%3E%20%E5%A4%87%E6%B3%A8%20%20%0A%3E%20Docker%E6%8C%82%E8%BD%BD%E4%B8%BB%E6%9C%BA%E7%9B%AE%E5%BD%95Docker%E8%AE%BF%E9%97%AE%E5%87%BA%E7%8E%B0%20cann't%20open%20directory.%3APermission%20denied%20%20%0A%3E%20%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%E5%9C%A8%E6%8C%82%E8%BD%BD%E7%9B%AE%E5%BD%95%E5%90%8E%E5%A2%9E%E5%8A%A0%20%60--privileged%20true%60%20%E5%8F%82%E6%95%B0%E5%8D%B3%E5%8F%AF%20%20%0A%60%5Broot%40master%20~%5D%23%20docker%20run%20-it%20-v%20%2FmydataVolume%3A%2FdataVolumeContainer%3A%20--privileged%20true%20centos%60%0A%0A%23%23%23%23%205.3.2%20DockerFile%E6%B7%BB%E5%8A%A0%0A1.%20%E6%96%B0%E5%BB%BAdockerfile%20%20%20%0A%0A%60%60%60%0Amkdir%20mydocker%20%20%0Acd%20mydocker%20%20%0Avi%20dockerfile%0A%E5%86%99%E5%85%A5%E5%A6%82%E4%B8%8B%E5%91%BD%E4%BB%A4%0A%0AFrom%20centos%0AVOLUME%20%5B%22%2FdataVolumeContainer01%22%2C%22%2FdataVolumeContainer02%22%5D%0ACMD%20echo%20%22finished%2C------success%22%0ACMD%20%2Fbin%2Fbash%0A%60%60%60%0A%0A2.%20%E7%94%9F%E6%88%90%E9%95%9C%E5%83%8F%20%20%0A%3E%20docker%20build%20-f%20%2Fmydocker%2Fdockerfile%20-t%20chris%2Fcentos%20.%20%20%0A%3E%20%E5%9C%A8%E5%BD%93%E5%89%8D%E7%9B%AE%E5%BD%95%E4%B8%8B%E6%A0%B9%E6%8D%AE%E6%8C%87%E5%AE%9A%E7%9A%84dockerfile%E7%94%9F%E6%88%90%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E4%B8%BAchris%E9%95%9C%E5%83%8F%E5%90%8D%E7%A7%B0%E4%B8%BAcentos%E7%9A%84%E9%95%9C%E5%83%8F%0A%0A%60%60%60%0A%5Broot%40master%20mydocker%5D%23%20docker%20build%20-f%20%2Fmydocker%2Fdockerfile%20-t%20chris%2Fcentos%20.%0ASending%20build%20context%20to%20Docker%20daemon%20%202.048kB%0AStep%201%2F4%20%3A%20From%20centos%0A%20---%3E%20300e315adb2f%0AStep%202%2F4%20%3A%20VOLUME%20%5B%22%2FdataVolumeContainer01%22%2C%22%2FdataVolumeContainer02%22%5D%0A%20---%3E%20Running%20in%203a2ba255152a%0ARemoving%20intermediate%20container%203a2ba255152a%0A%20---%3E%209522ef03e277%0AStep%203%2F4%20%3A%20CMD%20echo%20%22finished%2C------success%22%0A%20---%3E%20Running%20in%20b6c0a82df0ad%0ARemoving%20intermediate%20container%20b6c0a82df0ad%0A%20---%3E%207dff01de54a6%0AStep%204%2F4%20%3A%20CMD%20%2Fbin%2Fbash%0A%20---%3E%20Running%20in%20af67b3613d42%0ARemoving%20intermediate%20container%20af67b3613d42%0A%20---%3E%20f975da2854b7%0ASuccessfully%20built%20f975da2854b7%0ASuccessfully%20tagged%20chris%2Fcentos%3Alatest%0A%0A%5Broot%40master%20%2F%5D%23%20docker%20images%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Achris%2Fcentos%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20f975da2854b7%20%20%20%20%20%20%20%203%20minutes%20ago%20%20%20%20%20%20%20209MB%0A%60%60%60%0A%0A3.%20%E5%88%9B%E5%BB%BA%E5%AE%B9%E5%99%A8%20%20%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20docker%20run%20-it%20chris%2Fcentos%20%2Fbin%2Fbash%0A%5Broot%4022f74a27ccb0%20%2F%5D%23%20ls%20-l%0Atotal%200%0Alrwxrwxrwx.%20%20%201%20root%20root%20%20%207%20Nov%20%203%2015%3A22%20bin%20-%3E%20usr%2Fbin%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%206%20Apr%2025%2003%3A20%20dataVolumeContainer01%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%206%20Apr%2025%2003%3A20%20dataVolumeContainer02%0Adrwxr-xr-x.%20%20%205%20root%20root%20360%20Apr%2025%2003%3A20%20dev%0Adrwxr-xr-x.%20%20%201%20root%20root%20%2066%20Apr%2025%2003%3A20%20etc%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%206%20Nov%20%203%2015%3A22%20home%0Alrwxrwxrwx.%20%20%201%20root%20root%20%20%207%20Nov%20%203%2015%3A22%20lib%20-%3E%20usr%2Flib%0Alrwxrwxrwx.%20%20%201%20root%20root%20%20%209%20Nov%20%203%2015%3A22%20lib64%20-%3E%20usr%2Flib64%0Adrwx------.%20%20%202%20root%20root%20%20%206%20Dec%20%204%2017%3A37%20lost%2Bfound%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%206%20Nov%20%203%2015%3A22%20media%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%206%20Nov%20%203%2015%3A22%20mnt%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%206%20Nov%20%203%2015%3A22%20opt%0Adr-xr-xr-x.%20258%20root%20root%20%20%200%20Apr%2025%2003%3A20%20proc%0Adr-xr-x---.%20%20%202%20root%20root%20162%20Dec%20%204%2017%3A37%20root%0Adrwxr-xr-x.%20%2011%20root%20root%20163%20Dec%20%204%2017%3A37%20run%0Alrwxrwxrwx.%20%20%201%20root%20root%20%20%208%20Nov%20%203%2015%3A22%20sbin%20-%3E%20usr%2Fsbin%0Adrwxr-xr-x.%20%20%202%20root%20root%20%20%206%20Nov%20%203%2015%3A22%20srv%0Adr-xr-xr-x.%20%2013%20root%20root%20%20%200%20Apr%2023%2007%3A28%20sys%0Adrwxrwxrwt.%20%20%207%20root%20root%20145%20Dec%20%204%2017%3A37%20tmp%0Adrwxr-xr-x.%20%2012%20root%20root%20144%20Dec%20%204%2017%3A37%20usr%0Adrwxr-xr-x.%20%2020%20root%20root%20262%20Dec%20%204%2017%3A37%20var%0A%0A%60%60%60%0A%3E%20%E5%9C%A8%E6%95%B0%E6%8D%AE%E5%8D%B7%E4%B8%AD%E5%88%9B%E5%BB%BA%E6%96%87%E4%BB%B6%0A%60%60%60%0A%5Broot%4022f74a27ccb0%20%2F%5D%23%20cd%20dataVolumeContainer01%0A%5Broot%4022f74a27ccb0%20dataVolumeContainer01%5D%23%20vi%20container.txt%0A%60%60%60%0A%0A%3E%20%E6%9F%A5%E7%9C%8B%E6%95%B0%E6%8D%AE%E5%8D%B7%E5%9C%A8%E5%AE%B9%E5%99%A8%E5%92%8C%E5%AE%BF%E4%B8%BB%E6%9C%BA%E4%B9%8B%E9%97%B4%E7%9A%84%E8%B7%AF%E5%BE%84%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20docker%20ps%0ACONTAINER%20ID%20%20%20%20%20%20%20%20IMAGE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20COMMAND%20%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20STATUS%20%20%20%20%20%20%20%20%20%20%20%20%20%20PORTS%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NAMES%0A22f74a27ccb0%20%20%20%20%20%20%20%20chris%2Fcentos%20%20%20%20%20%20%20%20%22%2Fbin%2Fbash%22%20%20%20%20%20%20%20%20%2016%20minutes%20ago%20%20%20%20%20%20Up%2016%20minutes%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stupefied_cannon%0A692aee0e4bfe%20%20%20%20%20%20%20%20christomcat%3A1.0%20%20%20%20%20%22catalina.sh%20run%22%20%20%2042%20hours%20ago%20%20%20%20%20%20%20%20Up%2042%20hours%20%20%20%20%20%20%20%20%200.0.0.0%3A8888-%3E8080%2Ftcp%20%20%20epic_roentgen%0A3b7146c6590e%20%20%20%20%20%20%20%20tomcat%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22catalina.sh%20run%22%20%20%2043%20hours%20ago%20%20%20%20%20%20%20%20Up%2043%20hours%20%20%20%20%20%20%20%20%200.0.0.0%3A8088-%3E8080%2Ftcp%20%20%20tomcat2%0A%5Broot%40master%20~%5D%23%20docker%20inspect%2022f74a27ccb0%0A%22Mounts%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Type%22%3A%20%22volume%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Name%22%3A%20%22f893623ee2039a23c820361dda8b45a164dc9a6a3e4329d30533ea6a73ad36e9%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Source%22%3A%20%22%2Fvar%2Flib%2Fdocker%2Fvolumes%2Ff893623ee2039a23c820361dda8b45a164dc9a6a3e4329d30533ea6a73ad36e9%2F_data%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Destination%22%3A%20%22%2FdataVolumeContainer01%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Driver%22%3A%20%22local%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Mode%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22RW%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Propagation%22%3A%20%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Type%22%3A%20%22volume%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Name%22%3A%20%22feb81fb00529025525f7b27c20edc417eced5ce517cdf73c754343e943af50ba%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Source%22%3A%20%22%2Fvar%2Flib%2Fdocker%2Fvolumes%2Ffeb81fb00529025525f7b27c20edc417eced5ce517cdf73c754343e943af50ba%2F_data%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Destination%22%3A%20%22%2FdataVolumeContainer02%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Driver%22%3A%20%22local%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Mode%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22RW%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Propagation%22%3A%20%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%0A%5Broot%40master%20~%5D%23%20cd%20%2Fvar%2Flib%2Fdocker%2Fvolumes%2Ff893623ee2039a23c820361dda8b45a164dc9a6a3e4329d30533ea6a73ad36e9%2F_data%0A%5Broot%40master%20_data%5D%23%20ll%0Atotal%204%0A-rw-r--r--.%201%20root%20root%2029%20Apr%2025%2011%3A36%20container.txt%0A%20%20%20%20%20%20%20%20%0A%60%60%60%0A%0A%0A%23%23%23%205.4%20%E6%95%B0%E6%8D%AE%E5%8D%B7%E5%AE%B9%E5%99%A8%0A%3E%20%E5%91%BD%E5%90%8D%E7%9A%84%E5%AE%B9%E5%99%A8%E6%8C%82%E8%BD%BD%E6%95%B0%E6%8D%AE%E5%8D%B7%EF%BC%8C%E5%85%B6%E5%AE%83%E5%AE%B9%E5%99%A8%E9%80%9A%E8%BF%87%E6%8C%82%E8%BD%BD%E8%BF%99%E4%B8%AA%E7%88%B6%E5%AE%B9%E5%99%A8%E5%AE%9E%E7%8E%B0%E6%95%B0%E6%8D%AE%E5%85%B1%E4%BA%AB%EF%BC%8C%E6%8C%82%E8%BD%BD%E6%95%B0%E6%8D%AE%E5%8D%B7%E7%9A%84%E5%AE%B9%E5%99%A8%E7%A7%B0%E4%B9%8B%E4%B8%BA%E6%95%B0%E6%8D%AE%E5%8D%B7%E5%AE%B9%E5%99%A8%20%20%0A%3E%20%E5%AE%B9%E5%99%A8%E4%B9%8B%E9%97%B4%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E7%9A%84%E4%BC%A0%E9%80%92%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%8D%B7%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E4%B8%80%E7%9B%B4%E6%8C%81%E7%BB%AD%E5%88%B0%E6%B2%A1%E6%9C%89%E5%AE%B9%E5%99%A8%E4%BD%BF%E7%94%A8%E5%AE%83%E4%B8%BA%E6%AD%A2%0A%0A%0A%0A%60%60%60%0A%5Broot%40master%20_data%5D%23%20docker%20run%20-it%20--name%20dc01%20chris%2Fcentos%0A%5Broot%40ca18f7f9d24c%20%2F%5D%23%20cd%20dataVolumeContainer02%0A%5Broot%40ca18f7f9d24c%20dataVolumeContainer02%5D%23%20touch%20dc01_add.txt%0A%0A%5Broot%40master%20~%5D%23%20docker%20run%20-it%20--volumes-from%20dc01%20--name%20dc02%20chris%2Fcentos%0A%5Broot%40defe4e49519f%20%2F%5D%23%20ls%0Abin%20%20dataVolumeContainer01%20%20dataVolumeContainer02%20%20dev%09etc%20%20home%20%20lib%09lib64%20%20lost%2Bfound%20%20media%20%20mnt%20%20opt%20%20proc%20%20root%09run%20%20sbin%20%20srv%09sys%20%20tmp%20%20usr%20%20var%0A%5Broot%40defe4e49519f%20%2F%5D%23%20cd%20dataVolumeContainer0%0A%5Broot%40defe4e49519f%20dataVolumeContainer02%5D%23%20ls%0Adc01_add.txt%20%20%0A%0A%60%60%60%0A%0A%23%23%206%20DockerFile%0A%23%23%23%206.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20DockerFile%E6%98%AF%E7%94%A8%E6%9D%A5%E6%9E%84%E5%BB%BADocker%E9%95%9C%E5%83%8F%E7%9A%84%E6%9E%84%E5%BB%BA%E6%96%87%E4%BB%B6%EF%BC%8C%E6%98%AF%E7%94%B1%E4%B8%80%E7%B3%BB%E5%88%97%E7%9A%84%E5%91%BD%E4%BB%A4%E5%92%8C%E5%8F%82%E6%95%B0%E7%BB%84%E6%88%90%E7%9A%84%E8%84%9A%E6%9C%AC%E3%80%82%0A%23%23%23%206.2%20%E6%9E%84%E5%BB%BA%E4%B8%89%E6%AD%A5%E9%AA%A4%0A1.%20%E7%BC%96%E5%86%99DockerFile%20%20%0A2.%20%E6%9E%84%E5%BB%BADocker%E9%95%9C%E5%83%8F%20%20%0A3.%20%E8%BF%90%E8%A1%8C%20%20%0A%0A%23%23%23%206.3%20DockerFile%E7%9A%84%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B%0A%23%23%23%23%206.3.1%20DockerFile%E7%9A%84%E5%86%85%E5%AE%B9%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%0A%3E%201.%20%E6%AF%8F%E4%B8%AA%E4%BF%9D%E7%95%99%E5%AD%97%E5%91%BD%E4%BB%A4%E5%BF%85%E9%A1%BB%E4%B8%BA%E5%A4%A7%E5%86%99%E5%AD%97%E6%AF%8D%E5%B9%B6%E4%B8%94%E5%90%8E%E9%9D%A2%E8%87%B3%E5%B0%91%E8%B7%9F%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%0A%3E%202.%20%E6%8C%87%E4%BB%A4%E6%8C%89%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E9%A1%BA%E5%BA%8F%E6%89%A7%E8%A1%8C%0A%3E%203.%20%23%E8%A1%A8%E7%A4%BA%E6%B3%A8%E9%87%8A%0A%3E%204.%20%E6%AF%8F%E6%9D%A1%E6%8C%87%E4%BB%A4%E9%83%BD%E4%BC%9A%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E9%95%9C%E5%83%8F%E5%B1%82%EF%BC%8C%E5%B9%B6%E5%AF%B9%E9%95%9C%E5%83%8F%E8%BF%9B%E8%A1%8C%E6%8F%90%E4%BA%A4%0A%0A%23%23%23%23%206.3.2%20DockerFile%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B%0A%3E%201.%20docker%E4%BB%8E%E5%9F%BA%E7%A1%80%E9%95%9C%E5%83%8F%E8%BF%90%E8%A1%8C%E4%B8%80%E4%B8%AA%E5%AE%B9%E5%99%A8%20%20%0A%3E%202.%20%E6%89%A7%E8%A1%8C%E4%B8%80%E6%9D%A1%E6%8C%87%E5%AE%9A%E5%B9%B6%E5%AF%B9%E5%AE%B9%E5%99%A8%E4%BD%9C%E5%87%BA%E4%BF%AE%E6%94%B9%0A%3E%203.%20%E6%89%A7%E8%A1%8C%E7%B1%BB%E4%BC%BCdocker%20commit%20%E7%9A%84%E6%93%8D%E4%BD%9C%E6%8F%90%E4%BA%A4%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E9%95%9C%E5%83%8F%E5%B1%82%0A%3E%204.%20docker%E5%9F%BA%E4%BA%8E%E5%88%99%E6%8F%90%E4%BA%A4%E7%9A%84%E9%95%9C%E5%83%8F%E5%86%8D%E8%BF%90%E8%A1%8C%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E5%AE%B9%E5%99%A8%0A%3E%205.%20%E6%89%A7%E8%A1%8CDockerFile%E4%B8%AD%E7%9A%84%E4%B8%8B%E4%B8%80%E6%9D%A1%E6%8C%87%E4%BB%A4%EF%BC%8C%E7%9B%B4%E5%88%B0%E6%89%80%E6%9C%89%E7%9A%84%E6%8C%87%E4%BB%A4%E9%83%BD%E8%A2%AB%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%88%90%E3%80%82%0A%0A%3E%20DockerFile%E6%98%AF%E8%BD%AF%E4%BB%B6%E7%9A%84%E5%8E%9F%E6%9D%90%E6%96%99%20%20%0A%3E%20Docker%E9%95%9C%E5%83%8F%E6%98%AF%E8%BD%AF%E4%BB%B6%E7%9A%84%E4%BA%A4%E4%BB%98%E7%89%A9%20%20%0A%3E%20Docker%E5%AE%B9%E5%99%A8%E5%8F%AF%E4%BB%A5%E7%9C%8B%E6%88%90%E6%98%AF%E8%BD%AF%E4%BB%B6%E7%9A%84%E8%BF%90%E8%A1%8C%E6%80%81%20%20%0A%3E%20DockerFile%E9%9D%A2%E5%90%91%E5%BC%80%E5%8F%91%EF%BC%8CDocker%E9%95%9C%E5%83%8F%E6%88%90%E4%B8%BA%E8%BD%AF%E4%BB%B6%E7%9A%84%E4%BA%A4%E4%BB%98%E6%A0%87%E5%87%86%EF%BC%8CDocker%E5%AE%B9%E5%99%A8%E5%88%99%E6%B6%89%E5%8F%8A%E9%83%A8%E7%BD%B2%E5%88%B0%E8%BF%90%E7%BB%B4%EF%BC%8C%E4%B8%89%E8%80%85%E7%BC%BA%E4%B8%80%E4%B8%8D%E5%8F%AF%0A%0A!%5Bimage%5D(EDF06D029F0A43E18C5AD72A6E4BDEA8)%0A%0A%23%23%23%206.4%20%E6%8C%87%E4%BB%A4%0A%0A%E5%91%BD%E4%BB%A4%20%7C%20%E6%8F%8F%E8%BF%B0%0A--------%7C--------%0AFROM%20%20%20%20%20%20%20%7C%20%E5%9F%BA%E7%A1%80%E9%95%9C%E5%83%8F%EF%BC%8C%E5%BD%93%E5%89%8D%E9%95%9C%E5%83%8F%E6%98%AF%E5%9F%BA%E4%BA%8E%E5%93%AA%E4%B8%AA%E9%95%9C%E5%83%8F%E7%9A%84%0AMAINTAINER%20%7C%20%E4%BD%9C%E8%80%85%E5%8F%8A%E5%85%B6%E9%82%AE%E7%AE%B1%0ARUN%20%20%20%20%20%20%20%20%7C%20%E5%AE%B9%E5%99%A8%E6%9E%84%E5%BB%BA%E6%97%B6%E9%9C%80%E8%A6%81%E8%BF%90%E8%A1%8C%E7%9A%84linux%E5%91%BD%E4%BB%A4%0AEXPOSE%20%20%20%20%20%7C%20%E5%AE%B9%E5%99%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E5%AF%B9%E5%A4%96%E6%9A%B4%E9%9C%B2%E7%9A%84%E7%AB%AF%E5%8F%A3%E5%8F%B7%0AWORKDIR%20%20%20%20%7C%20%E8%BF%9B%E5%85%A5%E5%AE%B9%E5%99%A8%E8%BF%90%E8%A1%8C%E5%90%8E%E7%9A%84%E7%9B%AE%E5%BD%95%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E6%8C%87%E5%AE%9A%E5%B0%B1%E6%98%AF%E6%A0%B9%E7%9B%AE%E5%BD%95%0AENV%20%20%20%20%20%20%20%20%7C%20%E5%9C%A8%E6%9E%84%E5%BB%BA%E9%95%9C%E5%83%8F%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%E8%AE%BE%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%0AADD%20%20%20%20%20%20%20%20%7C%20%E5%B0%86%E5%AE%BF%E4%B8%BB%E6%9C%BA%E7%9A%84%E6%96%87%E4%BB%B6%E6%8B%B7%E8%B4%9D%E8%BF%9B%E9%95%9C%E5%83%8F%E4%B8%94ADD%E5%91%BD%E4%BB%A4%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%A4%84%E7%90%86URL%E5%92%8C%E8%A7%A3%E5%8E%8BTAR%E5%8E%8B%E7%BC%A9%E5%8C%85%0ACOPY%20%20%20%20%20%20%20%7C%20%E7%B1%BB%E4%BC%BCADD%EF%BC%8C%E5%B0%86%E6%96%87%E4%BB%B6%E6%88%96%E7%9B%AE%E5%BD%95%E6%8B%B7%E8%B4%9D%E5%88%B0%E9%95%9C%E5%83%8F%E4%B8%AD%EF%BC%8C%E5%B0%86%E4%BB%8E%E6%9E%84%E5%BB%BA%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9B%AE%E5%BD%95%E4%B8%AD%3C%E6%BA%90%E8%B7%AF%E5%BE%84%3E%E7%9A%84%E6%96%87%E4%BB%B6%2F%E7%9B%AE%E5%BD%95%E5%A4%8D%E5%88%B6%E5%88%B0%E6%96%B0%E7%9A%84%E4%B8%80%E5%B1%82%E9%95%9C%E5%83%8F%E5%86%85%E7%9A%84%3C%E7%9B%AE%E6%A0%87%E8%B7%AF%E5%BE%84%3E%E4%BD%8D%E7%BD%AE%20COPY%20SRC%20DEST%0AVOLUME%20%20%20%20%20%7C%20%E6%8C%87%E5%AE%9A%E6%95%B0%E6%8D%AE%E5%8D%B7%EF%BC%8C%E7%94%A8%E4%BA%8E%E6%95%B0%E6%8D%AE%E5%85%B1%E4%BA%AB%E5%92%8C%E6%8C%81%E4%B9%85%E5%8C%96%0ACMD%20%20%20%20%20%20%20%20%7C%20%E6%8C%87%E5%AE%9A%E4%B8%80%E4%B8%AA%E5%AE%B9%E5%99%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E9%9C%80%E8%A6%81%E8%BF%90%E8%A1%8C%E7%9A%84%E5%91%BD%E4%BB%A4%2CDockerFile%E4%B8%AD%E5%8F%AF%E4%BB%A5%E6%9C%89%E5%A4%9A%E4%B8%AACMD%E6%8C%87%E4%BB%A4%EF%BC%8C%E4%BD%86%E6%98%AF%E5%8F%AA%E6%9C%89%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AA%E7%94%9F%E6%95%88%EF%BC%8CCMD%E4%BC%9A%E8%A2%ABdocker%20run%E4%B9%8B%E5%90%8E%E7%9A%84%E5%8F%82%E6%95%B0%E6%9B%BF%E6%8D%A2%0AENTRYPOINT%20%7C%20%E5%92%8CCMD%E4%B8%80%E6%A0%B7%EF%BC%8C%E6%8C%87%E5%AE%9A%E4%B8%80%E4%B8%AA%E5%AE%B9%E5%99%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E9%9C%80%E8%A6%81%E8%BF%90%E8%A1%8C%E7%9A%84%E5%91%BD%E4%BB%A4%EF%BC%8C%E4%BD%86%E6%98%AFENTRYPOINT%E5%8F%AA%E4%BC%9A%E8%BF%BD%E5%8A%A0%EF%BC%8C%E4%B8%8D%E4%BC%9A%E8%A6%86%E7%9B%96%E4%B9%8B%E5%89%8D%E7%9A%84%E5%91%BD%E4%BB%A4%0AONBUILD%20%20%20%20%7C%20%E5%BD%93%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%A2%AB%E7%BB%A7%E6%89%BF%E7%9A%84DockerFile%E6%97%B6%E8%BF%90%E8%A1%8C%E5%91%BD%E4%BB%A4%EF%BC%8C%E7%88%B6%E9%95%9C%E5%83%8F%E5%9C%A8%E8%A2%AB%E5%AD%90%E7%BB%A7%E6%89%BF%E5%90%8E%E7%88%B6%E9%95%9C%E5%83%8F%E7%9A%84ONBUILD%E8%A2%AB%E8%A7%A6%E5%8F%91%0A%0A%0A%23%23%23%206.5.%20%E6%A1%88%E4%BE%8B%0A%23%23%23%206.5.1%20Base%E9%95%9C%E5%83%8F(scratch)%0ADockerHub%E4%B8%AD%E6%9C%8999%25%E7%9A%84%E9%95%9C%E5%83%8F%E9%83%BD%E6%98%AF%E9%80%9A%E8%BF%87%E5%9C%A8Base%E9%95%9C%E5%83%8F%E4%B8%AD%E5%AE%89%E8%A3%85%E6%88%96%E9%85%8D%E7%BD%AE%E9%9C%80%E8%A6%81%E8%BD%AF%E4%BB%B6%E6%9E%84%E5%BB%BA%E5%87%BA%E6%9D%A5%E7%9A%84%0A%23%23%23%206.5.2%20%E8%87%AA%E5%AE%9A%E4%B9%89%E9%95%9C%E5%83%8F(mycentos)%0A1.%20%E7%BC%96%E5%86%99dockerfile%0A%0A%60%60%60%0Acd%20%2Fmydocker%0Avi%20dockerfile_mycentos%0A%0AFROM%20centos%0AENV%20MYPATH%20%2Fusr%2Flocal%0AWORKDIR%20%24MYPATH%0A%0ARUN%20yum%20-y%20install%20vim%0ARUN%20yum%20-y%20install%20net-tools%0A%0AEXPOSE%2080%0A%0ACMD%20echo%20%24MYPATH%0ACMD%20echo%20%22success%20-------%22%0ACMD%20%2Fbin%2Fbash%0A%0A%60%60%60%0A2.%20%E6%9E%84%E5%BB%BA%0A%0A%60%60%60%0A%5Broot%40master%20mydocker%5D%23%20docker%20build%20-f%20dockerfile_mycentos%20-t%20chris%2Fmycentos%20.%0ASending%20build%20context%20to%20Docker%20daemon%20%202.048kB%0AStep%201%2F9%20%3A%20FROM%20centos%0A%20---%3E%20300e315adb2f%0AStep%202%2F9%20%3A%20ENV%20MYPATH%20%2Fusr%2Flocal%0A%20---%3E%20Running%20in%202949185ee980%0ARemoving%20intermediate%20container%202949185ee980%0A%20---%3E%200f46cb36876f%0AStep%203%2F9%20%3A%20WORKDIR%20%24MYPATH%0A%20---%3E%20Running%20in%20fe888cab4aa9%0ARemoving%20intermediate%20container%20fe888cab4aa9%0A%20---%3E%2064d820bebb93%0AStep%204%2F9%20%3A%20RUN%20yum%20-y%20install%20vim%0A%20---%3E%20Running%20in%2096061faccf00%0A......%0A%0A%20---%3E%20be8b79c33752%0AStep%206%2F9%20%3A%20EXPOSE%2080%0A%20---%3E%20Running%20in%20b2d74036a236%0ARemoving%20intermediate%20container%20b2d74036a236%0A%20---%3E%20b7b067e37daa%0AStep%207%2F9%20%3A%20CMD%20echo%20%24MYPATH%0A%20---%3E%20Running%20in%201532b91d6170%0ARemoving%20intermediate%20container%201532b91d6170%0A%20---%3E%20d4370aa3b2ff%0AStep%208%2F9%20%3A%20CMD%20echo%20%22success%20-------ok%22%0A%20---%3E%20Running%20in%200fe95c30e852%0ARemoving%20intermediate%20container%200fe95c30e852%0A%20---%3E%206c3800d76c3c%0AStep%209%2F9%20%3A%20CMD%20%2Fbin%2Fbash%0A%20---%3E%20Running%20in%203a47cc176453%0ARemoving%20intermediate%20container%203a47cc176453%0A%20---%3E%20eee12504217a%0ASuccessfully%20built%20eee12504217a%0ASuccessfully%20tagged%20chris%2Fmycentos%3Alatest%0A%5Broot%40master%20mydocker%5D%23%20docker%20images%20%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Achris%2Fmycentos%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20eee12504217a%20%20%20%20%20%20%20%202%20minutes%20ago%20%20%20%20%20%20%20291MB%0Atomcat%20%20%20%20%20%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20c0e850d7b9bb%20%20%20%20%20%20%20%208%20days%20ago%20%20%20%20%20%20%20%20%20%20667MB%0Ahello-world%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20d1165f221234%20%20%20%20%20%20%20%208%20weeks%20ago%20%20%20%20%20%20%20%20%2013.3kB%0Acentos%20%20%20%20%20%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20300e315adb2f%20%20%20%20%20%20%20%204%20months%20ago%20%20%20%20%20%20%20%20209MB%0A%60%60%60%0A%0A3.%20%E8%BF%90%E8%A1%8C%0A%0A%60%60%60%0A%5Broot%40master%20mydocker%5D%23%20docker%20run%20-it%20--name%20centos02%20chris%2Fmycentos%0A%5Broot%40960bafdfce5e%20local%5D%23%20pwd%0A%2Fusr%2Flocal%0A%60%60%60%0A4.%20%E5%88%97%E5%87%BA%E9%95%9C%E5%83%8F%E7%9A%84%E5%8F%98%E6%9B%B4%E5%8E%86%E5%8F%B2%0A%0A%3E%20docker%20history%20%E9%95%9C%E5%83%8F%E5%90%8D%7CID%20%20%0A%3E%20%E4%BB%8E%E4%B8%8B%E5%BE%80%E4%B8%8A%E6%9F%A5%E7%9C%8B%E9%95%9C%E5%83%8F%E7%9A%84%E7%94%9F%E6%88%90%E5%8E%86%E5%8F%B2%0A%60%60%60%0A%5Broot%40master%20chris%5D%23%20docker%20images%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Achris%2Fmycentos%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20eee12504217a%20%20%20%20%20%20%20%2015%20minutes%20ago%20%20%20%20%20%20291MB%0Atomcat%20%20%20%20%20%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20c0e850d7b9bb%20%20%20%20%20%20%20%208%20days%20ago%20%20%20%20%20%20%20%20%20%20667MB%0Ahello-world%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20d1165f221234%20%20%20%20%20%20%20%208%20weeks%20ago%20%20%20%20%20%20%20%20%2013.3kB%0Acentos%20%20%20%20%20%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20300e315adb2f%20%20%20%20%20%20%20%204%20months%20ago%20%20%20%20%20%20%20%20209MB%0A%5Broot%40master%20chris%5D%23%20docker%20history%20chris%2Fmycentos%0AIMAGE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20BY%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20COMMENT%0Aeee12504217a%20%20%20%20%20%20%20%2015%20minutes%20ago%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20%20CMD%20%5B%22%2Fbin%2Fsh%22%20%22-c%22%20%22%2Fbin%E2%80%A6%20%20%200B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A6c3800d76c3c%20%20%20%20%20%20%20%2015%20minutes%20ago%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20%20CMD%20%5B%22%2Fbin%2Fsh%22%20%22-c%22%20%22echo%E2%80%A6%20%20%200B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0Ad4370aa3b2ff%20%20%20%20%20%20%20%2015%20minutes%20ago%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20%20CMD%20%5B%22%2Fbin%2Fsh%22%20%22-c%22%20%22echo%E2%80%A6%20%20%200B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0Ab7b067e37daa%20%20%20%20%20%20%20%2015%20minutes%20ago%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20%20EXPOSE%2080%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%200B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0Abe8b79c33752%20%20%20%20%20%20%20%2015%20minutes%20ago%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20yum%20-y%20install%20net-tools%20%20%20%20%20%20%20%20%20%20%20%20%2023.4MB%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A7b1c6d927962%20%20%20%20%20%20%20%2016%20minutes%20ago%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20yum%20-y%20install%20vim%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2058.1MB%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A64d820bebb93%20%20%20%20%20%20%20%2016%20minutes%20ago%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20WORKDIR%20%2Fusr%2Flocal%20%20%20%20%20%20%20%20%20%20%20%200B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A0f46cb36876f%20%20%20%20%20%20%20%2016%20minutes%20ago%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20%20ENV%20MYPATH%3D%2Fusr%2Flocal%20%20%20%20%20%20%20%200B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A300e315adb2f%20%20%20%20%20%20%20%204%20months%20ago%20%20%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20%20CMD%20%5B%22%2Fbin%2Fbash%22%5D%20%20%20%20%20%20%20%20%20%20%20%200B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%3Cmissing%3E%20%20%20%20%20%20%20%20%20%20%204%20months%20ago%20%20%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20%20LABEL%20org.label-schema.sc%E2%80%A6%20%20%200B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%3Cmissing%3E%20%20%20%20%20%20%20%20%20%20%204%20months%20ago%20%20%20%20%20%20%20%20%2Fbin%2Fsh%20-c%20%23(nop)%20ADD%20file%3Abd7a2aed6ede423b7%E2%80%A6%20%20%20209MB%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%5Broot%40master%20chris%5D%23%20%0A%0A%60%60%60%0A%0A%23%23%23%206.5.3%20CMD%E5%92%8CENTRYPOINT%E7%9A%84%E5%8C%BA%E5%88%AB%0A%0A%3E%20CMD%20%E6%8C%87%E7%9A%84%E6%98%AF%E4%B8%8B%E5%88%97%E8%A1%A8%E9%87%8C%E9%9D%A2%E7%9A%84COMMAND%0A%0A%60%60%60%0A%5Broot%40master%20chris%5D%23%20docker%20ps%0ACONTAINER%20ID%20%20%20%20%20%20%20%20IMAGE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20COMMAND%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20STATUS%20%20%20%20%20%20%20%20%20%20%20%20%20%20PORTS%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NAMES%0A960bafdfce5e%20%20%20%20%20%20%20%20chris%2Fmycentos%20%20%20%20%20%20%22%2Fbin%2Fsh%20-c%20%2Fbin%2Fbash%22%20%20%2015%20minutes%20ago%20%20%20%20%20%20Up%2015%20minutes%20%20%20%20%20%20%2080%2Ftcp%20%20%20%20%20%20%20%20%20%20%20%20%20%20centos02%0A8034e792d331%20%20%20%20%20%20%20%20centos%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%2Fbin%2Fbash%22%20%20%20%20%20%20%20%20%20%20%20%20%20%2026%20minutes%20ago%20%20%20%20%20%20Up%2026%20minutes%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20centos01%0A%0A%5Broot%40master%20chris%5D%23%20docker%20run%20-it%20--name%20tomcat02%20-p%208888%3A8080%20%20tomcat%0A%5Broot%40master%20chris%5D%23%20docker%20ps%20%0ACONTAINER%20ID%20%20%20%20%20%20%20%20IMAGE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20COMMAND%20%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20STATUS%20%20%20%20%20%20%20%20%20%20%20%20%20%20PORTS%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NAMES%0A6b0b3c209535%20%20%20%20%20%20%20%20tomcat%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22catalina.sh%20run%22%20%20%205%20seconds%20ago%20%20%20%20%20%20%20Up%204%20seconds%20%20%20%20%20%20%20%200.0.0.0%3A8888-%3E8080%2Ftcp%20%20%20tomcat02%0A%60%60%60%0A%0A%3E%20%E5%9C%A8%E5%90%8E%E9%9D%A2%E5%8A%A0%20ls%20-l%E5%91%BD%E4%BB%A4%E5%90%8E%EF%BC%8C%E6%96%B0%E5%A2%9E%E7%9A%84tomcat03%E5%AE%B9%E5%99%A8%E5%B9%B6%E6%B2%A1%E6%9C%89%E5%90%AF%E5%8A%A8%0A%0A%60%60%60%0A%5Broot%40master%20chris%5D%23%20docker%20run%20-it%20--name%20tomcat03%20-p%208088%3A8080%20%20tomcat%20ls%20-l%0Atotal%20128%0A-rw-r--r--.%201%20root%20root%2018984%20Mar%2030%2010%3A29%20BUILDING.txt%0A-rw-r--r--.%201%20root%20root%20%205587%20Mar%2030%2010%3A29%20CONTRIBUTING.md%0A-rw-r--r--.%201%20root%20root%2057092%20Mar%2030%2010%3A29%20LICENSE%0A-rw-r--r--.%201%20root%20root%20%202333%20Mar%2030%2010%3A29%20NOTICE%0A-rw-r--r--.%201%20root%20root%20%203257%20Mar%2030%2010%3A29%20README.md%0A-rw-r--r--.%201%20root%20root%20%206898%20Mar%2030%2010%3A29%20RELEASE-NOTES%0A-rw-r--r--.%201%20root%20root%2016507%20Mar%2030%2010%3A29%20RUNNING.txt%0Adrwxr-xr-x.%202%20root%20root%20%204096%20Apr%2022%2023%3A10%20bin%0Adrwxr-xr-x.%202%20root%20root%20%20%20238%20Mar%2030%2010%3A29%20conf%0Adrwxr-xr-x.%202%20root%20root%20%204096%20Apr%2022%2023%3A09%20lib%0Adrwxrwxrwx.%202%20root%20root%20%20%20%20%206%20Mar%2030%2010%3A29%20logs%0Adrwxr-xr-x.%202%20root%20root%20%20%20134%20Apr%2022%2023%3A10%20native-jni-lib%0Adrwxrwxrwx.%202%20root%20root%20%20%20%2030%20Apr%2022%2023%3A09%20temp%0Adrwxr-xr-x.%202%20root%20root%20%20%20%20%206%20Apr%2022%2023%3A09%20webapps%0Adrwxr-xr-x.%207%20root%20root%20%20%20%2081%20Mar%2030%2010%3A29%20webapps.dist%0Adrwxrwxrwx.%202%20root%20root%20%20%20%20%206%20Mar%2030%2010%3A29%20work%0A%0A%5Broot%40master%20chris%5D%23%20docker%20ps%20-a%0ACONTAINER%20ID%20%20%20%20%20%20%20%20IMAGE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20COMMAND%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20STATUS%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20PORTS%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NAMES%0A81cbfbd01279%20%20%20%20%20%20%20%20tomcat%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22ls%20-l%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%206%20seconds%20ago%20%20%20%20%20%20%20Exited%20(0)%205%20seconds%20ago%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tomcat03%0A%60%60%60%0A%0A%3E%20%E5%8E%9F%E5%9B%A0%EF%BC%9Atomcat%20dockerfile%20%E6%9C%80%E5%90%8E%E4%B8%80%E8%A1%8C%E7%9A%84CMD%E5%91%BD%E4%BB%A4%E8%A2%AB%20docker%20run%20%E5%90%8E%E9%9D%A2%E7%9A%84%20ls%20-l%20%E6%9B%BF%E6%8D%A2%E6%8E%89%0A%0A%60%60%60%0AEXPOSE%208080%0ACMD%20%5B%22catalina.sh%22%2C%20%22run%22%5D%0A%60%60%60%0A%0A%0A%60%60%60%0A%5Broot%40master%5D%23%20cd%20%2Fmydocker%0A%5Broot%40master%5D%23%20vi%20myip01%0AFROM%20centos%0ARUN%20yum%20-y%20install%20curl%0ACMD%20%5B%22curl%22%2C%22-s%22%2C%22http%3A%2F%2Fwww.ip.cn%22%5D%0A%0A%5Broot%40master%20mydocker%5D%23%20docker%20build%20-f%20myip01%20-t%20myip01%3A1.0%20.%0A%5Broot%40master%20mydocker%5D%23%20docker%20images%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Amyip01%20%20%20%20%20%20%20%20%20%20%20%20%20%201.0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%200ea4cc5030b2%20%20%20%20%20%20%20%207%20seconds%20ago%20%20%20%20%20%20%20243MB%0A%60%60%60%0A%0A%60%60%60%0A%5Broot%40master%5D%23%20cd%20%2Fmydocker%0A%5Broot%40master%5D%23%20vi%20myip02%0AFROM%20centos%0ARUN%20yum%20-y%20install%20curl%0AENTRYPOINT%20%5B%22curl%22%2C%22-s%22%2C%22http%3A%2F%2Fwww.ip.cn%22%5D%0A%0A%5Broot%40master%20mydocker%5D%23%20docker%20build%20-f%20myip02%20-t%20myip02%3A1.0%20.%0ASending%20build%20context%20to%20Docker%20daemon%20%204.096kB%0AStep%201%2F3%20%3A%20FROM%20centos%0A%20---%3E%20300e315adb2f%0AStep%202%2F3%20%3A%20RUN%20yum%20-y%20install%20curl%0A%20---%3E%20Using%20cache%0A%20---%3E%20552703ee39c9%0AStep%203%2F3%20%3A%20ENTRYPOINT%20%5B%22curl%22%2C%22-s%22%2C%22http%3A%2F%2Fwww.ip.cn%22%5D%0A%20---%3E%20Running%20in%200dbc34763358%0ARemoving%20intermediate%20container%200dbc34763358%0A%20---%3E%20a8f738d4a45a%0ASuccessfully%20built%20a8f738d4a45a%0ASuccessfully%20tagged%20myip02%3A1.0%0A%0A%60%60%60%0A%0A%23%23%23%206.5.4%20ONBUILD%0A%0A%0A%60%60%60%0A%5Broot%40master%5D%23%20cd%20%2Fmydocker%0A%5Broot%40master%20mydocker%5D%23%20vi%20myip02_father%0A%0AFROM%20centos%0ARUN%20yum%20-y%20install%20curl%0AENTRYPOINT%20%5B%22curl%22%2C%22-s%22%2C%22cip.cc%22%5D%0AONBUILD%20RUN%20echo%20%22myip02_father%20image%20onbuild-----ok%22%0A%0A%5Broot%40master%20mydocker%5D%23%20docker%20build%20-f%20myip02_father%20-t%20myip02_father%3A1.0%20.%0ASending%20build%20context%20to%20Docker%20daemon%20%20%205.12kB%0AStep%201%2F3%20%3A%20FROM%20centos%0A%20---%3E%20300e315adb2f%0AStep%202%2F3%20%3A%20RUN%20yum%20-y%20install%20curl%0A%20---%3E%20Using%20cache%0A%20---%3E%20552703ee39c9%0AStep%203%2F3%20%3A%20ENTRYPOINT%20%5B%22curl%22%2C%22-s%22%2C%22http%3A%2F%2Fwww.ip.cn%22%5D%0A%20---%3E%20Using%20cache%0A%20---%3E%20a8f738d4a45a%0ASuccessfully%20built%20a8f738d4a45a%0ASuccessfully%20tagged%20myip02_father%3A1.0%0A%5Broot%40master%20mydocker%5D%23%20docker%20images%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Amyip02_father%20%20%20%20%20%20%201.0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a8f738d4a45a%20%20%20%20%20%20%20%203%20minutes%20ago%20%20%20%20%20%20%20243MB%0A%60%60%60%0A%0A%0A%60%60%60%0A%5Broot%40master%5D%23%20cd%20%2Fmydocker%0A%5Broot%40master%20mydocker%5D%23%20vi%20myip02_kid%0AFROM%20myip02_father%3A1.0%0ARUN%20yum%20-y%20install%20curl%0AENTRYPOINT%20%5B%22curl%22%2C%22-s%22%2C%22cip.cc%22%5D%0A%0A%5Broot%40master%20mydocker%5D%23%20docker%20build%20-f%20myip02_kid%20-t%20myip02_kid%3A1.0%20.%0ASending%20build%20context%20to%20Docker%20daemon%20%206.144kB%0AStep%201%2F3%20%3A%20FROM%20myip02_father%3A1.0%0A%23%20Executing%201%20build%20trigger%0A%20---%3E%20Running%20in%2061b5fd1fece7%0Amyip02_father%20image%20onbuild-----ok%0ARemoving%20intermediate%20container%2061b5fd1fece7%0A%20---%3E%204d14bc2d40e8%0AStep%202%2F3%20%3A%20RUN%20yum%20-y%20install%20curl%0A%20---%3E%20Running%20in%20e328e5961d4f%0ALast%20metadata%20expiration%20check%3A%200%3A08%3A57%20ago%20on%20Sun%20May%20%202%2001%3A54%3A21%202021.%0APackage%20curl-7.61.1-14.el8_3.1.x86_64%20is%20already%20installed.%0ADependencies%20resolved.%0ANothing%20to%20do.%0AComplete!%0ARemoving%20intermediate%20container%20e328e5961d4f%0A%20---%3E%20e44a48f55d44%0AStep%203%2F3%20%3A%20ENTRYPOINT%20%5B%22curl%22%2C%22-s%22%2C%22cip.cc%22%5D%0A%20---%3E%20Running%20in%20d5e81a13e501%0ARemoving%20intermediate%20container%20d5e81a13e501%0A%20---%3E%20df8fa730dfe4%0ASuccessfully%20built%20df8fa730dfe4%0ASuccessfully%20tagged%20myip02_kid%3A1.0%0A%0A%60%60%60%0A%0A%23%23%23%206.5.5%20%E8%87%AA%E5%AE%9A%E4%B9%89tomcat9%0A1.%20%E5%88%9B%E5%BB%BA%E7%9B%AE%E5%BD%95%0A%0A%60%60%60%0Amkdir%20-p%20%2Fmydocker%2Fchristomcat9%0A%60%60%60%0A2.%20%E5%88%9B%E5%BB%BA%E6%96%87%E4%BB%B6%0A%60%60%60%0A%5Broot%40master%5D%23%20cd%20%2Fmydocker%2Fchristomcat9%0A%5Broot%40master%20chrisTomcat9%5D%23%20touch%20c.txt%0A%5Broot%40master%20chrisTomcat9%5D%23%20cp%20%2Fopt%2Fjdk-8u191-linux-x64.tar.gz%20.%0A%5Broot%40master%20chrisTomcat9%5D%23%20cp%20%2Fopt%2Fapache-tomcat-9.0.38.tar.gz%20.%0A%5Broot%40master%20chrisTomcat9%5D%23%20touch%20Dockerfile%0A%0AFROM%20%20%20%20%20%20%20%20%20centos%0AMAINTAINER%20%20%20%20chris%3Clilunlogic%40163.com%3E%0A%23%E6%8A%8A%E5%AE%BF%E4%B8%BB%E6%9C%BA%E5%BD%93%E5%89%8D%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84c.txt%E6%8B%B7%E8%B4%9D%E5%88%B0%E5%AE%B9%E5%99%A8%2Fusr%2Flocal%2F%E8%B7%AF%E5%BE%84%E4%B8%8B%0ACOPY%20c.txt%20%2Fusr%2Flocal%2Fcincontainer.txt%0A%23%E6%8A%8Ajava%E4%B8%8Etomcat%E6%B7%BB%E5%8A%A0%E5%88%B0%E5%AE%B9%E5%99%A8%E4%B8%AD%0AADD%20jdk-8u191-linux-x64.tar.gz%20%20%2Fusr%2Flocal%2F%0AADD%20apache-tomcat-9.0.38.tar.gz%20%2Fusr%2Flocal%2F%0A%23%E5%AE%89%E8%A3%85vim%E7%BC%96%E8%BE%91%E5%99%A8%0ARUN%20yum%20-y%20install%20vim%0A%23%E8%AE%BE%E7%BD%AE%E5%B7%A5%E4%BD%9C%E8%AE%BF%E9%97%AE%E6%97%B6%E5%80%99%E7%9A%84WORKDIR%E8%B7%AF%E5%BE%84%EF%BC%8C%E7%99%BB%E5%BD%95%E8%90%BD%E8%84%9A%E7%82%B9%0AENV%20MYPATH%20%2Fusr%2Flocal%0AWORKDIR%20%24MYPATH%0A%23%E9%85%8D%E7%BD%AEjava%E4%B8%8Etomcat%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%0AENV%20JAVA_HOME%20%2Fusr%2Flocal%2Fjdk1.8.0_191%0AENV%20CLASSPATH%20%24JAVA_HOME%2Flib%2Fdt.jar%3A%24JAVA_HOME%2Flib%2Ftools.jar%0AENV%20CATALINA_HOME%20%2Fusr%2Flocal%2Fapache-tomcat-9.0.38%0AENV%20CATALINA_BASE%20%2Fusr%2Flocal%2Fapache-tomcat-9.0.38%0AENV%20PATH%20%24PATH%3A%24JAVA_HOME%2Fbin%3A%24CATALINA_HOME%2Flib%3A%24CATALINA_HOME%2Fbin%0A%23%E5%AE%B9%E5%99%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E7%9B%91%E5%90%AC%E7%9A%84%E7%AB%AF%E5%8F%A3%0AEXPOSE%20%208080%0A%23%E5%90%AF%E5%8A%A8%E6%97%B6%E8%BF%90%E8%A1%8Ctomcat%0A%23%20ENTRYPOINT%20%5B%22%2Fusr%2Flocal%2Fapache-tomcat-9.0.38%2Fbin%2Fstartup.sh%22%20%5D%0A%23%20CMD%20%5B%22%2Fusr%2Flocal%2Fapache-tomcat-9.0.38%2Fbin%2Fcatalina.sh%22%2C%22run%22%5D%0ACMD%20%2Fusr%2Flocal%2Fapache-tomcat-9.0.38%2Fbin%2Fstartup.sh%20%26%26%20tail%20-F%20%2Fusr%2Flocal%2Fapache-tomcat-9.0.38%2Fbin%2Flogs%2Fcatalina.out%0A%60%60%60%0A%0A3.%20%E6%9E%84%E5%BB%BA%0A%0A%60%60%60%0A%5Broot%40master%20chrisTomcat9%5D%23%20docker%20build%20-t%20christomcat9%20.%0A%5Broot%40master%20opt%5D%23%20docker%20images%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Achristomcat9%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20a02261dc7206%20%20%20%20%20%20%20%208%20minutes%20ago%20%20%20%20%20%20%20680MB%0A%0A%60%60%60%0A%0A4.%20%E8%BF%90%E8%A1%8C%0A%0A%60%60%60%0A%5Broot%40master%5D%23%20docker%20run%20-d%20-p%209080%3A8080%20--name%20christomcat9%20-v%20%2Fmydocker%2Ftomcat9%2Ftest%3A%2Fusr%2Flocal%2Fapache-tomcat-9.0.38%2Fwebapps%2Ftest%20-v%20%2Fmydocker%2Ftomcat9%2Ftomcat9logs%2F%3A%2Fusr%2Flocal%2Fapache-tomcat-9.0.38%2Flogs%20--privileged%3Dtrue%20christomcat9%0A%0A%5Broot%40master%5D%23%20docker%20ps%0ACONTAINER%20ID%20%20%20%20%20%20%20%20IMAGE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20COMMAND%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20STATUS%20%20%20%20%20%20%20%20%20%20%20%20%20%20PORTS%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NAMES%0Ab2d9623ad57d%20%20%20%20%20%20%20%20christomcat9%20%20%20%20%20%20%20%20%22%2Fbin%2Fsh%20-c%20'%2Fusr%2Flo%E2%80%A6%22%20%20%207%20seconds%20ago%20%20%20%20%20%20%20Up%206%20seconds%20%20%20%20%20%20%20%200.0.0.0%3A9080-%3E8080%2Ftcp%20%20%20christomcat9%0A%0A%5Broot%40master%5D%23%20docker%20exec%20-it%20christomcat9%20java%20-version%0Ajava%20version%20%221.8.0_191%22%0AJava(TM)%20SE%20Runtime%20Environment%20(build%201.8.0_191-b12)%0AJava%20HotSpot(TM)%2064-Bit%20Server%20VM%20(build%2025.191-b12%2C%20mixed%20mode)%0A%0A%60%60%60%0A%0A%23%23%207%20%E5%B0%86%E9%95%9C%E5%83%8F%E4%B8%8A%E4%BC%A0%E5%88%B0%E9%98%BF%E9%87%8C%E4%BA%91%0A%0A1.%20%E5%88%9B%E5%BB%BA%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%20%20%0A%3E%20https%3A%2F%2Fcr.console.aliyun.com%2Fcn-hangzhou%2Finstance%2Frepositories%20%20%0A%3E%20%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%EF%BC%9Achris0716%20%20%0A%3E%20%E4%BB%93%E5%BA%93%E5%90%8D%E7%A7%B0%EF%BC%9Amydocker%20%20%0A%0A%0A!%5Bimage%5D(7A20D10AB35A41C7A5375D7D460CB036)%0A!%5Bimage%5D(B74671A1C17342BD8896FA1037085AA6)%0A%0A%0A2.%20%E4%B8%8A%E4%BC%A0%E9%95%9C%E5%83%8F%0A%0A%60%60%60%0A%24%20sudo%20docker%20login%20--username%3Dlilunlogic%40163.com%20registry.cn-hangzhou.aliyuncs.com%0A%24%20pwd%3ALilun215%2B%0A%0A%24%20sudo%20docker%20tag%20%5BImageId%5D%20registry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%3A%5B%E9%98%BF%E9%87%8C%E4%BA%91%E4%B8%8A%E6%98%BE%E7%A4%BA%E7%9A%84%E9%95%9C%E5%83%8F%E7%89%88%E6%9C%AC%E5%8F%B7%5D%0A%24%20sudo%20docker%20push%20registry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%3A%5B%E9%98%BF%E9%87%8C%E4%BA%91%E4%B8%8A%E6%98%BE%E7%A4%BA%E7%9A%84%E9%95%9C%E5%83%8F%E7%89%88%E6%9C%AC%E5%8F%B7%5D%0A%60%60%60%0A%0A!%5Bimage%5D(2EBB90A445994282990207541DDAB848)%0A%0A%0A%60%60%60%0A%5Broot%40master%20chris%5D%23%20docker%20images%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Achristomcat9%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20de6f4c6c9bcb%20%20%20%20%20%20%20%2017%20hours%20ago%20%20%20%20%20%20%20%20680MB%0Aregistry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%20%20%201.0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20de6f4c6c9bcb%20%20%20%20%20%20%20%2017%20hours%20ago%20%20%20%20%20%20%20%20680MB%0A%5Broot%40master%20chris%5D%23%20docker%20rmi%20registry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%3A1.0%0AUntagged%3A%20registry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%3A1.0%0AUntagged%3A%20registry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%40sha256%3A9ed6c267619595e22642c02a585bc75600d685cd7d93b4ea5c46c6292b30efd3%0A%5Broot%40master%20chris%5D%23%20docker%20pull%20registry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%3A1.0%0A1.0%3A%20Pulling%20from%20chris0716%2Fmydocker%0ADigest%3A%20sha256%3A9ed6c267619595e22642c02a585bc75600d685cd7d93b4ea5c46c6292b30efd3%0AStatus%3A%20Downloaded%20newer%20image%20for%20registry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%3A1.0%0Aregistry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%3A1.0%0A%5Broot%40master%20chris%5D%23%20docker%20images%0AREPOSITORY%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TAG%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20IMAGE%20ID%20%20%20%20%20%20%20%20%20%20%20%20CREATED%20%20%20%20%20%20%20%20%20%20%20%20%20SIZE%0Achristomcat9%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20latest%20%20%20%20%20%20%20%20%20%20%20%20%20%20de6f4c6c9bcb%20%20%20%20%20%20%20%2017%20hours%20ago%20%20%20%20%20%20%20%20680MB%0Aregistry.cn-hangzhou.aliyuncs.com%2Fchris0716%2Fmydocker%20%20%201.0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20de6f4c6c9bcb%20%20%20%20%20%20%20%2017%20hours%20ago%20%20%20%20%20%20%20%20680MB%0A%0A%60%60%60%0A

位运算

创建时间:2022/11/30 22:53
更新时间:2024/4/9 21:24
作者:Chris

位运算是什么

位运算分为两类 :

逻辑位运算符

位与 &

只有当两个位都是1的时候结果是1否则结果是0

位或 |

只有当两个位都是0的时候结果才是0,否则结果为1

异或 ^

只有当两个位不同的时候结果才是1.否则结果为0

接位取反 ~

是一个一元运算符,就是把当前数转为二进制后0变1,1变0

位移运算符

左移 <<

i/ 2的n次方

@Test
public void leftShift() {
    int i = 3;
    System.out.println(i << 1);
    System.out.println(i << 2);
    System.out.println(i << 3);
}

右移 >>

如果i是正数则 i / 2的n次方并向下取整

-8
-4
-2
-1
-1

@Test
public void rightShift() {
    int i = -16;
    System.out.println(i >> 1);
    System.out.println(i >> 2);
    System.out.println(i >> 3);
    System.out.println(i >> 4);
    System.out.println(i >> 5);
}
%5Btoc%5D%0A%0A%23%23%20%E4%BD%8D%E8%BF%90%E7%AE%97%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20%E4%BD%8D%E8%BF%90%E7%AE%97%E5%88%86%E4%B8%BA%E4%B8%A4%E7%B1%BB%20%3A%20%0A-%20%E9%80%BB%E8%BE%91%E4%BD%8D%E8%BF%90%E7%AE%97%E7%AC%A6%0A-%20%E4%BD%8D%E7%A7%BB%E8%BF%90%E7%AE%97%E7%AC%A6%0A%0A%23%23%20%E9%80%BB%E8%BE%91%E4%BD%8D%E8%BF%90%E7%AE%97%E7%AC%A6%0A%23%23%23%20%E4%BD%8D%E4%B8%8E%20%26%20%20%0A%3E%20%E5%8F%AA%E6%9C%89%E5%BD%93%E4%B8%A4%E4%B8%AA%E4%BD%8D%E9%83%BD%E6%98%AF1%E7%9A%84%E6%97%B6%E5%80%99%E7%BB%93%E6%9E%9C%E6%98%AF1%E5%90%A6%E5%88%99%E7%BB%93%E6%9E%9C%E6%98%AF0%0A%0A!%5Bef35b61080e367151ad4e93639929247.png%5D(en-resource%3A%2F%2Fdatabase%2F613%3A1)%0A%0A%0A%23%23%23%20%E4%BD%8D%E6%88%96%20%7C%20%0A%3E%20%E5%8F%AA%E6%9C%89%E5%BD%93%E4%B8%A4%E4%B8%AA%E4%BD%8D%E9%83%BD%E6%98%AF0%E7%9A%84%E6%97%B6%E5%80%99%E7%BB%93%E6%9E%9C%E6%89%8D%E6%98%AF0%EF%BC%8C%E5%90%A6%E5%88%99%E7%BB%93%E6%9E%9C%E4%B8%BA1%0A%0A!%5Bdf7bd0e705e693646841339d41cca500.png%5D(en-resource%3A%2F%2Fdatabase%2F614%3A1)%0A%0A%23%23%23%20%E5%BC%82%E6%88%96%20%5E%20%0A%3E%20%E5%8F%AA%E6%9C%89%E5%BD%93%E4%B8%A4%E4%B8%AA%E4%BD%8D%E4%B8%8D%E5%90%8C%E7%9A%84%E6%97%B6%E5%80%99%E7%BB%93%E6%9E%9C%E6%89%8D%E6%98%AF1.%E5%90%A6%E5%88%99%E7%BB%93%E6%9E%9C%E4%B8%BA0%0A%0A!%5B5447ed5f4f635de9f89248a536453b9d.png%5D(en-resource%3A%2F%2Fdatabase%2F615%3A1)%0A%0A%0A%23%23%23%20%E6%8E%A5%E4%BD%8D%E5%8F%96%E5%8F%8D%20~%0A%3E%20%E6%98%AF%E4%B8%80%E4%B8%AA%E4%B8%80%E5%85%83%E8%BF%90%E7%AE%97%E7%AC%A6%EF%BC%8C%E5%B0%B1%E6%98%AF%E6%8A%8A%E5%BD%93%E5%89%8D%E6%95%B0%E8%BD%AC%E4%B8%BA%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%90%8E0%E5%8F%981%EF%BC%8C1%E5%8F%980%0A%0A!%5Bca0462314f4e4d9fda58e3cbf472cfe2.png%5D(en-resource%3A%2F%2Fdatabase%2F616%3A1)%0A%0A%0A%23%23%20%E4%BD%8D%E7%A7%BB%E8%BF%90%E7%AE%97%E7%AC%A6%0A%0A%23%23%23%20%E5%B7%A6%E7%A7%BB%20%3C%3C%0A%3E%20i%2F%202%E7%9A%84n%E6%AC%A1%E6%96%B9%0A%60%60%60java%0A%40Test%0Apublic%20void%20leftShift()%20%7B%0A%20%20%20%20int%20i%20%3D%203%3B%0A%20%20%20%20System.out.println(i%20%3C%3C%201)%3B%0A%20%20%20%20System.out.println(i%20%3C%3C%202)%3B%0A%20%20%20%20System.out.println(i%20%3C%3C%203)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%E5%8F%B3%E7%A7%BB%20%3E%3E%0A%3E%E5%A6%82%E6%9E%9Ci%E6%98%AF%E6%AD%A3%E6%95%B0%E5%88%99%20i%20%2F%202%E7%9A%84n%E6%AC%A1%E6%96%B9%E5%B9%B6%E5%90%91%E4%B8%8B%E5%8F%96%E6%95%B4%0A%3E%0A%3E-8%0A%3E-4%0A%3E-2%0A%3E-1%0A%3E-1%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20rightShift()%20%7B%0A%20%20%20%20int%20i%20%3D%20-16%3B%0A%20%20%20%20System.out.println(i%20%3E%3E%201)%3B%0A%20%20%20%20System.out.println(i%20%3E%3E%202)%3B%0A%20%20%20%20System.out.println(i%20%3E%3E%203)%3B%0A%20%20%20%20System.out.println(i%20%3E%3E%204)%3B%0A%20%20%20%20System.out.println(i%20%3E%3E%205)%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A

mysql 8.0.27 安装

创建时间:2022/3/4 20:00
更新时间:2024/3/24 20:09
作者:Chris

1 下载

1.1 查看操作系统内核版本信息

[root@master chris]# uname -a
Linux master 3.10.0-1127.el7.x86_64 #1 SMP Tue Mar 31 23:36:51 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

1.2 下载 RPM Bundle安装文件

https://downloads.mysql.com/archives/community/

下载后的压缩文件为
mysql-8.0.27-1.el7.x86_64.rpm-bundle.tar

tar xvf mysql-8.0.27-1.el7.x86_64.rpm-bundle.tar

mysql-community-client-8.0.27-1.el7.x86_64.rpm
mysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm
mysql-community-common-8.0.27-1.el7.x86_64.rpm
mysql-community-devel-8.0.27-1.el7.x86_64.rpm
mysql-community-embedded-compat-8.0.27-1.el7.x86_64.rpm
mysql-community-libs-8.0.27-1.el7.x86_64.rpm
mysql-community-libs-compat-8.0.27-1.el7.x86_64.rpm
mysql-community-server-8.0.27-1.el7.x86_64.rpm
mysql-community-test-8.0.27-1.el7.x86_64.rpm

只需要安装下面这几个文件

mysql-community-client-8.0.27-1.el7.x86_64.rpm
mysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm
mysql-community-common-8.0.27-1.el7.x86_64.rpm
mysql-community-libs-8.0.27-1.el7.x86_64.rpm
mysql-community-server-8.0.27-1.el7.x86_64.rpm

1.3 检查是否已经安装过mysql

执行命令

[root@localhost /]# rpm -qa | grep mysql
[root@localhost /]# rpm -qa | grep -i MariaDB

从执行结果,可以看出我们已经安装了mysql-libs-5.1.73-5.el6_6.x86_64,执行删除命令

[root@localhost /]# rpm -e --nodeps mysql-libs-5.1.73-5.el6_6.x86_64

2 安装

2.1 检查/tmp目录权限

由于mysql安装过程中会通过/tmp目录创建临时文件tmp_db,所以需要给/tmp赋予较大权限

chmod -R 777 /tmp

2.2 安装前检查依赖

[root@master /]# rpm -qa | grep libaio
libaio-0.3.109-13.el7.x86_64

[root@master /]# rpm -qa | grep net-tools
net-tools-2.0-0.25.20131004git.el7.x86_64

2.3 检查mysql用户组和用户

检查mysql用户组和用户是否存在,如果没有,则创建

[root@localhost /]# cat /etc/group | grep mysql
[root@localhost /]# cat /etc/passwd |grep mysql
[root@localhost /]# groupadd mysql
[root@localhost /]# useradd -m -d /home/mysql -s /bin/bash -g mysql mysql

2.4 按顺序安装

安装过程中必须严格按照如下顺序进行

rpm -ivh mysql-community-common-8.0.27-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm
rpm -ivh mysql-community-libs-8.0.27-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-8.0.27-1.el7.x86_64.rpm
rpm -ivh mysql-community-server-8.0.27-1.el7.x86_64.rpm
[root@master mysql]# rpm -ivh mysql-community-common-8.0.27-1.el7.x86_64.rpm
warning: mysql-community-common-8.0.27-1.el7.x86_64.rpm: Header V3 DSA/SHA256 Signature, key ID 5072e1f5: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:mysql-community-common-8.0.27-1.e################################# [100%]
[root@master mysql]# rpm -ivh mysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm
warning: mysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm: Header V3 DSA/SHA256 Signature, key ID 5072e1f5: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:mysql-community-client-plugins-8.################################# [100%]
[root@master mysql]# rpm -ivh mysql-community-libs-8.0.27-1.el7.x86_64.rpm
warning: mysql-community-libs-8.0.27-1.el7.x86_64.rpm: Header V3 DSA/SHA256 Signature, key ID 5072e1f5: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:mysql-community-libs-8.0.27-1.el7################################# [100%]
[root@master mysql]# rpm -ivh mysql-community-client-8.0.27-1.el7.x86_64.rpm
warning: mysql-community-client-8.0.27-1.el7.x86_64.rpm: Header V3 DSA/SHA256 Signature, key ID 5072e1f5: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:mysql-community-client-8.0.27-1.e################################# [100%]
[root@master mysql]# rpm -ivh mysql-community-server-8.0.27-1.el7.x86_64.rpm
warning: mysql-community-server-8.0.27-1.el7.x86_64.rpm: Header V3 DSA/SHA256 Signature, key ID 5072e1f5: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:mysql-community-server-8.0.27-1.e################################# [100%]

2.5 检查是否安装成功

[root@master mysql]# mysql --version
mysql  Ver 8.0.27 for Linux on x86_64 (MySQL Community Server - GPL)

[root@master mysql]# rpm -qa | grep -i mysql
mysql-community-server-8.0.27-1.el7.x86_64
mysql-community-client-plugins-8.0.27-1.el7.x86_64
mysql-community-libs-8.0.27-1.el7.x86_64
mysql-community-client-8.0.27-1.el7.x86_64
mysql-community-common-8.0.27-1.el7.x86_64

[root@master mysql]# systemctl status mysqld
● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
[root@master mysql]# systemctl start mysqld
[root@master mysql]# systemctl status mysqld
● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2022-03-04 21:18:55 CST; 4s ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 3374 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
 Main PID: 3457 (mysqld)
   Status: "Server is operational"
    Tasks: 38
   CGroup: /system.slice/mysqld.service
           └─3457 /usr/sbin/mysqld

Mar 04 21:18:48 master systemd[1]: Starting MySQL Server...
Mar 04 21:18:55 master systemd[1]: Started MySQL Server.

2.6 安装问题解决

问题1.

解决办法:
yum remove mysql-libs 清除之前安装过的依赖即可,清除过程中遇到是否继续选择 y

3 启动mysql

3.1 手动启动mysql

[root@master mysql]# systemctl status mysqld
● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
[root@master mysql]# systemctl start mysqld
[root@master mysql]# systemctl status mysqld
● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2022-03-04 21:18:55 CST; 4s ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 3374 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
 Main PID: 3457 (mysqld)
   Status: "Server is operational"
    Tasks: 38
   CGroup: /system.slice/mysqld.service
           └─3457 /usr/sbin/mysqld

Mar 04 21:18:48 master systemd[1]: Starting MySQL Server...
Mar 04 21:18:55 master systemd[1]: Started MySQL Server.

3.2 将mysqld服务加入开机自启动

[root@master system]# pwd
/usr/lib/systemd/system
[root@master system]# ll | grep mysql
-rw-r--r--. 1 root root 2034 Sep 28 22:07 mysqld.service
-rw-r--r--. 1 root root 2065 Sep 28 22:07 mysqld@.service

[root@master mysql]# systemctl enable mysqld
[root@master mysql]# systemctl is-enabled mysqld
enabled

[root@master mysql]# systemctl list-units | grep mysql
mysqld.service                                                                                             loaded active running   MySQL Server
[root@master mysql]# systemctl list-unit-files | grep mysql
mysqld.service                                  enabled 
mysqld@.service                               disabled

4 服务初始化

为了保证目录与文件的所有者为mysql登录用户,如果你是以root身份运行mysql服务需要执行下面命令进行初始化

mysqld --initialize --user=mysql

--initialize 默认是以安全模式来初始化,则会为root用户生成一个密码标记为过期,登录后你需要设置一个新的密码,生成的临时密码会在日志中记录一份

cat /var/log/mysqld.log

2022-04-03T01:42:48.981139Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: kghUF<wCM4U5

5 登录后修改密码

如果登录后不修改密码会提示

ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

修改密码时遇到问题:

mysql> alter user 'root'@'localhost' identified by '65536' ;
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

解决办法:

mysql> set global validate_password.policy=0;
mysql> set global validate_password.length=5;
mysql> alter user 'root'@'localhost' identified by '65536' ;
Query OK, 0 rows affected (0.01 sec)
mysql> show variables like 'validate_password%';

mysql> quit
Bye
[root@master mysql]# mysql -uroot -p
Enter password:  此处用新密码登录

密码policy对照表

6 远程连接

宿主机host文件

C:\Windows\System32\drivers\etc\hosts
192.168.101.127 master

问题1:

解决步骤

  1. 查看宿主机到master的连通性
C:\Users\Dell>ping master
C:\Users\Dell>telnet master 3066

如果连通性有问题需要关闭宿主机的firewall

  1. 查看mysql中的用户是否只允许本地访问
mysql> select host , user from mysql.user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| localhost | mysql.infoschema |
| localhost | mysql.session      |
| localhost | mysql.sys             |
| localhost | root                      |
+-----------+------------------+
4 rows in set (0.00 sec)

mysql> update mysql.user set host='%' where user='root';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> select host , user from mysql.user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| %         | root             |
| localhost | mysql.infoschema |
| localhost | mysql.session    |
| localhost | mysql.sys        |
+-----------+------------------+
4 rows in set (0.00 sec)

mysql>flush privileges; //刷新系统权限表

host='%' 表示允许所有客户端访问,
也可以改为 host='192.168.101.%' 表示只允许101这个网段的客户端访问

问题2:
错误号码 2058,分析是 mysql 密码加密方法变了

解决方法:

Linux下 mysql -u root -p 登录你的 mysql 数据库,然后 执行这条SQL:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'abc123';

7 新增用户

7.1 创建用户

create user chris identified by '65536';

7.2 赋权

with grant option : 表示允许用户将自己的权限授权给其它用户

grant all privileges on *.* to 'chris'@'%';
grant all privileges on *.* to 'chris'@'%' with grant option;






grant all privileges on schema-name.* to chris'@'%' identified by '65536';
grant all privileges on schema-name.* to chris@% identified by '65536' with grant option;
grant select,update,delete,insert privileges on schema-name.* to chris@'%' identified by '65536';
%5Btoc%5D%0A%0A%23%23%201%20%E4%B8%8B%E8%BD%BD%0A%0A%23%23%23%23%201.1%20%E6%9F%A5%E7%9C%8B%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%86%85%E6%A0%B8%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF%0A%60%60%60%0A%5Broot%40master%20chris%5D%23%20uname%20-a%0ALinux%20master%203.10.0-1127.el7.x86_64%20%231%20SMP%20Tue%20Mar%2031%2023%3A36%3A51%20UTC%202020%20x86_64%20x86_64%20x86_64%20GNU%2FLinux%0A%60%60%60%0A%0A%23%23%23%23%201.2%20%E4%B8%8B%E8%BD%BD%20RPM%20Bundle%E5%AE%89%E8%A3%85%E6%96%87%E4%BB%B6%0A%0Ahttps%3A%2F%2Fdownloads.mysql.com%2Farchives%2Fcommunity%2F%0A!%5B8de2eab85fdd2a9f553c6a93706eb80d.png%5D(en-resource%3A%2F%2Fdatabase%2F618%3A1)%0A%0A%E4%B8%8B%E8%BD%BD%E5%90%8E%E7%9A%84%E5%8E%8B%E7%BC%A9%E6%96%87%E4%BB%B6%E4%B8%BA%0Amysql-8.0.27-1.el7.x86_64.rpm-bundle.tar%0A%0A%60%60%60%0Atar%20xvf%20mysql-8.0.27-1.el7.x86_64.rpm-bundle.tar%0A%60%60%60%0A%0A%3E%20mysql-community-client-8.0.27-1.el7.x86_64.rpm%0Amysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm%0Amysql-community-common-8.0.27-1.el7.x86_64.rpm%0Amysql-community-devel-8.0.27-1.el7.x86_64.rpm%0Amysql-community-embedded-compat-8.0.27-1.el7.x86_64.rpm%0Amysql-community-libs-8.0.27-1.el7.x86_64.rpm%0Amysql-community-libs-compat-8.0.27-1.el7.x86_64.rpm%0Amysql-community-server-8.0.27-1.el7.x86_64.rpm%0Amysql-community-test-8.0.27-1.el7.x86_64.rpm%0A%0A%E5%8F%AA%E9%9C%80%E8%A6%81%E5%AE%89%E8%A3%85%E4%B8%8B%E9%9D%A2%E8%BF%99%E5%87%A0%E4%B8%AA%E6%96%87%E4%BB%B6%0A%3E%20mysql-community-client-8.0.27-1.el7.x86_64.rpm%0Amysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm%0Amysql-community-common-8.0.27-1.el7.x86_64.rpm%0Amysql-community-libs-8.0.27-1.el7.x86_64.rpm%0Amysql-community-server-8.0.27-1.el7.x86_64.rpm%0A%0A%23%23%23%23%201.3%20%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%B7%B2%E7%BB%8F%E5%AE%89%E8%A3%85%E8%BF%87mysql%0A%0A%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%0A%0A%60%60%60shell%0A%5Broot%40localhost%20%2F%5D%23%20rpm%20-qa%20%7C%20grep%20mysql%0A%5Broot%40localhost%20%2F%5D%23%20rpm%20-qa%20%7C%20grep%20-i%20MariaDB%0A%60%60%60%0A%0A%E4%BB%8E%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BA%E6%88%91%E4%BB%AC%E5%B7%B2%E7%BB%8F%E5%AE%89%E8%A3%85%E4%BA%86mysql-libs-5.1.73-5.el6_6.x86_64%EF%BC%8C%E6%89%A7%E8%A1%8C%E5%88%A0%E9%99%A4%E5%91%BD%E4%BB%A4%0A%60%60%60%0A%5Broot%40localhost%20%2F%5D%23%20rpm%20-e%20--nodeps%20mysql-libs-5.1.73-5.el6_6.x86_64%0A%60%60%60%0A%0A%0A%23%23%202%20%E5%AE%89%E8%A3%85%0A%0A%23%23%23%23%202.1%20%E6%A3%80%E6%9F%A5%2Ftmp%E7%9B%AE%E5%BD%95%E6%9D%83%E9%99%90%0A%3E%20%E7%94%B1%E4%BA%8Emysql%E5%AE%89%E8%A3%85%E8%BF%87%E7%A8%8B%E4%B8%AD%E4%BC%9A%E9%80%9A%E8%BF%87%2Ftmp%E7%9B%AE%E5%BD%95%E5%88%9B%E5%BB%BA%E4%B8%B4%E6%97%B6%E6%96%87%E4%BB%B6tmp_db%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E7%BB%99%2Ftmp%E8%B5%8B%E4%BA%88%E8%BE%83%E5%A4%A7%E6%9D%83%E9%99%90%0A%60%60%60%0Achmod%20-R%20777%20%2Ftmp%0A%60%60%60%0A%0A%23%23%23%23%202.2%20%E5%AE%89%E8%A3%85%E5%89%8D%E6%A3%80%E6%9F%A5%E4%BE%9D%E8%B5%96%0A%60%60%60%0A%5Broot%40master%20%2F%5D%23%20rpm%20-qa%20%7C%20grep%20libaio%0Alibaio-0.3.109-13.el7.x86_64%0A%0A%5Broot%40master%20%2F%5D%23%20rpm%20-qa%20%7C%20grep%20net-tools%0Anet-tools-2.0-0.25.20131004git.el7.x86_64%0A%60%60%60%0A%0A%23%23%23%23%202.3%20%E6%A3%80%E6%9F%A5mysql%E7%94%A8%E6%88%B7%E7%BB%84%E5%92%8C%E7%94%A8%E6%88%B7%0A%3E%20%E6%A3%80%E6%9F%A5mysql%E7%94%A8%E6%88%B7%E7%BB%84%E5%92%8C%E7%94%A8%E6%88%B7%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%EF%BC%8C%E5%88%99%E5%88%9B%E5%BB%BA%0A%60%60%60%0A%5Broot%40localhost%20%2F%5D%23%20cat%20%2Fetc%2Fgroup%20%7C%20grep%20mysql%0A%5Broot%40localhost%20%2F%5D%23%20cat%20%2Fetc%2Fpasswd%20%7Cgrep%20mysql%0A%5Broot%40localhost%20%2F%5D%23%20groupadd%20mysql%0A%5Broot%40localhost%20%2F%5D%23%20useradd%20-m%20-d%20%2Fhome%2Fmysql%20-s%20%2Fbin%2Fbash%20-g%20mysql%20mysql%0A%60%60%60%0A%0A%23%23%23%23%202.4%20%E6%8C%89%E9%A1%BA%E5%BA%8F%E5%AE%89%E8%A3%85%0A%E5%AE%89%E8%A3%85%E8%BF%87%E7%A8%8B%E4%B8%AD%E5%BF%85%E9%A1%BB%E4%B8%A5%E6%A0%BC%E6%8C%89%E7%85%A7%E5%A6%82%E4%B8%8B%E9%A1%BA%E5%BA%8F%E8%BF%9B%E8%A1%8C%0A%60%60%60%0Arpm%20-ivh%20mysql-community-common-8.0.27-1.el7.x86_64.rpm%0Arpm%20-ivh%20mysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm%0Arpm%20-ivh%20mysql-community-libs-8.0.27-1.el7.x86_64.rpm%0Arpm%20-ivh%20mysql-community-client-8.0.27-1.el7.x86_64.rpm%0Arpm%20-ivh%20mysql-community-server-8.0.27-1.el7.x86_64.rpm%0A%60%60%60%0A%0A%60%60%60shell%0A%5Broot%40master%20mysql%5D%23%20rpm%20-ivh%20mysql-community-common-8.0.27-1.el7.x86_64.rpm%0Awarning%3A%20mysql-community-common-8.0.27-1.el7.x86_64.rpm%3A%20Header%20V3%20DSA%2FSHA256%20Signature%2C%20key%20ID%205072e1f5%3A%20NOKEY%0APreparing...%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0AUpdating%20%2F%20installing...%0A%20%20%201%3Amysql-community-common-8.0.27-1.e%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0A%5Broot%40master%20mysql%5D%23%20rpm%20-ivh%20mysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm%0Awarning%3A%20mysql-community-client-plugins-8.0.27-1.el7.x86_64.rpm%3A%20Header%20V3%20DSA%2FSHA256%20Signature%2C%20key%20ID%205072e1f5%3A%20NOKEY%0APreparing...%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0AUpdating%20%2F%20installing...%0A%20%20%201%3Amysql-community-client-plugins-8.%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0A%5Broot%40master%20mysql%5D%23%20rpm%20-ivh%20mysql-community-libs-8.0.27-1.el7.x86_64.rpm%0Awarning%3A%20mysql-community-libs-8.0.27-1.el7.x86_64.rpm%3A%20Header%20V3%20DSA%2FSHA256%20Signature%2C%20key%20ID%205072e1f5%3A%20NOKEY%0APreparing...%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0AUpdating%20%2F%20installing...%0A%20%20%201%3Amysql-community-libs-8.0.27-1.el7%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0A%5Broot%40master%20mysql%5D%23%20rpm%20-ivh%20mysql-community-client-8.0.27-1.el7.x86_64.rpm%0Awarning%3A%20mysql-community-client-8.0.27-1.el7.x86_64.rpm%3A%20Header%20V3%20DSA%2FSHA256%20Signature%2C%20key%20ID%205072e1f5%3A%20NOKEY%0APreparing...%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0AUpdating%20%2F%20installing...%0A%20%20%201%3Amysql-community-client-8.0.27-1.e%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0A%5Broot%40master%20mysql%5D%23%20rpm%20-ivh%20mysql-community-server-8.0.27-1.el7.x86_64.rpm%0Awarning%3A%20mysql-community-server-8.0.27-1.el7.x86_64.rpm%3A%20Header%20V3%20DSA%2FSHA256%20Signature%2C%20key%20ID%205072e1f5%3A%20NOKEY%0APreparing...%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0AUpdating%20%2F%20installing...%0A%20%20%201%3Amysql-community-server-8.0.27-1.e%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20%5B100%25%5D%0A%60%60%60%0A%23%23%23%23%202.5%20%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%AE%89%E8%A3%85%E6%88%90%E5%8A%9F%0A%0A%60%60%60shell%0A%5Broot%40master%20mysql%5D%23%20mysql%20--version%0Amysql%20%20Ver%208.0.27%20for%20Linux%20on%20x86_64%20(MySQL%20Community%20Server%20-%20GPL)%0A%0A%5Broot%40master%20mysql%5D%23%20rpm%20-qa%20%7C%20grep%20-i%20mysql%0Amysql-community-server-8.0.27-1.el7.x86_64%0Amysql-community-client-plugins-8.0.27-1.el7.x86_64%0Amysql-community-libs-8.0.27-1.el7.x86_64%0Amysql-community-client-8.0.27-1.el7.x86_64%0Amysql-community-common-8.0.27-1.el7.x86_64%0A%0A%5Broot%40master%20mysql%5D%23%20systemctl%20status%20mysqld%0A%E2%97%8F%20mysqld.service%20-%20MySQL%20Server%0A%20%20%20Loaded%3A%20loaded%20(%2Fusr%2Flib%2Fsystemd%2Fsystem%2Fmysqld.service%3B%20enabled%3B%20vendor%20preset%3A%20disabled)%0A%20%20%20Active%3A%20inactive%20(dead)%0A%20%20%20%20%20Docs%3A%20man%3Amysqld(8)%0A%20%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2Fen%2Fusing-systemd.html%0A%5Broot%40master%20mysql%5D%23%20systemctl%20start%20mysqld%0A%5Broot%40master%20mysql%5D%23%20systemctl%20status%20mysqld%0A%E2%97%8F%20mysqld.service%20-%20MySQL%20Server%0A%20%20%20Loaded%3A%20loaded%20(%2Fusr%2Flib%2Fsystemd%2Fsystem%2Fmysqld.service%3B%20enabled%3B%20vendor%20preset%3A%20disabled)%0A%20%20%20Active%3A%20active%20(running)%20since%20Fri%202022-03-04%2021%3A18%3A55%20CST%3B%204s%20ago%0A%20%20%20%20%20Docs%3A%20man%3Amysqld(8)%0A%20%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2Fen%2Fusing-systemd.html%0A%20%20Process%3A%203374%20ExecStartPre%3D%2Fusr%2Fbin%2Fmysqld_pre_systemd%20(code%3Dexited%2C%20status%3D0%2FSUCCESS)%0A%20Main%20PID%3A%203457%20(mysqld)%0A%20%20%20Status%3A%20%22Server%20is%20operational%22%0A%20%20%20%20Tasks%3A%2038%0A%20%20%20CGroup%3A%20%2Fsystem.slice%2Fmysqld.service%0A%20%20%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%803457%20%2Fusr%2Fsbin%2Fmysqld%0A%0AMar%2004%2021%3A18%3A48%20master%20systemd%5B1%5D%3A%20Starting%20MySQL%20Server...%0AMar%2004%2021%3A18%3A55%20master%20systemd%5B1%5D%3A%20Started%20MySQL%20Server.%0A%60%60%60%0A%0A%23%23%23%23%202.6%20%E5%AE%89%E8%A3%85%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3%0A%E9%97%AE%E9%A2%981.%0A!%5Bb0a666037f82d68f03895c706066e284.png%5D(en-resource%3A%2F%2Fdatabase%2F619%3A1)%0A%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%EF%BC%9A%0A%60yum%20remove%20mysql-libs%60%20%E6%B8%85%E9%99%A4%E4%B9%8B%E5%89%8D%E5%AE%89%E8%A3%85%E8%BF%87%E7%9A%84%E4%BE%9D%E8%B5%96%E5%8D%B3%E5%8F%AF%EF%BC%8C%E6%B8%85%E9%99%A4%E8%BF%87%E7%A8%8B%E4%B8%AD%E9%81%87%E5%88%B0%E6%98%AF%E5%90%A6%E7%BB%A7%E7%BB%AD%E9%80%89%E6%8B%A9%20%60y%60%20%20%0A%0A%0A%23%23%203%20%E5%90%AF%E5%8A%A8mysql%0A%23%23%23%23%203.1%20%E6%89%8B%E5%8A%A8%E5%90%AF%E5%8A%A8mysql%0A%60%60%60%0A%5Broot%40master%20mysql%5D%23%20systemctl%20status%20mysqld%0A%E2%97%8F%20mysqld.service%20-%20MySQL%20Server%0A%20%20%20Loaded%3A%20loaded%20(%2Fusr%2Flib%2Fsystemd%2Fsystem%2Fmysqld.service%3B%20enabled%3B%20vendor%20preset%3A%20disabled)%0A%20%20%20Active%3A%20inactive%20(dead)%0A%20%20%20%20%20Docs%3A%20man%3Amysqld(8)%0A%20%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2Fen%2Fusing-systemd.html%0A%5Broot%40master%20mysql%5D%23%20systemctl%20start%20mysqld%0A%5Broot%40master%20mysql%5D%23%20systemctl%20status%20mysqld%0A%E2%97%8F%20mysqld.service%20-%20MySQL%20Server%0A%20%20%20Loaded%3A%20loaded%20(%2Fusr%2Flib%2Fsystemd%2Fsystem%2Fmysqld.service%3B%20enabled%3B%20vendor%20preset%3A%20disabled)%0A%20%20%20Active%3A%20active%20(running)%20since%20Fri%202022-03-04%2021%3A18%3A55%20CST%3B%204s%20ago%0A%20%20%20%20%20Docs%3A%20man%3Amysqld(8)%0A%20%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2Fen%2Fusing-systemd.html%0A%20%20Process%3A%203374%20ExecStartPre%3D%2Fusr%2Fbin%2Fmysqld_pre_systemd%20(code%3Dexited%2C%20status%3D0%2FSUCCESS)%0A%20Main%20PID%3A%203457%20(mysqld)%0A%20%20%20Status%3A%20%22Server%20is%20operational%22%0A%20%20%20%20Tasks%3A%2038%0A%20%20%20CGroup%3A%20%2Fsystem.slice%2Fmysqld.service%0A%20%20%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%803457%20%2Fusr%2Fsbin%2Fmysqld%0A%0AMar%2004%2021%3A18%3A48%20master%20systemd%5B1%5D%3A%20Starting%20MySQL%20Server...%0AMar%2004%2021%3A18%3A55%20master%20systemd%5B1%5D%3A%20Started%20MySQL%20Server.%0A%60%60%60%0A%0A%23%23%23%23%203.2%20%E5%B0%86mysqld%E6%9C%8D%E5%8A%A1%E5%8A%A0%E5%85%A5%E5%BC%80%E6%9C%BA%E8%87%AA%E5%90%AF%E5%8A%A8%0A%60%60%60%0A%5Broot%40master%20system%5D%23%20pwd%0A%2Fusr%2Flib%2Fsystemd%2Fsystem%0A%5Broot%40master%20system%5D%23%20ll%20%7C%20grep%20mysql%0A-rw-r--r--.%201%20root%20root%202034%20Sep%2028%2022%3A07%20mysqld.service%0A-rw-r--r--.%201%20root%20root%202065%20Sep%2028%2022%3A07%20mysqld%40.service%0A%0A%5Broot%40master%20mysql%5D%23%20systemctl%20enable%20mysqld%0A%5Broot%40master%20mysql%5D%23%20systemctl%20is-enabled%20mysqld%0Aenabled%0A%0A%5Broot%40master%20mysql%5D%23%20systemctl%20list-units%20%7C%20grep%20mysql%0Amysqld.service%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loaded%20active%20running%20%20%20MySQL%20Server%0A%5Broot%40master%20mysql%5D%23%20systemctl%20list-unit-files%20%7C%20grep%20mysql%0Amysqld.service%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enabled%20%0Amysqld%40.service%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20disabled%0A%0A%60%60%60%0A%0A%23%23%204%20%E6%9C%8D%E5%8A%A1%E5%88%9D%E5%A7%8B%E5%8C%96%0A%3E%20%E4%B8%BA%E4%BA%86%E4%BF%9D%E8%AF%81%E7%9B%AE%E5%BD%95%E4%B8%8E%E6%96%87%E4%BB%B6%E7%9A%84%E6%89%80%E6%9C%89%E8%80%85%E4%B8%BAmysql%E7%99%BB%E5%BD%95%E7%94%A8%E6%88%B7%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%BD%A0%E6%98%AF%E4%BB%A5root%E8%BA%AB%E4%BB%BD%E8%BF%90%E8%A1%8Cmysql%E6%9C%8D%E5%8A%A1%E9%9C%80%E8%A6%81%E6%89%A7%E8%A1%8C%E4%B8%8B%E9%9D%A2%E5%91%BD%E4%BB%A4%E8%BF%9B%E8%A1%8C%E5%88%9D%E5%A7%8B%E5%8C%96%0A%60%60%60%0Amysqld%20--initialize%20--user%3Dmysql%0A%60%60%60%0A%3E%20%60--initialize%60%20%20%E9%BB%98%E8%AE%A4%E6%98%AF%E4%BB%A5%E5%AE%89%E5%85%A8%E6%A8%A1%E5%BC%8F%E6%9D%A5%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%E5%88%99%E4%BC%9A%E4%B8%BAroot%E7%94%A8%E6%88%B7%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E5%AF%86%E7%A0%81%E6%A0%87%E8%AE%B0%E4%B8%BA%E8%BF%87%E6%9C%9F%EF%BC%8C%E7%99%BB%E5%BD%95%E5%90%8E%E4%BD%A0%E9%9C%80%E8%A6%81%E8%AE%BE%E7%BD%AE%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E5%AF%86%E7%A0%81%EF%BC%8C%E7%94%9F%E6%88%90%E7%9A%84%E4%B8%B4%E6%97%B6%E5%AF%86%E7%A0%81%E4%BC%9A%E5%9C%A8%E6%97%A5%E5%BF%97%E4%B8%AD%E8%AE%B0%E5%BD%95%E4%B8%80%E4%BB%BD%0A%60%60%60%0Acat%20%2Fvar%2Flog%2Fmysqld.log%0A%0A2022-04-03T01%3A42%3A48.981139Z%206%20%5BNote%5D%20%5BMY-010454%5D%20%5BServer%5D%20A%20temporary%20password%20is%20generated%20for%20root%40localhost%3A%20kghUF%3CwCM4U5%0A%60%60%60%0A%0A%23%23%205%20%E7%99%BB%E5%BD%95%E5%90%8E%E4%BF%AE%E6%94%B9%E5%AF%86%E7%A0%81%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E7%99%BB%E5%BD%95%E5%90%8E%E4%B8%8D%E4%BF%AE%E6%94%B9%E5%AF%86%E7%A0%81%E4%BC%9A%E6%8F%90%E7%A4%BA%0A%60%60%60%0AERROR%201820%20(HY000)%3A%20You%20must%20reset%20your%20password%20using%20ALTER%20USER%20statement%20before%20executing%20this%20statement.%0A%60%60%60%0A%0A%E4%BF%AE%E6%94%B9%E5%AF%86%E7%A0%81%E6%97%B6%E9%81%87%E5%88%B0%E9%97%AE%E9%A2%98%EF%BC%9A%0A%60%60%60%0Amysql%3E%20alter%20user%20'root'%40'localhost'%20identified%20by%20'65536'%20%3B%0AERROR%201819%20(HY000)%3A%20Your%20password%20does%20not%20satisfy%20the%20current%20policy%20requirements%0A%60%60%60%0A%0A%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%EF%BC%9A%0A%60%60%60sql%0Amysql%3E%20set%20global%20validate_password.policy%3D0%3B%0Amysql%3E%20set%20global%20validate_password.length%3D5%3B%0Amysql%3E%20alter%20user%20'root'%40'localhost'%20identified%20by%20'65536'%20%3B%0AQuery%20OK%2C%200%20rows%20affected%20(0.01%20sec)%0Amysql%3E%20show%20variables%20like%20'validate_password%25'%3B%0A%60%60%60%0A!%5Be583c9ab1061c31ac2760f99c9d90937.png%5D(en-resource%3A%2F%2Fdatabase%2F621%3A1)%0A%0A%0A%60%60%60%0Amysql%3E%20quit%0ABye%0A%5Broot%40master%20mysql%5D%23%20mysql%20-uroot%20-p%0AEnter%20password%3A%20%20%E6%AD%A4%E5%A4%84%E7%94%A8%E6%96%B0%E5%AF%86%E7%A0%81%E7%99%BB%E5%BD%95%0A%60%60%60%0A%0A%E5%AF%86%E7%A0%81policy%E5%AF%B9%E7%85%A7%E8%A1%A8%0A!%5Bc5a4a440fa6e682d85172cfcb1157326.png%5D(en-resource%3A%2F%2Fdatabase%2F620%3A1)%0A%0A%0A%23%23%206%20%E8%BF%9C%E7%A8%8B%E8%BF%9E%E6%8E%A5%0A%E5%AE%BF%E4%B8%BB%E6%9C%BAhost%E6%96%87%E4%BB%B6%0A%3E%20C%3A%5CWindows%5CSystem32%5Cdrivers%5Cetc%5Chosts%0A%3E%20192.168.101.127%20%20%20%20%20%20%20%20master%0A%0A%E9%97%AE%E9%A2%981%EF%BC%9A%0A!%5Be0572d5f4b3539f6600781e87ca9ea39.png%5D(en-resource%3A%2F%2Fdatabase%2F622%3A1)%0A%0A%E8%A7%A3%E5%86%B3%E6%AD%A5%E9%AA%A4%0A1.%20%E6%9F%A5%E7%9C%8B%E5%AE%BF%E4%B8%BB%E6%9C%BA%E5%88%B0master%E7%9A%84%E8%BF%9E%E9%80%9A%E6%80%A7%0A%60%60%60%0AC%3A%5CUsers%5CDell%3Eping%20master%0AC%3A%5CUsers%5CDell%3Etelnet%20master%203066%0A%60%60%60%0A%3E%20%E5%A6%82%E6%9E%9C%E8%BF%9E%E9%80%9A%E6%80%A7%E6%9C%89%E9%97%AE%E9%A2%98%E9%9C%80%E8%A6%81%E5%85%B3%E9%97%AD%E5%AE%BF%E4%B8%BB%E6%9C%BA%E7%9A%84firewall%0A%0A2.%20%E6%9F%A5%E7%9C%8Bmysql%E4%B8%AD%E7%9A%84%E7%94%A8%E6%88%B7%E6%98%AF%E5%90%A6%E5%8F%AA%E5%85%81%E8%AE%B8%E6%9C%AC%E5%9C%B0%E8%AE%BF%E9%97%AE%0A%60%60%60sql%0Amysql%3E%20select%20host%20%2C%20user%20from%20mysql.user%3B%0A%2B-----------%2B------------------%2B%0A%7C%20host%20%20%20%20%20%20%7C%20user%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%2B-----------%2B------------------%2B%0A%7C%20localhost%20%7C%20mysql.infoschema%20%7C%0A%7C%20localhost%20%7C%20mysql.session%20%20%20%20%20%20%7C%0A%7C%20localhost%20%7C%20mysql.sys%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20localhost%20%7C%20root%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%2B-----------%2B------------------%2B%0A4%20rows%20in%20set%20(0.00%20sec)%0A%0Amysql%3E%20update%20mysql.user%20set%20host%3D'%25'%20where%20user%3D'root'%3B%0AQuery%20OK%2C%201%20row%20affected%20(0.01%20sec)%0ARows%20matched%3A%201%20%20Changed%3A%201%20%20Warnings%3A%200%0Amysql%3E%20select%20host%20%2C%20user%20from%20mysql.user%3B%0A%2B-----------%2B------------------%2B%0A%7C%20host%20%20%20%20%20%20%7C%20user%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%2B-----------%2B------------------%2B%0A%7C%20%25%20%20%20%20%20%20%20%20%20%7C%20root%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20localhost%20%7C%20mysql.infoschema%20%7C%0A%7C%20localhost%20%7C%20mysql.session%20%20%20%20%7C%0A%7C%20localhost%20%7C%20mysql.sys%20%20%20%20%20%20%20%20%7C%0A%2B-----------%2B------------------%2B%0A4%20rows%20in%20set%20(0.00%20sec)%0A%0Amysql%3Eflush%20privileges%3B%20%2F%2F%E5%88%B7%E6%96%B0%E7%B3%BB%E7%BB%9F%E6%9D%83%E9%99%90%E8%A1%A8%0A%60%60%60%0A%3E%20host%3D'%25'%20%E8%A1%A8%E7%A4%BA%E5%85%81%E8%AE%B8%E6%89%80%E6%9C%89%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%BF%E9%97%AE%EF%BC%8C%0A%3E%20%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%94%B9%E4%B8%BA%20host%3D'192.168.101.%25'%20%E8%A1%A8%E7%A4%BA%E5%8F%AA%E5%85%81%E8%AE%B8101%E8%BF%99%E4%B8%AA%E7%BD%91%E6%AE%B5%E7%9A%84%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%BF%E9%97%AE%0A%0A%E9%97%AE%E9%A2%982%EF%BC%9A%0A%E9%94%99%E8%AF%AF%E5%8F%B7%E7%A0%81%202058%EF%BC%8C%E5%88%86%E6%9E%90%E6%98%AF%20mysql%20%E5%AF%86%E7%A0%81%E5%8A%A0%E5%AF%86%E6%96%B9%E6%B3%95%E5%8F%98%E4%BA%86%0A!%5B50baf2ffd33e7acf8540a11ddea79ac8.png%5D(en-resource%3A%2F%2Fdatabase%2F623%3A1)%0A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%EF%BC%9A%0A%3E%20Linux%E4%B8%8B%20mysql%20-u%20root%20-p%20%E7%99%BB%E5%BD%95%E4%BD%A0%E7%9A%84%20mysql%20%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%8C%E7%84%B6%E5%90%8E%20%E6%89%A7%E8%A1%8C%E8%BF%99%E6%9D%A1SQL%EF%BC%9A%0A%60%60%60%0AALTER%20USER%20'root'%40'%25'%20IDENTIFIED%20WITH%20mysql_native_password%20BY%20'abc123'%3B%0A%60%60%60%0A%23%23%207%20%E6%96%B0%E5%A2%9E%E7%94%A8%E6%88%B7%0A%23%23%23%207.1%20%E5%88%9B%E5%BB%BA%E7%94%A8%E6%88%B7%0A%0A%60%60%60sql%0Acreate%20user%20chris%20identified%20by%20'65536'%3B%0A%60%60%60%0A%0A%23%23%23%207.2%20%E8%B5%8B%E6%9D%83%0A%3E%20with%20grant%20option%20%3A%20%E8%A1%A8%E7%A4%BA%E5%85%81%E8%AE%B8%E7%94%A8%E6%88%B7%E5%B0%86%E8%87%AA%E5%B7%B1%E7%9A%84%E6%9D%83%E9%99%90%E6%8E%88%E6%9D%83%E7%BB%99%E5%85%B6%E5%AE%83%E7%94%A8%E6%88%B7%0A%0A%60%60%60sql%0Agrant%20all%20privileges%20on%20*.*%20to%20'chris'%40'%25'%3B%0Agrant%20all%20privileges%20on%20*.*%20to%20'chris'%40'%25'%20with%20grant%20option%3B%0A%0A%0A%0A%0A%0A%0Agrant%20all%20privileges%20on%20schema-name.*%20to%20chris'%40'%25'%20identified%20by%20'65536'%3B%0Agrant%20all%20privileges%20on%20schema-name.*%20to%20chris%40%25%20identified%20by%20'65536'%20with%20grant%20option%3B%0Agrant%20select%2Cupdate%2Cdelete%2Cinsert%20privileges%20on%20schema-name.*%20to%20chris%40'%25'%20identified%20by%20'65536'%3B%0A%60%60%60%0A

mysql summary

创建时间:2020/9/5 13:49
更新时间:2024/9/10 21:51
作者:Chris
来源:https://www.cnblogs.com/ichimoku/p/7880959.html

用户操作

1.1 新增用户
create user canal identified by '65536';
1.2 赋权

with grant option : 表示允许用户将自己的权限授权给其它用户

grant all privileges on schema-name.* to `user-name`@`localhost` identified by 'password';
grant all privileges on schema-name.* to `user-name`@`localhost` identified by 'password' 
with grant option;
grant select,update,delete,insert privileges on schema-name.* to `user-name`@`localhost` identified by 'password';

注意:此处的"localhost",是指该用户只能在本地登录,不能在另外一台机器上远程登录。如果想远程登录的话,将"localhost"改为"%",表示在任何一台电脑上都可以登录。也可以指定某台机器可以远程登录。

回收权限

revoke delete on schema-name.* from `user-name`@`host` ;

查看用户权限

show grants for 'yangxin'@'localhost';
1.1 新增用户

1 常用SQL

1.1 查询数据库版本
select @@version;
select version();
1.2 查看事务隔离级别
select @@global.tx_isolation;

-- mysql 8.0 后
select@@global.transaction_isolation
1.3 查询数据库自增锁
1. select @@innodb_autoinc_lock_mode;
2. show variables like 'innodb_autoinc_lock_mode';
1.4 engine
1.4.1 查询数据库支持的engine
show engines

1.4.2 查看默认的引擎
show variables like %storage_engine%

1.4.3 查看InnoDB引擎分页大小

InnoDB存储引擎将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小默认为 16 KB

show variables like 'innodb_page_size';

所以当你用postman测试一个分页查询接口时,发现第一次打印耗时300 ~ 400ms,往后不停的查找下一页都是30 ~ 40ms,原因就是第一次请求接口时,读数据库的时候需要读磁盘,从磁盘加载16KB的数据到内存,往后下一页的数据都是从内存中获取,没有再读磁盘,除非在内存中的16KB的数据中找不到,才会再次读磁盘获取下一个16KB的数据到内存中。

1.4.4 查看InnoDB默认行格式

mysql中是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为行格式或者记录格式
行格式有4种,分别是
Dynamic、Compact、Redundant、Compressed
默认的行格式为: Dynamic

SHOW VARIABLES LIKE 'innodb_default_row_format';

1.5 查看binlog是否开启
show variables like 'log_bin'

2.建表

2.1 建表语句
CREATE TABLE `t_dg_user_address` (
  `id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `user_id` bigint(20) NOT NULL COMMENT '用户ID,根据user_type可能是app用户或小程序用户',
  `user_type` smallint(6) DEFAULT '1' COMMENT '用户类型:1-代购,2-比柚商家,3-小程序',
  `country_id` bigint(20) DEFAULT '0' COMMENT '国家编号',
  `province_id` bigint(20) DEFAULT '0' COMMENT '省份ID',
  `city_id` bigint(20) DEFAULT '0' COMMENT '城市ID',
  `county_id` bigint(20) DEFAULT '0' COMMENT '区县ID',
  `district_id` bigint(20) DEFAULT '0' COMMENT '街道ID',
  `receiving_name` varchar(64) DEFAULT NULL COMMENT '收货人',
  `receiving_phone` varchar(64) DEFAULT NULL COMMENT '收货电话',
  `receiving_address` varchar(256) DEFAULT NULL COMMENT '收货地址',
  `dft` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否默认 0-否 1-是',
  `record_status` char(1) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT 'A' COMMENT '是否已经失效:A、有效;I、无效',
  `create_date` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
  `creator_id` bigint(20) DEFAULT NULL,
  `update_date` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  `updater_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `index_name` (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户收货地址';
1.2 复制表结构

只复制表结构到新表

#旧表的所有字段类型都复制到新表
CREATE TABLE 新表 LIKE 旧表 ;

#主键类型和自增方式是不会复制过去的
CREATE TABLE 新表 SELECT * FROM 旧表 WHERE 1=2; 
1.3 复制表结构及数据

CREATE TABLE 新表 SELECT * FROM 旧表

#假设两个表结构一样
INSERT INTO 新表 SELECT * FROM 旧表

#假设两个表结构不一样
INSERT INTO 新表(字段1,字段2,.......) SELECT 字段1,字段2,...... FROM 旧表

3.修改表结构

3.1 增删字段
ALTER TABLE employee ADD COLUMN abc VARCHAR(255) NOT NULL DEFAULT '';
ALTER TABLE employee DROP COLUMN abc;

这条语句会向已有的表中加入一列,这一列在表的最后一列位置。如果我们希望添加在指定的一列,可以用:
alter table 表名 add column 列名 varchar(20) not null after user1;

上面这个命令的意思是说添加addr列到user1这一列后面。如果想添加到第一列的话,可以用:
alter table 表名 add column 列名 varchar(20) not null first;

4.insert into select

4.1 语法
INSERT INTO table_xxx VALUES();
INSERT INTO table_xxx SELECT xxx from table_yyy;
4.2 表结构一致

当表A和表B的表结构一致时,直接插入即可。

insert into A select * from B;
4.3 表结构不一致

当表结构不一致时(字段大小、类型都相同)

insert into A(col1, col2) select col1, col2 from B;
4.4 批量生成ID
-- 查询操作人的userId
select t.user_id from ipd_user_core.t_user t where t.user_name='xxx';

-- 用上面查询出来的 user_id 替换 {0}

SET @k:=(SELECT max(prm.id) FROM t_project_role_menu prm);

INSERT INTO t_project_role_menu SELECT
	(@k:= @k+1) as id,
	(SELECT pt.id FROM t_project_type pt WHERE pt.`name` = 'xxx' ) AS project_type_id,
	NULL as template_id,
	c.CODE AS role_code,
	( SELECT pm.id FROM t_project_menu pm WHERE pm.menu_name = 'xxx' ) as menu_id,
	0 as del_flag,
	2 as app_id,
	{0} as create_id, -- need fix
	CURRENT_TIMESTAMP as create_time, 
	{0} as update_id, -- need fix
	CURRENT_TIMESTAMP as update_time,
	'' as project_sec_level 
FROM
	(
	SELECT t.`code`  FROM t_project_team_template t 
	WHERE t.del_flag = 0  AND t.STATUS = 1  AND t.template_id = 1000 
	UNION
	SELECT tt.`code` FROM t_team_constant tt 
	WHERE tt.type = 2 
	) c;

5. 常用函数

5.1 FIND_IN_SET(str, strlist)

str 要查询的字符串
strlist 字段名 参数以”,”分隔 如 (1,2,6,8,10,22)
查询字段(strlist)中包含(str)的结果,返回结果为null或记录

SELECT FIND_IN_SET('b', 'a,b,c,d');
结果:2
因为b 在strlist集合中放在2的位置 从1开始

select FIND_IN_SET('2', '1,2'); 返回2
select FIND_IN_SET('6', '1'); 返回0 strlist中不存在str,所以返回0。

5.2 concat()

MySQL中concat以及group_concat的使用

功能:将多个字符串连接成一个字符串。
语法:concat(str1, str2,...)返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。

5.3 concat_ws()

功能:和concat()一样,将多个字符串连接成一个字符串,但是可以一次性指定分隔符~(concat_ws就是concat with separator)
语法:concat_ws(separator, str1, str2, ...)
第一个参数指定分隔符。需要注意的是分隔符不能为null,如果为null,则返回结果为null。

把分隔符指定为null,结果全部变成了null:

5.4 group_concat()

功能:将group by产生的同一个分组中的值连接起来,返回一个字符串结果。
语法:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc  ] [separator '分隔符'] )

说明:通过使用distinct可以排除重复值;如果希望对结果中的值进行排序,可以使用order by子句;separator是一个字符串值,缺省为一个逗号。

将的id号从大到小排序,且用'_' 作为分隔符:

上面的查询中显示了以name分组的每组中所有的id。接下来我们要查询以name分组的所有组的id和score:

SELECT
	t.process_instance_id,
	t.task_instance_id,
	t.process_title,
	GROUP_CONCAT( t.use_assignee, '(', t.assignee, ')' ) AS assignee,
	t.update_time,
	t.del_flag 
FROM
	t_process_instance_task t 
WHERE
	t.del_flag = 0 
GROUP BY
	t.process_instance_id
5.5 DATE_FORMAT()
SELECT
*
FROM
t_dg_buy_user t
WHERE
im_token IS NOT NULL
AND t.create_date >= DATE_FORMAT('2019-12-19 00:00:00', '%Y-%m-%d %H:%i:%s')
AND t.create_date <= DATE_FORMAT('2019-12-19 23:00:00', '%Y-%m-%d %H:%i:%s')
ORDER BY
t.create_date DESC;
5.6 REGEXP
select * from t_ms_merchant t where t.shop REGEXP '^[a-z]+ [a-z]+ [a-z]';
5.7 RANK()

RANK()函数为结果集的分区中的每一行分配一个排名。
行的等级由一加上前面的等级数指定。

RANK() OVER (
PARTITION BY <expression>[{,<expression>...}]    
ORDER BY <expression> [ASC|DESC], [{,<expression>...}]) 

在这个语法中:

与ROW_NUMBER()函数不同,RANK()函数并不总是返回连续的整数。

select t.val, rank() over(order by t.val) from rankdemo t;

第二行和第三行具有相同的关系,因此它们获得相同的等级2。
第四行具有等级4,因为RANK()功能跳过等级3。

SELECT
        sales_employee,
        fiscal_year,
        sale,
        RANK( ) OVER ( 
                PARTITION BY fiscal_year 
                ORDER BY sale DESC
        ) sales_rank 
FROM
        sales; 

5.8 ROW_NUMBER

ROW_NUMBER()是一个窗口函数或分析函数,它为从1开始应用的每一行分配一个序号

ROW_NUMBER() OVER (<partition_definition> <order_definition> 
ORDER BY <expression> [ASC|DESC],[{,<expression>}...] ) 

使用公用表表达式(CTE)返回要删除的重复行和delete语句

WITH dups AS (
    SELECT         
        id,        
        name,        
        ROW_NUMBER() 
        OVER(PARTITION BY name ORDER BY name) AS row_num
    FROM rowNumberDemo)
DELETE rowNumberDemo FROM rowNumberDemo INNER JOIN dups ON rowNumberDemo.id = dups.id
WHERE dups.row_num <> 1; 
5.9 INSTR

函数语法 INSTR(str,substr)
instr(源字符串, 目标字符串)参数说明:str:源字符串中搜索;substr: 要搜索的子字符串。
例如:instr('apple','a'),返回的查询结果是1a出现在字符串‘apple’中的第一个索引;

6. CTE

公用表表达式是一个命名的临时结果集
仅在单个SQL语句(例如SELECT,INSERT,UPDATE或DELETE)的执行范围内存在.

与派生表不同,CTE可以是自引用(递归CTE),也可以在同一查询中多次引用。 此外,与派生表相比,CTE提供了更好的可读性和性能。

6.1 基本语法
WITH cte_name (column_list) AS ( 
    query
 ) 
 SELECT * FROM cte_name;

查询中的列数必须与column_list中的列数相同。
如果省略column_list,CTE将使用定义CTE的查询的列列表。

6.2 实例

CTE的名称为customers_in_usa,定义CTE的查询返回两列:customerName和state。
因此,customers_in_usa CTE返回位于美国的所有客户。
在定义美国CTE的客户之后,我们可在SELECT语句中引用它,例如,仅查询选择位于California 的客户

WITH customers_in_usa AS
(
    SELECT 
        customerName, state 
    FROM customers 
    WHERE country = 'USA'
)
SELECT customerName FROM customers_in_usa WHERE state = 'CA' ORDER BY customerName;

返回了在2013年前五名的销售代表。
之后,我们引用了topsales2013 CTE来获取有关销售代表的其他信息,包括名字和姓氏。

WITH topsales2013 AS (
SELECT
    salesRepEmployeeNumber employeeNumber, 
    SUM(quantityOrdered * priceEach) sales                     
FROM orders
    INNER JOIN orderdetails USING (orderNumber) 
    INNER JOIN customers USING (customerNumber)                      
WHERE YEAR(shippedDate) = 2013                        
AND status = 'Shipped'                     
GROUP BY salesRepEmployeeNumber                      
ORDER BY sales DESC                      
LIMIT 5)
SELECT 
    employeeNumber, firstName, lastName, sales 
FROM 
    employees JOIN topsales2013 USING (employeeNumber);

在同一查询中有两个CTE。
第一个CTE(salesrep)获得职位是销售代表的员工。
第二个CTE(customer_salesrep)使用INNER JOIN子句与第一个CTE连接来获取每个销售代表负责的客户。
在使用第二个CTE之后,使用带有ORDER BY子句的简单SELECT语句来查询来自该CTE的数据。

WITH salesrep AS (
    SELECT employeeNumber,
           CONCAT(firstName, ' ', lastName) AS salesrepName
    FROM employees
    WHERE jobTitle = 'Sales Rep'
),
    customer_salesrep AS (
         SELECT customerName,
                salesrepName
         FROM customers
                  INNER JOIN
              salesrep ON employeeNumber = salesrepEmployeeNumber
    )
SELECT *
FROM customer_salesrep
ORDER BY customerName;
6.2 WITH子句用法
    WITH ... SELECT ... 
    WITH ... UPDATE ... 
    WITH ... DELETE ..
    SELECT ... WHERE id IN (WITH ... SELECT ...); 
    SELECT * FROM (WITH ... SELECT ...) AS derived_table;

7 JSon

7.1基本方法
7.1.1 JSON_UNQUOTE
 JSON_UNQUOTE(val)

去掉val的引号。如果val为NULL,则返回NULL。

SELECT JSON_UNQUOTE("\"123\""); -- 123

去除json字符串的引号,将值转成string类型

SELECT
    userId,
    JSON_EXTRACT(loginInfo, "$.cellphone") cellphone,
    JSON_EXTRACT(loginInfo, "$.wxchat") wxchat
FROM UserLogin;

SELECT
    userId,
    JSON_UNQUOTE(JSON_EXTRACT(loginInfo, "$.cellphone")) cellphone,
    JSON_UNQUOTE(JSON_EXTRACT(loginInfo, "$.wxchat")) wxchat
FROM UserLogin;

7.1.2 JSON_LENGTH
JSON_LENGTH(json_doc[, path])

获取指定路径下的长度。如果参数为NULL,则返回NULL。 
长度的计算规则:
标量的长度为1;
json array的长度为元素的个数;
json object的长度为key的个数。

SELECT JSON_LENGTH('[1, 2, {"a": 3}]'); -- 3
SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}'); -- 2
SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b'); -- 1
7.1.3 JSON_VALID
JSON_VALID(val)

判断val是否为有效的json格式,是为1,不是为0。如果参数为NUL,则返回NULL。

SELECT JSON_VALID('{"a": 1}'); -- 1
SELECT JSON_VALID('hello'), JSON_VALID('"hello"'); -- 1
7.1.4 JSON_KEYS
JSON_KEYS(json_doc[, path])

获取json文档在指定路径下的所有键值,返回一个json array。如果有参数为NULL或path不存在,则返回NULL。

SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}'); -- ["a", "b"]
SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b'); -- ["c"]
7.1.5 JSON_TYPE
JSON_TYPE(json_val)

获取json文档的具体类型。如果参数为NULL,则返回NULL。

select JSON_TYPE('[1,2]'); -- ARRAY

For a non-NULL, non-error result, the following list describes the possible - JSON_TYPE() return values:

7.2 查询
7.2.1 JSON_EXTRACT
JSON_EXTRACT(json_doc, path[, path] ...)

从json文档里抽取数据。如果有参数有NULL或path不存在,则返回NULL。如果抽取出多个path,则返回的数据封闭在一个json array里

set @j2 = '[10, 20, [30, 40]]';
SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]'); -- 20
SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]'); -- [20, 10]
SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]'); -- [30, 40]

使用方式
$.paramsName:取出一个key对应的value。
$**.paramsName 、$.[*].paramsName :取出json数组所有该字段key对应的value并以,的方式拼接在一起

SELECT
    userId,
    JSON_EXTRACT(loginInfo, "$.cellphone") cellphone,
    JSON_EXTRACT(loginInfo, "$.wxchat") wxchat
FROM UserLogin;

select json_extract(t.loginInfo, "$**.cellphone") from userlogin t;

7.2.2 JSON_SEARCH
JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...])

查询包含指定字符串的paths,并作为一个json array返回。如果有参数为NUL或path不存在,则返回NULL。
one_or_all:"one"表示查询到一个即返回;"all"表示查询所有。
search_str:要查询的字符串。 可以用LIKE里的'%'或‘_’匹配。
path:在指定path下查。

SET @j3 = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]';
SELECT JSON_SEARCH(@j3, 'one', 'abc'); -- "$[0]"
SELECT JSON_SEARCH(@j3, 'all', 'abc'); -- ["$[0]", "$[2].x"]
SELECT JSON_SEARCH(@j3, 'all', 'abc', NULL, '$[2]'); -- "$[2].x"
SELECT JSON_SEARCH(@j3, 'all', '10'); -- "$[1][0].k"
SELECT JSON_SEARCH(@j3, 'all', '%b%'); -- ["$[0]", "$[2].x", "$[3].y"]
SELECT JSON_SEARCH(@j3, 'all', '%b%', NULL, '$[2]'); -- "$[2].x"
7.3 判断
7.3.1 JSON_CONTAINS
JSON_CONTAINS(target, candidate[, path])

判断candidate的是否被包含在target中
target和candidate为json document
如果提供了path参数,则判断target中指定路径下是否包含candidate
包含返回1,未包含返回0

SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
SET @j2 = '1';
SELECT JSON_CONTAINS(@j, @j2, '$.a'); -- 1
SELECT JSON_CONTAINS(@j, @j2, '$.b'); -- 0

SET @j2 = '{"d": 4}';
SELECT JSON_CONTAINS(@j, @j2, '$.a'); -- 0
SELECT JSON_CONTAINS(@j, @j2, '$.c'); -- 1
7.3.2 JSON_CONTAINS_PATH
JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...)

查询是否存在指定路径,存在则返回1,否则返回0。如果有参数为NULL,则返回NULL。
one_or_all只能取值"one"或"all",one表示只要有一个存在即可;all表示所有的都存在才行。

7.4 指定位置数组操作
7.4.1 JSON_ARRAY_APPEND
JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)

在指定path的json array尾部追加val。
如果指定path是一个json object,则将其封装成一个json array再追加。
如果有参数为NULL,则返回NULL。

SET @j4 = '["a", ["b", "c"], "d"]';
SELECT JSON_ARRAY_APPEND(@j4, '$[1][0]', 3); -- ["a", [["b", 3], "c"], "d"]
SET @j5 = '{"a": 1, "b": [2, 3], "c": 4}';
SELECT JSON_ARRAY_APPEND(@j5, '$.b', 'x'); -- {"a": 1, "b": [2, 3, "x"], "c": 4}
SELECT JSON_ARRAY_APPEND(@j5, '$.c', 'y'); -- {"a": 1, "b": [2, 3], "c": [4, "y"]}
SELECT JSON_ARRAY_APPEND(@j5, '$', 'z'); -- [{"a": 1, "b": [2, 3], "c": 4}, "z"]
7.4.2 JSON_ARRAY_INSERT
JSON_ARRAY_INSERT(json_doc, path, val[, path, val] ...)

在path指定的json array元素插入val,原位置及以右的元素顺次右移。如果path指定的数据非json array元素,则略过此val;如果指定的元素下标超过json array的长度,则插入尾部。

SET @j6 = '["a", {"b": [1, 2]}, [3, 4]]';
SELECT JSON_ARRAY_INSERT(@j6, '$[1]', 'x'); -- ["a", "x", {"b": [1, 2]}, [3, 4]]
SELECT JSON_ARRAY_INSERT(@j6, '$[100]', 'x'); -- ["a", {"b": [1, 2]}, [3, 4], "x"]
SELECT JSON_ARRAY_INSERT(@j6, '$[1].b[0]', 'x'); -- ["a", {"b": ["x", 1, 2]}, [3, 4]]
SELECT JSON_ARRAY_INSERT(@j6, '$[0]', 'x', '$[3][1]', 'y'); -- ["x", "a", {"b": [1, 2]}, [3, "y", 4]]
7.4.3 JSON_ARRAY
JSON_ARRAY(val1,val2,val3...)

生成一个包含指定元素的json数组。

SELECT JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME()); -- [1, "abc", null, true, "10:37:08.000000"]
7.5 指定位置修改操作
7.5.1 JSON_INSERT
JSON_INSERT(json_doc, path, val[, path, val] ...)

在指定path下插入数据,如果path已存在,则忽略此val(不存在才插入)

SET @j7 = '{ "a": 1, "b": [2, 3]}';
SELECT JSON_INSERT(@j7, '$.a', 10, '$.c', '[true, false]'); -- {"a": 1, "b": [2, 3], "c": "[true, false]"}
7.5.2 JSON_REPLACE
 JSON_REPLACE(json_doc, path, val[, path, val] ...)

替换指定路径的数据,如果某个路径不存在则略过(存在才替换)。
如果有参数为NULL,则返回NULL。

SELECT JSON_REPLACE(@j7, '$.a', 10, '$.c', '[true, false]'); -- {"a": 10, "b": [2, 3]}
7.5.3 JSON_SET
JSON_SET(json_doc, path, val[, path, val] ...)

设置指定路径的数据(不管是否存在)。如果有参数为NULL,则返回NULL。

SELECT JSON_SET(@j7, '$.a', 10, '$.c', '[true, false]'); -- {"a": 10, "b": [2, 3], "c": "[true, false]"}
7.5.4 JSON_MERGE
JSON_MERGE(json_doc, json_doc[, json_doc] ...)

merge多个json文档。规则如下:
如果都是json array,则结果自动merge为一个json array;
如果都是json object,则结果自动merge为一个json object;
如果有多种类型,则将非json array的元素封装成json array再按照规则一进行mege。

SELECT JSON_MERGE('[1, 2]', '[true, false]'); -- [1, 2, true, false]
SELECT JSON_MERGE('{"name": "x"}', '{"id": 47}'); -- {"id": 47, "name": "x"}
SELECT JSON_MERGE('1', 'true'); -- [1, true]
SELECT JSON_MERGE('[1, 2]', '{"id": 47}'); -- [1, 2, {"id": 47}]
7.5.5 JSON_REMOVE
JSON_REMOVE(json_doc, path[, path] ...)

移除指定路径的数据,如果某个路径不存在则略过此路径。
如果有参数为NULL,则返回NULL。

SET @j8 = '["a", ["b", "c"], "d"]';
SELECT JSON_REMOVE(@j8, '$[1]'); -- ["a", "d"]
7.5.6 综合实例
# update act_ru_variable's TEXT_ for each ProcessInstanceID

with json_obj_location as (
    select inx1,
           if(json_contains(json_extract(j_inx.TEXT_, concat(inx2, '.', 'roleIds')), json_array('POST_PERSON')), inx2, '$[999]') inx2,
           inx3,
           PROC_INST_ID_,
           NAME_
    from (
             select substring_index(json_unquote(json_search(c.TEXT_, 'one', 'risk_confirm_modify')), '.', 1) as inx1,
                    substring_index(json_unquote(json_search(c.TEXT_, 'one', 'risk_finnal_confirm')), '.', 1) as inx2,
                    substring_index(json_unquote(json_search(c.TEXT_, 'one', 'create')), '.', 1)              as inx3,
                    c.PROC_INST_ID_,
                    c.NAME_,
                    c.TEXT_
             from act_ru_variable c
             where c.PROC_INST_ID_ in (${processInsID})
               and c.NAME_ = 'users'
               and c.TASK_ID_ is null) j_inx
)
update act_ru_variable uc inner join json_obj_location js on js.NAME_ = uc.NAME_ and js.PROC_INST_ID_ = uc.PROC_INST_ID_
set uc.TEXT_= (select a.json_str_result
               from (select json_replace(c.TEXT_,
                                         concat(js.inx1, '.', 'userIds'), json_array('111111'),
                                         concat(js.inx1, '.', 'userNames'), json_array('Chris'),
                                         concat(js.inx2, '.', 'userIds'), json_array('111111'),
                                         concat(js.inx2, '.', 'userNames'), json_array('Chris'),
                                         concat(js.inx3, '.', 'userIds'), json_array('111111'),
                                         concat(js.inx3, '.', 'userNames'), json_array('Chris')) as json_str_result
                     from act_ru_variable c
                     where c.PROC_INST_ID_ = js.PROC_INST_ID_
                       and c.NAME_ = js.NAME_
                       and c.TASK_ID_ is null) a)
where uc.PROC_INST_ID_ = js.PROC_INST_ID_
  and uc.NAME_ = js.NAME_
  and uc.TASK_ID_ is null;


# check act_ru_variable result after update
select cast(v.TEXT_ as json) from act_ru_variable v where v.PROC_INST_ID_ in (${processInsID}) and v.NAME_ = 'users' and v.TASK_ID_ is null ;

8 行行比较

SQL-92 中加入了行与行比较的功能,这样一来,比较谓词 = 、< 、> 和 IN 谓词的参数就不再只是标量值了,还可以是值列表了
行行比较比较的是in的多字段写法

SELECT * 
FROM table
WHERE (字段1 , 字段2,...字段N)
in (
(查询条件1 , 查询条件2,...查询条件N),
(查询条件1 , 查询条件2,...查询条件N),
)

CREATE TABLE `sys_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `user_name` varchar(32) DEFAULT NULL COMMENT '全名',
  `account` varchar(200) NOT NULL COMMENT '账号',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
SELECT *  FROM user WHERE (id , user_name)in ((1,'u1'),(2,'u2'))

从上面对比发现所谓的行行比较就是多个 or条件的简写版,上面的SQL语句也可以用条件or来表达

SELECT * 
FROM user
WHERE 
(id=1 and user_name = 'u1')
OR
(id=2 and user_name = 'u2')
%5Btoc%5D%0A%0A%23%23%23%23%20%E7%94%A8%E6%88%B7%E6%93%8D%E4%BD%9C%0A%23%23%23%23%23%201.1%20%E6%96%B0%E5%A2%9E%E7%94%A8%E6%88%B7%0A%0A%60%60%60sql%0Acreate%20user%20canal%20identified%20by%20'65536'%3B%0A%60%60%60%0A%0A%23%23%23%23%23%201.2%20%E8%B5%8B%E6%9D%83%0A%3E%20with%20grant%20option%20%3A%20%E8%A1%A8%E7%A4%BA%E5%85%81%E8%AE%B8%E7%94%A8%E6%88%B7%E5%B0%86%E8%87%AA%E5%B7%B1%E7%9A%84%E6%9D%83%E9%99%90%E6%8E%88%E6%9D%83%E7%BB%99%E5%85%B6%E5%AE%83%E7%94%A8%E6%88%B7%0A%0A%60%60%60sql%0Agrant%20all%20privileges%20on%20schema-name.*%20to%20%60user-name%60%40%60localhost%60%20identified%20by%20'password'%3B%0Agrant%20all%20privileges%20on%20schema-name.*%20to%20%60user-name%60%40%60localhost%60%20identified%20by%20'password'%20%0Awith%20grant%20option%3B%0Agrant%20select%2Cupdate%2Cdelete%2Cinsert%20privileges%20on%20schema-name.*%20to%20%60user-name%60%40%60localhost%60%20identified%20by%20'password'%3B%0A%60%60%60%0A%3E%20%E6%B3%A8%E6%84%8F%EF%BC%9A%E6%AD%A4%E5%A4%84%E7%9A%84%22localhost%22%EF%BC%8C%E6%98%AF%E6%8C%87%E8%AF%A5%E7%94%A8%E6%88%B7%E5%8F%AA%E8%83%BD%E5%9C%A8%E6%9C%AC%E5%9C%B0%E7%99%BB%E5%BD%95%EF%BC%8C%E4%B8%8D%E8%83%BD%E5%9C%A8%E5%8F%A6%E5%A4%96%E4%B8%80%E5%8F%B0%E6%9C%BA%E5%99%A8%E4%B8%8A%E8%BF%9C%E7%A8%8B%E7%99%BB%E5%BD%95%E3%80%82%E5%A6%82%E6%9E%9C%E6%83%B3%E8%BF%9C%E7%A8%8B%E7%99%BB%E5%BD%95%E7%9A%84%E8%AF%9D%EF%BC%8C%E5%B0%86%22localhost%22%E6%94%B9%E4%B8%BA%22%25%22%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%9C%A8%E4%BB%BB%E4%BD%95%E4%B8%80%E5%8F%B0%E7%94%B5%E8%84%91%E4%B8%8A%E9%83%BD%E5%8F%AF%E4%BB%A5%E7%99%BB%E5%BD%95%E3%80%82%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E6%9F%90%E5%8F%B0%E6%9C%BA%E5%99%A8%E5%8F%AF%E4%BB%A5%E8%BF%9C%E7%A8%8B%E7%99%BB%E5%BD%95%E3%80%82%0A%0A%0A%3E%20%E5%9B%9E%E6%94%B6%E6%9D%83%E9%99%90%0A%0A%60%60%60sql%0Arevoke%20delete%20on%20schema-name.*%20from%20%60user-name%60%40%60host%60%20%3B%0A%60%60%60%0A%0A%3E%20%E6%9F%A5%E7%9C%8B%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%0A%60%60%60sql%0Ashow%20grants%20for%20'yangxin'%40'localhost'%3B%0A%60%60%60%0A%0A%23%23%23%23%23%201.1%20%E6%96%B0%E5%A2%9E%E7%94%A8%E6%88%B7%0A%0A%23%23%23%23%201%20%E5%B8%B8%E7%94%A8SQL%0A%23%23%23%23%23%201.1%20%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%BA%93%E7%89%88%E6%9C%AC%0A%60%60%60sql%0Aselect%20%40%40version%3B%0Aselect%20version()%3B%0A%60%60%60%0A%0A%23%23%23%23%23%201.2%20%E6%9F%A5%E7%9C%8B%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%0A%60%60%60sql%0Aselect%20%40%40global.tx_isolation%3B%0A%0A--%20mysql%208.0%20%E5%90%8E%0Aselect%40%40global.transaction_isolation%0A%60%60%60%0A%0A%23%23%23%23%23%201.3%20%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%BA%93%E8%87%AA%E5%A2%9E%E9%94%81%0A%60%60%60sql%0A1.%20select%20%40%40innodb_autoinc_lock_mode%3B%0A2.%20show%20variables%20like%20'innodb_autoinc_lock_mode'%3B%0A%60%60%60%0A%0A%23%23%23%23%23%201.4%20engine%0A%23%23%23%23%23%23%201.4.1%20%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%BA%93%E6%94%AF%E6%8C%81%E7%9A%84engine%0A%60%60%60sql%0Ashow%20engines%0A%60%60%60%0A!%5B3a9cacd28b34279af91f572327b7a36b.png%5D(en-resource%3A%2F%2Fdatabase%2F625%3A1)%0A%0A%23%23%23%23%23%23%201.4.2%20%E6%9F%A5%E7%9C%8B%E9%BB%98%E8%AE%A4%E7%9A%84%E5%BC%95%E6%93%8E%0A%0A%60%60%60%0Ashow%20variables%20like%20%25storage_engine%25%0A%60%60%60%0A!%5Beb27aeeb8a0c48c35610893e9ada40b6.png%5D(en-resource%3A%2F%2Fdatabase%2F638%3A1)%0A%0A%0A%23%23%23%23%23%23%201.4.3%20%E6%9F%A5%E7%9C%8BInnoDB%E5%BC%95%E6%93%8E%E5%88%86%E9%A1%B5%E5%A4%A7%E5%B0%8F%0A%3E%20InnoDB%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E%E5%B0%86%E6%95%B0%E6%8D%AE%E5%88%92%E5%88%86%E4%B8%BA%E8%8B%A5%E5%B9%B2%E4%B8%AA%E9%A1%B5%EF%BC%8C%E4%BB%A5%E9%A1%B5%E4%BD%9C%E4%B8%BA%E7%A3%81%E7%9B%98%E5%92%8C%E5%86%85%E5%AD%98%E4%B9%8B%E9%97%B4%E4%BA%A4%E4%BA%92%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%8D%95%E4%BD%8D%EF%BC%8CInnoDB%E4%B8%AD%E9%A1%B5%E7%9A%84%E5%A4%A7%E5%B0%8F%E9%BB%98%E8%AE%A4%E4%B8%BA%20%6016%20KB%60%0A%60%60%60%0Ashow%20variables%20like%20'innodb_page_size'%3B%0A%60%60%60%0A%3E%20%E6%89%80%E4%BB%A5%E5%BD%93%E4%BD%A0%E7%94%A8postman%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%AA%E5%88%86%E9%A1%B5%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3%E6%97%B6%EF%BC%8C%E5%8F%91%E7%8E%B0%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%89%93%E5%8D%B0%E8%80%97%E6%97%B6300%20~%20400ms%EF%BC%8C%E5%BE%80%E5%90%8E%E4%B8%8D%E5%81%9C%E7%9A%84%E6%9F%A5%E6%89%BE%E4%B8%8B%E4%B8%80%E9%A1%B5%E9%83%BD%E6%98%AF30%20~%2040ms%EF%BC%8C%E5%8E%9F%E5%9B%A0%E5%B0%B1%E6%98%AF%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%AF%B7%E6%B1%82%E6%8E%A5%E5%8F%A3%E6%97%B6%EF%BC%8C%E8%AF%BB%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E6%97%B6%E5%80%99%E9%9C%80%E8%A6%81%E8%AF%BB%E7%A3%81%E7%9B%98%EF%BC%8C%E4%BB%8E%E7%A3%81%E7%9B%98%E5%8A%A0%E8%BD%BD16KB%E7%9A%84%E6%95%B0%E6%8D%AE%E5%88%B0%E5%86%85%E5%AD%98%EF%BC%8C%E5%BE%80%E5%90%8E%E4%B8%8B%E4%B8%80%E9%A1%B5%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E6%98%AF%E4%BB%8E%E5%86%85%E5%AD%98%E4%B8%AD%E8%8E%B7%E5%8F%96%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%86%8D%E8%AF%BB%E7%A3%81%E7%9B%98%EF%BC%8C%E9%99%A4%E9%9D%9E%E5%9C%A8%E5%86%85%E5%AD%98%E4%B8%AD%E7%9A%8416KB%E7%9A%84%E6%95%B0%E6%8D%AE%E4%B8%AD%E6%89%BE%E4%B8%8D%E5%88%B0%EF%BC%8C%E6%89%8D%E4%BC%9A%E5%86%8D%E6%AC%A1%E8%AF%BB%E7%A3%81%E7%9B%98%E8%8E%B7%E5%8F%96%E4%B8%8B%E4%B8%80%E4%B8%AA16KB%E7%9A%84%E6%95%B0%E6%8D%AE%E5%88%B0%E5%86%85%E5%AD%98%E4%B8%AD%E3%80%82%0A%0A%23%23%23%23%23%23%201.4.4%20%E6%9F%A5%E7%9C%8BInnoDB%E9%BB%98%E8%AE%A4%E8%A1%8C%E6%A0%BC%E5%BC%8F%0A%3E%20mysql%E4%B8%AD%E6%98%AF%E4%BB%A5%E8%AE%B0%E5%BD%95%E4%B8%BA%E5%8D%95%E4%BD%8D%E6%9D%A5%E5%90%91%E8%A1%A8%E4%B8%AD%E6%8F%92%E5%85%A5%E6%95%B0%E6%8D%AE%E7%9A%84%EF%BC%8C%E8%BF%99%E4%BA%9B%E8%AE%B0%E5%BD%95%E5%9C%A8%E7%A3%81%E7%9B%98%E4%B8%8A%E7%9A%84%E5%AD%98%E6%94%BE%E6%96%B9%E5%BC%8F%E4%B9%9F%E8%A2%AB%E7%A7%B0%E4%B8%BA%60%E8%A1%8C%E6%A0%BC%E5%BC%8F%E6%88%96%E8%80%85%E8%AE%B0%E5%BD%95%E6%A0%BC%E5%BC%8F%60%E3%80%82%0A%3E%20%E8%A1%8C%E6%A0%BC%E5%BC%8F%E6%9C%894%E7%A7%8D%EF%BC%8C%E5%88%86%E5%88%AB%E6%98%AF%0A%3E%20Dynamic%E3%80%81Compact%E3%80%81Redundant%E3%80%81Compressed%0A%3E%20%E9%BB%98%E8%AE%A4%E7%9A%84%E8%A1%8C%E6%A0%BC%E5%BC%8F%E4%B8%BA%3A%20Dynamic%0A%0A%60%60%60%0ASHOW%20VARIABLES%20LIKE%20'innodb_default_row_format'%3B%0A%60%60%60%0A!%5B81c9f1eb2dae11f5c130fc5b69ca902a.png%5D(en-resource%3A%2F%2Fdatabase%2F637%3A1)%0A%0A%0A%23%23%23%23%23%201.5%20%E6%9F%A5%E7%9C%8Bbinlog%E6%98%AF%E5%90%A6%E5%BC%80%E5%90%AF%0A%60%60%60sql%0Ashow%20variables%20like%20'log_bin'%0A%60%60%60%20%0A%0A%23%23%23%23%202.%E5%BB%BA%E8%A1%A8%0A%0A%23%23%23%23%23%202.1%20%E5%BB%BA%E8%A1%A8%E8%AF%AD%E5%8F%A5%0A%60%60%60sql%0ACREATE%20TABLE%20%60t_dg_user_address%60%20(%0A%20%20%60id%60%20bigint(64)%20NOT%20NULL%20AUTO_INCREMENT%20COMMENT%20'ID'%2C%0A%20%20%60user_id%60%20bigint(20)%20NOT%20NULL%20COMMENT%20'%E7%94%A8%E6%88%B7ID%2C%E6%A0%B9%E6%8D%AEuser_type%E5%8F%AF%E8%83%BD%E6%98%AFapp%E7%94%A8%E6%88%B7%E6%88%96%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%94%A8%E6%88%B7'%2C%0A%20%20%60user_type%60%20smallint(6)%20DEFAULT%20'1'%20COMMENT%20'%E7%94%A8%E6%88%B7%E7%B1%BB%E5%9E%8B%3A1-%E4%BB%A3%E8%B4%AD%2C2-%E6%AF%94%E6%9F%9A%E5%95%86%E5%AE%B6%2C3-%E5%B0%8F%E7%A8%8B%E5%BA%8F'%2C%0A%20%20%60country_id%60%20bigint(20)%20DEFAULT%20'0'%20COMMENT%20'%E5%9B%BD%E5%AE%B6%E7%BC%96%E5%8F%B7'%2C%0A%20%20%60province_id%60%20bigint(20)%20DEFAULT%20'0'%20COMMENT%20'%E7%9C%81%E4%BB%BDID'%2C%0A%20%20%60city_id%60%20bigint(20)%20DEFAULT%20'0'%20COMMENT%20'%E5%9F%8E%E5%B8%82ID'%2C%0A%20%20%60county_id%60%20bigint(20)%20DEFAULT%20'0'%20COMMENT%20'%E5%8C%BA%E5%8E%BFID'%2C%0A%20%20%60district_id%60%20bigint(20)%20DEFAULT%20'0'%20COMMENT%20'%E8%A1%97%E9%81%93ID'%2C%0A%20%20%60receiving_name%60%20varchar(64)%20DEFAULT%20NULL%20COMMENT%20'%E6%94%B6%E8%B4%A7%E4%BA%BA'%2C%0A%20%20%60receiving_phone%60%20varchar(64)%20DEFAULT%20NULL%20COMMENT%20'%E6%94%B6%E8%B4%A7%E7%94%B5%E8%AF%9D'%2C%0A%20%20%60receiving_address%60%20varchar(256)%20DEFAULT%20NULL%20COMMENT%20'%E6%94%B6%E8%B4%A7%E5%9C%B0%E5%9D%80'%2C%0A%20%20%60dft%60%20tinyint(4)%20NOT%20NULL%20DEFAULT%20'0'%20COMMENT%20'%E6%98%AF%E5%90%A6%E9%BB%98%E8%AE%A4%200-%E5%90%A6%201-%E6%98%AF'%2C%0A%20%20%60record_status%60%20char(1)%20CHARACTER%20SET%20utf8%20COLLATE%20utf8_unicode_ci%20NOT%20NULL%20DEFAULT%20'A'%20COMMENT%20'%E6%98%AF%E5%90%A6%E5%B7%B2%E7%BB%8F%E5%A4%B1%E6%95%88%3AA%E3%80%81%E6%9C%89%E6%95%88%3BI%E3%80%81%E6%97%A0%E6%95%88'%2C%0A%20%20%60create_date%60%20datetime%20NOT%20NULL%20ON%20UPDATE%20CURRENT_TIMESTAMP%2C%0A%20%20%60creator_id%60%20bigint(20)%20DEFAULT%20NULL%2C%0A%20%20%60update_date%60%20timestamp%20NULL%20DEFAULT%20NULL%20ON%20UPDATE%20CURRENT_TIMESTAMP%2C%0A%20%20%60updater_id%60%20bigint(20)%20DEFAULT%20NULL%2C%0A%20%20PRIMARY%20KEY%20(%60id%60)%20USING%20BTREE%2C%0A%20%20KEY%20%60index_name%60%20(%60user_id%60)%20USING%20BTREE%0A)%20ENGINE%3DInnoDB%20DEFAULT%20CHARSET%3Dutf8mb4%20COMMENT%3D'%E7%94%A8%E6%88%B7%E6%94%B6%E8%B4%A7%E5%9C%B0%E5%9D%80'%3B%0A%60%60%60%0A%0A%23%23%23%23%23%201.2%20%E5%A4%8D%E5%88%B6%E8%A1%A8%E7%BB%93%E6%9E%84%0A%0A%E5%8F%AA%E5%A4%8D%E5%88%B6%E8%A1%A8%E7%BB%93%E6%9E%84%E5%88%B0%E6%96%B0%E8%A1%A8%0A%0A%0A%60%60%60sql%0A%23%E6%97%A7%E8%A1%A8%E7%9A%84%E6%89%80%E6%9C%89%E5%AD%97%E6%AE%B5%E7%B1%BB%E5%9E%8B%E9%83%BD%E5%A4%8D%E5%88%B6%E5%88%B0%E6%96%B0%E8%A1%A8%0ACREATE%20TABLE%20%E6%96%B0%E8%A1%A8%20LIKE%20%E6%97%A7%E8%A1%A8%20%3B%0A%0A%23%E4%B8%BB%E9%94%AE%E7%B1%BB%E5%9E%8B%E5%92%8C%E8%87%AA%E5%A2%9E%E6%96%B9%E5%BC%8F%E6%98%AF%E4%B8%8D%E4%BC%9A%E5%A4%8D%E5%88%B6%E8%BF%87%E5%8E%BB%E7%9A%84%0ACREATE%20TABLE%20%E6%96%B0%E8%A1%A8%20SELECT%20*%20FROM%20%E6%97%A7%E8%A1%A8%20WHERE%201%3D2%3B%20%0A%60%60%60%0A%0A%0A%23%23%23%23%23%201.3%20%E5%A4%8D%E5%88%B6%E8%A1%A8%E7%BB%93%E6%9E%84%E5%8F%8A%E6%95%B0%E6%8D%AE%0A%60%60%60sql%0A%0ACREATE%20TABLE%20%E6%96%B0%E8%A1%A8%20SELECT%20*%20FROM%20%E6%97%A7%E8%A1%A8%0A%0A%23%E5%81%87%E8%AE%BE%E4%B8%A4%E4%B8%AA%E8%A1%A8%E7%BB%93%E6%9E%84%E4%B8%80%E6%A0%B7%0AINSERT%20INTO%20%E6%96%B0%E8%A1%A8%20SELECT%20*%20FROM%20%E6%97%A7%E8%A1%A8%0A%0A%23%E5%81%87%E8%AE%BE%E4%B8%A4%E4%B8%AA%E8%A1%A8%E7%BB%93%E6%9E%84%E4%B8%8D%E4%B8%80%E6%A0%B7%0AINSERT%20INTO%20%E6%96%B0%E8%A1%A8(%E5%AD%97%E6%AE%B51%2C%E5%AD%97%E6%AE%B52%2C.......)%20SELECT%20%E5%AD%97%E6%AE%B51%2C%E5%AD%97%E6%AE%B52%2C......%20FROM%20%E6%97%A7%E8%A1%A8%0A%60%60%60%0A%0A%23%23%23%23%203.%E4%BF%AE%E6%94%B9%E8%A1%A8%E7%BB%93%E6%9E%84%0A%23%23%23%23%23%203.1%20%E5%A2%9E%E5%88%A0%E5%AD%97%E6%AE%B5%0A%60%60%60%0AALTER%20TABLE%20employee%20ADD%20COLUMN%20abc%20VARCHAR(255)%20NOT%20NULL%20DEFAULT%20''%3B%0AALTER%20TABLE%20employee%20DROP%20COLUMN%20abc%3B%0A%60%60%60%0A%3E%20%E8%BF%99%E6%9D%A1%E8%AF%AD%E5%8F%A5%E4%BC%9A%E5%90%91%E5%B7%B2%E6%9C%89%E7%9A%84%E8%A1%A8%E4%B8%AD%E5%8A%A0%E5%85%A5%E4%B8%80%E5%88%97%EF%BC%8C%E8%BF%99%E4%B8%80%E5%88%97%E5%9C%A8%E8%A1%A8%E7%9A%84%E6%9C%80%E5%90%8E%E4%B8%80%E5%88%97%E4%BD%8D%E7%BD%AE%E3%80%82%E5%A6%82%E6%9E%9C%E6%88%91%E4%BB%AC%E5%B8%8C%E6%9C%9B%E6%B7%BB%E5%8A%A0%E5%9C%A8%E6%8C%87%E5%AE%9A%E7%9A%84%E4%B8%80%E5%88%97%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8%EF%BC%9A%0A%60alter%20table%20%E8%A1%A8%E5%90%8D%20add%20column%20%E5%88%97%E5%90%8D%20varchar(20)%20not%20null%20after%20user1%3B%60%0A%0A%3E%20%E4%B8%8A%E9%9D%A2%E8%BF%99%E4%B8%AA%E5%91%BD%E4%BB%A4%E7%9A%84%E6%84%8F%E6%80%9D%E6%98%AF%E8%AF%B4%E6%B7%BB%E5%8A%A0addr%E5%88%97%E5%88%B0user1%E8%BF%99%E4%B8%80%E5%88%97%E5%90%8E%E9%9D%A2%E3%80%82%E5%A6%82%E6%9E%9C%E6%83%B3%E6%B7%BB%E5%8A%A0%E5%88%B0%E7%AC%AC%E4%B8%80%E5%88%97%E7%9A%84%E8%AF%9D%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8%EF%BC%9A%0A%60alter%20table%20%E8%A1%A8%E5%90%8D%20add%20column%20%E5%88%97%E5%90%8D%20varchar(20)%20not%20null%20first%3B%60%0A%0A%0A%0A%0A%0A%23%23%23%23%204.insert%20into%20select%0A%0A%0A%23%23%23%23%23%204.1%20%E8%AF%AD%E6%B3%95%0A%60%60%60%0AINSERT%20INTO%20table_xxx%20VALUES()%3B%0AINSERT%20INTO%20table_xxx%20SELECT%20xxx%20from%20table_yyy%3B%0A%60%60%60%0A%0A%23%23%23%23%23%204.2%20%E8%A1%A8%E7%BB%93%E6%9E%84%E4%B8%80%E8%87%B4%0A%E5%BD%93%E8%A1%A8A%E5%92%8C%E8%A1%A8B%E7%9A%84%E8%A1%A8%E7%BB%93%E6%9E%84%E4%B8%80%E8%87%B4%E6%97%B6%EF%BC%8C%E7%9B%B4%E6%8E%A5%E6%8F%92%E5%85%A5%E5%8D%B3%E5%8F%AF%E3%80%82%0A%60%60%60%0Ainsert%20into%20A%20select%20*%20from%20B%3B%0A%60%60%60%0A%23%23%23%23%23%204.3%20%E8%A1%A8%E7%BB%93%E6%9E%84%E4%B8%8D%E4%B8%80%E8%87%B4%0A%E5%BD%93%E8%A1%A8%E7%BB%93%E6%9E%84%E4%B8%8D%E4%B8%80%E8%87%B4%E6%97%B6%EF%BC%88%E5%AD%97%E6%AE%B5%E5%A4%A7%E5%B0%8F%E3%80%81%E7%B1%BB%E5%9E%8B%E9%83%BD%E7%9B%B8%E5%90%8C%EF%BC%89%0A%60%60%60%0Ainsert%20into%20A(col1%2C%20col2)%20select%20col1%2C%20col2%20from%20B%3B%0A%60%60%60%0A%0A%23%23%23%23%23%204.4%20%E6%89%B9%E9%87%8F%E7%94%9F%E6%88%90ID%0A%60%60%60sql%0A--%20%E6%9F%A5%E8%AF%A2%E6%93%8D%E4%BD%9C%E4%BA%BA%E7%9A%84userId%0Aselect%20t.user_id%20from%20ipd_user_core.t_user%20t%20where%20t.user_name%3D'xxx'%3B%0A%0A--%20%E7%94%A8%E4%B8%8A%E9%9D%A2%E6%9F%A5%E8%AF%A2%E5%87%BA%E6%9D%A5%E7%9A%84%20user_id%20%E6%9B%BF%E6%8D%A2%20%7B0%7D%0A%0ASET%20%40k%3A%3D(SELECT%20max(prm.id)%20FROM%20t_project_role_menu%20prm)%3B%0A%0AINSERT%20INTO%20t_project_role_menu%20SELECT%0A%09(%40k%3A%3D%20%40k%2B1)%20as%20id%2C%0A%09(SELECT%20pt.id%20FROM%20t_project_type%20pt%20WHERE%20pt.%60name%60%20%3D%20'xxx'%20)%20AS%20project_type_id%2C%0A%09NULL%20as%20template_id%2C%0A%09c.CODE%20AS%20role_code%2C%0A%09(%20SELECT%20pm.id%20FROM%20t_project_menu%20pm%20WHERE%20pm.menu_name%20%3D%20'xxx'%20)%20as%20menu_id%2C%0A%090%20as%20del_flag%2C%0A%092%20as%20app_id%2C%0A%09%7B0%7D%20as%20create_id%2C%20--%20need%20fix%0A%09CURRENT_TIMESTAMP%20as%20create_time%2C%20%0A%09%7B0%7D%20as%20update_id%2C%20--%20need%20fix%0A%09CURRENT_TIMESTAMP%20as%20update_time%2C%0A%09''%20as%20project_sec_level%20%0AFROM%0A%09(%0A%09SELECT%20t.%60code%60%20%20FROM%20t_project_team_template%20t%20%0A%09WHERE%20t.del_flag%20%3D%200%20%20AND%20t.STATUS%20%3D%201%20%20AND%20t.template_id%20%3D%201000%20%0A%09UNION%0A%09SELECT%20tt.%60code%60%20FROM%20t_team_constant%20tt%20%0A%09WHERE%20tt.type%20%3D%202%20%0A%09)%20c%3B%0A%0A%60%60%60%0A%0A%23%23%23%23%205.%20%E5%B8%B8%E7%94%A8%E5%87%BD%E6%95%B0%0A%0A%23%23%23%23%23%205.1%20FIND_IN_SET(str%2C%20strlist)%0A%3E%20str%20%E8%A6%81%E6%9F%A5%E8%AF%A2%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%0A%3E%20strlist%20%E5%AD%97%E6%AE%B5%E5%90%8D%20%E5%8F%82%E6%95%B0%E4%BB%A5%E2%80%9D%2C%E2%80%9D%E5%88%86%E9%9A%94%20%E5%A6%82%20(1%2C2%2C6%2C8%2C10%2C22)%0A%3E%20%E6%9F%A5%E8%AF%A2%E5%AD%97%E6%AE%B5(strlist)%E4%B8%AD%E5%8C%85%E5%90%AB(str)%E7%9A%84%E7%BB%93%E6%9E%9C%EF%BC%8C%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E4%B8%BAnull%E6%88%96%E8%AE%B0%E5%BD%95%0A%0ASELECT%20FIND_IN_SET('b'%2C%20'a%2Cb%2Cc%2Cd')%3B%0A%E7%BB%93%E6%9E%9C%EF%BC%9A2%0A%E5%9B%A0%E4%B8%BAb%20%E5%9C%A8strlist%E9%9B%86%E5%90%88%E4%B8%AD%E6%94%BE%E5%9C%A82%E7%9A%84%E4%BD%8D%E7%BD%AE%20%E4%BB%8E1%E5%BC%80%E5%A7%8B%0A%0Aselect%20FIND_IN_SET('2'%2C%20'1%EF%BC%8C2')%3B%20%E8%BF%94%E5%9B%9E2%0Aselect%20FIND_IN_SET('6'%2C%20'1')%3B%20%E8%BF%94%E5%9B%9E0%20strlist%E4%B8%AD%E4%B8%8D%E5%AD%98%E5%9C%A8str%EF%BC%8C%E6%89%80%E4%BB%A5%E8%BF%94%E5%9B%9E0%E3%80%82%0A%0A%23%23%23%23%23%205.2%20concat()%0A%0A%5BMySQL%E4%B8%ADconcat%E4%BB%A5%E5%8F%8Agroup_concat%E7%9A%84%E4%BD%BF%E7%94%A8%5D(https%3A%2F%2Fwww.cnblogs.com%2Fxinruyi%2Fp%2F11222724.html)%0A%0A%E5%8A%9F%E8%83%BD%EF%BC%9A%E5%B0%86%E5%A4%9A%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BF%9E%E6%8E%A5%E6%88%90%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%82%0A%E8%AF%AD%E6%B3%95%EF%BC%9Aconcat(str1%2C%20str2%2C...)%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E4%B8%BA%E8%BF%9E%E6%8E%A5%E5%8F%82%E6%95%B0%E4%BA%A7%E7%94%9F%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9C%89%E4%BB%BB%E4%BD%95%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%E4%B8%BAnull%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9E%E5%80%BC%E4%B8%BAnull%E3%80%82%0A%0A!%5B347b1ca7910136421c9e5926911ab4b3.png%5D(en-resource%3A%2F%2Fdatabase%2F626%3A1)%0A%0A%23%23%23%23%23%205.3%20concat_ws()%0A%0A%E5%8A%9F%E8%83%BD%EF%BC%9A%E5%92%8Cconcat()%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%B0%86%E5%A4%9A%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BF%9E%E6%8E%A5%E6%88%90%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E4%BD%86%E6%98%AF%E5%8F%AF%E4%BB%A5%E4%B8%80%E6%AC%A1%E6%80%A7%E6%8C%87%E5%AE%9A%E5%88%86%E9%9A%94%E7%AC%A6%EF%BD%9E%EF%BC%88concat_ws%E5%B0%B1%E6%98%AFconcat%20with%20separator%EF%BC%89%20%20%0A%E8%AF%AD%E6%B3%95%EF%BC%9Aconcat_ws(separator%2C%20str1%2C%20str2%2C%20...)%20%20%20%0A%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%E6%8C%87%E5%AE%9A%E5%88%86%E9%9A%94%E7%AC%A6%E3%80%82%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%E5%88%86%E9%9A%94%E7%AC%A6%E4%B8%8D%E8%83%BD%E4%B8%BAnull%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%BAnull%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E4%B8%BAnull%E3%80%82%0A%0A!%5B821b17064bdcf9dfdbb987830a866676.png%5D(en-resource%3A%2F%2Fdatabase%2F627%3A1)%0A%0A%0A%E6%8A%8A%E5%88%86%E9%9A%94%E7%AC%A6%E6%8C%87%E5%AE%9A%E4%B8%BAnull%EF%BC%8C%E7%BB%93%E6%9E%9C%E5%85%A8%E9%83%A8%E5%8F%98%E6%88%90%E4%BA%86null%EF%BC%9A%0A%0A!%5Bb106ebba3327577dbc87d9606507ccd5.png%5D(en-resource%3A%2F%2Fdatabase%2F628%3A1)%0A%0A%23%23%23%23%23%205.4%20group_concat()%0A%0A%3E%20%E5%8A%9F%E8%83%BD%EF%BC%9A%E5%B0%86group%20by%E4%BA%A7%E7%94%9F%E7%9A%84%E5%90%8C%E4%B8%80%E4%B8%AA%E5%88%86%E7%BB%84%E4%B8%AD%E7%9A%84%E5%80%BC%E8%BF%9E%E6%8E%A5%E8%B5%B7%E6%9D%A5%EF%BC%8C%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%BB%93%E6%9E%9C%E3%80%82%0A%E8%AF%AD%E6%B3%95%EF%BC%9Agroup_concat(%20%5Bdistinct%5D%20%E8%A6%81%E8%BF%9E%E6%8E%A5%E7%9A%84%E5%AD%97%E6%AE%B5%20%5Border%20by%20%E6%8E%92%E5%BA%8F%E5%AD%97%E6%AE%B5%20asc%2Fdesc%20%C2%A0%5D%20%5Bseparator%20'%E5%88%86%E9%9A%94%E7%AC%A6'%5D%20)%0A%0A%E8%AF%B4%E6%98%8E%EF%BC%9A%E9%80%9A%E8%BF%87%E4%BD%BF%E7%94%A8distinct%E5%8F%AF%E4%BB%A5%E6%8E%92%E9%99%A4%E9%87%8D%E5%A4%8D%E5%80%BC%EF%BC%9B%E5%A6%82%E6%9E%9C%E5%B8%8C%E6%9C%9B%E5%AF%B9%E7%BB%93%E6%9E%9C%E4%B8%AD%E7%9A%84%E5%80%BC%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8order%20by%E5%AD%90%E5%8F%A5%EF%BC%9Bseparator%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%80%BC%EF%BC%8C%E7%BC%BA%E7%9C%81%E4%B8%BA%E4%B8%80%E4%B8%AA%E9%80%97%E5%8F%B7%E3%80%82%0A%0A%0A%3E%20%E5%B0%86%E7%9A%84id%E5%8F%B7%E4%BB%8E%E5%A4%A7%E5%88%B0%E5%B0%8F%E6%8E%92%E5%BA%8F%EF%BC%8C%E4%B8%94%E7%94%A8'_'%20%E4%BD%9C%E4%B8%BA%E5%88%86%E9%9A%94%E7%AC%A6%EF%BC%9A%0A%0A!%5B5649423610c08f6845a91424cf36ac14.png%5D(en-resource%3A%2F%2Fdatabase%2F629%3A1)%0A%0A%3E%20%E4%B8%8A%E9%9D%A2%E7%9A%84%E6%9F%A5%E8%AF%A2%E4%B8%AD%E6%98%BE%E7%A4%BA%E4%BA%86%E4%BB%A5name%E5%88%86%E7%BB%84%E7%9A%84%E6%AF%8F%E7%BB%84%E4%B8%AD%E6%89%80%E6%9C%89%E7%9A%84id%E3%80%82%E6%8E%A5%E4%B8%8B%E6%9D%A5%E6%88%91%E4%BB%AC%E8%A6%81%E6%9F%A5%E8%AF%A2%E4%BB%A5name%E5%88%86%E7%BB%84%E7%9A%84%E6%89%80%E6%9C%89%E7%BB%84%E7%9A%84id%E5%92%8Cscore%EF%BC%9A%0A%3E%20%0A!%5B900b749678596f06dbe348a8caab546f.png%5D(en-resource%3A%2F%2Fdatabase%2F630%3A1)%0A%0A%60%60%60sql%0ASELECT%0A%09t.process_instance_id%2C%0A%09t.task_instance_id%2C%0A%09t.process_title%2C%0A%09GROUP_CONCAT(%20t.use_assignee%2C%20'('%2C%20t.assignee%2C%20')'%20)%20AS%20assignee%2C%0A%09t.update_time%2C%0A%09t.del_flag%20%0AFROM%0A%09t_process_instance_task%20t%20%0AWHERE%0A%09t.del_flag%20%3D%200%20%0AGROUP%20BY%0A%09t.process_instance_id%0A%60%60%60%0A%0A%0A%23%23%23%23%23%205.5%20DATE_FORMAT()%0A%0A%60%60%60sql%0ASELECT%0A*%0AFROM%0At_dg_buy_user%20t%0AWHERE%0Aim_token%20IS%20NOT%20NULL%0AAND%20t.create_date%20%3E%3D%20DATE_FORMAT('2019-12-19%2000%3A00%3A00'%2C%20'%25Y-%25m-%25d%20%25H%3A%25i%3A%25s')%0AAND%20t.create_date%20%3C%3D%20DATE_FORMAT('2019-12-19%2023%3A00%3A00'%2C%20'%25Y-%25m-%25d%20%25H%3A%25i%3A%25s')%0AORDER%20BY%0At.create_date%20DESC%3B%0A%60%60%60%0A%0A%23%23%23%23%23%205.6%20REGEXP%0A%60%60%60sql%0Aselect%20*%20from%20t_ms_merchant%20t%20where%20t.shop%20REGEXP%20'%5E%5Ba-z%5D%2B%E3%80%80%5Ba-z%5D%2B%E3%80%80%5Ba-z%5D'%3B%0A%60%60%60%0A%0A%23%23%23%23%23%205.7%20RANK()%0A%3E%20%20RANK()%E5%87%BD%E6%95%B0%E4%B8%BA%E7%BB%93%E6%9E%9C%E9%9B%86%E7%9A%84%E5%88%86%E5%8C%BA%E4%B8%AD%E7%9A%84%E6%AF%8F%E4%B8%80%E8%A1%8C%E5%88%86%E9%85%8D%E4%B8%80%E4%B8%AA%E6%8E%92%E5%90%8D%E3%80%82%0A%3E%20%20%E8%A1%8C%E7%9A%84%E7%AD%89%E7%BA%A7%E7%94%B1%E4%B8%80%E5%8A%A0%E4%B8%8A%E5%89%8D%E9%9D%A2%E7%9A%84%E7%AD%89%E7%BA%A7%E6%95%B0%E6%8C%87%E5%AE%9A%E3%80%82%0A%60%60%60%20sql%0ARANK()%20OVER%20(%0APARTITION%20BY%20%3Cexpression%3E%5B%7B%2C%3Cexpression%3E...%7D%5D%20%20%20%20%0AORDER%20BY%20%3Cexpression%3E%20%5BASC%7CDESC%5D%2C%20%5B%7B%2C%3Cexpression%3E...%7D%5D)%20%0A%60%60%60%0A%3E%20%0A%E5%9C%A8%E8%BF%99%E4%B8%AA%E8%AF%AD%E6%B3%95%E4%B8%AD%EF%BC%9A%0A-%20%E9%A6%96%E5%85%88%EF%BC%8CPARTITION%20BY%E5%AD%90%E5%8F%A5%E5%B0%86%E7%BB%93%E6%9E%9C%E9%9B%86%E5%88%92%E5%88%86%E4%B8%BA%E5%88%86%E5%8C%BA%E3%80%82RANK()%E5%8A%9F%E8%83%BD%E5%9C%A8%E5%88%86%E5%8C%BA%E5%86%85%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%B9%B6%E5%9C%A8%E8%B7%A8%E8%B6%8A%E5%88%86%E5%8C%BA%E8%BE%B9%E7%95%8C%E6%97%B6%E9%87%8D%E6%96%B0%E5%88%9D%E5%A7%8B%E5%8C%96%E3%80%82%0A-%20%E5%85%B6%E6%AC%A1%EF%BC%8CORDER%20BY%E5%AD%90%E5%8F%A5%E6%8C%89%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E5%88%97%E6%88%96%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%AF%B9%E5%88%86%E5%8C%BA%E5%86%85%E7%9A%84%E8%A1%8C%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%E3%80%82%0A%0A%0A%3E%20%E4%B8%8EROW_NUMBER()%E5%87%BD%E6%95%B0%E4%B8%8D%E5%90%8C%EF%BC%8CRANK()%E5%87%BD%E6%95%B0%E5%B9%B6%E4%B8%8D%E6%80%BB%E6%98%AF%E8%BF%94%E5%9B%9E%E8%BF%9E%E7%BB%AD%E7%9A%84%E6%95%B4%E6%95%B0%E3%80%82%0A%0A%60%60%60sql%0Aselect%20t.val%2C%20rank()%20over(order%20by%20t.val)%20from%20rankdemo%20t%3B%0A%60%60%60%0A!%5B8778b59d4c715ab278544ab8313a97ea.png%5D(en-resource%3A%2F%2Fdatabase%2F631%3A1)%0A%0A%0A%3E%20%E7%AC%AC%E4%BA%8C%E8%A1%8C%E5%92%8C%E7%AC%AC%E4%B8%89%E8%A1%8C%E5%85%B7%E6%9C%89%E7%9B%B8%E5%90%8C%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%AE%83%E4%BB%AC%E8%8E%B7%E5%BE%97%E7%9B%B8%E5%90%8C%E7%9A%84%E7%AD%89%E7%BA%A72%E3%80%82%0A%3E%20%E7%AC%AC%E5%9B%9B%E8%A1%8C%E5%85%B7%E6%9C%89%E7%AD%89%E7%BA%A74%EF%BC%8C%E5%9B%A0%E4%B8%BARANK()%E5%8A%9F%E8%83%BD%E8%B7%B3%E8%BF%87%E7%AD%89%E7%BA%A73%E3%80%82%0A%0A%0A%0A%60%60%60sql%0ASELECT%0A%20%20%20%20%20%20%20%20sales_employee%2C%0A%20%20%20%20%20%20%20%20fiscal_year%2C%0A%20%20%20%20%20%20%20%20sale%2C%0A%20%20%20%20%20%20%20%20RANK(%20)%20OVER%20(%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20PARTITION%20BY%20fiscal_year%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ORDER%20BY%20sale%20DESC%0A%20%20%20%20%20%20%20%20)%20sales_rank%20%0AFROM%0A%20%20%20%20%20%20%20%20sales%3B%20%0A%60%60%60%0A!%5B01862f9771846124ba91b0aabc94613c.png%5D(en-resource%3A%2F%2Fdatabase%2F632%3A1)%0A%0A%0A%23%23%23%23%23%205.8%20ROW_NUMBER%0A%3E%20ROW_NUMBER()%E6%98%AF%E4%B8%80%E4%B8%AA%E7%AA%97%E5%8F%A3%E5%87%BD%E6%95%B0%E6%88%96%E5%88%86%E6%9E%90%E5%87%BD%E6%95%B0%EF%BC%8C%E5%AE%83%E4%B8%BA%E4%BB%8E1%E5%BC%80%E5%A7%8B%E5%BA%94%E7%94%A8%E7%9A%84%E6%AF%8F%E4%B8%80%E8%A1%8C%E5%88%86%E9%85%8D%E4%B8%80%E4%B8%AA%E5%BA%8F%E5%8F%B7%0A%0A%60%60%60sql%0AROW_NUMBER()%20OVER%20(%3Cpartition_definition%3E%20%3Corder_definition%3E%20%0AORDER%20BY%20%3Cexpression%3E%20%5BASC%7CDESC%5D%2C%5B%7B%2C%3Cexpression%3E%7D...%5D%20)%20%0A%60%60%60%0A%0A%3E%20%E4%BD%BF%E7%94%A8%E5%85%AC%E7%94%A8%E8%A1%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%88CTE%EF%BC%89%E8%BF%94%E5%9B%9E%E8%A6%81%E5%88%A0%E9%99%A4%E7%9A%84%E9%87%8D%E5%A4%8D%E8%A1%8C%E5%92%8Cdelete%E8%AF%AD%E5%8F%A5%0A%0A%60%60%60sql%0AWITH%20dups%20AS%20(%0A%20%20%20%20SELECT%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20id%2C%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20name%2C%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20ROW_NUMBER()%20%0A%20%20%20%20%20%20%20%20OVER(PARTITION%20BY%20name%20ORDER%20BY%20name)%20AS%20row_num%0A%20%20%20%20FROM%20rowNumberDemo)%0ADELETE%20rowNumberDemo%20FROM%20rowNumberDemo%20INNER%20JOIN%20dups%20ON%20rowNumberDemo.id%20%3D%20dups.id%0AWHERE%20dups.row_num%20%3C%3E%201%3B%20%0A%60%60%60%0A%0A%23%23%23%23%23%205.9%20INSTR%0A%3E%20%E5%87%BD%E6%95%B0%E8%AF%AD%E6%B3%95%20INSTR(str%2Csubstr)%0A%3E%20instr(%E6%BA%90%E5%AD%97%E7%AC%A6%E4%B8%B2%2C%20%E7%9B%AE%E6%A0%87%E5%AD%97%E7%AC%A6%E4%B8%B2)%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E%EF%BC%9Astr%EF%BC%9A%E6%BA%90%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E6%90%9C%E7%B4%A2%EF%BC%9Bsubstr%3A%20%E8%A6%81%E6%90%9C%E7%B4%A2%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%82%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%9Ainstr('apple'%2C'a')%EF%BC%8C%E8%BF%94%E5%9B%9E%E7%9A%84%E6%9F%A5%E8%AF%A2%E7%BB%93%E6%9E%9C%E6%98%AF1a%E5%87%BA%E7%8E%B0%E5%9C%A8%E5%AD%97%E7%AC%A6%E4%B8%B2%E2%80%98apple%E2%80%99%E4%B8%AD%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%EF%BC%9B%0A%0A%23%23%23%23%206.%20CTE%0A%0A%3E%20%E5%85%AC%E7%94%A8%E8%A1%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%98%AF%E4%B8%80%E4%B8%AA%E5%91%BD%E5%90%8D%E7%9A%84%E4%B8%B4%E6%97%B6%E7%BB%93%E6%9E%9C%E9%9B%86%0A%3E%20%E4%BB%85%E5%9C%A8%E5%8D%95%E4%B8%AASQL%E8%AF%AD%E5%8F%A5(%E4%BE%8B%E5%A6%82SELECT%EF%BC%8CINSERT%EF%BC%8CUPDATE%E6%88%96DELETE)%E7%9A%84%E6%89%A7%E8%A1%8C%E8%8C%83%E5%9B%B4%E5%86%85%E5%AD%98%E5%9C%A8.%0A%0A%0A%3E%20%E4%B8%8E%E6%B4%BE%E7%94%9F%E8%A1%A8%E4%B8%8D%E5%90%8C%EF%BC%8CCTE%E5%8F%AF%E4%BB%A5%E6%98%AF%E8%87%AA%E5%BC%95%E7%94%A8(%E9%80%92%E5%BD%92CTE)%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%90%8C%E4%B8%80%E6%9F%A5%E8%AF%A2%E4%B8%AD%E5%A4%9A%E6%AC%A1%E5%BC%95%E7%94%A8%E3%80%82%20%E6%AD%A4%E5%A4%96%EF%BC%8C%E4%B8%8E%E6%B4%BE%E7%94%9F%E8%A1%A8%E7%9B%B8%E6%AF%94%EF%BC%8CCTE%E6%8F%90%E4%BE%9B%E4%BA%86%E6%9B%B4%E5%A5%BD%E7%9A%84%E5%8F%AF%E8%AF%BB%E6%80%A7%E5%92%8C%E6%80%A7%E8%83%BD%E3%80%82%0A%0A%0A%23%23%23%23%23%206.1%20%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95%0A%60%60%60sql%0AWITH%20cte_name%20(column_list)%20AS%20(%20%0A%20%20%20%20query%0A%20)%20%0A%20SELECT%20*%20FROM%20cte_name%3B%0A%60%60%60%0A%0A%3E%20%E6%9F%A5%E8%AF%A2%E4%B8%AD%E7%9A%84%E5%88%97%E6%95%B0%E5%BF%85%E9%A1%BB%E4%B8%8Ecolumn_list%E4%B8%AD%E7%9A%84%E5%88%97%E6%95%B0%E7%9B%B8%E5%90%8C%E3%80%82%20%0A%3E%20%E5%A6%82%E6%9E%9C%E7%9C%81%E7%95%A5column_list%EF%BC%8CCTE%E5%B0%86%E4%BD%BF%E7%94%A8%E5%AE%9A%E4%B9%89CTE%E7%9A%84%E6%9F%A5%E8%AF%A2%E7%9A%84%E5%88%97%E5%88%97%E8%A1%A8%E3%80%82%0A%0A%23%23%23%23%23%206.2%20%E5%AE%9E%E4%BE%8B%20%0A%0A%3E%20CTE%E7%9A%84%E5%90%8D%E7%A7%B0%E4%B8%BAcustomers_in_usa%EF%BC%8C%E5%AE%9A%E4%B9%89CTE%E7%9A%84%E6%9F%A5%E8%AF%A2%E8%BF%94%E5%9B%9E%E4%B8%A4%E5%88%97%EF%BC%9AcustomerName%E5%92%8Cstate%E3%80%82%0A%3E%20%E5%9B%A0%E6%AD%A4%EF%BC%8Ccustomers_in_usa%20CTE%E8%BF%94%E5%9B%9E%E4%BD%8D%E4%BA%8E%E7%BE%8E%E5%9B%BD%E7%9A%84%E6%89%80%E6%9C%89%E5%AE%A2%E6%88%B7%E3%80%82%0A%3E%20%E5%9C%A8%E5%AE%9A%E4%B9%89%E7%BE%8E%E5%9B%BDCTE%E7%9A%84%E5%AE%A2%E6%88%B7%E4%B9%8B%E5%90%8E%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E5%9C%A8SELECT%E8%AF%AD%E5%8F%A5%E4%B8%AD%E5%BC%95%E7%94%A8%E5%AE%83%EF%BC%8C%E4%BE%8B%E5%A6%82%EF%BC%8C%E4%BB%85%E6%9F%A5%E8%AF%A2%E9%80%89%E6%8B%A9%E4%BD%8D%E4%BA%8ECalifornia%20%E7%9A%84%E5%AE%A2%E6%88%B7%0A%0A%60%60%60sql%0AWITH%20customers_in_usa%20AS%0A(%0A%20%20%20%20SELECT%20%0A%20%20%20%20%20%20%20%20customerName%2C%20state%20%0A%20%20%20%20FROM%20customers%20%0A%20%20%20%20WHERE%20country%20%3D%20'USA'%0A)%0ASELECT%20customerName%20FROM%20customers_in_usa%20WHERE%20state%20%3D%20'CA'%20ORDER%20BY%20customerName%3B%0A%60%60%60%0A%0A%0A%3E%E8%BF%94%E5%9B%9E%E4%BA%86%E5%9C%A82013%E5%B9%B4%E5%89%8D%E4%BA%94%E5%90%8D%E7%9A%84%E9%94%80%E5%94%AE%E4%BB%A3%E8%A1%A8%E3%80%82%0A%3E%E4%B9%8B%E5%90%8E%EF%BC%8C%E6%88%91%E4%BB%AC%E5%BC%95%E7%94%A8%E4%BA%86topsales2013%20CTE%E6%9D%A5%E8%8E%B7%E5%8F%96%E6%9C%89%E5%85%B3%E9%94%80%E5%94%AE%E4%BB%A3%E8%A1%A8%E7%9A%84%E5%85%B6%E4%BB%96%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%8C%85%E6%8B%AC%E5%90%8D%E5%AD%97%E5%92%8C%E5%A7%93%E6%B0%8F%E3%80%82%0A%60%60%60sql%0AWITH%20topsales2013%20AS%20(%0ASELECT%0A%20%20%20%20salesRepEmployeeNumber%20employeeNumber%2C%20%0A%20%20%20%20SUM(quantityOrdered%20*%20priceEach)%20sales%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%0AFROM%20orders%0A%20%20%20%20INNER%20JOIN%20orderdetails%20USING%20(orderNumber)%C2%A0%0A%20%20%20%20INNER%20JOIN%20customers%20USING%20(customerNumber)%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%0AWHERE%20YEAR(shippedDate)%20%3D%202013%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%0AAND%20status%20%3D%20'Shipped'%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%0AGROUP%20BY%20salesRepEmployeeNumber%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%0AORDER%20BY%20sales%20DESC%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%0ALIMIT%205)%0ASELECT%20%0A%20%20%20%20employeeNumber%2C%20firstName%2C%20lastName%2C%20sales%20%0AFROM%20%0A%20%20%20%20employees%20JOIN%20topsales2013%20USING%20(employeeNumber)%3B%0A%60%60%60%0A%0A%0A%3E%20%E5%9C%A8%E5%90%8C%E4%B8%80%E6%9F%A5%E8%AF%A2%E4%B8%AD%E6%9C%89%E4%B8%A4%E4%B8%AACTE%E3%80%82%0A%3E%20%20%E7%AC%AC%E4%B8%80%E4%B8%AACTE(salesrep)%E8%8E%B7%E5%BE%97%E8%81%8C%E4%BD%8D%E6%98%AF%E9%94%80%E5%94%AE%E4%BB%A3%E8%A1%A8%E7%9A%84%E5%91%98%E5%B7%A5%E3%80%82%20%0A%3E%20%20%E7%AC%AC%E4%BA%8C%E4%B8%AACTE(customer_salesrep)%E4%BD%BF%E7%94%A8INNER%20JOIN%E5%AD%90%E5%8F%A5%E4%B8%8E%E7%AC%AC%E4%B8%80%E4%B8%AACTE%E8%BF%9E%E6%8E%A5%E6%9D%A5%E8%8E%B7%E5%8F%96%E6%AF%8F%E4%B8%AA%E9%94%80%E5%94%AE%E4%BB%A3%E8%A1%A8%E8%B4%9F%E8%B4%A3%E7%9A%84%E5%AE%A2%E6%88%B7%E3%80%82%0A%3E%20%20%E5%9C%A8%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%BA%8C%E4%B8%AACTE%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%BD%BF%E7%94%A8%E5%B8%A6%E6%9C%89ORDER%20BY%E5%AD%90%E5%8F%A5%E7%9A%84%E7%AE%80%E5%8D%95SELECT%E8%AF%AD%E5%8F%A5%E6%9D%A5%E6%9F%A5%E8%AF%A2%E6%9D%A5%E8%87%AA%E8%AF%A5CTE%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A%60%60%60sql%0AWITH%20salesrep%20AS%20(%0A%20%20%20%20SELECT%20employeeNumber%2C%0A%20%20%20%20%20%20%20%20%20%20%20CONCAT(firstName%2C%20'%20'%2C%20lastName)%20AS%20salesrepName%0A%20%20%20%20FROM%20employees%0A%20%20%20%20WHERE%20jobTitle%20%3D%20'Sales%20Rep'%0A)%2C%0A%20%20%20%20customer_salesrep%20AS%20(%0A%20%20%20%20%20%20%20%20%20SELECT%20customerName%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20salesrepName%0A%20%20%20%20%20%20%20%20%20FROM%20customers%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20INNER%20JOIN%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20salesrep%20ON%20employeeNumber%20%3D%20salesrepEmployeeNumber%0A%20%20%20%20)%0ASELECT%20*%0AFROM%20customer_salesrep%0AORDER%20BY%20customerName%3B%0A%60%60%60%0A%0A%23%23%23%23%23%206.2%20%20WITH%E5%AD%90%E5%8F%A5%E7%94%A8%E6%B3%95%0A-%20%E5%9C%A8SELECT%EF%BC%8CUPDATE%E5%92%8CDELETE%E8%AF%AD%E5%8F%A5%E7%9A%84%E5%BC%80%E5%A4%B4%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8WITH%E5%AD%90%E5%8F%A5%0A%60%60%60sql%0A%20%20%20%20WITH%20...%20SELECT%20...%20%0A%20%20%20%20WITH%20...%20UPDATE%20...%20%0A%20%20%20%20WITH%20...%20DELETE%20..%0A%60%60%60%0A-%20%E5%9C%A8%E5%AD%90%E6%9F%A5%E8%AF%A2%E6%88%96%E6%B4%BE%E7%94%9F%E8%A1%A8%E5%AD%90%E6%9F%A5%E8%AF%A2%E7%9A%84%E5%BC%80%E5%A4%B4%E4%BD%BF%E7%94%A8WITH%E5%AD%90%E5%8F%A5%0A%60%60%60sql%0A%20%20%20%20SELECT%20...%20WHERE%20id%20IN%20(WITH%20...%20SELECT%20...)%3B%20%0A%20%20%20%20SELECT%20*%20FROM%20(WITH%20...%20SELECT%20...)%20AS%20derived_table%3B%0A%60%60%60%0A%0A%23%23%23%23%207%20JSon%0A%23%23%23%23%23%207.1%E5%9F%BA%E6%9C%AC%E6%96%B9%E6%B3%95%0A%23%23%23%23%23%23%207.1.1%20JSON_UNQUOTE%0A%60%60%60%0A%20JSON_UNQUOTE(val)%0A%60%60%60%0A%3E%20%E5%8E%BB%E6%8E%89val%E7%9A%84%E5%BC%95%E5%8F%B7%E3%80%82%E5%A6%82%E6%9E%9Cval%E4%B8%BANULL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%60%60%60sql%0ASELECT%20JSON_UNQUOTE(%22%5C%22123%5C%22%22)%3B%20--%20123%0A%60%60%60%0A%0A%3E%20%E5%8E%BB%E9%99%A4json%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%BC%95%E5%8F%B7%EF%BC%8C%E5%B0%86%E5%80%BC%E8%BD%AC%E6%88%90string%E7%B1%BB%E5%9E%8B%0A%60%60%60sql%0ASELECT%0A%20%20%20%20userId%2C%0A%20%20%20%20JSON_EXTRACT(loginInfo%2C%20%22%24.cellphone%22)%20cellphone%2C%0A%20%20%20%20JSON_EXTRACT(loginInfo%2C%20%22%24.wxchat%22)%20wxchat%0AFROM%20UserLogin%3B%0A%60%60%60%0A!%5Badd7bf69dae0c8dac156e0e83be213d1.png%5D(en-resource%3A%2F%2Fdatabase%2F635%3A1)%0A%0A%60%60%60sql%0ASELECT%0A%20%20%20%20userId%2C%0A%20%20%20%20JSON_UNQUOTE(JSON_EXTRACT(loginInfo%2C%20%22%24.cellphone%22))%20cellphone%2C%0A%20%20%20%20JSON_UNQUOTE(JSON_EXTRACT(loginInfo%2C%20%22%24.wxchat%22))%20wxchat%0AFROM%20UserLogin%3B%0A%60%60%60%0A!%5Bac65e9005952c27c5432190c2684ed7e.png%5D(en-resource%3A%2F%2Fdatabase%2F636%3A1)%0A%0A%23%23%23%23%23%23%207.1.2%20JSON_LENGTH%0A%60%60%60sql%0AJSON_LENGTH(json_doc%5B%2C%20path%5D)%0A%60%60%60%0A%3E%20%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%9A%84%E9%95%BF%E5%BA%A6%E3%80%82%E5%A6%82%E6%9E%9C%E5%8F%82%E6%95%B0%E4%B8%BANULL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%E3%80%80%0A%3E%20%E9%95%BF%E5%BA%A6%E7%9A%84%E8%AE%A1%E7%AE%97%E8%A7%84%E5%88%99%EF%BC%9A%0A%3E%20%E6%A0%87%E9%87%8F%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%BA1%EF%BC%9B%0A%3E%20json%20array%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%BA%E5%85%83%E7%B4%A0%E7%9A%84%E4%B8%AA%E6%95%B0%EF%BC%9B%0A%3E%20json%20object%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%BAkey%E7%9A%84%E4%B8%AA%E6%95%B0%E3%80%82%0A%0A%60%60%60sql%0ASELECT%20JSON_LENGTH('%5B1%2C%202%2C%20%7B%22a%22%3A%203%7D%5D')%3B%20--%203%0ASELECT%20JSON_LENGTH('%7B%22a%22%3A%201%2C%20%22b%22%3A%20%7B%22c%22%3A%2030%7D%7D')%3B%20--%202%0ASELECT%20JSON_LENGTH('%7B%22a%22%3A%201%2C%20%22b%22%3A%20%7B%22c%22%3A%2030%7D%7D'%2C%20'%24.b')%3B%20--%201%0A%60%60%60%0A%20%20%20%20%0A%23%23%23%23%23%23%207.1.3%20JSON_VALID%0A%60%60%60%0AJSON_VALID(val)%0A%60%60%60%0A%3E%20%E5%88%A4%E6%96%ADval%E6%98%AF%E5%90%A6%E4%B8%BA%E6%9C%89%E6%95%88%E7%9A%84json%E6%A0%BC%E5%BC%8F%EF%BC%8C%E6%98%AF%E4%B8%BA1%EF%BC%8C%E4%B8%8D%E6%98%AF%E4%B8%BA0%E3%80%82%E5%A6%82%E6%9E%9C%E5%8F%82%E6%95%B0%E4%B8%BANUL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%0A%60%60%60sql%0ASELECT%20JSON_VALID('%7B%22a%22%3A%201%7D')%3B%20--%201%0ASELECT%20JSON_VALID('hello')%2C%20JSON_VALID('%22hello%22')%3B%20--%201%0A%60%60%60%0A%23%23%23%23%23%23%207.1.4%20JSON_KEYS%0A%60%60%60%0AJSON_KEYS(json_doc%5B%2C%20path%5D)%0A%60%60%60%0A%3E%20%E8%8E%B7%E5%8F%96json%E6%96%87%E6%A1%A3%E5%9C%A8%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%9A%84%E6%89%80%E6%9C%89%E9%94%AE%E5%80%BC%EF%BC%8C%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AAjson%20array%E3%80%82%E5%A6%82%E6%9E%9C%E6%9C%89%E5%8F%82%E6%95%B0%E4%B8%BANULL%E6%88%96path%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%0A%60%60%60sql%0ASELECT%20JSON_KEYS('%7B%22a%22%3A%201%2C%20%22b%22%3A%20%7B%22c%22%3A%2030%7D%7D')%3B%20--%20%5B%22a%22%2C%20%22b%22%5D%0ASELECT%20JSON_KEYS('%7B%22a%22%3A%201%2C%20%22b%22%3A%20%7B%22c%22%3A%2030%7D%7D'%2C%20'%24.b')%3B%20--%20%5B%22c%22%5D%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.1.5%20JSON_TYPE%0A%60%60%60%0AJSON_TYPE(json_val)%0A%60%60%60%0A%3E%20%E8%8E%B7%E5%8F%96json%E6%96%87%E6%A1%A3%E7%9A%84%E5%85%B7%E4%BD%93%E7%B1%BB%E5%9E%8B%E3%80%82%E5%A6%82%E6%9E%9C%E5%8F%82%E6%95%B0%E4%B8%BANULL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%60%60%60sql%0Aselect%20JSON_TYPE('%5B1%2C2%5D')%3B%20--%20ARRAY%0A%60%60%60%0A%3E%20For%20a%20non-NULL%2C%20non-error%20result%2C%20the%20following%20list%20describes%20the%20possible%20-%20JSON_TYPE()%20return%20values%3A%0A%0A-%20Purely%20JSON%20types%3A%0A%20%20%20%20%3E%20-%20%60OBJECT%60%3A%20JSON%20objects%0A%20%20%20%20%3E%20-%20%60ARRAY%60%3A%20JSON%20arrays%0A%20%20%20%20%3E%20-%20%60BOOLEAN%60%3A%20The%20JSON%20true%20and%20false%20literals%0A%20%20%20%20%3E%20-%20%60NULL%60%3A%20The%20JSON%20null%20literal%0A%0A-%20Numeric%20types%3A%0A%20%20%20%20%3E%20-%20INTEGER%3A%20MySQL%20TINYINT%2C%20SMALLINT%2C%20MEDIUMINT%20and%20INT%20and%20BIGINT%20scalars%0A%20%20%20%20%3E%20-%20%60DOUBLE%60%3A%20MySQL%20DOUBLE%20FLOAT%20scalars%0A%20%20%20%20%3E%20-%20%60DECIMAL%60%3A%20MySQL%20DECIMAL%20and%20NUMERIC%20scalars%0A%0A-%20Temporal%20types%3A%0A%20%20%20%20%3E%20-%20%60DATETIME%60%3A%20MySQL%20DATETIME%20and%20TIMESTAMP%20scalars%0A%20%20%20%20%3E%20-%20%60DATE%60%3A%20MySQL%20DATE%20scalars%0A%20%20%20%20%3E%20-%20%60TIME%60%3A%20MySQL%20TIME%20scalars%0A%0A-%20String%20types%3A%0A%20%20%20%20%3E%20-%20%60STRING%60%3A%20MySQL%20utf8%20character%20type%20scalars%3A%20%0A%20%20%20%20%3E%20-%20CHAR%2C%20VARCHAR%2C%20TEXT%2C%20ENUM%2C%20and%20SET%0A%0A-%20Binary%20types%3A%0A%20%20%20%20%3E%20-%20%60BLOB%60%3A%20MySQL%20binary%20type%20scalars%20including%20%0A%20%20%20%20%3E%20-%20BINARY%2C%20VARBINARY%2C%20BLOB%2C%20and%20BIT%0A%0A%23%23%23%23%23%207.2%20%E6%9F%A5%E8%AF%A2%0A%23%23%23%23%23%23%207.2.1%20JSON_EXTRACT%0A%60%60%60%0AJSON_EXTRACT(json_doc%2C%20path%5B%2C%20path%5D%20...)%0A%60%60%60%0A%3E%20%E4%BB%8Ejson%E6%96%87%E6%A1%A3%E9%87%8C%E6%8A%BD%E5%8F%96%E6%95%B0%E6%8D%AE%E3%80%82%E5%A6%82%E6%9E%9C%E6%9C%89%E5%8F%82%E6%95%B0%E6%9C%89NULL%E6%88%96path%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%E5%A6%82%E6%9E%9C%E6%8A%BD%E5%8F%96%E5%87%BA%E5%A4%9A%E4%B8%AApath%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9E%E7%9A%84%E6%95%B0%E6%8D%AE%E5%B0%81%E9%97%AD%E5%9C%A8%E4%B8%80%E4%B8%AAjson%20array%E9%87%8C%0A%0A%60%60%60sql%0Aset%20%40j2%20%3D%20'%5B10%2C%2020%2C%20%5B30%2C%2040%5D%5D'%3B%0ASELECT%20JSON_EXTRACT('%5B10%2C%2020%2C%20%5B30%2C%2040%5D%5D'%2C%20'%24%5B1%5D')%3B%20--%2020%0ASELECT%20JSON_EXTRACT('%5B10%2C%2020%2C%20%5B30%2C%2040%5D%5D'%2C%20'%24%5B1%5D'%2C%20'%24%5B0%5D')%3B%20--%20%5B20%2C%2010%5D%0ASELECT%20JSON_EXTRACT('%5B10%2C%2020%2C%20%5B30%2C%2040%5D%5D'%2C%20'%24%5B2%5D%5B*%5D')%3B%20--%20%5B30%2C%2040%5D%0A%60%60%60%0A%3E%20%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F%0A%3E%20%60%24.paramsName%60%EF%BC%9A%E5%8F%96%E5%87%BA%E4%B8%80%E4%B8%AAkey%E5%AF%B9%E5%BA%94%E7%9A%84value%E3%80%82%0A%3E%20%60%24**.paramsName%20%E3%80%81%24.%5B*%5D.paramsName%60%20%EF%BC%9A%E5%8F%96%E5%87%BAjson%E6%95%B0%E7%BB%84%E6%89%80%E6%9C%89%E8%AF%A5%E5%AD%97%E6%AE%B5key%E5%AF%B9%E5%BA%94%E7%9A%84value%E5%B9%B6%E4%BB%A5%EF%BC%8C%E7%9A%84%E6%96%B9%E5%BC%8F%E6%8B%BC%E6%8E%A5%E5%9C%A8%E4%B8%80%E8%B5%B7%0A%60%60%60sql%0ASELECT%0A%20%20%20%20userId%2C%0A%20%20%20%20JSON_EXTRACT(loginInfo%2C%20%22%24.cellphone%22)%20cellphone%2C%0A%20%20%20%20JSON_EXTRACT(loginInfo%2C%20%22%24.wxchat%22)%20wxchat%0AFROM%20UserLogin%3B%0A%60%60%60%0A!%5B5e4863a582b2c3517b5ee862e31202d0.png%5D(en-resource%3A%2F%2Fdatabase%2F633%3A1)%0A%0A%60%60%60sql%0Aselect%20json_extract(t.loginInfo%2C%20%22%24**.cellphone%22)%20from%20userlogin%20t%3B%0A%60%60%60%0A!%5B63629d80caa4296af23c5f2754bfd298.png%5D(en-resource%3A%2F%2Fdatabase%2F634%3A1)%0A%0A%23%23%23%23%23%23%207.2.2%20JSON_SEARCH%0A%60%60%60%0AJSON_SEARCH(json_doc%2C%20one_or_all%2C%20search_str%5B%2C%20escape_char%5B%2C%20path%5D%20...%5D)%0A%60%60%60%0A%3E%20%E6%9F%A5%E8%AF%A2%E5%8C%85%E5%90%AB%E6%8C%87%E5%AE%9A%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84paths%EF%BC%8C%E5%B9%B6%E4%BD%9C%E4%B8%BA%E4%B8%80%E4%B8%AAjson%20array%E8%BF%94%E5%9B%9E%E3%80%82%E5%A6%82%E6%9E%9C%E6%9C%89%E5%8F%82%E6%95%B0%E4%B8%BANUL%E6%88%96path%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%3E%20one_or_all%EF%BC%9A%22one%22%E8%A1%A8%E7%A4%BA%E6%9F%A5%E8%AF%A2%E5%88%B0%E4%B8%80%E4%B8%AA%E5%8D%B3%E8%BF%94%E5%9B%9E%EF%BC%9B%22all%22%E8%A1%A8%E7%A4%BA%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%E3%80%82%0A%3E%20search_str%EF%BC%9A%E8%A6%81%E6%9F%A5%E8%AF%A2%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%82%20%E5%8F%AF%E4%BB%A5%E7%94%A8LIKE%E9%87%8C%E7%9A%84'%25'%E6%88%96%E2%80%98_%E2%80%99%E5%8C%B9%E9%85%8D%E3%80%82%0A%3E%20path%EF%BC%9A%E5%9C%A8%E6%8C%87%E5%AE%9Apath%E4%B8%8B%E6%9F%A5%E3%80%82%0A%0A%60%60%60sql%0ASET%20%40j3%20%3D%20'%5B%22abc%22%2C%20%5B%7B%22k%22%3A%20%2210%22%7D%2C%20%22def%22%5D%2C%20%7B%22x%22%3A%22abc%22%7D%2C%20%7B%22y%22%3A%22bcd%22%7D%5D'%3B%0ASELECT%20JSON_SEARCH(%40j3%2C%20'one'%2C%20'abc')%3B%20--%20%22%24%5B0%5D%22%0ASELECT%20JSON_SEARCH(%40j3%2C%20'all'%2C%20'abc')%3B%20--%20%5B%22%24%5B0%5D%22%2C%20%22%24%5B2%5D.x%22%5D%0ASELECT%20JSON_SEARCH(%40j3%2C%20'all'%2C%20'abc'%2C%20NULL%2C%20'%24%5B2%5D')%3B%20--%20%22%24%5B2%5D.x%22%0ASELECT%20JSON_SEARCH(%40j3%2C%20'all'%2C%20'10')%3B%20--%20%22%24%5B1%5D%5B0%5D.k%22%0ASELECT%20JSON_SEARCH(%40j3%2C%20'all'%2C%20'%25b%25')%3B%20--%20%5B%22%24%5B0%5D%22%2C%20%22%24%5B2%5D.x%22%2C%20%22%24%5B3%5D.y%22%5D%0ASELECT%20JSON_SEARCH(%40j3%2C%20'all'%2C%20'%25b%25'%2C%20NULL%2C%20'%24%5B2%5D')%3B%20--%20%22%24%5B2%5D.x%22%0A%60%60%60%0A%0A%23%23%23%23%23%207.3%20%E5%88%A4%E6%96%AD%0A%23%23%23%23%23%23%20%207.3.1%20JSON_CONTAINS%0A%60%60%60%0AJSON_CONTAINS(target%2C%C2%A0candidate%5B%2C%C2%A0path%5D)%0A%60%60%60%0A%3E%20%E5%88%A4%E6%96%ADcandidate%E7%9A%84%E6%98%AF%E5%90%A6%E8%A2%AB%E5%8C%85%E5%90%AB%E5%9C%A8target%E4%B8%AD%0A%3E%20target%E5%92%8Ccandidate%E4%B8%BAjson%20document%0A%3E%20%E5%A6%82%E6%9E%9C%E6%8F%90%E4%BE%9B%E4%BA%86path%E5%8F%82%E6%95%B0%EF%BC%8C%E5%88%99%E5%88%A4%E6%96%ADtarget%E4%B8%AD%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%E4%B8%8B%E6%98%AF%E5%90%A6%E5%8C%85%E5%90%ABcandidate%0A%3E%20%E5%8C%85%E5%90%AB%E8%BF%94%E5%9B%9E1%EF%BC%8C%E6%9C%AA%E5%8C%85%E5%90%AB%E8%BF%94%E5%9B%9E0%0A%0A%60%60%60sql%0ASET%20%40j%20%3D%20'%7B%22a%22%3A%201%2C%20%22b%22%3A%202%2C%20%22c%22%3A%20%7B%22d%22%3A%204%7D%7D'%3B%0ASET%20%40j2%20%3D%20'1'%3B%0ASELECT%20JSON_CONTAINS(%40j%2C%20%40j2%2C%20'%24.a')%3B%20--%201%0ASELECT%20JSON_CONTAINS(%40j%2C%20%40j2%2C%20'%24.b')%3B%20--%200%0A%0ASET%20%40j2%20%3D%20'%7B%22d%22%3A%204%7D'%3B%0ASELECT%20JSON_CONTAINS(%40j%2C%20%40j2%2C%20'%24.a')%3B%20--%200%0ASELECT%20JSON_CONTAINS(%40j%2C%20%40j2%2C%20'%24.c')%3B%20--%201%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.3.2%20JSON_CONTAINS_PATH%0A%60%60%60%0AJSON_CONTAINS_PATH(json_doc%2C%C2%A0one_or_all%2C%C2%A0path%5B%2C%C2%A0path%5D%20...)%0A%60%60%60%0A%3E%20%E6%9F%A5%E8%AF%A2%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%EF%BC%8C%E5%AD%98%E5%9C%A8%E5%88%99%E8%BF%94%E5%9B%9E1%EF%BC%8C%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9E0%E3%80%82%E5%A6%82%E6%9E%9C%E6%9C%89%E5%8F%82%E6%95%B0%E4%B8%BANULL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%3Eone_or_all%E5%8F%AA%E8%83%BD%E5%8F%96%E5%80%BC%22one%22%E6%88%96%22all%22%EF%BC%8Cone%E8%A1%A8%E7%A4%BA%E5%8F%AA%E8%A6%81%E6%9C%89%E4%B8%80%E4%B8%AA%E5%AD%98%E5%9C%A8%E5%8D%B3%E5%8F%AF%EF%BC%9Ball%E8%A1%A8%E7%A4%BA%E6%89%80%E6%9C%89%E7%9A%84%E9%83%BD%E5%AD%98%E5%9C%A8%E6%89%8D%E8%A1%8C%E3%80%82%0A%0A%23%23%23%23%23%207.4%20%E6%8C%87%E5%AE%9A%E4%BD%8D%E7%BD%AE%E6%95%B0%E7%BB%84%E6%93%8D%E4%BD%9C%0A%23%23%23%23%23%23%207.4.1%20JSON_ARRAY_APPEND%0A%0A%60%60%60%0AJSON_ARRAY_APPEND(json_doc%2C%20path%2C%20val%5B%2C%20path%2C%20val%5D%20...)%0A%60%60%60%0A%3E%20%E5%9C%A8%E6%8C%87%E5%AE%9Apath%E7%9A%84json%20array%E5%B0%BE%E9%83%A8%E8%BF%BD%E5%8A%A0val%E3%80%82%0A%3E%20%E5%A6%82%E6%9E%9C%E6%8C%87%E5%AE%9Apath%E6%98%AF%E4%B8%80%E4%B8%AAjson%20object%EF%BC%8C%E5%88%99%E5%B0%86%E5%85%B6%E5%B0%81%E8%A3%85%E6%88%90%E4%B8%80%E4%B8%AAjson%20array%E5%86%8D%E8%BF%BD%E5%8A%A0%E3%80%82%0A%3E%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%8F%82%E6%95%B0%E4%B8%BANULL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%0A%60%60%60sql%0ASET%20%40j4%20%3D%20'%5B%22a%22%2C%20%5B%22b%22%2C%20%22c%22%5D%2C%20%22d%22%5D'%3B%0ASELECT%20JSON_ARRAY_APPEND(%40j4%2C%20'%24%5B1%5D%5B0%5D'%2C%203)%3B%20--%20%5B%22a%22%2C%20%5B%5B%22b%22%2C%203%5D%2C%20%22c%22%5D%2C%20%22d%22%5D%0ASET%20%40j5%20%3D%20'%7B%22a%22%3A%201%2C%20%22b%22%3A%20%5B2%2C%203%5D%2C%20%22c%22%3A%204%7D'%3B%0ASELECT%20JSON_ARRAY_APPEND(%40j5%2C%20'%24.b'%2C%20'x')%3B%20--%20%7B%22a%22%3A%201%2C%20%22b%22%3A%20%5B2%2C%203%2C%20%22x%22%5D%2C%20%22c%22%3A%204%7D%0ASELECT%20JSON_ARRAY_APPEND(%40j5%2C%20'%24.c'%2C%20'y')%3B%20--%20%7B%22a%22%3A%201%2C%20%22b%22%3A%20%5B2%2C%203%5D%2C%20%22c%22%3A%20%5B4%2C%20%22y%22%5D%7D%0ASELECT%20JSON_ARRAY_APPEND(%40j5%2C%20'%24'%2C%20'z')%3B%20--%20%5B%7B%22a%22%3A%201%2C%20%22b%22%3A%20%5B2%2C%203%5D%2C%20%22c%22%3A%204%7D%2C%20%22z%22%5D%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.4.2%20JSON_ARRAY_INSERT%0A%60%60%60%0AJSON_ARRAY_INSERT(json_doc%2C%20path%2C%20val%5B%2C%20path%2C%20val%5D%20...)%0A%60%60%60%0A%3E%20%E5%9C%A8path%E6%8C%87%E5%AE%9A%E7%9A%84json%20array%E5%85%83%E7%B4%A0%E6%8F%92%E5%85%A5val%EF%BC%8C%E5%8E%9F%E4%BD%8D%E7%BD%AE%E5%8F%8A%E4%BB%A5%E5%8F%B3%E7%9A%84%E5%85%83%E7%B4%A0%E9%A1%BA%E6%AC%A1%E5%8F%B3%E7%A7%BB%E3%80%82%E5%A6%82%E6%9E%9Cpath%E6%8C%87%E5%AE%9A%E7%9A%84%E6%95%B0%E6%8D%AE%E9%9D%9Ejson%20array%E5%85%83%E7%B4%A0%EF%BC%8C%E5%88%99%E7%95%A5%E8%BF%87%E6%AD%A4val%EF%BC%9B%E5%A6%82%E6%9E%9C%E6%8C%87%E5%AE%9A%E7%9A%84%E5%85%83%E7%B4%A0%E4%B8%8B%E6%A0%87%E8%B6%85%E8%BF%87json%20array%E7%9A%84%E9%95%BF%E5%BA%A6%EF%BC%8C%E5%88%99%E6%8F%92%E5%85%A5%E5%B0%BE%E9%83%A8%E3%80%82%0A%60%60%60sql%0ASET%20%40j6%20%3D%20'%5B%22a%22%2C%20%7B%22b%22%3A%20%5B1%2C%202%5D%7D%2C%20%5B3%2C%204%5D%5D'%3B%0ASELECT%20JSON_ARRAY_INSERT(%40j6%2C%20'%24%5B1%5D'%2C%20'x')%3B%20--%20%5B%22a%22%2C%20%22x%22%2C%20%7B%22b%22%3A%20%5B1%2C%202%5D%7D%2C%20%5B3%2C%204%5D%5D%0ASELECT%20JSON_ARRAY_INSERT(%40j6%2C%20'%24%5B100%5D'%2C%20'x')%3B%20--%20%5B%22a%22%2C%20%7B%22b%22%3A%20%5B1%2C%202%5D%7D%2C%20%5B3%2C%204%5D%2C%20%22x%22%5D%0ASELECT%20JSON_ARRAY_INSERT(%40j6%2C%20'%24%5B1%5D.b%5B0%5D'%2C%20'x')%3B%20--%20%5B%22a%22%2C%20%7B%22b%22%3A%20%5B%22x%22%2C%201%2C%202%5D%7D%2C%20%5B3%2C%204%5D%5D%0ASELECT%20JSON_ARRAY_INSERT(%40j6%2C%20'%24%5B0%5D'%2C%20'x'%2C%20'%24%5B3%5D%5B1%5D'%2C%20'y')%3B%20--%20%5B%22x%22%2C%20%22a%22%2C%20%7B%22b%22%3A%20%5B1%2C%202%5D%7D%2C%20%5B3%2C%20%22y%22%2C%204%5D%5D%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.4.3%20JSON_ARRAY%0A%60%60%60%0AJSON_ARRAY(val1%2Cval2%2Cval3...)%0A%60%60%60%0A%3E%20%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E5%8C%85%E5%90%AB%E6%8C%87%E5%AE%9A%E5%85%83%E7%B4%A0%E7%9A%84json%E6%95%B0%E7%BB%84%E3%80%82%0A%60%60%60sql%0ASELECT%20JSON_ARRAY(1%2C%20%22abc%22%2C%20NULL%2C%20TRUE%2C%20CURTIME())%3B%20--%20%5B1%2C%20%22abc%22%2C%20null%2C%20true%2C%20%2210%3A37%3A08.000000%22%5D%0A%60%60%60%0A%0A%23%23%23%23%23%207.5%20%E6%8C%87%E5%AE%9A%E4%BD%8D%E7%BD%AE%E4%BF%AE%E6%94%B9%E6%93%8D%E4%BD%9C%0A%23%23%23%23%23%23%207.5.1%20JSON_INSERT%C2%A0%0A%20%0A%60%60%60%0AJSON_INSERT(json_doc%2C%20path%2C%20val%5B%2C%20path%2C%20val%5D%20...)%0A%60%60%60%0A%3E%20%E5%9C%A8%E6%8C%87%E5%AE%9Apath%E4%B8%8B%E6%8F%92%E5%85%A5%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E6%9E%9Cpath%E5%B7%B2%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%88%99%E5%BF%BD%E7%95%A5%E6%AD%A4val%EF%BC%88%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%89%8D%E6%8F%92%E5%85%A5%EF%BC%89%0A%60%60%60java%0ASET%20%40j7%20%3D%20'%7B%20%22a%22%3A%201%2C%20%22b%22%3A%20%5B2%2C%203%5D%7D'%3B%0ASELECT%20JSON_INSERT(%40j7%2C%20'%24.a'%2C%2010%2C%20'%24.c'%2C%20'%5Btrue%2C%20false%5D')%3B%20--%20%7B%22a%22%3A%201%2C%20%22b%22%3A%20%5B2%2C%203%5D%2C%20%22c%22%3A%20%22%5Btrue%2C%20false%5D%22%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.5.2%20JSON_REPLACE%0A%60%60%60%0A%20JSON_REPLACE(json_doc%2C%20path%2C%20val%5B%2C%20path%2C%20val%5D%20...)%0A%60%60%60%0A%3E%20%E6%9B%BF%E6%8D%A2%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9F%90%E4%B8%AA%E8%B7%AF%E5%BE%84%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%88%99%E7%95%A5%E8%BF%87%EF%BC%88%E5%AD%98%E5%9C%A8%E6%89%8D%E6%9B%BF%E6%8D%A2%EF%BC%89%E3%80%82%0A%3E%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%8F%82%E6%95%B0%E4%B8%BANULL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%0A%60%60%60sql%0ASELECT%20JSON_REPLACE(%40j7%2C%20'%24.a'%2C%2010%2C%20'%24.c'%2C%20'%5Btrue%2C%20false%5D')%3B%20--%20%7B%22a%22%3A%2010%2C%20%22b%22%3A%20%5B2%2C%203%5D%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.5.3%20JSON_SET%0A%60%60%60%0AJSON_SET(json_doc%2C%20path%2C%20val%5B%2C%20path%2C%20val%5D%20...)%0A%60%60%60%0A%3E%20%E8%AE%BE%E7%BD%AE%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%88%E4%B8%8D%E7%AE%A1%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%89%E3%80%82%E5%A6%82%E6%9E%9C%E6%9C%89%E5%8F%82%E6%95%B0%E4%B8%BANULL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%60%60%60sql%0ASELECT%20JSON_SET(%40j7%2C%20'%24.a'%2C%2010%2C%20'%24.c'%2C%20'%5Btrue%2C%20false%5D')%3B%20--%20%7B%22a%22%3A%2010%2C%20%22b%22%3A%20%5B2%2C%203%5D%2C%20%22c%22%3A%20%22%5Btrue%2C%20false%5D%22%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.5.4%20JSON_MERGE%0A%60%60%60%0AJSON_MERGE(json_doc%2C%20json_doc%5B%2C%20json_doc%5D%20...)%0A%60%60%60%0A%3E%20merge%E5%A4%9A%E4%B8%AAjson%E6%96%87%E6%A1%A3%E3%80%82%E8%A7%84%E5%88%99%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%3E%20%E5%A6%82%E6%9E%9C%E9%83%BD%E6%98%AFjson%20array%EF%BC%8C%E5%88%99%E7%BB%93%E6%9E%9C%E8%87%AA%E5%8A%A8merge%E4%B8%BA%E4%B8%80%E4%B8%AAjson%20array%EF%BC%9B%0A%3E%20%E5%A6%82%E6%9E%9C%E9%83%BD%E6%98%AFjson%20object%EF%BC%8C%E5%88%99%E7%BB%93%E6%9E%9C%E8%87%AA%E5%8A%A8merge%E4%B8%BA%E4%B8%80%E4%B8%AAjson%20object%EF%BC%9B%0A%3E%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%A4%9A%E7%A7%8D%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%88%99%E5%B0%86%E9%9D%9Ejson%20array%E7%9A%84%E5%85%83%E7%B4%A0%E5%B0%81%E8%A3%85%E6%88%90json%20array%E5%86%8D%E6%8C%89%E7%85%A7%E8%A7%84%E5%88%99%E4%B8%80%E8%BF%9B%E8%A1%8Cmege%E3%80%82%0A%0A%60%60%60sql%0ASELECT%20JSON_MERGE('%5B1%2C%202%5D'%2C%20'%5Btrue%2C%20false%5D')%3B%20--%20%5B1%2C%202%2C%20true%2C%20false%5D%0ASELECT%20JSON_MERGE('%7B%22name%22%3A%20%22x%22%7D'%2C%20'%7B%22id%22%3A%2047%7D')%3B%20--%20%7B%22id%22%3A%2047%2C%20%22name%22%3A%20%22x%22%7D%0ASELECT%20JSON_MERGE('1'%2C%20'true')%3B%20--%20%5B1%2C%20true%5D%0ASELECT%20JSON_MERGE('%5B1%2C%202%5D'%2C%20'%7B%22id%22%3A%2047%7D')%3B%20--%20%5B1%2C%202%2C%20%7B%22id%22%3A%2047%7D%5D%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.5.5%20JSON_REMOVE%C2%A0%0A%60%60%60%0AJSON_REMOVE(json_doc%2C%20path%5B%2C%20path%5D%20...)%0A%60%60%60%0A%3E%20%E7%A7%BB%E9%99%A4%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9F%90%E4%B8%AA%E8%B7%AF%E5%BE%84%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%88%99%E7%95%A5%E8%BF%87%E6%AD%A4%E8%B7%AF%E5%BE%84%E3%80%82%0A%3E%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%8F%82%E6%95%B0%E4%B8%BANULL%EF%BC%8C%E5%88%99%E8%BF%94%E5%9B%9ENULL%E3%80%82%0A%0A%60%60%60sql%0ASET%20%40j8%20%3D%20'%5B%22a%22%2C%20%5B%22b%22%2C%20%22c%22%5D%2C%20%22d%22%5D'%3B%0ASELECT%20JSON_REMOVE(%40j8%2C%20'%24%5B1%5D')%3B%20--%20%5B%22a%22%2C%20%22d%22%5D%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.5.6%20%E7%BB%BC%E5%90%88%E5%AE%9E%E4%BE%8B%0A%60%60%60sql%0A%23%20update%20act_ru_variable's%20TEXT_%20for%20each%20ProcessInstanceID%0A%0Awith%20json_obj_location%20as%20(%0A%20%20%20%20select%20inx1%2C%0A%20%20%20%20%20%20%20%20%20%20%20if(json_contains(json_extract(j_inx.TEXT_%2C%20concat(inx2%2C%20'.'%2C%20'roleIds'))%2C%20json_array('POST_PERSON'))%2C%20inx2%2C%20'%24%5B999%5D')%20inx2%2C%0A%20%20%20%20%20%20%20%20%20%20%20inx3%2C%0A%20%20%20%20%20%20%20%20%20%20%20PROC_INST_ID_%2C%0A%20%20%20%20%20%20%20%20%20%20%20NAME_%0A%20%20%20%20from%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20select%20substring_index(json_unquote(json_search(c.TEXT_%2C%20'one'%2C%20'risk_confirm_modify'))%2C%20'.'%2C%201)%20as%20inx1%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20substring_index(json_unquote(json_search(c.TEXT_%2C%20'one'%2C%20'risk_finnal_confirm'))%2C%20'.'%2C%201)%20as%20inx2%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20substring_index(json_unquote(json_search(c.TEXT_%2C%20'one'%2C%20'create'))%2C%20'.'%2C%201)%20%20%20%20%20%20%20%20%20%20%20%20%20%20as%20inx3%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20c.PROC_INST_ID_%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20c.NAME_%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20c.TEXT_%0A%20%20%20%20%20%20%20%20%20%20%20%20%20from%20act_ru_variable%20c%0A%20%20%20%20%20%20%20%20%20%20%20%20%20where%20c.PROC_INST_ID_%20in%20(%24%7BprocessInsID%7D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20and%20c.NAME_%20%3D%20'users'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20and%20c.TASK_ID_%20is%20null)%20j_inx%0A)%0Aupdate%20act_ru_variable%20uc%20inner%20join%20json_obj_location%20js%20on%20js.NAME_%20%3D%20uc.NAME_%20and%20js.PROC_INST_ID_%20%3D%20uc.PROC_INST_ID_%0Aset%20uc.TEXT_%3D%20(select%20a.json_str_result%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20(select%20json_replace(c.TEXT_%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20concat(js.inx1%2C%20'.'%2C%20'userIds')%2C%20json_array('111111')%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20concat(js.inx1%2C%20'.'%2C%20'userNames')%2C%20json_array('Chris')%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20concat(js.inx2%2C%20'.'%2C%20'userIds')%2C%20json_array('111111')%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20concat(js.inx2%2C%20'.'%2C%20'userNames')%2C%20json_array('Chris')%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20concat(js.inx3%2C%20'.'%2C%20'userIds')%2C%20json_array('111111')%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20concat(js.inx3%2C%20'.'%2C%20'userNames')%2C%20json_array('Chris'))%20as%20json_str_result%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20act_ru_variable%20c%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20where%20c.PROC_INST_ID_%20%3D%20js.PROC_INST_ID_%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20and%20c.NAME_%20%3D%20js.NAME_%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20and%20c.TASK_ID_%20is%20null)%20a)%0Awhere%20uc.PROC_INST_ID_%20%3D%20js.PROC_INST_ID_%0A%20%20and%20uc.NAME_%20%3D%20js.NAME_%0A%20%20and%20uc.TASK_ID_%20is%20null%3B%0A%0A%0A%23%20check%20act_ru_variable%20result%20after%20update%0Aselect%20cast(v.TEXT_%20as%20json)%20from%20act_ru_variable%20v%20where%20v.PROC_INST_ID_%20in%20(%24%7BprocessInsID%7D)%20and%20v.NAME_%20%3D%20'users'%20and%20v.TASK_ID_%20is%20null%20%3B%0A%60%60%60%0A%0A%23%23%23%23%208%20%E8%A1%8C%E8%A1%8C%E6%AF%94%E8%BE%83%0A%3E%20SQL-92%20%E4%B8%AD%E5%8A%A0%E5%85%A5%E4%BA%86%E8%A1%8C%E4%B8%8E%E8%A1%8C%E6%AF%94%E8%BE%83%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E8%BF%99%E6%A0%B7%E4%B8%80%E6%9D%A5%EF%BC%8C%E6%AF%94%E8%BE%83%E8%B0%93%E8%AF%8D%20%3D%20%E3%80%81%3C%20%E3%80%81%3E%20%E5%92%8C%20IN%20%E8%B0%93%E8%AF%8D%E7%9A%84%E5%8F%82%E6%95%B0%E5%B0%B1%E4%B8%8D%E5%86%8D%E5%8F%AA%E6%98%AF%E6%A0%87%E9%87%8F%E5%80%BC%E4%BA%86%EF%BC%8C%E8%BF%98%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%80%BC%E5%88%97%E8%A1%A8%E4%BA%86%0A%3E%20%E8%A1%8C%E8%A1%8C%E6%AF%94%E8%BE%83%E6%AF%94%E8%BE%83%E7%9A%84%E6%98%AFin%E7%9A%84%E5%A4%9A%E5%AD%97%E6%AE%B5%E5%86%99%E6%B3%95%0A%0A%0A%60%60%60sql%0ASELECT%20*%20%0AFROM%20table%0AWHERE%20(%E5%AD%97%E6%AE%B51%20%2C%20%E5%AD%97%E6%AE%B52%2C...%E5%AD%97%E6%AE%B5N)%0Ain%20(%0A(%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B61%20%2C%20%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B62%2C...%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6N)%2C%0A(%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B61%20%2C%20%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B62%2C...%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6N)%2C%0A)%0A%0A%60%60%60%0A%0A%60%60%60sql%0ACREATE%20TABLE%20%60sys_user%60%20(%0A%20%20%60id%60%20bigint(20)%20NOT%20NULL%20AUTO_INCREMENT%20COMMENT%20'id'%2C%0A%20%20%60user_name%60%20varchar(32)%20DEFAULT%20NULL%20COMMENT%20'%E5%85%A8%E5%90%8D'%2C%0A%20%20%60account%60%20varchar(200)%20NOT%20NULL%20COMMENT%20'%E8%B4%A6%E5%8F%B7'%2C%0A%20%20PRIMARY%20KEY%20(%60id%60)%0A)%20ENGINE%3DInnoDB%20AUTO_INCREMENT%3D17%20DEFAULT%20CHARSET%3Dutf8mb4%20COMMENT%3D'%E7%94%A8%E6%88%B7%E8%A1%A8'%3B%0A%60%60%60%0A%0A%60%60%60sql%0ASELECT%20*%20%20FROM%20user%20WHERE%20(id%20%2C%20user_name)in%20((1%2C'u1')%2C(2%2C'u2'))%0A%60%60%60%0A%3E%20%E4%BB%8E%E4%B8%8A%E9%9D%A2%E5%AF%B9%E6%AF%94%E5%8F%91%E7%8E%B0%E6%89%80%E8%B0%93%E7%9A%84%E8%A1%8C%E8%A1%8C%E6%AF%94%E8%BE%83%E5%B0%B1%E6%98%AF%E5%A4%9A%E4%B8%AA%20or%E6%9D%A1%E4%BB%B6%E7%9A%84%E7%AE%80%E5%86%99%E7%89%88%EF%BC%8C%E4%B8%8A%E9%9D%A2%E7%9A%84SQL%E8%AF%AD%E5%8F%A5%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A1%E4%BB%B6or%E6%9D%A5%E8%A1%A8%E8%BE%BE%0A%0A%60%60%60sql%0ASELECT%20*%20%0AFROM%20user%0AWHERE%20%0A(id%3D1%20and%20user_name%20%3D%20'u1')%0AOR%0A(id%3D2%20and%20user_name%20%3D%20'u2')%0A%60%60%60

2022读书单

创建时间:2021/12/27 17:40
更新时间:2022/6/2 11:38
作者:Chris
来源:https://www.szlib.org.cn/Search/searchdetail.jsp?v_tablearray=bibliosm,serbibm,apabibibm,mmbibm,&v_recno=5136156&v_curtable=bibliosm&site=null

1 游戏力=Let the children play

(芬)帕西·萨尔伯格,(英)威廉·多伊尔著;耿一岚

2 断舍离/(日)山下英子著;吴倩译


3 百年孤独

4 North and South

North and South - Elizabeth Gaskell.pdf


The Surrender Experiment



枪炮、病菌与钢铁:人类社会的命运




存在与时间/(德)海德格尔(Martin Heidegger)著;陈嘉映,王庆节译



RegExp

创建时间:2022/5/26 15:39
更新时间:2022/5/30 19:57
作者:Chris
来源:https://blog.csdn.net/ywb201314/article/details/106801253/

1. 查找并替换

将名称按词典中的词条转成全英文词条
例如 : 开始基于数据库进行数据比对 转成 START_BASE_DATA_DATA_COMPARE

sb是一个StringBuffer,replaceContext待替换的字符串,这个方法会把匹配到的内容替换为replaceContext,并且把从上次替换的位置到这次替换位置之间的字符串也拿到,然后,加上这次替换后的结果一起追加到StringBuffer里
假如这次替换是第一次替换,那就是只追加替换后的字符串啦。

matcher.appendReplacement(sb, replaceContent):

sb是一个StringBuffer,这个方法是把最后一次匹配到内容之后的字符串追加到StringBuffer中。

matcher.appendTail(sb);

例子:

@Test
public void buildCode() {
    List<String> nameLines = getNameLines();
    Map<String, String> codeMap = getCodeMap();
    for (String nameLine : nameLines) {
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : codeMap.entrySet()) {
            Pattern p = Pattern.compile(entry.getKey());
            Matcher m = p.matcher(nameLine);
            while (m.find()) {
                m.appendReplacement(sb, "_" + entry.getValue() + "_");
            }
            m.appendTail(sb);
            nameLine = sb.toString();
            sb.setLength(0);
        }
        String result =  nameLine;
        result = result.replaceAll("__", "_");
        String suffix = result.substring(result.length() - 1);
        if (suffix.equals("_")) {
            result = result.substring(0, result.length() - 1);
        }
        System.out.println(result.toUpperCase(Locale.ROOT));
    }
}
%5Btoc%5D%0A%23%23%201.%20%E6%9F%A5%E6%89%BE%E5%B9%B6%E6%9B%BF%E6%8D%A2%0A%3E%20%E5%B0%86%E5%90%8D%E7%A7%B0%E6%8C%89%E8%AF%8D%E5%85%B8%E4%B8%AD%E7%9A%84%E8%AF%8D%E6%9D%A1%E8%BD%AC%E6%88%90%E5%85%A8%E8%8B%B1%E6%96%87%E8%AF%8D%E6%9D%A1%0A%3E%20%E4%BE%8B%E5%A6%82%20%EF%BC%9A%20%60%E5%BC%80%E5%A7%8B%E5%9F%BA%E4%BA%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E6%AF%94%E5%AF%B9%20%E8%BD%AC%E6%88%90%20START_BASE_DATA_DATA_COMPARE%60%0A%0A%3E%20sb%E6%98%AF%E4%B8%80%E4%B8%AAStringBuffer%EF%BC%8CreplaceContext%E5%BE%85%E6%9B%BF%E6%8D%A2%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E4%BC%9A%E6%8A%8A%E5%8C%B9%E9%85%8D%E5%88%B0%E7%9A%84%E5%86%85%E5%AE%B9%E6%9B%BF%E6%8D%A2%E4%B8%BAreplaceContext%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%8A%8A%E4%BB%8E%E4%B8%8A%E6%AC%A1%E6%9B%BF%E6%8D%A2%E7%9A%84%E4%BD%8D%E7%BD%AE%E5%88%B0%E8%BF%99%E6%AC%A1%E6%9B%BF%E6%8D%A2%E4%BD%8D%E7%BD%AE%E4%B9%8B%E9%97%B4%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B9%9F%E6%8B%BF%E5%88%B0%EF%BC%8C%E7%84%B6%E5%90%8E%EF%BC%8C%E5%8A%A0%E4%B8%8A%E8%BF%99%E6%AC%A1%E6%9B%BF%E6%8D%A2%E5%90%8E%E7%9A%84%E7%BB%93%E6%9E%9C%E4%B8%80%E8%B5%B7%E8%BF%BD%E5%8A%A0%E5%88%B0StringBuffer%E9%87%8C%0A%3E%20%E5%81%87%E5%A6%82%E8%BF%99%E6%AC%A1%E6%9B%BF%E6%8D%A2%E6%98%AF%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%9B%BF%E6%8D%A2%EF%BC%8C%E9%82%A3%E5%B0%B1%E6%98%AF%E5%8F%AA%E8%BF%BD%E5%8A%A0%E6%9B%BF%E6%8D%A2%E5%90%8E%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%95%A6%E3%80%82%0A%60%60%60java%0Amatcher.appendReplacement(sb%2C%20replaceContent)%3A%0A%60%60%60%0A%0A%3E%20sb%E6%98%AF%E4%B8%80%E4%B8%AAStringBuffer%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E6%98%AF%E6%8A%8A%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%8C%B9%E9%85%8D%E5%88%B0%E5%86%85%E5%AE%B9%E4%B9%8B%E5%90%8E%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BF%BD%E5%8A%A0%E5%88%B0StringBuffer%E4%B8%AD%E3%80%82%0A%0A%60%60%60java%0Amatcher.appendTail(sb)%3B%0A%60%60%60%0A%0A%3E%20%E4%BE%8B%E5%AD%90%EF%BC%9A%0A%60%60%60java%0A%40Test%0Apublic%20void%20buildCode()%20%7B%0A%20%20%20%20List%3CString%3E%20nameLines%20%3D%20getNameLines()%3B%0A%20%20%20%20Map%3CString%2C%20String%3E%20codeMap%20%3D%20getCodeMap()%3B%0A%20%20%20%20for%20(String%20nameLine%20%3A%20nameLines)%20%7B%0A%20%20%20%20%20%20%20%20StringBuffer%20sb%20%3D%20new%20StringBuffer()%3B%0A%20%20%20%20%20%20%20%20for%20(Map.Entry%3CString%2C%20String%3E%20entry%20%3A%20codeMap.entrySet())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Pattern%20p%20%3D%20Pattern.compile(entry.getKey())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Matcher%20m%20%3D%20p.matcher(nameLine)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20while%20(m.find())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20m.appendReplacement(sb%2C%20%22_%22%20%2B%20entry.getValue()%20%2B%20%22_%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20m.appendTail(sb)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20nameLine%20%3D%20sb.toString()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20sb.setLength(0)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20String%20result%20%3D%20%20nameLine%3B%0A%20%20%20%20%20%20%20%20result%20%3D%20result.replaceAll(%22__%22%2C%20%22_%22)%3B%0A%20%20%20%20%20%20%20%20String%20suffix%20%3D%20result.substring(result.length()%20-%201)%3B%0A%20%20%20%20%20%20%20%20if%20(suffix.equals(%22_%22))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20result%20%3D%20result.substring(0%2C%20result.length()%20-%201)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20System.out.println(result.toUpperCase(Locale.ROOT))%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60

maven tag

创建时间:2022/5/26 19:51
更新时间:2022/5/26 20:03
作者:Chris

1. dependencyManagement

  • 使用 dependencyManagement可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,不用每个模块项目都弄一个版本号,不利于管理.
  • 当需要变更版本号的时候只需要在父类容器里更新,不需要任何一个子项目的修改;
  • 如果某个子项目需要另外一个特殊的版本号时,只需要在自己的模块dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。

dependencies 区别:

%0A%5Btoc%5D%0A%0A%23%23%23%23%201.%20dependencyManagement%0A%3E%20-%20%E4%BD%BF%E7%94%A8%20%60dependencyManagement%20%60%E5%8F%AF%E4%BB%A5%E7%BB%9F%E4%B8%80%E7%AE%A1%E7%90%86%E9%A1%B9%E7%9B%AE%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%EF%BC%8C%E7%A1%AE%E4%BF%9D%E5%BA%94%E7%94%A8%E7%9A%84%E5%90%84%E4%B8%AA%E9%A1%B9%E7%9B%AE%E7%9A%84%E4%BE%9D%E8%B5%96%E5%92%8C%E7%89%88%E6%9C%AC%E4%B8%80%E8%87%B4%EF%BC%8C%E4%B8%8D%E7%94%A8%E6%AF%8F%E4%B8%AA%E6%A8%A1%E5%9D%97%E9%A1%B9%E7%9B%AE%E9%83%BD%E5%BC%84%E4%B8%80%E4%B8%AA%E7%89%88%E6%9C%AC%E5%8F%B7%EF%BC%8C%E4%B8%8D%E5%88%A9%E4%BA%8E%E7%AE%A1%E7%90%86.%0A%3E%20-%20%E5%BD%93%E9%9C%80%E8%A6%81%E5%8F%98%E6%9B%B4%E7%89%88%E6%9C%AC%E5%8F%B7%E7%9A%84%E6%97%B6%E5%80%99%E5%8F%AA%E9%9C%80%E8%A6%81%E5%9C%A8%E7%88%B6%E7%B1%BB%E5%AE%B9%E5%99%A8%E9%87%8C%E6%9B%B4%E6%96%B0%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E4%BB%BB%E4%BD%95%E4%B8%80%E4%B8%AA%E5%AD%90%E9%A1%B9%E7%9B%AE%E7%9A%84%E4%BF%AE%E6%94%B9%EF%BC%9B%0A%3E%20-%20%E5%A6%82%E6%9E%9C%E6%9F%90%E4%B8%AA%E5%AD%90%E9%A1%B9%E7%9B%AE%E9%9C%80%E8%A6%81%E5%8F%A6%E5%A4%96%E4%B8%80%E4%B8%AA%E7%89%B9%E6%AE%8A%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%E6%97%B6%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E5%9C%A8%E8%87%AA%E5%B7%B1%E7%9A%84%E6%A8%A1%E5%9D%97dependencies%E4%B8%AD%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E7%89%88%E6%9C%AC%E5%8F%B7%E5%8D%B3%E5%8F%AF%E3%80%82%E5%AD%90%E7%B1%BB%E5%B0%B1%E4%BC%9A%E4%BD%BF%E7%94%A8%E5%AD%90%E7%B1%BB%E5%A3%B0%E6%98%8E%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%EF%BC%8C%E4%B8%8D%E7%BB%A7%E6%89%BF%E4%BA%8E%E7%88%B6%E7%B1%BB%E7%89%88%E6%9C%AC%E5%8F%B7%E3%80%82%0A%0A%3E%20%E4%B8%8E%20%60dependencies%60%20%E5%8C%BA%E5%88%AB%EF%BC%9A%0A%0A-%201.%20dependencies%20%E7%9B%B8%E5%AF%B9%E4%BA%8E%20dependencyManagement%EF%BC%8C%E6%89%80%E6%9C%89%E5%A3%B0%E6%98%8E%E5%9C%A8dependencies%E9%87%8C%E7%9A%84%E4%BE%9D%E8%B5%96%E9%83%BD%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%BC%95%E5%85%A5%EF%BC%8C%E5%B9%B6%E9%BB%98%E8%AE%A4%E8%A2%AB%E6%89%80%E6%9C%89%E7%9A%84%E5%AD%90%E9%A1%B9%E7%9B%AE%E7%BB%A7%E6%89%BF%E3%80%82%0A-%202.%20dependencyManagement%20%E9%87%8C%E5%8F%AA%E6%98%AF%E5%A3%B0%E6%98%8E%E4%BE%9D%E8%B5%96%EF%BC%8C%E5%B9%B6%E4%B8%8D%E8%87%AA%E5%8A%A8%E5%AE%9E%E7%8E%B0%E5%BC%95%E5%85%A5%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%AD%90%E9%A1%B9%E7%9B%AE%E9%9C%80%E8%A6%81%E6%98%BE%E7%A4%BA%E7%9A%84%E5%A3%B0%E6%98%8E%E9%9C%80%E8%A6%81%E7%94%A8%E7%9A%84%E4%BE%9D%E8%B5%96%E3%80%82%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%9C%A8%E5%AD%90%E9%A1%B9%E7%9B%AE%E4%B8%AD%E5%A3%B0%E6%98%8E%E4%BE%9D%E8%B5%96%EF%BC%8C%E6%98%AF%E4%B8%8D%E4%BC%9A%E4%BB%8E%E7%88%B6%E9%A1%B9%E7%9B%AE%E4%B8%AD%E7%BB%A7%E6%89%BF%E4%B8%8B%E6%9D%A5%E7%9A%84%EF%BC%9B%E5%8F%AA%E6%9C%89%E5%9C%A8%E5%AD%90%E9%A1%B9%E7%9B%AE%E4%B8%AD%E5%86%99%E4%BA%86%E8%AF%A5%E4%BE%9D%E8%B5%96%E9%A1%B9%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%B2%A1%E6%9C%89%E6%8C%87%E5%AE%9A%E5%85%B7%E4%BD%93%E7%89%88%E6%9C%AC%EF%BC%8C%E6%89%8D%E4%BC%9A%E4%BB%8E%E7%88%B6%E9%A1%B9%E7%9B%AE%E4%B8%AD%E7%BB%A7%E6%89%BF%E8%AF%A5%E9%A1%B9%EF%BC%8C%E5%B9%B6%E4%B8%94version%E5%92%8Cscope%E9%83%BD%E8%AF%BB%E5%8F%96%E8%87%AA%E7%88%B6pom%3B%E5%8F%A6%E5%A4%96%E5%A6%82%E6%9E%9C%E5%AD%90%E9%A1%B9%E7%9B%AE%E4%B8%AD%E6%8C%87%E5%AE%9A%E4%BA%86%E7%89%88%E6%9C%AC%E5%8F%B7%EF%BC%8C%E9%82%A3%E4%B9%88%E4%BC%9A%E4%BD%BF%E7%94%A8%E5%AD%90%E9%A1%B9%E7%9B%AE%E4%B8%AD%E6%8C%87%E5%AE%9A%E7%9A%84jar%E7%89%88%E6%9C%AC%E3%80%82

springboot整合mybatis-plus

创建时间:2020/9/7 18:24
更新时间:2022/11/24 23:05
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU2NDEyMzIzOA==&mid=2247497407&idx=1&sn=53fbaa061431dfebf6fa1acd19b55036&chksm=fc4d75b6cb3afca0038a66b9f6394a8985cadec45ff75b24fd5282504113c119475ed6b0359d&mpshare=1&scene=24&srcid=1124xCCO7kvjM8QK3RDC9gWK&sharer_sharetime=1669283182282&sharer_shareid=8f247ffae0fc886917cba955f4d8c07b&key=f4ead0e9638c50a143e761be201913cbd5935d4c7cd89c6cd3db1b57ff662e2ee459528c045b7bf83d95292a8dc58c83d8777e4e32631b29ed14c9a361b52c72fd7edbd6674bf4c3631dddac42018444c7dddf70e9c33d971c1ce9fb0515ec385f3670fe2a707cf17abf89ff4778bb1dd74e28d31fce578e2ef0d1d4970f0595&ascene=14&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=6307062c&lang=en&exportkey=n_ChQIAhIQlzDglFYyWl27QNTVHoOLQxLdAQIE97dBBAEAAAAAAFtoCuw%2B1DIAAAAOpnltbLcz9gKNyK89dVj0owZaTGiVjPddxbnMdB%2BO6n3pRh6LElsmyVfrZcxXkEIZgCZEbrlfFcxWAx5dXrwn%2Bo%2Fm09Az4g2DyCXC8YysBhMpHYDbiDKbVaaNoj3ItSw83cHMC4tjUzu052RXBUrGQXX0hQOoTcxsiAAQbDkdXViQHXeooWF%2Fke14dIJgPs371sSG4YI6vp3OMz2AcU77WIt5OUFyaACHeRQI%2BcY6KUblxhPSMAk13x66CsZ2GyLyp%2B0ivPZX&acctmode=0&pass_ticket=ygM%2FDKEbhQ2O1P3Rtj%2Bmi3ux8foheQNbGuQzROQ7MO49S6RV8mtwxKbfB6nNo6Mx&wx_header=0&fontgear=3

mybatis-plus

1. 官网

1.1 文档

https://baomidou.com/guide/

1.2 源码

https://github.com/baomidou/mybatis-plus

1.3 课程

http://www.baizhiedu.xin/front/index#/main

2.mybatis-plus

2.1 是什么

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

2.2 能干什么

强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求

内置分页插件

内置性能分析插件

支持 Lambda 形式调用

支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )

支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

2.3 怎么玩
2.3.1 入门实例
  1. 建项目

     <groupId>com.chris.mybatis-plus</groupId>
     <artifactId>mybatis-plus2020</artifactId>
    
  2. 改pom

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.3.3.RELEASE</version>
           <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.chris.mybatis-plus</groupId>
       <artifactId>mybatis-plus2020</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>mybatis-plus2020</name>
       <description>Demo project for Spring Boot</description>
    
       <properties>
           <java.version>1.8</java.version>
           <mybatis.plus.version>3.2.0</mybatis.plus.version>
           <mysql.connector.version>6.0.6</mysql.connector.version>
           <druid-version>1.1.10</druid-version>
       </properties>
    
       <dependencies>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
    
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-devtools</artifactId>
               <scope>runtime</scope>
               <optional>true</optional>
           </dependency>
           <dependency>
               <groupId>mysql</groupId>
               <artifactId>mysql-connector-java</artifactId>
               <version>${mysql.connector.version}</version>
               <scope>runtime</scope>
           </dependency>
           <dependency>
               <groupId>org.projectlombok</groupId>
               <artifactId>lombok</artifactId>
               <optional>true</optional>
           </dependency>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>
           <dependency>
               <groupId>com.baomidou</groupId>
               <artifactId>mybatis-plus-boot-starter</artifactId>
               <version>${mybatis.plus.version}</version>
           </dependency>
           <dependency>
               <groupId>cn.hutool</groupId>
               <artifactId>hutool-all</artifactId>
               <version>5.3.5</version>
           </dependency>
           <dependency>
               <groupId>com.alibaba</groupId>
               <artifactId>druid-spring-boot-starter</artifactId>
               <version>${druid-version}</version>
           </dependency>
       </dependencies>
    
       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
               <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-surefire-plugin</artifactId>
                   <version>3.0.0-M5</version>
                   <configuration>
                       <skipTests>true</skipTests>
                   </configuration>
               </plugin>
           </plugins>
       </build>
    </project>
    
  3. 建yml

    server:
      port: 4003
      servlet:
        context-path: /api
      tomcat:
        uri-encoding: UTF-8
    
    spring:
      application:
        name: mybatis-plus2020
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.140.127:3306/chris?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
        username: root
        password: 65536
        druid:
          #初始化时建立物理连接的个数
          initial-size: 5
          #最小连接池数量
          min-idle: 5
          #最大连接池数量 maxIdle已经不再使用
          max-active: 20
          #获取连接时最大等待时间,单位毫秒
          max-wait: 60000
          #申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
          test-while-idle: true
          #既作为检测的间隔时间又作为testWhileIdel执行的依据
          time-between-eviction-runs-millis: 60000
          #销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接
          min-evictable-idle-time-millis: 30000
          #用来检测连接是否有效的sql 必须是一个查询语句
          #mysql中为 select 'x'
          #oracle中为 select 1 from dual
          validation-query: select 'x'
          #申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
          test-on-borrow: false
          #归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
          test-on-return: false
          #当数据库抛出不可恢复的异常时,抛弃该连接
          #exception-sorter: true
          #是否缓存preparedStatement,mysql5.5+建议开启
          pool-prepared-statements: true
          #当值大于0时poolPreparedStatements会自动修改为true
          max-pool-prepared-statement-per-connection-size: 20
          #配置扩展插件
          filters: stat,wall,slf4j,config
          #通过connectProperties属性来打开mergeSql功能;慢SQL记录
          connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;config.decrypt=false;config.decrypt.key=
          #合并多个DruidDataSource的监控数据
          use-global-data-source-stat: true
          #设置访问druid监控页的账号和密码,默认没有
          stat-view-servlet:
            login-username: admin
            login-password: allsale
          filter:
            wall:
              config:
                comment-allow: true
              enabled: true
    
      redis:
        host: master
        password: 123456
        port: 6379
        timeout: 1000
    
      servlet:
        multipart: # 文件传输大小
          max-request-size: 100MB
          max-file-size: 100MB
    
    mybatis-plus:
      mapper-locations: classpath:mappers/*.xml
      global-config:
        db-config:
          #驼峰下划线转换
          #column-underline: true
          #逻辑删除配置
          logic-delete-value: I
          logic-not-delete-value: A
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      #为所有Entity类所在包起默认别名
      type-aliases-package: com.chris.mybatisplus.entities
    
    logging:
      level:
        #根日志级别
        root: info
        #数据查询接口级别
        com.chris.mybatisplus.dao.mapper: debug
    
  4. 主启动

    package com.chris.mybatisplus;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    @MapperScan ("com.chris.mybatisplus.dao.mapper")
    public class MybatisPlusMain {
    
        public static void main(String[] args) {a
            SpringApplication.run(MybatisPlusMain.class, args);
        }
    }
    
  5. 接口类

    package com.chris.mybatisplus.dao.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.chris.mybatisplus.entities.User;
    
    // 使用mybatis-plus增强接口
    public interface UserMapper extends BaseMapper<User> {
    }
    
  6. 业务类

    package com.chris.mybatisplus.entities;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import lombok.experimental.Accessors;
    
    import java.util.Date;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Accessors (chain = true)
    public class User {
    
        private Integer id;
        private String name;
        private Integer age;
        private Date bir;
    }
    
  7. 测试类

    package com.chris.mybatis;
    
    import com.chris.mybatisplus.MybatisPlusMain;
    import com.chris.mybatisplus.dao.mapper.UserMapper;
    import com.chris.mybatisplus.entities.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.List;
    
    @SpringBootTest (classes = MybatisPlusMain.class)
    public class TestMybaisPlus {
    
        @Autowired
        public UserMapper userMapper;
    
        //查询所有
        @Test
        public void testFindAll() {
            List<User> users = userMapper.selectList(null);
            users.forEach(user -> System.out.println("user:" + user));
        }
    }
    
2.3.2 注解
  1. 如果类名与表名一致时,@TableName可以省略

    @TableName("t_user") //在不配置的情况下默认表名与类名一致
    public class User 
    
  2. @TableId代表主键,也可以完成主键的生成策略

    /**
         * AUTO:数据库自增
         * INPUT:inset前自行设置主键值
         * ASSIGN_ID:分配ID,主键类型为Number(Integer和Long)使用接口IdentifierGenerator的nextId方法(默认实现类为DefaultIdentifierGenerator雪花算法)
         * ASSIGN_UUID:分配UUID,主键类型为String,使用接口IdentifierGenerator的nextId方法(默认default方法)
         */
        @TableId(value = "tableId", type = IdType.AUTO)
        private Integer id;
    
  3. @TableField表中列名与Java类中属性的映射

    /**
         * 表中列名与Java类中属性的映射
         * 如果列名和属性名一致可以不用配置此注解
         */
    
        @TableField("last_name")
        private String name;
    
2.3.3 分页插件
  1. 配置MybatisPlusConfig

    package com.chris.mybatisplus.config;
    
    import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    @Configuration
    @EnableTransactionManagement
    @MapperScan("com.chris.mybatisplus.dao.mapper")
    public class MybatisPlusConfig {
    
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
            // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
            paginationInterceptor.setOverflow(true);
            // 设置最大单页限制数量,默认 500 条,-1 不受限制
            // paginationInterceptor.setLimit(500);
            // 开启 count 的 join 优化,只针对部分 left join
            paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
            return paginationInterceptor;
        }
    }
    
  2. 测试类

    @SpringBootTest(classes = MybatisPlusMain.class)
    public class PaginationTest {
        @Autowired
        private UserMapper userMapper;
    
        @Test
        public void paginationSelect() {
            //参数1:当前页数,参数2:每页记录数
            IPage<User> page = new Page<>(2, 2);
    
            // queryWrapper没有设置条件则查询所有记录
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            IPage<User> ipage = userMapper.selectPage(page, queryWrapper);
            long total = ipage.getTotal();
            System.out.println("total:" + total);
            ipage.getRecords().forEach(user -> System.out.println("user:" + user));
        }
    }
    
  3. 注意

    目前分页插件只能支持单表查询,多表关联查询时分页插件不可用

2.3.4 逻辑删除配置
  1. 改pom

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>3.2.0</version>
    </dependency>
    
  2. yml

    数据源配置

    spring:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          #初始化时建立物理连接的个数
          initial-size: 5
          #最小连接池数量
          min-idle: 5
          #最大连接池数量 maxIdle已经不再使用
          max-active: 20
          #获取连接时最大等待时间,单位毫秒
          max-wait: 60000
          #申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
          test-while-idle: true
          #既作为检测的间隔时间又作为testWhileIdel执行的依据
          time-between-eviction-runs-millis: 60000
          #销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接
          min-evictable-idle-time-millis: 30000
          #用来检测连接是否有效的sql 必须是一个查询语句
          #mysql中为 select 'x'
          #oracle中为 select 1 from dual
          validation-query: select 'x'
          #申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
          test-on-borrow: false
          #归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
          test-on-return: false
          #当数据库抛出不可恢复的异常时,抛弃该连接
          #exception-sorter: true
          #是否缓存preparedStatement,mysql5.5+建议开启
          pool-prepared-statements: true
          #当值大于0时poolPreparedStatements会自动修改为true
          max-pool-prepared-statement-per-connection-size: 20
          #配置扩展插件
          filters: stat,wall,slf4j,config
          #通过connectProperties属性来打开mergeSql功能;慢SQL记录
          connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;config.decrypt=false;config.decrypt.key=
          #合并多个DruidDataSource的监控数据
          use-global-data-source-stat: true
          #设置访问druid监控页的账号和密码,默认没有
          stat-view-servlet:
            login-username: admin
            login-password: allsale
          filter:
            wall:
              config:
                comment-allow: true
              enabled: true
        dynamic:
          #指定默认数据源
          datasource:
            #配置了两个数据源
            master:
              url: jdbc:mysql://192.168.140.127:3306/chris?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
              username: root
              password: 65536
              driverClassName: com.mysql.cj.jdbc.Driver
            cluster:
              url: jdbc:mysql://192.168.140.127:3306/slave01?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
              username: root
              password: 65536
              driverClassName: com.mysql.cj.jdbc.Driver
          primary: master
    

    profile

    spring:
      application:
        name: mybatis-plus2020
      profiles:
        active: multidatasource
    

  3. 接口类

    public interface UserService {
        List<User> findAll();
        int save(User user);
    }
    
  4. 实现类

    数据源的切换要在service层,在dao层不能实现数据源的自由切换

    @DS()用来切换数据源作用在类上和方法上

    如果不在这个注解,默认使用primary: master上配置的数据源

    如果方法和类上都加了这个注解,以方法上的注解优先,遵循局部优先原则

    @Service
    @DS("master")
    public class UserServiceImpl implements UserService {
        @Resource
        private UserMapper userMapper;
    
        @Override
        public List<User> findAll() {
            return userMapper.selectList(null);
        }
    
        @Override
        @DS("cluster")
        public int save(User user) {
            return userMapper.insert(user);
        }
    }
    
  5. 测试类

    @SpringBootTest(classes = MybatisPlusMain.class)
    public class MultiDataSource {
        @Resource
        private UserService userService;
    
        @Test
        public void testFindAll() {
            userService.findAll().parallelStream().forEach(user -> System.out.println("user:" + user));
        }
        @Test
        public void testSave() {
            User user = new User();
            user.setBir(new Date()).setAge(22).setName("Sopher");
            userService.save(user);
        }
    }
    
2.3.5 逻辑删除配置

很多情况下我们的系统都需要逻辑删除,方便恢复查找误删除的数据。
通过 mybatis-plus 可以通过全局配置的方式,而不需要再去手动处理。针对更新和查询操作有效,新增不做限制。

方式1

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: isDelete # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以不使用@TableLogic)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

方式2 通过注解@TableLogic

2.3.6 自动填充

@TableFeild 当中有个属性叫做 fill,通过FieldFill 设置属性,这个就是做自动填充用的

public enum FieldFill {
   /**
    * 默认不处理
    */
   DEFAULT,
   /**
    * 插入填充字段
    */
   INSERT,
   /**
    * 更新填充字段
    */
   UPDATE,
   /**
    * 插入和更新填充字段
    */
   INSERT_UPDATE
}

但是这个直接是不能使用的,需要通过实现 mybatis-plus 提供的接口,增加如下配置启动自动填充功能:

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        // 起始版本 3.3.0(推荐使用)
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        // 起始版本 3.3.0(推荐)
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }
}
/**
 * 时间字段,自动添加
 */
@TableField(value = "create_time",fill = FieldFill.INSERT)
private LocalDateTime createTime;
mybatis-plus%0A%0A%5Btoc%5D%0A%0A%23%23%23%23%201.%20%E5%AE%98%E7%BD%91%0A%0A%23%23%23%23%23%201.1%20%E6%96%87%E6%A1%A3%20%0A%0Ahttps%3A%2F%2Fbaomidou.com%2Fguide%2F%0A%0A%23%23%23%23%23%201.2%20%E6%BA%90%E7%A0%81%0A%0Ahttps%3A%2F%2Fgithub.com%2Fbaomidou%2Fmybatis-plus%0A%0A%23%23%23%23%23%201.3%20%E8%AF%BE%E7%A8%8B%0A%0Ahttp%3A%2F%2Fwww.baizhiedu.xin%2Ffront%2Findex%23%2Fmain%0A%0A%0A%0A%23%23%23%23%202.mybatis-plus%0A%0A%23%23%23%23%23%202.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%5BMyBatis-Plus%5D(https%3A%2F%2Fgithub.com%2Fbaomidou%2Fmybatis-plus)%EF%BC%88%E7%AE%80%E7%A7%B0%20MP%EF%BC%89%E6%98%AF%E4%B8%80%E4%B8%AA%20%5BMyBatis%5D(http%3A%2F%2Fwww.mybatis.org%2Fmybatis-3%2F)%20%E7%9A%84%E5%A2%9E%E5%BC%BA%E5%B7%A5%E5%85%B7%EF%BC%8C%E5%9C%A8%20MyBatis%20%E7%9A%84%E5%9F%BA%E7%A1%80%E4%B8%8A%E5%8F%AA%E5%81%9A%E5%A2%9E%E5%BC%BA%E4%B8%8D%E5%81%9A%E6%94%B9%E5%8F%98%EF%BC%8C%E4%B8%BA%E7%AE%80%E5%8C%96%E5%BC%80%E5%8F%91%E3%80%81%E6%8F%90%E9%AB%98%E6%95%88%E7%8E%87%E8%80%8C%E7%94%9F%E3%80%82%0A%0A%23%23%23%23%23%202.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A**%E5%BC%BA%E5%A4%A7%E7%9A%84%20CRUD%20%E6%93%8D%E4%BD%9C**%EF%BC%9A%E5%86%85%E7%BD%AE%E9%80%9A%E7%94%A8%20Mapper%E3%80%81%E9%80%9A%E7%94%A8%20Service%EF%BC%8C%E4%BB%85%E4%BB%85%E9%80%9A%E8%BF%87%E5%B0%91%E9%87%8F%E9%85%8D%E7%BD%AE%E5%8D%B3%E5%8F%AF%E5%AE%9E%E7%8E%B0%E5%8D%95%E8%A1%A8%E5%A4%A7%E9%83%A8%E5%88%86%20CRUD%20%E6%93%8D%E4%BD%9C%EF%BC%8C%E6%9B%B4%E6%9C%89%E5%BC%BA%E5%A4%A7%E7%9A%84%E6%9D%A1%E4%BB%B6%E6%9E%84%E9%80%A0%E5%99%A8%EF%BC%8C%E6%BB%A1%E8%B6%B3%E5%90%84%E7%B1%BB%E4%BD%BF%E7%94%A8%E9%9C%80%E6%B1%82%0A%0A**%E5%86%85%E7%BD%AE%E5%88%86%E9%A1%B5%E6%8F%92%E4%BB%B6**%0A%0A**%E5%86%85%E7%BD%AE%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E6%8F%92%E4%BB%B6**%0A%0A**%E6%94%AF%E6%8C%81%20Lambda%20%E5%BD%A2%E5%BC%8F%E8%B0%83%E7%94%A8**%0A%0A**%E6%94%AF%E6%8C%81%E8%87%AA%E5%AE%9A%E4%B9%89%E5%85%A8%E5%B1%80%E9%80%9A%E7%94%A8%E6%93%8D%E4%BD%9C**%EF%BC%9A%E6%94%AF%E6%8C%81%E5%85%A8%E5%B1%80%E9%80%9A%E7%94%A8%E6%96%B9%E6%B3%95%E6%B3%A8%E5%85%A5%EF%BC%88%20Write%20once%2C%20use%20anywhere%20%EF%BC%89%0A%0A**%E6%94%AF%E6%8C%81%E4%B8%BB%E9%94%AE%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90**%EF%BC%9A%E6%94%AF%E6%8C%81%E5%A4%9A%E8%BE%BE%204%20%E7%A7%8D%E4%B8%BB%E9%94%AE%E7%AD%96%E7%95%A5%EF%BC%88%E5%86%85%E5%90%AB%E5%88%86%E5%B8%83%E5%BC%8F%E5%94%AF%E4%B8%80%20ID%20%E7%94%9F%E6%88%90%E5%99%A8%20-%20Sequence%EF%BC%89%EF%BC%8C%E5%8F%AF%E8%87%AA%E7%94%B1%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%AE%8C%E7%BE%8E%E8%A7%A3%E5%86%B3%E4%B8%BB%E9%94%AE%E9%97%AE%E9%A2%98%0A%0A%0A%23%23%23%23%23%202.3%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%23%23%23%23%23%23%202.3.1%20%E5%85%A5%E9%97%A8%E5%AE%9E%E4%BE%8B%0A%0A1.%20%E5%BB%BA%E9%A1%B9%E7%9B%AE%0A%20%20%20%60%60%60xml%0A%20%20%20%20%3CgroupId%3Ecom.chris.mybatis-plus%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Emybatis-plus2020%3C%2FartifactId%3E%0A%20%20%20%20%60%60%60%0A%0A2.%20%E6%94%B9pom%0A%20%20%20%20%60%60%60xml%0A%20%20%20%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%20%20%20%3Cproject%20xmlns%3D%22http%3A%2F%2Fmaven.apache.org%2FPOM%2F4.0.0%22%20xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22%0A%20%20%20%20%20%20%20%20%20%20%20%20xsi%3AschemaLocation%3D%22http%3A%2F%2Fmaven.apache.org%2FPOM%2F4.0.0%20https%3A%2F%2Fmaven.apache.org%2Fxsd%2Fmaven-4.0.0.xsd%22%3E%0A%20%20%20%20%20%20%20%3CmodelVersion%3E4.0.0%3C%2FmodelVersion%3E%0A%20%20%20%20%20%20%20%3Cparent%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-parent%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E2.3.3.RELEASE%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CrelativePath%2F%3E%20%3C!--%20lookup%20parent%20from%20repository%20--%3E%0A%20%20%20%20%20%20%20%3C%2Fparent%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.chris.mybatis-plus%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Emybatis-plus2020%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3Cversion%3E0.0.1-SNAPSHOT%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%3Cname%3Emybatis-plus2020%3C%2Fname%3E%0A%20%20%20%20%20%20%20%3Cdescription%3EDemo%20project%20for%20Spring%20Boot%3C%2Fdescription%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Cproperties%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cjava.version%3E1.8%3C%2Fjava.version%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cmybatis.plus.version%3E3.2.0%3C%2Fmybatis.plus.version%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cmysql.connector.version%3E6.0.6%3C%2Fmysql.connector.version%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdruid-version%3E1.1.10%3C%2Fdruid-version%3E%0A%20%20%20%20%20%20%20%3C%2Fproperties%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-devtools%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Emysql%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Emysql-connector-java%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E%24%7Bmysql.connector.version%7D%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-test%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Etest%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecom.baomidou%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Emybatis-plus-boot-starter%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E%24%7Bmybatis.plus.version%7D%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecn.hutool%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ehutool-all%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E5.3.5%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Edruid-spring-boot-starter%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E%24%7Bdruid-version%7D%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C%2Fdependencies%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Cbuild%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cplugins%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cplugin%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-maven-plugin%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fplugin%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cplugin%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.maven.plugins%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Emaven-surefire-plugin%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E3.0.0-M5%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cconfiguration%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CskipTests%3Etrue%3C%2FskipTests%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fconfiguration%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fplugin%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fplugins%3E%0A%20%20%20%20%20%20%20%3C%2Fbuild%3E%0A%20%20%20%3C%2Fproject%3E%0A%20%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BAyml%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%204003%0A%20%20%20%20%20servlet%3A%0A%20%20%20%20%20%20%20context-path%3A%20%2Fapi%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20mybatis-plus2020%0A%20%20%20%20%20datasource%3A%0A%20%20%20%20%20%20%20type%3A%20com.alibaba.druid.pool.DruidDataSource%0A%20%20%20%20%20%20%20driverClassName%3A%20com.mysql.cj.jdbc.Driver%0A%20%20%20%20%20%20%20url%3A%20jdbc%3Amysql%3A%2F%2F192.168.140.127%3A3306%2Fchris%3FallowMultiQueries%3Dtrue%26useSSL%3Dfalse%26useUnicode%3Dtrue%26characterEncoding%3DUTF-8%26serverTimezone%3DCTT%0A%20%20%20%20%20%20%20username%3A%20root%0A%20%20%20%20%20%20%20password%3A%2065536%0A%20%20%20%20%20%20%20druid%3A%0A%20%20%20%20%20%20%20%20%20%23%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%E5%BB%BA%E7%AB%8B%E7%89%A9%E7%90%86%E8%BF%9E%E6%8E%A5%E7%9A%84%E4%B8%AA%E6%95%B0%0A%20%20%20%20%20%20%20%20%20initial-size%3A%205%0A%20%20%20%20%20%20%20%20%20%23%E6%9C%80%E5%B0%8F%E8%BF%9E%E6%8E%A5%E6%B1%A0%E6%95%B0%E9%87%8F%0A%20%20%20%20%20%20%20%20%20min-idle%3A%205%0A%20%20%20%20%20%20%20%20%20%23%E6%9C%80%E5%A4%A7%E8%BF%9E%E6%8E%A5%E6%B1%A0%E6%95%B0%E9%87%8F%20maxIdle%E5%B7%B2%E7%BB%8F%E4%B8%8D%E5%86%8D%E4%BD%BF%E7%94%A8%0A%20%20%20%20%20%20%20%20%20max-active%3A%2020%0A%20%20%20%20%20%20%20%20%20%23%E8%8E%B7%E5%8F%96%E8%BF%9E%E6%8E%A5%E6%97%B6%E6%9C%80%E5%A4%A7%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%EF%BC%8C%E5%8D%95%E4%BD%8D%E6%AF%AB%E7%A7%92%0A%20%20%20%20%20%20%20%20%20max-wait%3A%2060000%0A%20%20%20%20%20%20%20%20%20%23%E7%94%B3%E8%AF%B7%E8%BF%9E%E6%8E%A5%E7%9A%84%E6%97%B6%E5%80%99%E6%A3%80%E6%B5%8B%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%A9%BA%E9%97%B2%E6%97%B6%E9%97%B4%E5%A4%A7%E4%BA%8EtimeBetweenEvictionRunsMillis%EF%BC%8C%E6%89%A7%E8%A1%8CvalidationQuery%E6%A3%80%E6%B5%8B%E8%BF%9E%E6%8E%A5%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%88%E3%80%82%0A%20%20%20%20%20%20%20%20%20test-while-idle%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E6%97%A2%E4%BD%9C%E4%B8%BA%E6%A3%80%E6%B5%8B%E7%9A%84%E9%97%B4%E9%9A%94%E6%97%B6%E9%97%B4%E5%8F%88%E4%BD%9C%E4%B8%BAtestWhileIdel%E6%89%A7%E8%A1%8C%E7%9A%84%E4%BE%9D%E6%8D%AE%0A%20%20%20%20%20%20%20%20%20time-between-eviction-runs-millis%3A%2060000%0A%20%20%20%20%20%20%20%20%20%23%E9%94%80%E6%AF%81%E7%BA%BF%E7%A8%8B%E6%97%B6%E6%A3%80%E6%B5%8B%E5%BD%93%E5%89%8D%E8%BF%9E%E6%8E%A5%E7%9A%84%E6%9C%80%E5%90%8E%E6%B4%BB%E5%8A%A8%E6%97%B6%E9%97%B4%E5%92%8C%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4%E5%B7%AE%E5%A4%A7%E4%BA%8E%E8%AF%A5%E5%80%BC%E6%97%B6%EF%BC%8C%E5%85%B3%E9%97%AD%E5%BD%93%E5%89%8D%E8%BF%9E%E6%8E%A5%0A%20%20%20%20%20%20%20%20%20min-evictable-idle-time-millis%3A%2030000%0A%20%20%20%20%20%20%20%20%20%23%E7%94%A8%E6%9D%A5%E6%A3%80%E6%B5%8B%E8%BF%9E%E6%8E%A5%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%88%E7%9A%84sql%20%E5%BF%85%E9%A1%BB%E6%98%AF%E4%B8%80%E4%B8%AA%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5%0A%20%20%20%20%20%20%20%20%20%23mysql%E4%B8%AD%E4%B8%BA%20select%20'x'%0A%20%20%20%20%20%20%20%20%20%23oracle%E4%B8%AD%E4%B8%BA%20select%201%20from%20dual%0A%20%20%20%20%20%20%20%20%20validation-query%3A%20select%20'x'%0A%20%20%20%20%20%20%20%20%20%23%E7%94%B3%E8%AF%B7%E8%BF%9E%E6%8E%A5%E6%97%B6%E4%BC%9A%E6%89%A7%E8%A1%8CvalidationQuery%E6%A3%80%E6%B5%8B%E8%BF%9E%E6%8E%A5%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%88%2C%E5%BC%80%E5%90%AF%E4%BC%9A%E9%99%8D%E4%BD%8E%E6%80%A7%E8%83%BD%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20%20%20test-on-borrow%3A%20false%0A%20%20%20%20%20%20%20%20%20%23%E5%BD%92%E8%BF%98%E8%BF%9E%E6%8E%A5%E6%97%B6%E4%BC%9A%E6%89%A7%E8%A1%8CvalidationQuery%E6%A3%80%E6%B5%8B%E8%BF%9E%E6%8E%A5%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%88%2C%E5%BC%80%E5%90%AF%E4%BC%9A%E9%99%8D%E4%BD%8E%E6%80%A7%E8%83%BD%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20%20%20test-on-return%3A%20false%0A%20%20%20%20%20%20%20%20%20%23%E5%BD%93%E6%95%B0%E6%8D%AE%E5%BA%93%E6%8A%9B%E5%87%BA%E4%B8%8D%E5%8F%AF%E6%81%A2%E5%A4%8D%E7%9A%84%E5%BC%82%E5%B8%B8%E6%97%B6%2C%E6%8A%9B%E5%BC%83%E8%AF%A5%E8%BF%9E%E6%8E%A5%0A%20%20%20%20%20%20%20%20%20%23exception-sorter%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E6%98%AF%E5%90%A6%E7%BC%93%E5%AD%98preparedStatement%2Cmysql5.5%2B%E5%BB%BA%E8%AE%AE%E5%BC%80%E5%90%AF%0A%20%20%20%20%20%20%20%20%20pool-prepared-statements%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E5%BD%93%E5%80%BC%E5%A4%A7%E4%BA%8E0%E6%97%B6poolPreparedStatements%E4%BC%9A%E8%87%AA%E5%8A%A8%E4%BF%AE%E6%94%B9%E4%B8%BAtrue%0A%20%20%20%20%20%20%20%20%20max-pool-prepared-statement-per-connection-size%3A%2020%0A%20%20%20%20%20%20%20%20%20%23%E9%85%8D%E7%BD%AE%E6%89%A9%E5%B1%95%E6%8F%92%E4%BB%B6%0A%20%20%20%20%20%20%20%20%20filters%3A%20stat%2Cwall%2Cslf4j%2Cconfig%0A%20%20%20%20%20%20%20%20%20%23%E9%80%9A%E8%BF%87connectProperties%E5%B1%9E%E6%80%A7%E6%9D%A5%E6%89%93%E5%BC%80mergeSql%E5%8A%9F%E8%83%BD%EF%BC%9B%E6%85%A2SQL%E8%AE%B0%E5%BD%95%0A%20%20%20%20%20%20%20%20%20connection-properties%3A%20druid.stat.mergeSql%3Dtrue%3Bdruid.stat.slowSqlMillis%3D5000%3Bconfig.decrypt%3Dfalse%3Bconfig.decrypt.key%3D%0A%20%20%20%20%20%20%20%20%20%23%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AADruidDataSource%E7%9A%84%E7%9B%91%E6%8E%A7%E6%95%B0%E6%8D%AE%0A%20%20%20%20%20%20%20%20%20use-global-data-source-stat%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E8%AE%BE%E7%BD%AE%E8%AE%BF%E9%97%AEdruid%E7%9B%91%E6%8E%A7%E9%A1%B5%E7%9A%84%E8%B4%A6%E5%8F%B7%E5%92%8C%E5%AF%86%E7%A0%81%2C%E9%BB%98%E8%AE%A4%E6%B2%A1%E6%9C%89%0A%20%20%20%20%20%20%20%20%20stat-view-servlet%3A%0A%20%20%20%20%20%20%20%20%20%20%20login-username%3A%20admin%0A%20%20%20%20%20%20%20%20%20%20%20login-password%3A%20allsale%0A%20%20%20%20%20%20%20%20%20filter%3A%0A%20%20%20%20%20%20%20%20%20%20%20wall%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20config%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20comment-allow%3A%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20enabled%3A%20true%0A%20%20%20%0A%20%20%20%20%20redis%3A%0A%20%20%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20%20%20password%3A%20123456%0A%20%20%20%20%20%20%20port%3A%206379%0A%20%20%20%20%20%20%20timeout%3A%201000%0A%20%20%20%0A%20%20%20%20%20servlet%3A%0A%20%20%20%20%20%20%20multipart%3A%20%23%20%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93%E5%A4%A7%E5%B0%8F%0A%20%20%20%20%20%20%20%20%20max-request-size%3A%20100MB%0A%20%20%20%20%20%20%20%20%20max-file-size%3A%20100MB%0A%20%20%20%0A%20%20%20mybatis-plus%3A%0A%20%20%20%20%20mapper-locations%3A%20classpath%3Amappers%2F*.xml%0A%20%20%20%20%20global-config%3A%0A%20%20%20%20%20%20%20db-config%3A%0A%20%20%20%20%20%20%20%20%20%23%E9%A9%BC%E5%B3%B0%E4%B8%8B%E5%88%92%E7%BA%BF%E8%BD%AC%E6%8D%A2%0A%20%20%20%20%20%20%20%20%20%23column-underline%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E9%80%BB%E8%BE%91%E5%88%A0%E9%99%A4%E9%85%8D%E7%BD%AE%0A%20%20%20%20%20%20%20%20%20logic-delete-value%3A%20I%0A%20%20%20%20%20%20%20%20%20logic-not-delete-value%3A%20A%0A%20%20%20%20%20configuration%3A%0A%20%20%20%20%20%20%20log-impl%3A%20org.apache.ibatis.logging.stdout.StdOutImpl%0A%20%20%20%20%20%23%E4%B8%BA%E6%89%80%E6%9C%89Entity%E7%B1%BB%E6%89%80%E5%9C%A8%E5%8C%85%E8%B5%B7%E9%BB%98%E8%AE%A4%E5%88%AB%E5%90%8D%0A%20%20%20%20%20type-aliases-package%3A%20com.chris.mybatisplus.entities%0A%20%20%20%0A%20%20%20logging%3A%0A%20%20%20%20%20level%3A%0A%20%20%20%20%20%20%20%23%E6%A0%B9%E6%97%A5%E5%BF%97%E7%BA%A7%E5%88%AB%0A%20%20%20%20%20%20%20root%3A%20info%0A%20%20%20%20%20%20%20%23%E6%95%B0%E6%8D%AE%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3%E7%BA%A7%E5%88%AB%0A%20%20%20%20%20%20%20com.chris.mybatisplus.dao.mapper%3A%20debug%0A%20%20%20%20%60%60%60%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.mybatisplus%3B%0A%20%20%20%0A%20%20%20import%20org.mybatis.spring.annotation.MapperScan%3B%0A%20%20%20import%20org.springframework.boot.SpringApplication%3B%0A%20%20%20import%20org.springframework.boot.autoconfigure.SpringBootApplication%3B%0A%20%20%20%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40MapperScan%20(%22com.chris.mybatisplus.dao.mapper%22)%0A%20%20%20public%20class%20MybatisPlusMain%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7Ba%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(MybatisPlusMain.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E6%8E%A5%E5%8F%A3%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.mybatisplus.dao.mapper%3B%0A%20%20%20%0A%20%20%20import%20com.baomidou.mybatisplus.core.mapper.BaseMapper%3B%0A%20%20%20import%20com.chris.mybatisplus.entities.User%3B%0A%20%20%20%0A%20%20%20%2F%2F%20%E4%BD%BF%E7%94%A8mybatis-plus%E5%A2%9E%E5%BC%BA%E6%8E%A5%E5%8F%A3%0A%20%20%20public%20interface%20UserMapper%20extends%20BaseMapper%3CUser%3E%20%7B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A6.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.mybatisplus.entities%3B%0A%20%20%20%0A%20%20%20import%20lombok.AllArgsConstructor%3B%0A%20%20%20import%20lombok.Data%3B%0A%20%20%20import%20lombok.NoArgsConstructor%3B%0A%20%20%20import%20lombok.experimental.Accessors%3B%0A%20%20%20%0A%20%20%20import%20java.util.Date%3B%0A%20%20%20%0A%20%20%20%40Data%0A%20%20%20%40AllArgsConstructor%0A%20%20%20%40NoArgsConstructor%0A%20%20%20%40Accessors%20(chain%20%3D%20true)%0A%20%20%20public%20class%20User%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20private%20Integer%20id%3B%0A%20%20%20%20%20%20%20private%20String%20name%3B%0A%20%20%20%20%20%20%20private%20Integer%20age%3B%0A%20%20%20%20%20%20%20private%20Date%20bir%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A7.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.mybatis%3B%0A%20%20%20%0A%20%20%20import%20com.chris.mybatisplus.MybatisPlusMain%3B%0A%20%20%20import%20com.chris.mybatisplus.dao.mapper.UserMapper%3B%0A%20%20%20import%20com.chris.mybatisplus.entities.User%3B%0A%20%20%20import%20org.junit.jupiter.api.Test%3B%0A%20%20%20import%20org.springframework.beans.factory.annotation.Autowired%3B%0A%20%20%20import%20org.springframework.boot.test.context.SpringBootTest%3B%0A%20%20%20%0A%20%20%20import%20java.util.List%3B%0A%20%20%20%0A%20%20%20%40SpringBootTest%20(classes%20%3D%20MybatisPlusMain.class)%0A%20%20%20public%20class%20TestMybaisPlus%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Autowired%0A%20%20%20%20%20%20%20public%20UserMapper%20userMapper%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%2F%2F%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%0A%20%20%20%20%20%20%20%40Test%0A%20%20%20%20%20%20%20public%20void%20testFindAll()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20List%3CUser%3E%20users%20%3D%20userMapper.selectList(null)%3B%0A%20%20%20%20%20%20%20%20%20%20%20users.forEach(user%20-%3E%20System.out.println(%22user%3A%22%20%2B%20user))%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%202.3.2%20%E6%B3%A8%E8%A7%A3%0A%0A1.%20%E5%A6%82%E6%9E%9C%E7%B1%BB%E5%90%8D%E4%B8%8E%E8%A1%A8%E5%90%8D%E4%B8%80%E8%87%B4%E6%97%B6%EF%BC%8C%40TableName%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40TableName(%22t_user%22)%20%2F%2F%E5%9C%A8%E4%B8%8D%E9%85%8D%E7%BD%AE%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E9%BB%98%E8%AE%A4%E8%A1%A8%E5%90%8D%E4%B8%8E%E7%B1%BB%E5%90%8D%E4%B8%80%E8%87%B4%0A%20%20%20public%20class%20User%20%0A%20%20%20%60%60%60%0A%0A2.%20%40TableId%E4%BB%A3%E8%A1%A8%E4%B8%BB%E9%94%AE%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%AE%8C%E6%88%90%E4%B8%BB%E9%94%AE%E7%9A%84%E7%94%9F%E6%88%90%E7%AD%96%E7%95%A5%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20%20%20%20%20*%20AUTO%3A%E6%95%B0%E6%8D%AE%E5%BA%93%E8%87%AA%E5%A2%9E%0A%20%20%20%20%20%20%20%20*%20INPUT%3Ainset%E5%89%8D%E8%87%AA%E8%A1%8C%E8%AE%BE%E7%BD%AE%E4%B8%BB%E9%94%AE%E5%80%BC%0A%20%20%20%20%20%20%20%20*%20ASSIGN_ID%3A%E5%88%86%E9%85%8DID%EF%BC%8C%E4%B8%BB%E9%94%AE%E7%B1%BB%E5%9E%8B%E4%B8%BANumber(Integer%E5%92%8CLong)%E4%BD%BF%E7%94%A8%E6%8E%A5%E5%8F%A3IdentifierGenerator%E7%9A%84nextId%E6%96%B9%E6%B3%95%EF%BC%88%E9%BB%98%E8%AE%A4%E5%AE%9E%E7%8E%B0%E7%B1%BB%E4%B8%BADefaultIdentifierGenerator%E9%9B%AA%E8%8A%B1%E7%AE%97%E6%B3%95%EF%BC%89%0A%20%20%20%20%20%20%20%20*%20ASSIGN_UUID%3A%E5%88%86%E9%85%8DUUID%EF%BC%8C%E4%B8%BB%E9%94%AE%E7%B1%BB%E5%9E%8B%E4%B8%BAString%2C%E4%BD%BF%E7%94%A8%E6%8E%A5%E5%8F%A3IdentifierGenerator%E7%9A%84nextId%E6%96%B9%E6%B3%95%EF%BC%88%E9%BB%98%E8%AE%A4default%E6%96%B9%E6%B3%95%EF%BC%89%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%40TableId(value%20%3D%20%22tableId%22%2C%20type%20%3D%20IdType.AUTO)%0A%20%20%20%20%20%20%20private%20Integer%20id%3B%0A%20%20%20%60%60%60%0A%0A3.%20%40TableField%E8%A1%A8%E4%B8%AD%E5%88%97%E5%90%8D%E4%B8%8EJava%E7%B1%BB%E4%B8%AD%E5%B1%9E%E6%80%A7%E7%9A%84%E6%98%A0%E5%B0%84%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20%20%20%20%20*%20%E8%A1%A8%E4%B8%AD%E5%88%97%E5%90%8D%E4%B8%8EJava%E7%B1%BB%E4%B8%AD%E5%B1%9E%E6%80%A7%E7%9A%84%E6%98%A0%E5%B0%84%0A%20%20%20%20%20%20%20%20*%20%E5%A6%82%E6%9E%9C%E5%88%97%E5%90%8D%E5%92%8C%E5%B1%9E%E6%80%A7%E5%90%8D%E4%B8%80%E8%87%B4%E5%8F%AF%E4%BB%A5%E4%B8%8D%E7%94%A8%E9%85%8D%E7%BD%AE%E6%AD%A4%E6%B3%A8%E8%A7%A3%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%0A%20%20%20%20%20%20%20%40TableField(%22last_name%22)%0A%20%20%20%20%20%20%20private%20String%20name%3B%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%202.3.3%20%E5%88%86%E9%A1%B5%E6%8F%92%E4%BB%B6%0A%0A1.%20%E9%85%8D%E7%BD%AEMybatisPlusConfig%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.mybatisplus.config%3B%0A%20%20%20%0A%20%20%20import%20com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor%3B%0A%20%20%20import%20com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize%3B%0A%20%20%20import%20org.mybatis.spring.annotation.MapperScan%3B%0A%20%20%20import%20org.springframework.context.annotation.Bean%3B%0A%20%20%20import%20org.springframework.context.annotation.Configuration%3B%0A%20%20%20import%20org.springframework.transaction.annotation.EnableTransactionManagement%3B%0A%20%20%20%0A%20%20%20%40Configuration%0A%20%20%20%40EnableTransactionManagement%0A%20%20%20%40MapperScan(%22com.chris.mybatisplus.dao.mapper%22)%0A%20%20%20public%20class%20MybatisPlusConfig%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20public%20PaginationInterceptor%20paginationInterceptor()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20PaginationInterceptor%20paginationInterceptor%20%3D%20new%20PaginationInterceptor()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E8%AE%BE%E7%BD%AE%E8%AF%B7%E6%B1%82%E7%9A%84%E9%A1%B5%E9%9D%A2%E5%A4%A7%E4%BA%8E%E6%9C%80%E5%A4%A7%E9%A1%B5%E5%90%8E%E6%93%8D%E4%BD%9C%EF%BC%8C%20true%E8%B0%83%E5%9B%9E%E5%88%B0%E9%A6%96%E9%A1%B5%EF%BC%8Cfalse%20%E7%BB%A7%E7%BB%AD%E8%AF%B7%E6%B1%82%20%20%E9%BB%98%E8%AE%A4false%0A%20%20%20%20%20%20%20%20%20%20%20paginationInterceptor.setOverflow(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E8%AE%BE%E7%BD%AE%E6%9C%80%E5%A4%A7%E5%8D%95%E9%A1%B5%E9%99%90%E5%88%B6%E6%95%B0%E9%87%8F%EF%BC%8C%E9%BB%98%E8%AE%A4%20500%20%E6%9D%A1%EF%BC%8C-1%20%E4%B8%8D%E5%8F%97%E9%99%90%E5%88%B6%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20paginationInterceptor.setLimit(500)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E5%BC%80%E5%90%AF%20count%20%E7%9A%84%20join%20%E4%BC%98%E5%8C%96%2C%E5%8F%AA%E9%92%88%E5%AF%B9%E9%83%A8%E5%88%86%20left%20join%0A%20%20%20%20%20%20%20%20%20%20%20paginationInterceptor.setCountSqlParser(new%20JsqlParserCountOptimize(true))%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20paginationInterceptor%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A2.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootTest(classes%20%3D%20MybatisPlusMain.class)%0A%20%20%20public%20class%20PaginationTest%20%7B%0A%20%20%20%20%20%20%20%40Autowired%0A%20%20%20%20%20%20%20private%20UserMapper%20userMapper%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Test%0A%20%20%20%20%20%20%20public%20void%20paginationSelect()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%8F%82%E6%95%B01%EF%BC%9A%E5%BD%93%E5%89%8D%E9%A1%B5%E6%95%B0%EF%BC%8C%E5%8F%82%E6%95%B02%EF%BC%9A%E6%AF%8F%E9%A1%B5%E8%AE%B0%E5%BD%95%E6%95%B0%0A%20%20%20%20%20%20%20%20%20%20%20IPage%3CUser%3E%20page%20%3D%20new%20Page%3C%3E(2%2C%202)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20queryWrapper%E6%B2%A1%E6%9C%89%E8%AE%BE%E7%BD%AE%E6%9D%A1%E4%BB%B6%E5%88%99%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%E8%AE%B0%E5%BD%95%0A%20%20%20%20%20%20%20%20%20%20%20QueryWrapper%3CUser%3E%20queryWrapper%20%3D%20new%20QueryWrapper%3C%3E()%3B%0A%20%20%20%20%20%20%20%20%20%20%20IPage%3CUser%3E%20ipage%20%3D%20userMapper.selectPage(page%2C%20queryWrapper)%3B%0A%20%20%20%20%20%20%20%20%20%20%20long%20total%20%3D%20ipage.getTotal()%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22total%3A%22%20%2B%20total)%3B%0A%20%20%20%20%20%20%20%20%20%20%20ipage.getRecords().forEach(user%20-%3E%20System.out.println(%22user%3A%22%20%2B%20user))%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B3%A8%E6%84%8F%0A%0A%20%20%20%3E%20%E7%9B%AE%E5%89%8D%E5%88%86%E9%A1%B5%E6%8F%92%E4%BB%B6%E5%8F%AA%E8%83%BD%E6%94%AF%E6%8C%81%E5%8D%95%E8%A1%A8%E6%9F%A5%E8%AF%A2%EF%BC%8C%E5%A4%9A%E8%A1%A8%E5%85%B3%E8%81%94%E6%9F%A5%E8%AF%A2%E6%97%B6%E5%88%86%E9%A1%B5%E6%8F%92%E4%BB%B6%E4%B8%8D%E5%8F%AF%E7%94%A8%0A%0A%23%23%23%23%23%23%202.3.4%20%E9%80%BB%E8%BE%91%E5%88%A0%E9%99%A4%E9%85%8D%E7%BD%AE%0A%0A1.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.baomidou%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Edynamic-datasource-spring-boot-starter%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3Cversion%3E3.2.0%3C%2Fversion%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A2.%20yml%0A%0A%20%20%20%3E%20%E6%95%B0%E6%8D%AE%E6%BA%90%E9%85%8D%E7%BD%AE%0A%20%20%20%60%60%60xml%0A%20%20%20spring%3A%0A%20%20%20%20%20datasource%3A%0A%20%20%20%20%20%20%20type%3A%20com.alibaba.druid.pool.DruidDataSource%0A%20%20%20%20%20%20%20druid%3A%0A%20%20%20%20%20%20%20%20%20%23%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%E5%BB%BA%E7%AB%8B%E7%89%A9%E7%90%86%E8%BF%9E%E6%8E%A5%E7%9A%84%E4%B8%AA%E6%95%B0%0A%20%20%20%20%20%20%20%20%20initial-size%3A%205%0A%20%20%20%20%20%20%20%20%20%23%E6%9C%80%E5%B0%8F%E8%BF%9E%E6%8E%A5%E6%B1%A0%E6%95%B0%E9%87%8F%0A%20%20%20%20%20%20%20%20%20min-idle%3A%205%0A%20%20%20%20%20%20%20%20%20%23%E6%9C%80%E5%A4%A7%E8%BF%9E%E6%8E%A5%E6%B1%A0%E6%95%B0%E9%87%8F%20maxIdle%E5%B7%B2%E7%BB%8F%E4%B8%8D%E5%86%8D%E4%BD%BF%E7%94%A8%0A%20%20%20%20%20%20%20%20%20max-active%3A%2020%0A%20%20%20%20%20%20%20%20%20%23%E8%8E%B7%E5%8F%96%E8%BF%9E%E6%8E%A5%E6%97%B6%E6%9C%80%E5%A4%A7%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%EF%BC%8C%E5%8D%95%E4%BD%8D%E6%AF%AB%E7%A7%92%0A%20%20%20%20%20%20%20%20%20max-wait%3A%2060000%0A%20%20%20%20%20%20%20%20%20%23%E7%94%B3%E8%AF%B7%E8%BF%9E%E6%8E%A5%E7%9A%84%E6%97%B6%E5%80%99%E6%A3%80%E6%B5%8B%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%A9%BA%E9%97%B2%E6%97%B6%E9%97%B4%E5%A4%A7%E4%BA%8EtimeBetweenEvictionRunsMillis%EF%BC%8C%E6%89%A7%E8%A1%8CvalidationQuery%E6%A3%80%E6%B5%8B%E8%BF%9E%E6%8E%A5%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%88%E3%80%82%0A%20%20%20%20%20%20%20%20%20test-while-idle%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E6%97%A2%E4%BD%9C%E4%B8%BA%E6%A3%80%E6%B5%8B%E7%9A%84%E9%97%B4%E9%9A%94%E6%97%B6%E9%97%B4%E5%8F%88%E4%BD%9C%E4%B8%BAtestWhileIdel%E6%89%A7%E8%A1%8C%E7%9A%84%E4%BE%9D%E6%8D%AE%0A%20%20%20%20%20%20%20%20%20time-between-eviction-runs-millis%3A%2060000%0A%20%20%20%20%20%20%20%20%20%23%E9%94%80%E6%AF%81%E7%BA%BF%E7%A8%8B%E6%97%B6%E6%A3%80%E6%B5%8B%E5%BD%93%E5%89%8D%E8%BF%9E%E6%8E%A5%E7%9A%84%E6%9C%80%E5%90%8E%E6%B4%BB%E5%8A%A8%E6%97%B6%E9%97%B4%E5%92%8C%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4%E5%B7%AE%E5%A4%A7%E4%BA%8E%E8%AF%A5%E5%80%BC%E6%97%B6%EF%BC%8C%E5%85%B3%E9%97%AD%E5%BD%93%E5%89%8D%E8%BF%9E%E6%8E%A5%0A%20%20%20%20%20%20%20%20%20min-evictable-idle-time-millis%3A%2030000%0A%20%20%20%20%20%20%20%20%20%23%E7%94%A8%E6%9D%A5%E6%A3%80%E6%B5%8B%E8%BF%9E%E6%8E%A5%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%88%E7%9A%84sql%20%E5%BF%85%E9%A1%BB%E6%98%AF%E4%B8%80%E4%B8%AA%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5%0A%20%20%20%20%20%20%20%20%20%23mysql%E4%B8%AD%E4%B8%BA%20select%20'x'%0A%20%20%20%20%20%20%20%20%20%23oracle%E4%B8%AD%E4%B8%BA%20select%201%20from%20dual%0A%20%20%20%20%20%20%20%20%20validation-query%3A%20select%20'x'%0A%20%20%20%20%20%20%20%20%20%23%E7%94%B3%E8%AF%B7%E8%BF%9E%E6%8E%A5%E6%97%B6%E4%BC%9A%E6%89%A7%E8%A1%8CvalidationQuery%E6%A3%80%E6%B5%8B%E8%BF%9E%E6%8E%A5%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%88%2C%E5%BC%80%E5%90%AF%E4%BC%9A%E9%99%8D%E4%BD%8E%E6%80%A7%E8%83%BD%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20%20%20test-on-borrow%3A%20false%0A%20%20%20%20%20%20%20%20%20%23%E5%BD%92%E8%BF%98%E8%BF%9E%E6%8E%A5%E6%97%B6%E4%BC%9A%E6%89%A7%E8%A1%8CvalidationQuery%E6%A3%80%E6%B5%8B%E8%BF%9E%E6%8E%A5%E6%98%AF%E5%90%A6%E6%9C%89%E6%95%88%2C%E5%BC%80%E5%90%AF%E4%BC%9A%E9%99%8D%E4%BD%8E%E6%80%A7%E8%83%BD%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20%20%20test-on-return%3A%20false%0A%20%20%20%20%20%20%20%20%20%23%E5%BD%93%E6%95%B0%E6%8D%AE%E5%BA%93%E6%8A%9B%E5%87%BA%E4%B8%8D%E5%8F%AF%E6%81%A2%E5%A4%8D%E7%9A%84%E5%BC%82%E5%B8%B8%E6%97%B6%2C%E6%8A%9B%E5%BC%83%E8%AF%A5%E8%BF%9E%E6%8E%A5%0A%20%20%20%20%20%20%20%20%20%23exception-sorter%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E6%98%AF%E5%90%A6%E7%BC%93%E5%AD%98preparedStatement%2Cmysql5.5%2B%E5%BB%BA%E8%AE%AE%E5%BC%80%E5%90%AF%0A%20%20%20%20%20%20%20%20%20pool-prepared-statements%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E5%BD%93%E5%80%BC%E5%A4%A7%E4%BA%8E0%E6%97%B6poolPreparedStatements%E4%BC%9A%E8%87%AA%E5%8A%A8%E4%BF%AE%E6%94%B9%E4%B8%BAtrue%0A%20%20%20%20%20%20%20%20%20max-pool-prepared-statement-per-connection-size%3A%2020%0A%20%20%20%20%20%20%20%20%20%23%E9%85%8D%E7%BD%AE%E6%89%A9%E5%B1%95%E6%8F%92%E4%BB%B6%0A%20%20%20%20%20%20%20%20%20filters%3A%20stat%2Cwall%2Cslf4j%2Cconfig%0A%20%20%20%20%20%20%20%20%20%23%E9%80%9A%E8%BF%87connectProperties%E5%B1%9E%E6%80%A7%E6%9D%A5%E6%89%93%E5%BC%80mergeSql%E5%8A%9F%E8%83%BD%EF%BC%9B%E6%85%A2SQL%E8%AE%B0%E5%BD%95%0A%20%20%20%20%20%20%20%20%20connection-properties%3A%20druid.stat.mergeSql%3Dtrue%3Bdruid.stat.slowSqlMillis%3D5000%3Bconfig.decrypt%3Dfalse%3Bconfig.decrypt.key%3D%0A%20%20%20%20%20%20%20%20%20%23%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AADruidDataSource%E7%9A%84%E7%9B%91%E6%8E%A7%E6%95%B0%E6%8D%AE%0A%20%20%20%20%20%20%20%20%20use-global-data-source-stat%3A%20true%0A%20%20%20%20%20%20%20%20%20%23%E8%AE%BE%E7%BD%AE%E8%AE%BF%E9%97%AEdruid%E7%9B%91%E6%8E%A7%E9%A1%B5%E7%9A%84%E8%B4%A6%E5%8F%B7%E5%92%8C%E5%AF%86%E7%A0%81%2C%E9%BB%98%E8%AE%A4%E6%B2%A1%E6%9C%89%0A%20%20%20%20%20%20%20%20%20stat-view-servlet%3A%0A%20%20%20%20%20%20%20%20%20%20%20login-username%3A%20admin%0A%20%20%20%20%20%20%20%20%20%20%20login-password%3A%20allsale%0A%20%20%20%20%20%20%20%20%20filter%3A%0A%20%20%20%20%20%20%20%20%20%20%20wall%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20config%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20comment-allow%3A%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20enabled%3A%20true%0A%20%20%20%20%20%20%20dynamic%3A%0A%20%20%20%20%20%20%20%20%20%23%E6%8C%87%E5%AE%9A%E9%BB%98%E8%AE%A4%E6%95%B0%E6%8D%AE%E6%BA%90%0A%20%20%20%20%20%20%20%20%20datasource%3A%0A%20%20%20%20%20%20%20%20%20%20%20%23%E9%85%8D%E7%BD%AE%E4%BA%86%E4%B8%A4%E4%B8%AA%E6%95%B0%E6%8D%AE%E6%BA%90%0A%20%20%20%20%20%20%20%20%20%20%20master%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20url%3A%20jdbc%3Amysql%3A%2F%2F192.168.140.127%3A3306%2Fchris%3FallowMultiQueries%3Dtrue%26useSSL%3Dfalse%26useUnicode%3Dtrue%26characterEncoding%3DUTF-8%26serverTimezone%3DCTT%0A%20%20%20%20%20%20%20%20%20%20%20%20%20username%3A%20root%0A%20%20%20%20%20%20%20%20%20%20%20%20%20password%3A%2065536%0A%20%20%20%20%20%20%20%20%20%20%20%20%20driverClassName%3A%20com.mysql.cj.jdbc.Driver%0A%20%20%20%20%20%20%20%20%20%20%20cluster%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20url%3A%20jdbc%3Amysql%3A%2F%2F192.168.140.127%3A3306%2Fslave01%3FallowMultiQueries%3Dtrue%26useSSL%3Dfalse%26useUnicode%3Dtrue%26characterEncoding%3DUTF-8%26serverTimezone%3DCTT%0A%20%20%20%20%20%20%20%20%20%20%20%20%20username%3A%20root%0A%20%20%20%20%20%20%20%20%20%20%20%20%20password%3A%2065536%0A%20%20%20%20%20%20%20%20%20%20%20%20%20driverClassName%3A%20com.mysql.cj.jdbc.Driver%0A%20%20%20%20%20%20%20%20%20primary%3A%20master%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20profile%0A%0A%20%20%20%60%60%60xml%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20mybatis-plus2020%0A%20%20%20%20%20profiles%3A%0A%20%20%20%20%20%20%20active%3A%20multidatasource%0A%20%20%20%60%60%60%0A%20%20%20%20!%5B052eb4751a6fc144daa48786a138e01c.png%5D(en-resource%3A%2F%2Fdatabase%2F750%3A1)%0A%0A3.%20%E6%8E%A5%E5%8F%A3%E7%B1%BB%0A%20%20%20%60%60%60java%0A%20%20%20public%20interface%20UserService%20%7B%0A%20%20%20%20%20%20%20List%3CUser%3E%20findAll()%3B%0A%20%20%20%20%20%20%20int%20save(User%20user)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A4.%20%E5%AE%9E%E7%8E%B0%E7%B1%BB%0A%0A%20%20%20%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E5%88%87%E6%8D%A2%E8%A6%81%E5%9C%A8service%E5%B1%82%EF%BC%8C%E5%9C%A8dao%E5%B1%82%E4%B8%8D%E8%83%BD%E5%AE%9E%E7%8E%B0%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E8%87%AA%E7%94%B1%E5%88%87%E6%8D%A2%0A%0A%20%20%20%40DS()%E7%94%A8%E6%9D%A5%E5%88%87%E6%8D%A2%E6%95%B0%E6%8D%AE%E6%BA%90%E4%BD%9C%E7%94%A8%E5%9C%A8%E7%B1%BB%E4%B8%8A%E5%92%8C%E6%96%B9%E6%B3%95%E4%B8%8A%0A%0A%20%20%20%3E%20%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%9C%A8%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%BD%BF%E7%94%A8primary%3A%20master%E4%B8%8A%E9%85%8D%E7%BD%AE%E7%9A%84%E6%95%B0%E6%8D%AE%E6%BA%90%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%A6%82%E6%9E%9C%E6%96%B9%E6%B3%95%E5%92%8C%E7%B1%BB%E4%B8%8A%E9%83%BD%E5%8A%A0%E4%BA%86%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%EF%BC%8C%E4%BB%A5%E6%96%B9%E6%B3%95%E4%B8%8A%E7%9A%84%E6%B3%A8%E8%A7%A3%E4%BC%98%E5%85%88%EF%BC%8C%E9%81%B5%E5%BE%AA%E5%B1%80%E9%83%A8%E4%BC%98%E5%85%88%E5%8E%9F%E5%88%99%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Service%0A%20%20%20%40DS(%22master%22)%0A%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20UserMapper%20userMapper%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUser%3E%20findAll()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20userMapper.selectList(null)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%40DS(%22cluster%22)%0A%20%20%20%20%20%20%20public%20int%20save(User%20user)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20userMapper.insert(user)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A5.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootTest(classes%20%3D%20MybatisPlusMain.class)%0A%20%20%20public%20class%20MultiDataSource%20%7B%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20UserService%20userService%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Test%0A%20%20%20%20%20%20%20public%20void%20testFindAll()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20userService.findAll().parallelStream().forEach(user%20-%3E%20System.out.println(%22user%3A%22%20%2B%20user))%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%40Test%0A%20%20%20%20%20%20%20public%20void%20testSave()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20User%20user%20%3D%20new%20User()%3B%0A%20%20%20%20%20%20%20%20%20%20%20user.setBir(new%20Date()).setAge(22).setName(%22Sopher%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20userService.save(user)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%20%20%20%0A%23%23%23%23%23%23%202.3.5%20%E9%80%BB%E8%BE%91%E5%88%A0%E9%99%A4%E9%85%8D%E7%BD%AE%0A%0A%3E%20%E5%BE%88%E5%A4%9A%E6%83%85%E5%86%B5%E4%B8%8B%E6%88%91%E4%BB%AC%E7%9A%84%E7%B3%BB%E7%BB%9F%E9%83%BD%E9%9C%80%E8%A6%81%E9%80%BB%E8%BE%91%E5%88%A0%E9%99%A4%EF%BC%8C%E6%96%B9%E4%BE%BF%E6%81%A2%E5%A4%8D%E6%9F%A5%E6%89%BE%E8%AF%AF%E5%88%A0%E9%99%A4%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%0A%3E%20%E9%80%9A%E8%BF%87%20mybatis-plus%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E8%80%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E5%86%8D%E5%8E%BB%E6%89%8B%E5%8A%A8%E5%A4%84%E7%90%86%E3%80%82%E9%92%88%E5%AF%B9%E6%9B%B4%E6%96%B0%E5%92%8C%E6%9F%A5%E8%AF%A2%E6%93%8D%E4%BD%9C%E6%9C%89%E6%95%88%EF%BC%8C%E6%96%B0%E5%A2%9E%E4%B8%8D%E5%81%9A%E9%99%90%E5%88%B6%E3%80%82%0A%0A%3E%20%E6%96%B9%E5%BC%8F1%0A%60%60%60yml%0Amybatis-plus%3A%0A%C2%A0%C2%A0global-config%3A%0A%C2%A0%C2%A0%C2%A0%C2%A0db-config%3A%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0logic-delete-field%3A%C2%A0isDelete%C2%A0%23%C2%A0%E5%85%A8%E5%B1%80%E9%80%BB%E8%BE%91%E5%88%A0%E9%99%A4%E7%9A%84%E5%AE%9E%E4%BD%93%E5%AD%97%E6%AE%B5%E5%90%8D(since%C2%A03.3.0%2C%E9%85%8D%E7%BD%AE%E5%90%8E%E5%8F%AF%E4%BB%A5%E4%B8%8D%E4%BD%BF%E7%94%A8%40TableLogic)%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0logic-delete-value%3A%C2%A01%C2%A0%23%C2%A0%E9%80%BB%E8%BE%91%E5%B7%B2%E5%88%A0%E9%99%A4%E5%80%BC(%E9%BB%98%E8%AE%A4%E4%B8%BA%C2%A01)%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0logic-not-delete-value%3A%C2%A00%C2%A0%23%C2%A0%E9%80%BB%E8%BE%91%E6%9C%AA%E5%88%A0%E9%99%A4%E5%80%BC(%E9%BB%98%E8%AE%A4%E4%B8%BA%C2%A00)%0A%60%60%60%0A%0A%3E%20%E6%96%B9%E5%BC%8F2%20%E9%80%9A%E8%BF%87%E6%B3%A8%E8%A7%A3%60%40TableLogic%60%0A%0A%23%23%23%23%23%23%202.3.6%20%E8%87%AA%E5%8A%A8%E5%A1%AB%E5%85%85%0A%3E%20%60%40TableFeild%60%20%E5%BD%93%E4%B8%AD%E6%9C%89%E4%B8%AA%E5%B1%9E%E6%80%A7%E5%8F%AB%E5%81%9A%20fill%EF%BC%8C%E9%80%9A%E8%BF%87%60FieldFill%60%20%E8%AE%BE%E7%BD%AE%E5%B1%9E%E6%80%A7%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%B0%B1%E6%98%AF%E5%81%9A%E8%87%AA%E5%8A%A8%E5%A1%AB%E5%85%85%E7%94%A8%E7%9A%84%0A%20%60%60%60java%0A%20public%20enum%20FieldFill%20%7B%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E9%BB%98%E8%AE%A4%E4%B8%8D%E5%A4%84%E7%90%86%0A%20%20%20%20%20*%2F%0A%20%20%20%20DEFAULT%2C%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%8F%92%E5%85%A5%E5%A1%AB%E5%85%85%E5%AD%97%E6%AE%B5%0A%20%20%20%20%20*%2F%0A%20%20%20%20INSERT%2C%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%9B%B4%E6%96%B0%E5%A1%AB%E5%85%85%E5%AD%97%E6%AE%B5%0A%20%20%20%20%20*%2F%0A%20%20%20%20UPDATE%2C%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%8F%92%E5%85%A5%E5%92%8C%E6%9B%B4%E6%96%B0%E5%A1%AB%E5%85%85%E5%AD%97%E6%AE%B5%0A%20%20%20%20%20*%2F%0A%20%20%20%20INSERT_UPDATE%0A%20%7D%0A%60%60%60%0A%3E%20%E4%BD%86%E6%98%AF%E8%BF%99%E4%B8%AA%E7%9B%B4%E6%8E%A5%E6%98%AF%E4%B8%8D%E8%83%BD%E4%BD%BF%E7%94%A8%E7%9A%84%EF%BC%8C%E9%9C%80%E8%A6%81%E9%80%9A%E8%BF%87%E5%AE%9E%E7%8E%B0%20mybatis-plus%20%E6%8F%90%E4%BE%9B%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%A2%9E%E5%8A%A0%E5%A6%82%E4%B8%8B%E9%85%8D%E7%BD%AE%E5%90%AF%E5%8A%A8%E8%87%AA%E5%8A%A8%E5%A1%AB%E5%85%85%E5%8A%9F%E8%83%BD%EF%BC%9A%0A%0A%60%60%60java%0Aimport%20com.baomidou.mybatisplus.core.handlers.MetaObjectHandler%3B%0Aimport%20org.apache.ibatis.reflection.MetaObject%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0Aimport%20java.time.LocalDateTime%3B%0A%0A%40Component%0Apublic%20class%20MyMetaObjectHandler%20implements%20MetaObjectHandler%20%7B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20insertFill(MetaObject%20metaObject)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%B5%B7%E5%A7%8B%E7%89%88%E6%9C%AC%203.3.0(%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8)%0A%20%20%20%20%20%20%20%20this.strictInsertFill(metaObject%2C%20%22createTime%22%2C%20LocalDateTime.class%2C%20LocalDateTime.now())%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20updateFill(MetaObject%20metaObject)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%B5%B7%E5%A7%8B%E7%89%88%E6%9C%AC%203.3.0(%E6%8E%A8%E8%8D%90)%0A%20%20%20%20%20%20%20%20this.strictUpdateFill(metaObject%2C%20%22updateTime%22%2C%20LocalDateTime.class%2C%20LocalDateTime.now())%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E6%97%B6%E9%97%B4%E5%AD%97%E6%AE%B5%EF%BC%8C%E8%87%AA%E5%8A%A8%E6%B7%BB%E5%8A%A0%0A%20*%2F%0A%40TableField(value%20%3D%20%22create_time%22%2Cfill%20%3D%20FieldFill.INSERT)%0Aprivate%20LocalDateTime%20createTime%3B%0A%60%60%60

ScheduledThreadPoolExecutor

创建时间:2022/11/9 23:19
更新时间:2023/6/4 14:08
作者:Chris
来源:https://www.jianshu.com/p/925dba9f5969

scheduleWithFixedDelay

https://www.jianshu.com/p/925dba9f5969

介绍

自JDK1.5开始,JDK提供了ScheduledThreadPoolExecutor类来支持周期性任务的调度。在这之前的实现需要依靠Timer和TimerTask或者其它第三方工具来完成。

但Timer有不少的缺陷:

package com.chris.thread.future.scheduled;

import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.*;

public class ScheduledThreadTest {

    private ScheduledExecutorService scheduledExecutorService;

    @Before
    public void initScheduedExecutorService() {
        scheduledExecutorService = Executors.newScheduledThreadPool(2);
    }

    /**
     * 在指定延迟之后运行task。这个方法有个问题,就是没有办法获知task的执行结果
     * <p>
     * schedule with runnable
     * result:null
     */
    @Test
    public void scheduledWithRunnable() throws ExecutionException, InterruptedException {
        ScheduledFuture<?> scheduleWithRunnable = scheduledExecutorService.schedule(() ->
                System.out.println("schedule with runnable"), 2, TimeUnit.SECONDS);
        System.out.println("result:" + scheduleWithRunnable.get());
        scheduledExecutorService.shutdown();
    }

    /**
     * 与schedule (Runnable task)类似,也是在指定延迟之后运行task,不过它接收的是一个Callable实例
     * 此方法会返回一个ScheduleFuture对象,通过ScheduleFuture我们可以取消一个未执行的task,也可以获得这个task的执行结果
     * <p>
     * schedule with callable
     * result:callable success
     */
    @Test
    public void scheduledWithCallable() throws ExecutionException, InterruptedException {
        ScheduledFuture<?> scheduleWithRunnable = scheduledExecutorService.schedule((Callable<Object>) () -> {
            System.out.println("schedule with callable");
            return "callable success";
        }, 5, TimeUnit.SECONDS);
        System.out.println("result:" + scheduleWithRunnable.get());
        scheduledExecutorService.shutdown();
    }


    /**
     * 周期性的调度task执行。task第一次执行的延迟根据initialDelay参数确定,以后每一次执行都间隔period时长。
     * 在scheduleAtFixedRate中period指的两个任务开始执行的时间间隔,也就是当前任务的开始执行时间和下个任务的开始执行时间之间的间隔
     * 如果task的执行时间大于定义的period,那么下一个线程将在当前线程完成之后再执行。整个调度保证不会出现一个以上任务同时执行。
     * 因为是runnable所以没有返回结果
     */
    @Test
    public void scheudledAtFixedRate() throws ExecutionException, InterruptedException {
        ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(() ->
                System.out.println("schedule at fixed rate"), 5, 1, TimeUnit.SECONDS);

        System.out.println("result:" + scheduledFuture.get());
        scheduledExecutorService.shutdown();
    }

    /**
     * scheduleWithFixedDelay的参数和scheduleAtFixedRate参数完全一致,它们的不同之处在于对period调度周期的解释。
     * 在scheduleAtFixedRate中period指的当前任务的结束执行时间到下个任务的开始执行时间。
     * 因为是runnable所以没有返回结果
     */
    @Test
    public void scheduleWithFixedDelay() throws ExecutionException, InterruptedException {
        ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> {
            System.out.println("schedule with fixed rate");
        }, 5, 1, TimeUnit.SECONDS);

        System.out.println("result:" + scheduledFuture.get());
        scheduledExecutorService.shutdown();
    }

}

scheduleWithFixedDelay%0A%5Btoc%5D%0A%0A%3E%20https%3A%2F%2Fwww.jianshu.com%2Fp%2F925dba9f5969%0A%0A%23%23%20%E4%BB%8B%E7%BB%8D%0A%3E%20%E8%87%AAJDK1.5%E5%BC%80%E5%A7%8B%EF%BC%8CJDK%E6%8F%90%E4%BE%9B%E4%BA%86ScheduledThreadPoolExecutor%E7%B1%BB%E6%9D%A5%E6%94%AF%E6%8C%81%E5%91%A8%E6%9C%9F%E6%80%A7%E4%BB%BB%E5%8A%A1%E7%9A%84%E8%B0%83%E5%BA%A6%E3%80%82%E5%9C%A8%E8%BF%99%E4%B9%8B%E5%89%8D%E7%9A%84%E5%AE%9E%E7%8E%B0%E9%9C%80%E8%A6%81%E4%BE%9D%E9%9D%A0Timer%E5%92%8CTimerTask%E6%88%96%E8%80%85%E5%85%B6%E5%AE%83%E7%AC%AC%E4%B8%89%E6%96%B9%E5%B7%A5%E5%85%B7%E6%9D%A5%E5%AE%8C%E6%88%90%E3%80%82%0A%0A%3E%20%E4%BD%86Timer%E6%9C%89%E4%B8%8D%E5%B0%91%E7%9A%84%E7%BC%BA%E9%99%B7%EF%BC%9A%0A-%20Timer%E6%98%AF%E5%8D%95%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%BC%8F%EF%BC%9B%0A-%20%E5%A6%82%E6%9E%9C%E5%9C%A8%E6%89%A7%E8%A1%8C%E4%BB%BB%E5%8A%A1%E6%9C%9F%E9%97%B4%E6%9F%90%E4%B8%AATimerTask%E8%80%97%E6%97%B6%E8%BE%83%E4%B9%85%EF%BC%8C%E9%82%A3%E4%B9%88%E5%B0%B1%E4%BC%9A%E5%BD%B1%E5%93%8D%E5%85%B6%E5%AE%83%E4%BB%BB%E5%8A%A1%E7%9A%84%E8%B0%83%E5%BA%A6%EF%BC%9B%0A-%20Timer%E7%9A%84%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E6%98%AF%E5%9F%BA%E4%BA%8E%E7%BB%9D%E5%AF%B9%E6%97%B6%E9%97%B4%E7%9A%84%EF%BC%8C%E5%AF%B9%E7%B3%BB%E7%BB%9F%E6%97%B6%E9%97%B4%E6%95%8F%E6%84%9F%EF%BC%9B%0A-%20Timer%E4%B8%8D%E4%BC%9A%E6%8D%95%E8%8E%B7%E6%89%A7%E8%A1%8CTimerTask%E6%97%B6%E6%89%80%E6%8A%9B%E5%87%BA%E7%9A%84%E5%BC%82%E5%B8%B8%EF%BC%8C%E7%94%B1%E4%BA%8ETimer%E6%98%AF%E5%8D%95%E7%BA%BF%E7%A8%8B%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%80%E6%97%A6%E5%87%BA%E7%8E%B0%E5%BC%82%E5%B8%B8%EF%BC%8C%E5%88%99%E7%BA%BF%E7%A8%8B%E5%B0%B1%E4%BC%9A%E7%BB%88%E6%AD%A2%EF%BC%8C%E5%85%B6%E4%BB%96%E4%BB%BB%E5%8A%A1%E4%B9%9F%E5%BE%97%E4%B8%8D%E5%88%B0%E6%89%A7%E8%A1%8C%0A%0A!%5Bc66d7acb6b8e92f31302e091cacb4b4e.png%5D(en-resource%3A%2F%2Fdatabase%2F1391%3A1)%0A%0A%60%60%60java%0Apackage%20com.chris.thread.future.scheduled%3B%0A%0Aimport%20org.junit.Before%3B%0Aimport%20org.junit.Test%3B%0A%0Aimport%20java.util.concurrent.*%3B%0A%0Apublic%20class%20ScheduledThreadTest%20%7B%0A%0A%20%20%20%20private%20ScheduledExecutorService%20scheduledExecutorService%3B%0A%0A%20%20%20%20%40Before%0A%20%20%20%20public%20void%20initScheduedExecutorService()%20%7B%0A%20%20%20%20%20%20%20%20scheduledExecutorService%20%3D%20Executors.newScheduledThreadPool(2)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%9C%A8%E6%8C%87%E5%AE%9A%E5%BB%B6%E8%BF%9F%E4%B9%8B%E5%90%8E%E8%BF%90%E8%A1%8Ctask%E3%80%82%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E6%9C%89%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%8C%E5%B0%B1%E6%98%AF%E6%B2%A1%E6%9C%89%E5%8A%9E%E6%B3%95%E8%8E%B7%E7%9F%A5task%E7%9A%84%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20schedule%20with%20runnable%0A%20%20%20%20%20*%20result%3Anull%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20scheduledWithRunnable()%20throws%20ExecutionException%2C%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20ScheduledFuture%3C%3F%3E%20scheduleWithRunnable%20%3D%20scheduledExecutorService.schedule(()%20-%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22schedule%20with%20runnable%22)%2C%202%2C%20TimeUnit.SECONDS)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22result%3A%22%20%2B%20scheduleWithRunnable.get())%3B%0A%20%20%20%20%20%20%20%20scheduledExecutorService.shutdown()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E4%B8%8Eschedule%20(Runnable%20task)%E7%B1%BB%E4%BC%BC%EF%BC%8C%E4%B9%9F%E6%98%AF%E5%9C%A8%E6%8C%87%E5%AE%9A%E5%BB%B6%E8%BF%9F%E4%B9%8B%E5%90%8E%E8%BF%90%E8%A1%8Ctask%EF%BC%8C%E4%B8%8D%E8%BF%87%E5%AE%83%E6%8E%A5%E6%94%B6%E7%9A%84%E6%98%AF%E4%B8%80%E4%B8%AACallable%E5%AE%9E%E4%BE%8B%0A%20%20%20%20%20*%20%E6%AD%A4%E6%96%B9%E6%B3%95%E4%BC%9A%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AAScheduleFuture%E5%AF%B9%E8%B1%A1%EF%BC%8C%E9%80%9A%E8%BF%87ScheduleFuture%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E5%8F%96%E6%B6%88%E4%B8%80%E4%B8%AA%E6%9C%AA%E6%89%A7%E8%A1%8C%E7%9A%84task%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%BE%97%E8%BF%99%E4%B8%AAtask%E7%9A%84%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20schedule%20with%20callable%0A%20%20%20%20%20*%20result%3Acallable%20success%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20scheduledWithCallable()%20throws%20ExecutionException%2C%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20ScheduledFuture%3C%3F%3E%20scheduleWithRunnable%20%3D%20scheduledExecutorService.schedule((Callable%3CObject%3E)%20()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22schedule%20with%20callable%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%22callable%20success%22%3B%0A%20%20%20%20%20%20%20%20%7D%2C%205%2C%20TimeUnit.SECONDS)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22result%3A%22%20%2B%20scheduleWithRunnable.get())%3B%0A%20%20%20%20%20%20%20%20scheduledExecutorService.shutdown()%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%91%A8%E6%9C%9F%E6%80%A7%E7%9A%84%E8%B0%83%E5%BA%A6task%E6%89%A7%E8%A1%8C%E3%80%82task%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%89%A7%E8%A1%8C%E7%9A%84%E5%BB%B6%E8%BF%9F%E6%A0%B9%E6%8D%AEinitialDelay%E5%8F%82%E6%95%B0%E7%A1%AE%E5%AE%9A%EF%BC%8C%E4%BB%A5%E5%90%8E%E6%AF%8F%E4%B8%80%E6%AC%A1%E6%89%A7%E8%A1%8C%E9%83%BD%E9%97%B4%E9%9A%94period%E6%97%B6%E9%95%BF%E3%80%82%0A%20%20%20%20%20*%20%E5%9C%A8scheduleAtFixedRate%E4%B8%ADperiod%E6%8C%87%E7%9A%84%E4%B8%A4%E4%B8%AA%E4%BB%BB%E5%8A%A1%E5%BC%80%E5%A7%8B%E6%89%A7%E8%A1%8C%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%BD%93%E5%89%8D%E4%BB%BB%E5%8A%A1%E7%9A%84%E5%BC%80%E5%A7%8B%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E5%92%8C%E4%B8%8B%E4%B8%AA%E4%BB%BB%E5%8A%A1%E7%9A%84%E5%BC%80%E5%A7%8B%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E4%B9%8B%E9%97%B4%E7%9A%84%E9%97%B4%E9%9A%94%0A%20%20%20%20%20*%20%E5%A6%82%E6%9E%9Ctask%E7%9A%84%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E5%A4%A7%E4%BA%8E%E5%AE%9A%E4%B9%89%E7%9A%84period%EF%BC%8C%E9%82%A3%E4%B9%88%E4%B8%8B%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%B0%86%E5%9C%A8%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E5%AE%8C%E6%88%90%E4%B9%8B%E5%90%8E%E5%86%8D%E6%89%A7%E8%A1%8C%E3%80%82%E6%95%B4%E4%B8%AA%E8%B0%83%E5%BA%A6%E4%BF%9D%E8%AF%81%E4%B8%8D%E4%BC%9A%E5%87%BA%E7%8E%B0%E4%B8%80%E4%B8%AA%E4%BB%A5%E4%B8%8A%E4%BB%BB%E5%8A%A1%E5%90%8C%E6%97%B6%E6%89%A7%E8%A1%8C%E3%80%82%0A%20%20%20%20%20*%20%E5%9B%A0%E4%B8%BA%E6%98%AFrunnable%E6%89%80%E4%BB%A5%E6%B2%A1%E6%9C%89%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20scheudledAtFixedRate()%20throws%20ExecutionException%2C%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20ScheduledFuture%3C%3F%3E%20scheduledFuture%20%3D%20scheduledExecutorService.scheduleAtFixedRate(()%20-%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22schedule%20at%20fixed%20rate%22)%2C%205%2C%201%2C%20TimeUnit.SECONDS)%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(%22result%3A%22%20%2B%20scheduledFuture.get())%3B%0A%20%20%20%20%20%20%20%20scheduledExecutorService.shutdown()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20scheduleWithFixedDelay%E7%9A%84%E5%8F%82%E6%95%B0%E5%92%8CscheduleAtFixedRate%E5%8F%82%E6%95%B0%E5%AE%8C%E5%85%A8%E4%B8%80%E8%87%B4%EF%BC%8C%E5%AE%83%E4%BB%AC%E7%9A%84%E4%B8%8D%E5%90%8C%E4%B9%8B%E5%A4%84%E5%9C%A8%E4%BA%8E%E5%AF%B9period%E8%B0%83%E5%BA%A6%E5%91%A8%E6%9C%9F%E7%9A%84%E8%A7%A3%E9%87%8A%E3%80%82%0A%20%20%20%20%20*%20%E5%9C%A8scheduleAtFixedRate%E4%B8%ADperiod%E6%8C%87%E7%9A%84%E5%BD%93%E5%89%8D%E4%BB%BB%E5%8A%A1%E7%9A%84%E7%BB%93%E6%9D%9F%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E5%88%B0%E4%B8%8B%E4%B8%AA%E4%BB%BB%E5%8A%A1%E7%9A%84%E5%BC%80%E5%A7%8B%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E3%80%82%0A%20%20%20%20%20*%20%E5%9B%A0%E4%B8%BA%E6%98%AFrunnable%E6%89%80%E4%BB%A5%E6%B2%A1%E6%9C%89%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20scheduleWithFixedDelay()%20throws%20ExecutionException%2C%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20ScheduledFuture%3C%3F%3E%20scheduledFuture%20%3D%20scheduledExecutorService.scheduleWithFixedDelay(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22schedule%20with%20fixed%20rate%22)%3B%0A%20%20%20%20%20%20%20%20%7D%2C%205%2C%201%2C%20TimeUnit.SECONDS)%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(%22result%3A%22%20%2B%20scheduledFuture.get())%3B%0A%20%20%20%20%20%20%20%20scheduledExecutorService.shutdown()%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%0A%60%60%60

spring issues

创建时间:2020/9/8 14:01
更新时间:2022/11/6 18:39
作者:Chris
来源:https://blog.csdn.net/forezp/article/details/84313907

@ConditionalOnBean不生效

https://blog.csdn.net/forezp/article/details/84313907

@Configuration
public class Bean1Config {
    @Bean
    @ConditionalOnBean(value = Bean2.class )
    public Bean1 bean1(){
        return new Bean1();
    }
}

@Configuration
public class Bean2Config {
    @Bean
    public Bean2 bean2() {
        return new Bean2();
    }
}
@GetMapping("/getBean/{beanName}")
public void getBean(@PathVariable String beanName) {
    Object bean = SpringUtil.getApplicationContext().getBean(beanName);
    if (Objects.nonNull(bean)) {
        System.out.println(beanName + " init success");
    } else {
        System.out.println(beanName + "init fail");
    }
}

代码中bean1是定义在配置类中的,当执行到配置类解析的时候,@Component,@Service,@Controller ,@Configuration标注的类已经全部扫描,所以这些BeanDifinition已经被同步。 但是bean1的条件注解依赖的是bean2,bean2是被定义的配置类中的,所以此时配置类的解析无法保证先后顺序,就会出现不生效的情况。
在spring ioc的过程中,优先解析@Component,@Service,@Controller注解的类。其次解析配置类,也就是@Configuration标注的类。最后开始解析配置类中定义的bean

解决方法

  1. ConditionalOnClass(Bean2.class)来代替。
  2. 如果一定要区分两个配置类的先后顺序,可以将这两个类交与EnableAutoConfiguration管理和触发。也就是定义在META-INF\spring.factories中声明是配置类,然后通过@AutoConfigureBefore、AutoConfigureAfter  AutoConfigureOrder控制先后顺序。之所以这么做是因为这三个注解只对自动配置类的先后顺序生效
%5Btoc%5D%0A%23%23%23%23%20%40ConditionalOnBean%E4%B8%8D%E7%94%9F%E6%95%88%0Ahttps%3A%2F%2Fblog.csdn.net%2Fforezp%2Farticle%2Fdetails%2F84313907%0A%0A%60%60%60java%0A%40Configuration%0Apublic%20class%20Bean1Config%20%7B%0A%20%20%20%20%40Bean%0A%20%20%20%20%40ConditionalOnBean(value%20%3D%20Bean2.class%20)%0A%20%20%20%20public%20Bean1%20bean1()%7B%0A%20%20%20%20%20%20%20%20return%20new%20Bean1()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%40Configuration%0Apublic%20class%20Bean2Config%20%7B%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20Bean2%20bean2()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20Bean2()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%40GetMapping(%22%2FgetBean%2F%7BbeanName%7D%22)%0Apublic%20void%20getBean(%40PathVariable%20String%20beanName)%20%7B%0A%20%20%20%20Object%20bean%20%3D%20SpringUtil.getApplicationContext().getBean(beanName)%3B%0A%20%20%20%20if%20(Objects.nonNull(bean))%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(beanName%20%2B%20%22%20init%20success%22)%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(beanName%20%2B%20%22init%20fail%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%3E%20%E4%BB%A3%E7%A0%81%E4%B8%ADbean1%E6%98%AF%E5%AE%9A%E4%B9%89%E5%9C%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%E4%B8%AD%E7%9A%84%EF%BC%8C%E5%BD%93%E6%89%A7%E8%A1%8C%E5%88%B0%E9%85%8D%E7%BD%AE%E7%B1%BB%E8%A7%A3%E6%9E%90%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%40Component%EF%BC%8C%40Service%EF%BC%8C%40Controller%20%2C%40Configuration%E6%A0%87%E6%B3%A8%E7%9A%84%E7%B1%BB%E5%B7%B2%E7%BB%8F%E5%85%A8%E9%83%A8%E6%89%AB%E6%8F%8F%EF%BC%8C%E6%89%80%E4%BB%A5%E8%BF%99%E4%BA%9BBeanDifinition%E5%B7%B2%E7%BB%8F%E8%A2%AB%E5%90%8C%E6%AD%A5%E3%80%82%20%E4%BD%86%E6%98%AFbean1%E7%9A%84%E6%9D%A1%E4%BB%B6%E6%B3%A8%E8%A7%A3%E4%BE%9D%E8%B5%96%E7%9A%84%E6%98%AFbean2%EF%BC%8Cbean2%E6%98%AF%E8%A2%AB%E5%AE%9A%E4%B9%89%E7%9A%84%E9%85%8D%E7%BD%AE%E7%B1%BB%E4%B8%AD%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E6%AD%A4%E6%97%B6%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%9A%84%E8%A7%A3%E6%9E%90%E6%97%A0%E6%B3%95%E4%BF%9D%E8%AF%81%E5%85%88%E5%90%8E%E9%A1%BA%E5%BA%8F%EF%BC%8C%E5%B0%B1%E4%BC%9A%E5%87%BA%E7%8E%B0%E4%B8%8D%E7%94%9F%E6%95%88%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%0A%3E%20%E5%9C%A8spring%20ioc%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%EF%BC%8C%E4%BC%98%E5%85%88%E8%A7%A3%E6%9E%90%40Component%EF%BC%8C%40Service%EF%BC%8C%40Controller%E6%B3%A8%E8%A7%A3%E7%9A%84%E7%B1%BB%E3%80%82%E5%85%B6%E6%AC%A1%E8%A7%A3%E6%9E%90%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%40Configuration%E6%A0%87%E6%B3%A8%E7%9A%84%E7%B1%BB%E3%80%82%E6%9C%80%E5%90%8E%E5%BC%80%E5%A7%8B%E8%A7%A3%E6%9E%90%E9%85%8D%E7%BD%AE%E7%B1%BB%E4%B8%AD%E5%AE%9A%E4%B9%89%E7%9A%84bean%0A%0A%3E%20%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%0A%3E%201.%20ConditionalOnClass(Bean2.class)%E6%9D%A5%E4%BB%A3%E6%9B%BF%E3%80%82%0A%3E%202.%20%E5%A6%82%E6%9E%9C%E4%B8%80%E5%AE%9A%E8%A6%81%E5%8C%BA%E5%88%86%E4%B8%A4%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%9A%84%E5%85%88%E5%90%8E%E9%A1%BA%E5%BA%8F%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%B0%86%E8%BF%99%E4%B8%A4%E4%B8%AA%E7%B1%BB%E4%BA%A4%E4%B8%8EEnableAutoConfiguration%E7%AE%A1%E7%90%86%E5%92%8C%E8%A7%A6%E5%8F%91%E3%80%82%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%AE%9A%E4%B9%89%E5%9C%A8META-INF%5Cspring.factories%E4%B8%AD%E5%A3%B0%E6%98%8E%E6%98%AF%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E7%84%B6%E5%90%8E%E9%80%9A%E8%BF%87%40AutoConfigureBefore%E3%80%81AutoConfigureAfter%C2%A0%20AutoConfigureOrder%E6%8E%A7%E5%88%B6%E5%85%88%E5%90%8E%E9%A1%BA%E5%BA%8F%E3%80%82%E4%B9%8B%E6%89%80%E4%BB%A5%E8%BF%99%E4%B9%88%E5%81%9A%E6%98%AF%E5%9B%A0%E4%B8%BA%E8%BF%99%E4%B8%89%E4%B8%AA%E6%B3%A8%E8%A7%A3%E5%8F%AA%E5%AF%B9%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%9A%84%E5%85%88%E5%90%8E%E9%A1%BA%E5%BA%8F%E7%94%9F%E6%95%88

TransactionSynchronizationManager事务同步管理器与事务监听

创建时间:2022/11/6 15:24
更新时间:2022/11/6 16:01
作者:Chris
来源:https://www.jianshu.com/p/4b5eb29cc6d9

https://www.jianshu.com/p/4b5eb29cc6d9

1. 事务同步管理器是什么

TransactionSynchronizationManager 事务同步管理器。我们可以自定义实现

TransactionSynchronization ,监听Spring的事务操作。可以在事务提交之后,回调TransactionSynchronization类的方法。

在源码中的使用
org.springframework.cache.transaction.TransactionAwareCacheDecorator#put

 @Override
    public void put(final Object key, @Nullable final Object value) {
        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    TransactionAwareCacheDecorator.this.targetCache.put(key, value);
                }
            });
        }
        else {
            this.targetCache.put(key, value);
        }
    }

2. Connection与TransactionSynchronizationManager关系

  1. DataSourceTransactionManager

请求事务方法时,调用dobegin()将事务信息保存到TransactionSynchronizationManager中:在该方法中主要是在数据库连接池中获取一个Connection对象,然后将Connection对象放入到ThreadLocal中。实际上该事务方法的信息均由TransactionSynchronizationManager类管理。

源码:org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        Connection con = null;

        try {
            if (!txObject.hasConnectionHolder() ||
                    txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                    //在可见的数据源(连接池)中获取Connection对象
                Connection newCon = obtainDataSource().getConnection();
                if (logger.isDebugEnabled()) {
                    logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                }
                        
                txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
            }
            
            ...
          //关闭Connection对象的自动提交
           if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (logger.isDebugEnabled()) {
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
                con.setAutoCommit(false);
            }

            //将Connection对象绑定到Thread中
            if (txObject.isNewConnectionHolder()) {
                TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
            }
        }

        catch (Throwable ex) {
            if (txObject.isNewConnectionHolder()) {
                DataSourceUtils.releaseConnection(con, obtainDataSource());
                txObject.setConnectionHolder(null, false);
            }
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
        }
    }
public abstract class TransactionSynchronizationManager {
    private static final ThreadLocal<Map<Object, Object>> resources =
            new NamedThreadLocal<>("Transactional resources");

    public static void bindResource(Object key, Object value) throws IllegalStateException {
        Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
        Assert.notNull(value, "Value must not be null");
       
        Map<Object, Object> map = resources.get();
        // set ThreadLocal Map if none found
        if (map == null) {
            map = new HashMap<>();
            resources.set(map);
        }
        //将Connection对象绑定到resources 上。
        Object oldValue = map.put(actualKey, value);
        ...
    }}
  1. 执行sql语句时,实际上通过org.mybatis.spring.transaction.SpringManagedTransaction 类直接获取Connection对象。

源码:org.mybatis.spring.transaction.SpringManagedTransaction#openConnection

  private void openConnection() throws SQLException {
    //在ThreadLocal中获取Connection对象
    this.connection = DataSourceUtils.getConnection(this.dataSource);
    this.autoCommit = this.connection.getAutoCommit();
    //在ThreadLocal中获取是否开启事务
    this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
   ...
  }

源码:org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection

 public static Connection doGetConnection(DataSource dataSource) throws SQLException {
        Assert.notNull(dataSource, "No DataSource specified");
        //在doBegin()方法中,已经将创建的Connection对象放入到TransactionSynchronizationManager中
        ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
        if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
            conHolder.requested();
            if (!conHolder.hasConnection()) {
                logger.debug("Fetching resumed JDBC Connection from DataSource");
                conHolder.setConnection(fetchConnection(dataSource));
            }
            //直接返回Thread存储的Connection对象。
            return conHolder.getConnection();
        }

        ...

        return con;
    }

3. TransactionSynchronization

这个类是程序员对事务同步的扩展点:用于事务同步回调的接口

一般而言,我们在TransactionSynchronization使用最多的是 afterCommitafterCompletion方法。

可以在事务执行完毕之后,直接调用 afterCommit() 方法进行异步通知。
在 doCommit()方法中提交事务后,在cleanupAfterCompletion对connection进行重置,但依旧可以在afterCommit()回调中对数据库进行操作。

org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit

 private void processCommit(DefaultTransactionStatus status) throws TransactionException {
        try {
            //提交事务
            doCommit(status);
            ...
            try {
             //回调所有事务同步器的afterCommit方法。
                triggerAfterCommit(status);
            }
            finally {
            //回调所有事务同步器的afterCompletion方法。
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
            }
        }
        finally {
           //清除TransactionSynchronizationManager的ThreadLocal绑定的数据。
           //解除Thread绑定的resources资源。
           //将Commit设置为自动提交。
          //清理ConnectionHolder资源。
            cleanupAfterCompletion(status);
        }
    }
%0A%5Btoc%5D%0A%0Ahttps%3A%2F%2Fwww.jianshu.com%2Fp%2F4b5eb29cc6d9%0A%23%23%23%23%201.%20%E4%BA%8B%E5%8A%A1%E5%90%8C%E6%AD%A5%E7%AE%A1%E7%90%86%E5%99%A8%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20%60TransactionSynchronizationManager%60%20%20%E4%BA%8B%E5%8A%A1%E5%90%8C%E6%AD%A5%E7%AE%A1%E7%90%86%E5%99%A8%E3%80%82%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AE%9E%E7%8E%B0%0A%0A%3E%20%60TransactionSynchronization%60%20%EF%BC%8C%E7%9B%91%E5%90%ACSpring%E7%9A%84%E4%BA%8B%E5%8A%A1%E6%93%8D%E4%BD%9C%E3%80%82%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%BA%8B%E5%8A%A1%E6%8F%90%E4%BA%A4%E4%B9%8B%E5%90%8E%EF%BC%8C%E5%9B%9E%E8%B0%83TransactionSynchronization%E7%B1%BB%E7%9A%84%E6%96%B9%E6%B3%95%E3%80%82%0A%0A%0A%3E%20%E5%9C%A8%E6%BA%90%E7%A0%81%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8%0A%60org.springframework.cache.transaction.TransactionAwareCacheDecorator%23put%60%0A%60%60%60java%0A%20%40Override%0A%20%20%20%20public%20void%20put(final%20Object%20key%2C%20%40Nullable%20final%20Object%20value)%20%7B%0A%20%20%20%20%20%20%20%20if%20(TransactionSynchronizationManager.isSynchronizationActive())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20TransactionSynchronizationManager.registerSynchronization(new%20TransactionSynchronizationAdapter()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20public%20void%20afterCommit()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TransactionAwareCacheDecorator.this.targetCache.put(key%2C%20value)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.targetCache.put(key%2C%20value)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%23%23%23%23%202.%20Connection%E4%B8%8ETransactionSynchronizationManager%E5%85%B3%E7%B3%BB%0A%0A1.%20%20%60DataSourceTransactionManager%60%0A%3E%20%E8%AF%B7%E6%B1%82%E4%BA%8B%E5%8A%A1%E6%96%B9%E6%B3%95%E6%97%B6%EF%BC%8C%E8%B0%83%E7%94%A8dobegin()%E5%B0%86%E4%BA%8B%E5%8A%A1%E4%BF%A1%E6%81%AF%E4%BF%9D%E5%AD%98%E5%88%B0TransactionSynchronizationManager%E4%B8%AD%EF%BC%9A%E5%9C%A8%E8%AF%A5%E6%96%B9%E6%B3%95%E4%B8%AD%E4%B8%BB%E8%A6%81%E6%98%AF%E5%9C%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0%E4%B8%AD%E8%8E%B7%E5%8F%96%E4%B8%80%E4%B8%AAConnection%E5%AF%B9%E8%B1%A1%EF%BC%8C%E7%84%B6%E5%90%8E%E5%B0%86Connection%E5%AF%B9%E8%B1%A1%E6%94%BE%E5%85%A5%E5%88%B0ThreadLocal%E4%B8%AD%E3%80%82%E5%AE%9E%E9%99%85%E4%B8%8A%E8%AF%A5%E4%BA%8B%E5%8A%A1%E6%96%B9%E6%B3%95%E7%9A%84%E4%BF%A1%E6%81%AF%E5%9D%87%E7%94%B1TransactionSynchronizationManager%E7%B1%BB%E7%AE%A1%E7%90%86%E3%80%82%0A%0A%3E%20%E6%BA%90%E7%A0%81%EF%BC%9A%60org.springframework.jdbc.datasource.DataSourceTransactionManager%23doBegin%60%0A%60%60%60java%0Aprotected%20void%20doBegin(Object%20transaction%2C%20TransactionDefinition%20definition)%20%7B%0A%20%20%20%20%20%20%20%20DataSourceTransactionObject%20txObject%20%3D%20(DataSourceTransactionObject)%20transaction%3B%0A%20%20%20%20%20%20%20%20Connection%20con%20%3D%20null%3B%0A%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!txObject.hasConnectionHolder()%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20txObject.getConnectionHolder().isSynchronizedWithTransaction())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%9C%A8%E5%8F%AF%E8%A7%81%E7%9A%84%E6%95%B0%E6%8D%AE%E6%BA%90(%E8%BF%9E%E6%8E%A5%E6%B1%A0)%E4%B8%AD%E8%8E%B7%E5%8F%96Connection%E5%AF%B9%E8%B1%A1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Connection%20newCon%20%3D%20obtainDataSource().getConnection()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(logger.isDebugEnabled())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20logger.debug(%22Acquired%20Connection%20%5B%22%20%2B%20newCon%20%2B%20%22%5D%20for%20JDBC%20transaction%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20txObject.setConnectionHolder(new%20ConnectionHolder(newCon)%2C%20true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%85%B3%E9%97%ADConnection%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%87%AA%E5%8A%A8%E6%8F%90%E4%BA%A4%0A%20%20%20%20%20%20%20%20%20%20%20if%20(con.getAutoCommit())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20txObject.setMustRestoreAutoCommit(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(logger.isDebugEnabled())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20logger.debug(%22Switching%20JDBC%20Connection%20%5B%22%20%2B%20con%20%2B%20%22%5D%20to%20manual%20commit%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20con.setAutoCommit(false)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%B0%86Connection%E5%AF%B9%E8%B1%A1%E7%BB%91%E5%AE%9A%E5%88%B0Thread%E4%B8%AD%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(txObject.isNewConnectionHolder())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TransactionSynchronizationManager.bindResource(obtainDataSource()%2C%20txObject.getConnectionHolder())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20catch%20(Throwable%20ex)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(txObject.isNewConnectionHolder())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20DataSourceUtils.releaseConnection(con%2C%20obtainDataSource())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20txObject.setConnectionHolder(null%2C%20false)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20CannotCreateTransactionException(%22Could%20not%20open%20JDBC%20Connection%20for%20transaction%22%2C%20ex)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%60%60%60java%0Apublic%20abstract%20class%20TransactionSynchronizationManager%20%7B%0A%20%20%20%20private%20static%20final%20ThreadLocal%3CMap%3CObject%2C%20Object%3E%3E%20resources%20%3D%0A%20%20%20%20%20%20%20%20%20%20%20%20new%20NamedThreadLocal%3C%3E(%22Transactional%20resources%22)%3B%0A%0A%20%20%20%20public%20static%20void%20bindResource(Object%20key%2C%20Object%20value)%20throws%20IllegalStateException%20%7B%0A%20%20%20%20%20%20%20%20Object%20actualKey%20%3D%20TransactionSynchronizationUtils.unwrapResourceIfNecessary(key)%3B%0A%20%20%20%20%20%20%20%20Assert.notNull(value%2C%20%22Value%20must%20not%20be%20null%22)%3B%0A%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20Map%3CObject%2C%20Object%3E%20map%20%3D%20resources.get()%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20set%20ThreadLocal%20Map%20if%20none%20found%0A%20%20%20%20%20%20%20%20if%20(map%20%3D%3D%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20map%20%3D%20new%20HashMap%3C%3E()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20resources.set(map)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%2F%2F%E5%B0%86Connection%E5%AF%B9%E8%B1%A1%E7%BB%91%E5%AE%9A%E5%88%B0resources%20%E4%B8%8A%E3%80%82%0A%20%20%20%20%20%20%20%20Object%20oldValue%20%3D%20map.put(actualKey%2C%20value)%3B%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%7D%7D%0A%60%60%60%0A%0A%0A2.%20%E6%89%A7%E8%A1%8Csql%E8%AF%AD%E5%8F%A5%E6%97%B6%EF%BC%8C%E5%AE%9E%E9%99%85%E4%B8%8A%E9%80%9A%E8%BF%87%60org.mybatis.spring.transaction.SpringManagedTransaction%60%20%E7%B1%BB%E7%9B%B4%E6%8E%A5%E8%8E%B7%E5%8F%96Connection%E5%AF%B9%E8%B1%A1%E3%80%82%0A%3E%20%E6%BA%90%E7%A0%81%EF%BC%9A%60org.mybatis.spring.transaction.SpringManagedTransaction%23openConnection%60%0A%60%60%60java%0A%20%20private%20void%20openConnection()%20throws%20SQLException%20%7B%0A%20%20%20%20%2F%2F%E5%9C%A8ThreadLocal%E4%B8%AD%E8%8E%B7%E5%8F%96Connection%E5%AF%B9%E8%B1%A1%0A%20%20%20%20this.connection%20%3D%20DataSourceUtils.getConnection(this.dataSource)%3B%0A%20%20%20%20this.autoCommit%20%3D%20this.connection.getAutoCommit()%3B%0A%20%20%20%20%2F%2F%E5%9C%A8ThreadLocal%E4%B8%AD%E8%8E%B7%E5%8F%96%E6%98%AF%E5%90%A6%E5%BC%80%E5%90%AF%E4%BA%8B%E5%8A%A1%0A%20%20%20%20this.isConnectionTransactional%20%3D%20DataSourceUtils.isConnectionTransactional(this.connection%2C%20this.dataSource)%3B%0A%20%20%20...%0A%20%20%7D%0A%60%60%60%0A%0A%3E%20%E6%BA%90%E7%A0%81%EF%BC%9A%60org.springframework.jdbc.datasource.DataSourceUtils%23doGetConnection%60%0A%60%60%60java%0A%20public%20static%20Connection%20doGetConnection(DataSource%20dataSource)%20throws%20SQLException%20%7B%0A%20%20%20%20%20%20%20%20Assert.notNull(dataSource%2C%20%22No%20DataSource%20specified%22)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E5%9C%A8doBegin()%E6%96%B9%E6%B3%95%E4%B8%AD%EF%BC%8C%E5%B7%B2%E7%BB%8F%E5%B0%86%E5%88%9B%E5%BB%BA%E7%9A%84Connection%E5%AF%B9%E8%B1%A1%E6%94%BE%E5%85%A5%E5%88%B0TransactionSynchronizationManager%E4%B8%AD%0A%20%20%20%20%20%20%20%20ConnectionHolder%20conHolder%20%3D%20(ConnectionHolder)%20TransactionSynchronizationManager.getResource(dataSource)%3B%0A%20%20%20%20%20%20%20%20if%20(conHolder%20!%3D%20null%20%26%26%20(conHolder.hasConnection()%20%7C%7C%20conHolder.isSynchronizedWithTransaction()))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20conHolder.requested()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!conHolder.hasConnection())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20logger.debug(%22Fetching%20resumed%20JDBC%20Connection%20from%20DataSource%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20conHolder.setConnection(fetchConnection(dataSource))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E7%9B%B4%E6%8E%A5%E8%BF%94%E5%9B%9EThread%E5%AD%98%E5%82%A8%E7%9A%84Connection%E5%AF%B9%E8%B1%A1%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20conHolder.getConnection()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20...%0A%0A%20%20%20%20%20%20%20%20return%20con%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%23%23%23%23%203.%20TransactionSynchronization%0A%3E%20%E8%BF%99%E4%B8%AA%E7%B1%BB%E6%98%AF%E7%A8%8B%E5%BA%8F%E5%91%98%E5%AF%B9%E4%BA%8B%E5%8A%A1%E5%90%8C%E6%AD%A5%E7%9A%84%E6%89%A9%E5%B1%95%E7%82%B9%EF%BC%9A%E7%94%A8%E4%BA%8E%E4%BA%8B%E5%8A%A1%E5%90%8C%E6%AD%A5%E5%9B%9E%E8%B0%83%E7%9A%84%E6%8E%A5%E5%8F%A3%0A%0A%3E%20%E4%B8%80%E8%88%AC%E8%80%8C%E8%A8%80%EF%BC%8C%E6%88%91%E4%BB%AC%E5%9C%A8TransactionSynchronization%E4%BD%BF%E7%94%A8%E6%9C%80%E5%A4%9A%E7%9A%84%E6%98%AF%20%60afterCommit%60%20%E5%92%8C%20%60afterCompletion%60%E6%96%B9%E6%B3%95%E3%80%82%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%BA%8B%E5%8A%A1%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%E4%B9%8B%E5%90%8E%EF%BC%8C%E7%9B%B4%E6%8E%A5%E8%B0%83%E7%94%A8%20%60afterCommit()%60%20%E6%96%B9%E6%B3%95%E8%BF%9B%E8%A1%8C%E5%BC%82%E6%AD%A5%E9%80%9A%E7%9F%A5%E3%80%82%0A%3E%20%E5%9C%A8%20doCommit()%E6%96%B9%E6%B3%95%E4%B8%AD%E6%8F%90%E4%BA%A4%E4%BA%8B%E5%8A%A1%E5%90%8E%EF%BC%8C%E5%9C%A8cleanupAfterCompletion%E5%AF%B9connection%E8%BF%9B%E8%A1%8C%E9%87%8D%E7%BD%AE%EF%BC%8C%E4%BD%86%E4%BE%9D%E6%97%A7%E5%8F%AF%E4%BB%A5%E5%9C%A8afterCommit()%E5%9B%9E%E8%B0%83%E4%B8%AD%E5%AF%B9%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9B%E8%A1%8C%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A%3E%20%60%20%20org.springframework.transaction.support.AbstractPlatformTransactionManager%23processCommit%60%0A%60%60%60java%0A%20private%20void%20processCommit(DefaultTransactionStatus%20status)%20throws%20TransactionException%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E6%8F%90%E4%BA%A4%E4%BA%8B%E5%8A%A1%0A%20%20%20%20%20%20%20%20%20%20%20%20doCommit(status)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%9B%9E%E8%B0%83%E6%89%80%E6%9C%89%E4%BA%8B%E5%8A%A1%E5%90%8C%E6%AD%A5%E5%99%A8%E7%9A%84afterCommit%E6%96%B9%E6%B3%95%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20triggerAfterCommit(status)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%9B%9E%E8%B0%83%E6%89%80%E6%9C%89%E4%BA%8B%E5%8A%A1%E5%90%8C%E6%AD%A5%E5%99%A8%E7%9A%84afterCompletion%E6%96%B9%E6%B3%95%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20triggerAfterCompletion(status%2C%20TransactionSynchronization.STATUS_COMMITTED)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E6%B8%85%E9%99%A4TransactionSynchronizationManager%E7%9A%84ThreadLocal%E7%BB%91%E5%AE%9A%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E8%A7%A3%E9%99%A4Thread%E7%BB%91%E5%AE%9A%E7%9A%84resources%E8%B5%84%E6%BA%90%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%B0%86Commit%E8%AE%BE%E7%BD%AE%E4%B8%BA%E8%87%AA%E5%8A%A8%E6%8F%90%E4%BA%A4%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%E6%B8%85%E7%90%86ConnectionHolder%E8%B5%84%E6%BA%90%E3%80%82%0A%20%20%20%20%20%20%20%20%20%20%20%20cleanupAfterCompletion(status)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%60%60%60

transaction

创建时间:2020/9/2 15:44
更新时间:2022/11/6 15:20
作者:Chris
来源:https://blog.csdn.net/yanxin1213/article/details/100582643

1. Spring事务特点

Spring Framework 对事务管理提供了一致的抽象,其特点如下:

  1. 为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)
  2. 支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用
  3. 提供比其他事务API更简单的编程式事务管理API
  4. 与spring数据访问抽象的完美集成

2. 事务管理方式

Spring支持 编程式事务管理声明式事务管理 两种方式。

2.1 编程式事务

编程式事务管理使用TransactionTemplate

2.2 声明式事务

声明式事务管理建立在AOP之上的。

其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,

在执行完目标方法之后根据执行情况提交或者回滚事务。

3. 非自动提交(AutoCommit)

默认情况下,数据库处于自动提交模式。每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务。

对于正常的事务管理,是一组相关的操作处于一个事务之中,因此必须关闭数据库的自动提交模式。不过,这个我们不用担心,spring会将底层连接的自动提交特性设置为false。
org/springframework/jdbc/datasource/DataSourceTransactionManager.java

if (con.getautocommit()) {
  txobject.setmustrestoreautocommit(true);
  if (logger.isdebugenabled()) {
	logger.debug("switching jdbc connection [" + con + "] to manual commit");
  }
  con.setautocommit(false);
}

MyBatis自动参与到spring事务管理中,无需额外配置,只要org.mybatis.spring.SqlSessionFactoryBean 引用的数据源与DataSourceTransactionManager 引用的数据源一致即可,否则事务管理会不起作用。

4. spring事务特性

spring所有的事务管理策略类都继承自org.springframework.transaction.PlatformTransactionManager接口

5. 事务隔离级别

隔离级别是指若干个并发的事务之间的隔离程度。

5.1 五种隔离级别

TransactionDefinition 接口中定义了五个表示隔离级别的常量:

常量说明
ISOLATION_DEFAULT这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED
ISOLATION_READ_UNCOMMITTED该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别
ISOLATION_READ_COMMITTED该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值
ISOLATION_REPEATABLE_READ该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读
ISOLATION_SERIALIZABLE所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别

6 事务传播行为

6.1 七种传播行为
常量说明
PROPAGATION_REQUIRED如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值
PROPAGATION_REQUIRES_NEW创建一个新的事务,如果当前存在事务,则把当前事务挂起
PROPAGATION_SUPPORTS如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
PROPAGATION_NOT_SUPPORTED以非事务方式运行,如果当前存在事务,则把当前事务挂起
PROPAGATION_NEVER以非事务方式运行,如果当前存在事务,则抛出异常
PROPAGATION_MANDATORY如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
PROPAGATION_NESTED如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
6.2 NESTED

使嵌套的事务使用相同的物理事务,但是对嵌套调用设置了保存点|savepoint,所以 inner 事务可以独立于 outer 事务回滚。
如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.

6.3 REQUIRES_NEW

会创建一个新的物理事务,内层事务的提交回滚都是独立于外层事务的。

外层事务不受内层事务结果的影响,他们运行于独立的物理事务。

6.4 REQUIRED

如果当前方法的执行上下文中已经打开了事务,那么就使用当前这个事务。

如果当前没有事务,就创建一个新的。

如果多个方法都声明了 REQUIRED,并且他们嵌套调用,那么他们会共享同一个物理事务。就是 inner 产生了回滚,那么 outer 会跟着回滚。

7. Spring事务回滚规则

  1. 让spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。

  2. spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。

  3. 默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。

  4. 可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。

  5. 还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。

@Transactional注解

valueString可选的限定描述符,指定使用的事务管理器
propagationenum: Propagation可选的事务传播行为设置
isolationenum: Isolation可选的事务隔离级别设置
readOnlyboolean读写或只读事务,默认读写
timeoutint (in seconds granularity)事务超时时间设置
rollbackForClass对象数组,必须继承自Throwable导致事务回滚的异常类数组
rollbackForClassName类名数组,必须继承自Throwable导致事务回滚的异常类名字数组
noRollbackForClass对象数组,必须继承自Throwable不会导致事务回滚的异常类数组
noRollbackForClassName类名数组,必须继承自Throwable不会导致事务回滚的异常类名字数组
%0A%0A%23%23%23%23%201.%20Spring%E4%BA%8B%E5%8A%A1%E7%89%B9%E7%82%B9%0A%0ASpring%20Framework%20%E5%AF%B9%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E8%87%B4%E7%9A%84%E6%8A%BD%E8%B1%A1%EF%BC%8C%E5%85%B6%E7%89%B9%E7%82%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A1.%20%E4%B8%BA%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BA%8B%E5%8A%A1API%E6%8F%90%E4%BE%9B%E4%B8%80%E8%87%B4%E7%9A%84%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B%EF%BC%8C%E6%AF%94%E5%A6%82JTA(Java%20Transaction%20API)%2C%20JDBC%2C%20Hibernate%2C%20JPA(Java%20Persistence%20API%E5%92%8CJDO(Java%20Data%20Objects)%0A2.%20%E6%94%AF%E6%8C%81%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%EF%BC%8C%E7%89%B9%E5%88%AB%E6%98%AF%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E7%9A%84%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%EF%BC%8C%E7%AE%80%E5%8D%95%E6%98%93%E7%94%A8%0A3.%20%E6%8F%90%E4%BE%9B%E6%AF%94%E5%85%B6%E4%BB%96%E4%BA%8B%E5%8A%A1API%E6%9B%B4%E7%AE%80%E5%8D%95%E7%9A%84%E7%BC%96%E7%A8%8B%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86API%0A4.%20%E4%B8%8Espring%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%E6%8A%BD%E8%B1%A1%E7%9A%84%E5%AE%8C%E7%BE%8E%E9%9B%86%E6%88%90%0A%0A%23%23%23%23%202.%20%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E6%96%B9%E5%BC%8F%0A%0ASpring%E6%94%AF%E6%8C%81%20**%E7%BC%96%E7%A8%8B%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86**%20%E5%92%8C%20**%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86**%20%E4%B8%A4%E7%A7%8D%E6%96%B9%E5%BC%8F%E3%80%82%0A%0A%23%23%23%23%23%202.1%20%E7%BC%96%E7%A8%8B%E5%BC%8F%E4%BA%8B%E5%8A%A1%0A%0A%3E%20%E7%BC%96%E7%A8%8B%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E4%BD%BF%E7%94%A8TransactionTemplate%0A%0A%23%23%23%23%23%202.2%20%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%0A%0A%3E%20%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E5%BB%BA%E7%AB%8B%E5%9C%A8AOP%E4%B9%8B%E4%B8%8A%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%E5%85%B6%E6%9C%AC%E8%B4%A8%E6%98%AF%E5%AF%B9%E6%96%B9%E6%B3%95%E5%89%8D%E5%90%8E%E8%BF%9B%E8%A1%8C%E6%8B%A6%E6%88%AA%EF%BC%8C%E7%84%B6%E5%90%8E%E5%9C%A8%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E5%BC%80%E5%A7%8B%E4%B9%8B%E5%89%8D%E5%88%9B%E5%BB%BA%E6%88%96%E8%80%85%E5%8A%A0%E5%85%A5%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%EF%BC%8C%0A%3E%0A%3E%20%E5%9C%A8%E6%89%A7%E8%A1%8C%E5%AE%8C%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E4%B9%8B%E5%90%8E%E6%A0%B9%E6%8D%AE%E6%89%A7%E8%A1%8C%E6%83%85%E5%86%B5%E6%8F%90%E4%BA%A4%E6%88%96%E8%80%85%E5%9B%9E%E6%BB%9A%E4%BA%8B%E5%8A%A1%E3%80%82%0A%0A%0A%0A%23%23%23%23%203.%20%E9%9D%9E%E8%87%AA%E5%8A%A8%E6%8F%90%E4%BA%A4(AutoCommit)%0A%0A%E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%84%E4%BA%8E%E8%87%AA%E5%8A%A8%E6%8F%90%E4%BA%A4%E6%A8%A1%E5%BC%8F%E3%80%82%E6%AF%8F%E4%B8%80%E6%9D%A1%E8%AF%AD%E5%8F%A5%E5%A4%84%E4%BA%8E%E4%B8%80%E4%B8%AA%E5%8D%95%E7%8B%AC%E7%9A%84%E4%BA%8B%E5%8A%A1%E4%B8%AD%EF%BC%8C%E5%9C%A8%E8%BF%99%E6%9D%A1%E8%AF%AD%E5%8F%A5%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%E6%97%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%89%A7%E8%A1%8C%E6%88%90%E5%8A%9F%E5%88%99%E9%9A%90%E5%BC%8F%E7%9A%84%E6%8F%90%E4%BA%A4%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%89%A7%E8%A1%8C%E5%A4%B1%E8%B4%A5%E5%88%99%E9%9A%90%E5%BC%8F%E7%9A%84%E5%9B%9E%E6%BB%9A%E4%BA%8B%E5%8A%A1%E3%80%82%0A%0A%E5%AF%B9%E4%BA%8E%E6%AD%A3%E5%B8%B8%E7%9A%84%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%EF%BC%8C%E6%98%AF%E4%B8%80%E7%BB%84%E7%9B%B8%E5%85%B3%E7%9A%84%E6%93%8D%E4%BD%9C%E5%A4%84%E4%BA%8E%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E4%B9%8B%E4%B8%AD%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%BF%85%E9%A1%BB%E5%85%B3%E9%97%AD%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E8%87%AA%E5%8A%A8%E6%8F%90%E4%BA%A4%E6%A8%A1%E5%BC%8F%E3%80%82%E4%B8%8D%E8%BF%87%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%88%91%E4%BB%AC%E4%B8%8D%E7%94%A8%E6%8B%85%E5%BF%83%EF%BC%8Cspring%E4%BC%9A%E5%B0%86%E5%BA%95%E5%B1%82%E8%BF%9E%E6%8E%A5%E7%9A%84%E8%87%AA%E5%8A%A8%E6%8F%90%E4%BA%A4%E7%89%B9%E6%80%A7%E8%AE%BE%E7%BD%AE%E4%B8%BAfalse%E3%80%82%0A%60org%2Fspringframework%2Fjdbc%2Fdatasource%2FDataSourceTransactionManager.java%60%0A%0A%60%60%60java%0Aif%20(con.getautocommit())%20%7B%0A%20%20txobject.setmustrestoreautocommit(true)%3B%0A%20%20if%20(logger.isdebugenabled())%20%7B%0A%09logger.debug(%22switching%20jdbc%20connection%20%5B%22%20%2B%20con%20%2B%20%22%5D%20to%20manual%20commit%22)%3B%0A%20%20%7D%0A%20%20con.setautocommit(false)%3B%0A%7D%0A%60%60%60%0A!%5B4a1b2283076414b4a0cee2783a0dfb3a.png%5D(en-resource%3A%2F%2Fdatabase%2F1493%3A0)%0A%0A%0A%0A%3E%20MyBatis%E8%87%AA%E5%8A%A8%E5%8F%82%E4%B8%8E%E5%88%B0spring%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E4%B8%AD%EF%BC%8C%E6%97%A0%E9%9C%80%E9%A2%9D%E5%A4%96%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%8F%AA%E8%A6%81org.mybatis.spring.**SqlSessionFactoryBean**%20%E5%BC%95%E7%94%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E6%BA%90%E4%B8%8E**DataSourceTransactionManager**%20%E5%BC%95%E7%94%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E6%BA%90%E4%B8%80%E8%87%B4%E5%8D%B3%E5%8F%AF%EF%BC%8C%E5%90%A6%E5%88%99%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E4%BC%9A%E4%B8%8D%E8%B5%B7%E4%BD%9C%E7%94%A8%E3%80%82%0A%0A%0A%0A%23%23%23%23%204.%20spring%E4%BA%8B%E5%8A%A1%E7%89%B9%E6%80%A7%0A%0Aspring%E6%89%80%E6%9C%89%E7%9A%84%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E7%AD%96%E7%95%A5%E7%B1%BB%E9%83%BD%E7%BB%A7%E6%89%BF%E8%87%AAorg.springframework.transaction.**PlatformTransactionManager**%E6%8E%A5%E5%8F%A3%0A%0A%0A%0A%23%23%23%23%205.%20%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%0A%0A%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E6%98%AF%E6%8C%87%E8%8B%A5%E5%B9%B2%E4%B8%AA%E5%B9%B6%E5%8F%91%E7%9A%84%E4%BA%8B%E5%8A%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E9%9A%94%E7%A6%BB%E7%A8%8B%E5%BA%A6%E3%80%82%0A%0A%23%23%23%23%23%205.1%20%E4%BA%94%E7%A7%8D%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%0A%0A%3E%20%20TransactionDefinition%20%E6%8E%A5%E5%8F%A3%E4%B8%AD%E5%AE%9A%E4%B9%89%E4%BA%86%E4%BA%94%E4%B8%AA%E8%A1%A8%E7%A4%BA%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E7%9A%84%E5%B8%B8%E9%87%8F%EF%BC%9A%0A%0A%7C%20%E5%B8%B8%E9%87%8F%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E8%AF%B4%E6%98%8E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20--------------------------%20%7C%20------------------------------------------------------------%20%7C%0A%7C%20ISOLATION_DEFAULT%20%20%20%20%20%20%20%20%20%20%7C%20%E8%BF%99%E6%98%AF%E9%BB%98%E8%AE%A4%E5%80%BC%EF%BC%8C%E8%A1%A8%E7%A4%BA%E4%BD%BF%E7%94%A8%E5%BA%95%E5%B1%82%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E9%BB%98%E8%AE%A4%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E3%80%82%E5%AF%B9%E5%A4%A7%E9%83%A8%E5%88%86%E6%95%B0%E6%8D%AE%E5%BA%93%E8%80%8C%E8%A8%80%EF%BC%8C%E9%80%9A%E5%B8%B8%E8%BF%99%E5%80%BC%E5%B0%B1%E6%98%AFTransactionDefinition.ISOLATION_READ_COMMITTED%20%7C%0A%7C%20ISOLATION_READ_UNCOMMITTED%20%7C%20%E8%AF%A5%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%8F%AF%E4%BB%A5%E8%AF%BB%E5%8F%96%E5%8F%A6%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E4%BF%AE%E6%94%B9%E4%BD%86%E8%BF%98%E6%B2%A1%E6%9C%89%E6%8F%90%E4%BA%A4%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%E8%AF%A5%E7%BA%A7%E5%88%AB%E4%B8%8D%E8%83%BD%E9%98%B2%E6%AD%A2%E8%84%8F%E8%AF%BB%EF%BC%8C%E4%B8%8D%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%E5%92%8C%E5%B9%BB%E8%AF%BB%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%BE%88%E5%B0%91%E4%BD%BF%E7%94%A8%E8%AF%A5%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E3%80%82%E6%AF%94%E5%A6%82PostgreSQL%E5%AE%9E%E9%99%85%E4%B8%8A%E5%B9%B6%E6%B2%A1%E6%9C%89%E6%AD%A4%E7%BA%A7%E5%88%AB%20%7C%0A%7C%20ISOLATION_READ_COMMITTED%20%20%20%7C%20%E8%AF%A5%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%8F%AA%E8%83%BD%E8%AF%BB%E5%8F%96%E5%8F%A6%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%B7%B2%E7%BB%8F%E6%8F%90%E4%BA%A4%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%E8%AF%A5%E7%BA%A7%E5%88%AB%E5%8F%AF%E4%BB%A5%E9%98%B2%E6%AD%A2%E8%84%8F%E8%AF%BB%EF%BC%8C%E8%BF%99%E4%B9%9F%E6%98%AF%E5%A4%A7%E5%A4%9A%E6%95%B0%E6%83%85%E5%86%B5%E4%B8%8B%E7%9A%84%E6%8E%A8%E8%8D%90%E5%80%BC%20%7C%0A%7C%20ISOLATION_REPEATABLE_READ%20%20%7C%20%E8%AF%A5%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%9C%A8%E6%95%B4%E4%B8%AA%E8%BF%87%E7%A8%8B%E4%B8%AD%E5%8F%AF%E4%BB%A5%E5%A4%9A%E6%AC%A1%E9%87%8D%E5%A4%8D%E6%89%A7%E8%A1%8C%E6%9F%90%E4%B8%AA%E6%9F%A5%E8%AF%A2%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%AF%8F%E6%AC%A1%E8%BF%94%E5%9B%9E%E7%9A%84%E8%AE%B0%E5%BD%95%E9%83%BD%E7%9B%B8%E5%90%8C%E3%80%82%E8%AF%A5%E7%BA%A7%E5%88%AB%E5%8F%AF%E4%BB%A5%E9%98%B2%E6%AD%A2%E8%84%8F%E8%AF%BB%E5%92%8C%E4%B8%8D%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%20%7C%0A%7C%20ISOLATION_SERIALIZABLE%20%20%20%20%20%7C%20%E6%89%80%E6%9C%89%E7%9A%84%E4%BA%8B%E5%8A%A1%E4%BE%9D%E6%AC%A1%E9%80%90%E4%B8%AA%E6%89%A7%E8%A1%8C%EF%BC%8C%E8%BF%99%E6%A0%B7%E4%BA%8B%E5%8A%A1%E4%B9%8B%E9%97%B4%E5%B0%B1%E5%AE%8C%E5%85%A8%E4%B8%8D%E5%8F%AF%E8%83%BD%E4%BA%A7%E7%94%9F%E5%B9%B2%E6%89%B0%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E8%AF%A5%E7%BA%A7%E5%88%AB%E5%8F%AF%E4%BB%A5%E9%98%B2%E6%AD%A2%E8%84%8F%E8%AF%BB%E3%80%81%E4%B8%8D%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%E4%BB%A5%E5%8F%8A%E5%B9%BB%E8%AF%BB%E3%80%82%E4%BD%86%E6%98%AF%E8%BF%99%E5%B0%86%E4%B8%A5%E9%87%8D%E5%BD%B1%E5%93%8D%E7%A8%8B%E5%BA%8F%E7%9A%84%E6%80%A7%E8%83%BD%E3%80%82%E9%80%9A%E5%B8%B8%E6%83%85%E5%86%B5%E4%B8%8B%E4%B9%9F%E4%B8%8D%E4%BC%9A%E7%94%A8%E5%88%B0%E8%AF%A5%E7%BA%A7%E5%88%AB%20%7C%0A%0A%0A%0A%23%23%23%23%206%20%E4%BA%8B%E5%8A%A1%E4%BC%A0%E6%92%AD%E8%A1%8C%E4%B8%BA%0A%0A%23%23%23%23%23%206.1%20%E4%B8%83%E7%A7%8D%E4%BC%A0%E6%92%AD%E8%A1%8C%E4%B8%BA%0A%0A%7C%20%E5%B8%B8%E9%87%8F%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E8%AF%B4%E6%98%8E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20-------------------------%20%7C%20------------------------------------------------------------%20%7C%0A%7C%20PROPAGATION_REQUIRED%20%20%20%20%20%20%7C%20%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E5%AD%98%E5%9C%A8%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E5%8A%A0%E5%85%A5%E8%AF%A5%E4%BA%8B%E5%8A%A1%EF%BC%9B%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E6%B2%A1%E6%9C%89%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E4%BA%8B%E5%8A%A1%E3%80%82%E8%BF%99%E6%98%AF%E9%BB%98%E8%AE%A4%E5%80%BC%20%7C%0A%7C%20PROPAGATION_REQUIRES_NEW%20%20%7C%20%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E5%AD%98%E5%9C%A8%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E6%8A%8A%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E6%8C%82%E8%B5%B7%20%20%20%20%20%20%20%20%20%7C%0A%7C%20PROPAGATION_SUPPORTS%20%20%20%20%20%20%7C%20%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E5%AD%98%E5%9C%A8%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E5%8A%A0%E5%85%A5%E8%AF%A5%E4%BA%8B%E5%8A%A1%EF%BC%9B%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E6%B2%A1%E6%9C%89%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E4%BB%A5%E9%9D%9E%E4%BA%8B%E5%8A%A1%E7%9A%84%E6%96%B9%E5%BC%8F%E7%BB%A7%E7%BB%AD%E8%BF%90%E8%A1%8C%20%7C%0A%7C%20PROPAGATION_NOT_SUPPORTED%20%7C%20%E4%BB%A5%E9%9D%9E%E4%BA%8B%E5%8A%A1%E6%96%B9%E5%BC%8F%E8%BF%90%E8%A1%8C%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E5%AD%98%E5%9C%A8%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E6%8A%8A%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E6%8C%82%E8%B5%B7%20%20%20%20%20%20%20%20%20%7C%0A%7C%20PROPAGATION_NEVER%20%20%20%20%20%20%20%20%20%7C%20%E4%BB%A5%E9%9D%9E%E4%BA%8B%E5%8A%A1%E6%96%B9%E5%BC%8F%E8%BF%90%E8%A1%8C%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E5%AD%98%E5%9C%A8%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20PROPAGATION_MANDATORY%20%20%20%20%20%7C%20%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E5%AD%98%E5%9C%A8%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E5%8A%A0%E5%85%A5%E8%AF%A5%E4%BA%8B%E5%8A%A1%EF%BC%9B%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E6%B2%A1%E6%9C%89%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%20%7C%0A%7C%20PROPAGATION_NESTED%20%20%20%20%20%20%20%20%7C%20%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E5%AD%98%E5%9C%A8%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E4%BD%9C%E4%B8%BA%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E7%9A%84%E5%B5%8C%E5%A5%97%E4%BA%8B%E5%8A%A1%E6%9D%A5%E8%BF%90%E8%A1%8C%EF%BC%9B%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E6%B2%A1%E6%9C%89%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%88%99%E8%AF%A5%E5%8F%96%E5%80%BC%E7%AD%89%E4%BB%B7%E4%BA%8ETransactionDefinition.PROPAGATION_REQUIRED%E3%80%82%20%7C%0A%0A%23%23%23%23%23%206.2%20NESTED%0A%0A%3E%20%E4%BD%BF%E5%B5%8C%E5%A5%97%E7%9A%84%E4%BA%8B%E5%8A%A1%E4%BD%BF%E7%94%A8%E7%9B%B8%E5%90%8C%E7%9A%84%E7%89%A9%E7%90%86%E4%BA%8B%E5%8A%A1%EF%BC%8C%E4%BD%86%E6%98%AF%E5%AF%B9%E5%B5%8C%E5%A5%97%E8%B0%83%E7%94%A8%E8%AE%BE%E7%BD%AE%E4%BA%86**%E4%BF%9D%E5%AD%98%E7%82%B9%7Csavepoint**%EF%BC%8C%E6%89%80%E4%BB%A5%20inner%20%E4%BA%8B%E5%8A%A1%E5%8F%AF%E4%BB%A5%E7%8B%AC%E7%AB%8B%E4%BA%8E%20outer%20%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E3%80%82%0A%E5%A6%82%E6%9E%9C%E8%BF%99%E4%B8%AA%E5%B5%8C%E5%A5%97%E4%BA%8B%E5%8A%A1%E5%A4%B1%E8%B4%A5%2C%20%E6%88%91%E4%BB%AC%E5%B0%86%E5%9B%9E%E6%BB%9A%E5%88%B0%E6%AD%A4%20savepoint.%20%E6%BD%9C%E5%A5%97%E4%BA%8B%E5%8A%A1%E6%98%AF%E5%A4%96%E9%83%A8%E4%BA%8B%E5%8A%A1%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%2C%20%E5%8F%AA%E6%9C%89%E5%A4%96%E9%83%A8%E4%BA%8B%E5%8A%A1%E7%BB%93%E6%9D%9F%E5%90%8E%E5%AE%83%E6%89%8D%E4%BC%9A%E8%A2%AB%E6%8F%90%E4%BA%A4.%C2%A0%0A%0A%23%23%23%23%23%206.3%20REQUIRES_NEW%0A%0A%3E%20%E4%BC%9A%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E7%89%A9%E7%90%86%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%86%85%E5%B1%82%E4%BA%8B%E5%8A%A1%E7%9A%84%E6%8F%90%E4%BA%A4%E5%9B%9E%E6%BB%9A%E9%83%BD%E6%98%AF%E7%8B%AC%E7%AB%8B%E4%BA%8E%E5%A4%96%E5%B1%82%E4%BA%8B%E5%8A%A1%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%E5%A4%96%E5%B1%82%E4%BA%8B%E5%8A%A1%E4%B8%8D%E5%8F%97%E5%86%85%E5%B1%82%E4%BA%8B%E5%8A%A1%E7%BB%93%E6%9E%9C%E7%9A%84%E5%BD%B1%E5%93%8D%EF%BC%8C%E4%BB%96%E4%BB%AC%E8%BF%90%E8%A1%8C%E4%BA%8E%E7%8B%AC%E7%AB%8B%E7%9A%84%E7%89%A9%E7%90%86%E4%BA%8B%E5%8A%A1%E3%80%82%0A%0A%23%23%23%23%23%206.4%20REQUIRED%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E6%96%B9%E6%B3%95%E7%9A%84%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E5%B7%B2%E7%BB%8F%E6%89%93%E5%BC%80%E4%BA%86%E4%BA%8B%E5%8A%A1%EF%BC%8C%E9%82%A3%E4%B9%88%E5%B0%B1%E4%BD%BF%E7%94%A8%E5%BD%93%E5%89%8D%E8%BF%99%E4%B8%AA%E4%BA%8B%E5%8A%A1%E3%80%82%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E6%B2%A1%E6%9C%89%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%B0%B1%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E5%A4%9A%E4%B8%AA%E6%96%B9%E6%B3%95%E9%83%BD%E5%A3%B0%E6%98%8E%E4%BA%86%20REQUIRED%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BB%96%E4%BB%AC%E5%B5%8C%E5%A5%97%E8%B0%83%E7%94%A8%EF%BC%8C%E9%82%A3%E4%B9%88%E4%BB%96%E4%BB%AC%E4%BC%9A%E5%85%B1%E4%BA%AB%E5%90%8C%E4%B8%80%E4%B8%AA%E7%89%A9%E7%90%86%E4%BA%8B%E5%8A%A1%E3%80%82%E5%B0%B1%E6%98%AF%20inner%20%E4%BA%A7%E7%94%9F%E4%BA%86%E5%9B%9E%E6%BB%9A%EF%BC%8C%E9%82%A3%E4%B9%88%20outer%20%E4%BC%9A%E8%B7%9F%E7%9D%80%E5%9B%9E%E6%BB%9A%E3%80%82%0A%0A%0A!%5B2228589c7601a273e6776fef1f9f772e.png%5D(en-resource%3A%2F%2Fdatabase%2F672%3A1)%0A%0A%23%23%23%23%207.%20Spring%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E8%A7%84%E5%88%99%0A%0A1.%20%E8%AE%A9spring%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E5%99%A8%E5%9B%9E%E6%BB%9A%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E7%9A%84%E6%8E%A8%E8%8D%90%E6%96%B9%E6%B3%95%E6%98%AF%E5%9C%A8%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E7%9A%84%E4%B8%8A%E4%B8%8B%E6%96%87%E5%86%85%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E3%80%82%0A%0A2.%20spring%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E5%99%A8%E4%BC%9A%E6%8D%95%E6%8D%89%E4%BB%BB%E4%BD%95%E6%9C%AA%E5%A4%84%E7%90%86%E7%9A%84%E5%BC%82%E5%B8%B8%EF%BC%8C%E7%84%B6%E5%90%8E%E4%BE%9D%E6%8D%AE%E8%A7%84%E5%88%99%E5%86%B3%E5%AE%9A%E6%98%AF%E5%90%A6%E5%9B%9E%E6%BB%9A%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E7%9A%84%E4%BA%8B%E5%8A%A1%E3%80%82%0A%0A3.%20%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E4%B8%8B%EF%BC%8Cspring%E5%8F%AA%E6%9C%89%E5%9C%A8%E6%8A%9B%E5%87%BA%E7%9A%84%E5%BC%82%E5%B8%B8%E4%B8%BA%E8%BF%90%E8%A1%8C%E6%97%B6unchecked%E5%BC%82%E5%B8%B8%E6%97%B6%E6%89%8D%E5%9B%9E%E6%BB%9A%E8%AF%A5%E4%BA%8B%E5%8A%A1%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%8A%9B%E5%87%BA%E7%9A%84%E5%BC%82%E5%B8%B8%E4%B8%BARuntimeException%E7%9A%84%E5%AD%90%E7%B1%BB(Errors%E4%B9%9F%E4%BC%9A%E5%AF%BC%E8%87%B4%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A)%EF%BC%8C%E8%80%8C%E6%8A%9B%E5%87%BAchecked%E5%BC%82%E5%B8%B8%E5%88%99%E4%B8%8D%E4%BC%9A%E5%AF%BC%E8%87%B4%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E3%80%82%0A%0A4.%20%E5%8F%AF%E4%BB%A5%E6%98%8E%E7%A1%AE%E7%9A%84%E9%85%8D%E7%BD%AE%E5%9C%A8%E6%8A%9B%E5%87%BA%E9%82%A3%E4%BA%9B%E5%BC%82%E5%B8%B8%E6%97%B6%E5%9B%9E%E6%BB%9A%E4%BA%8B%E5%8A%A1%EF%BC%8C%E5%8C%85%E6%8B%ACchecked%E5%BC%82%E5%B8%B8%E3%80%82%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%98%8E%E7%A1%AE%E5%AE%9A%E4%B9%89%E9%82%A3%E4%BA%9B%E5%BC%82%E5%B8%B8%E6%8A%9B%E5%87%BA%E6%97%B6%E4%B8%8D%E5%9B%9E%E6%BB%9A%E4%BA%8B%E5%8A%A1%E3%80%82%0A%0A5.%20%E8%BF%98%E5%8F%AF%E4%BB%A5%E7%BC%96%E7%A8%8B%E6%80%A7%E7%9A%84%E9%80%9A%E8%BF%87setRollbackOnly()%E6%96%B9%E6%B3%95%E6%9D%A5%E6%8C%87%E7%A4%BA%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%BF%85%E9%A1%BB%E5%9B%9E%E6%BB%9A%EF%BC%8C%E5%9C%A8%E8%B0%83%E7%94%A8%E5%AE%8CsetRollbackOnly()%E5%90%8E%E4%BD%A0%E6%89%80%E8%83%BD%E6%89%A7%E8%A1%8C%E7%9A%84%E5%94%AF%E4%B8%80%E6%93%8D%E4%BD%9C%E5%B0%B1%E6%98%AF%E5%9B%9E%E6%BB%9A%E3%80%82%0A%0A**%40Transactional%E6%B3%A8%E8%A7%A3**%0A%0A%7C%20value%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20String%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E5%8F%AF%E9%80%89%E7%9A%84%E9%99%90%E5%AE%9A%E6%8F%8F%E8%BF%B0%E7%AC%A6%EF%BC%8C%E6%8C%87%E5%AE%9A%E4%BD%BF%E7%94%A8%E7%9A%84%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E5%99%A8%20%7C%0A%7C%20----------------------%20%7C%20----------------------------------%20%7C%20--------------------------------------%20%7C%0A%7C%20propagation%20%20%20%20%20%20%20%20%20%20%20%20%7C%20enum%3A%20Propagation%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E5%8F%AF%E9%80%89%E7%9A%84%E4%BA%8B%E5%8A%A1%E4%BC%A0%E6%92%AD%E8%A1%8C%E4%B8%BA%E8%AE%BE%E7%BD%AE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20isolation%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20enum%3A%20Isolation%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E5%8F%AF%E9%80%89%E7%9A%84%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E8%AE%BE%E7%BD%AE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20readOnly%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20boolean%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E8%AF%BB%E5%86%99%E6%88%96%E5%8F%AA%E8%AF%BB%E4%BA%8B%E5%8A%A1%EF%BC%8C%E9%BB%98%E8%AE%A4%E8%AF%BB%E5%86%99%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20timeout%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20int%20(in%20seconds%20granularity)%20%20%20%20%20%20%20%7C%20%E4%BA%8B%E5%8A%A1%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E8%AE%BE%E7%BD%AE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20rollbackFor%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Class%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84%EF%BC%8C%E5%BF%85%E9%A1%BB%E7%BB%A7%E6%89%BF%E8%87%AAThrowable%20%7C%20%E5%AF%BC%E8%87%B4%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E7%9A%84%E5%BC%82%E5%B8%B8%E7%B1%BB%E6%95%B0%E7%BB%84%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20rollbackForClassName%20%20%20%7C%20%E7%B1%BB%E5%90%8D%E6%95%B0%E7%BB%84%EF%BC%8C%E5%BF%85%E9%A1%BB%E7%BB%A7%E6%89%BF%E8%87%AAThrowable%20%20%20%20%20%20%7C%20%E5%AF%BC%E8%87%B4%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E7%9A%84%E5%BC%82%E5%B8%B8%E7%B1%BB%E5%90%8D%E5%AD%97%E6%95%B0%E7%BB%84%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20noRollbackFor%20%20%20%20%20%20%20%20%20%20%7C%20Class%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84%EF%BC%8C%E5%BF%85%E9%A1%BB%E7%BB%A7%E6%89%BF%E8%87%AAThrowable%20%7C%20%E4%B8%8D%E4%BC%9A%E5%AF%BC%E8%87%B4%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E7%9A%84%E5%BC%82%E5%B8%B8%E7%B1%BB%E6%95%B0%E7%BB%84%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20noRollbackForClassName%20%7C%20%E7%B1%BB%E5%90%8D%E6%95%B0%E7%BB%84%EF%BC%8C%E5%BF%85%E9%A1%BB%E7%BB%A7%E6%89%BF%E8%87%AAThrowable%20%20%20%20%20%20%7C%20%E4%B8%8D%E4%BC%9A%E5%AF%BC%E8%87%B4%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E7%9A%84%E5%BC%82%E5%B8%B8%E7%B1%BB%E5%90%8D%E5%AD%97%E6%95%B0%E7%BB%84%20%20%20%20%20%20%20%7C

prometheus-grafana

创建时间:2022/11/5 18:46
更新时间:2022/11/5 19:20
作者:Chris

改pom.xml

加入下面依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--将SpringBoot产生的标准端点数据转换成prometheus需要的数据格式-->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <scope>runtime</scope>
</dependency>

改yml

加入如下配置信息

management:
  endpoints:
    web:
      exposure:
        include: "*" # 对外暴露所有的监控指标
      base-path: /admin # actuator暴露接口的前缀,默认为 /actuator
  endpoint:
    prometheus:
      enabled: true # 激活prometheus
    health:
      show-details: always # 一直显示健康详细信息
  metrics:
    export:
      prometheus:
        enabled: true # 允许导出 prometheus 中的指标信息
  server:
    port: 8888

添加业务方法

@RequestMapping("/heap/test")
@RestController
public class TestController {
    public static final Map<String, Object> map = new ConcurrentHashMap<>();

    @RequestMapping("")
    public String testHeapUsed() {
        for (int i = 0; i < 1000000; i++) {
            map.put(i + "", new Object());
        }
        return "ok";
    }
}

http://localhost:8888/admin/

改启动类

在向prometheus注册信息中加入应用名称信息

@Bean
MeterRegistryCustomizer<MeterRegistry> config(@Value("${spring.application.name}") String applicationName) {
    return (registry) -> registry.config().commonTags("fuck", applicationName);
}

http://192.168.0.104:8888/admin/prometheus

安装prometheus

mkdir /etc/prometheus
vi 
global:
  scrape_interval:     15s # By default, scrape targets every 15 seconds.
  evaluation_interval: 15s # Evaluate rules every 15 seconds.

  # Attach these extra labels to all timeseries collected by this Prometheus instance.
  external_labels:
    monitor: 'codelab-monitor'
rule_files:
  - 'prometheus.rules.yml'

scrape_configs:
  - job_name: 'prometheus'

    # Override the global default and scrape targets from this job every 5 seconds.
    scrape_interval: 5s

    static_configs:
      - targets: ['localhost:9090']

  ## 以下内容为springboot应该配置,每隔5s向192.168.0.104:8888的/admin/prometheus端点发起请求获取指标数据并存储在本地
  - job_name: 'springboot-prometheus'
    # Override the global default and scrape targets from this job every 5 seconds.
    scrape_interval: 5s
    metrics_path: '/admin/prometheus'
    static_configs:
      - targets: ['192.168.0.104:8888']
        labels:
          group: 'production'
docker run -d --name=prometheus -p 9090:9090 -v /etc/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus

http://master:9090



安装grafana

docker run -d --name=grafana -p 3000:3000 grafana/grafana

http://master:3000/

配置数据源

配置prometheus访问地址
http://192.168.139.127:9090

导入模板

输入4701, 并选择刚才配置的prometheus数据源后点击 导入

%5Btoc%5D%0A%23%23%20%E6%94%B9pom.xml%0A%3E%20%E5%8A%A0%E5%85%A5%E4%B8%8B%E9%9D%A2%E4%BE%9D%E8%B5%96%0A%60%60%60xml%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Espring-boot-starter-actuator%3C%2FartifactId%3E%0A%3C%2Fdependency%3E%0A%3C!--%E5%B0%86SpringBoot%E4%BA%A7%E7%94%9F%E7%9A%84%E6%A0%87%E5%87%86%E7%AB%AF%E7%82%B9%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2%E6%88%90prometheus%E9%9C%80%E8%A6%81%E7%9A%84%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F--%3E%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Eio.micrometer%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Emicrometer-registry-prometheus%3C%2FartifactId%3E%0A%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%3C%2Fdependency%3E%0A%60%60%60%0A%0A%23%23%20%E6%94%B9yml%0A%3E%20%E5%8A%A0%E5%85%A5%E5%A6%82%E4%B8%8B%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%0A%0A%60%60%60yml%0Amanagement%3A%0A%20%20endpoints%3A%0A%20%20%20%20web%3A%0A%20%20%20%20%20%20exposure%3A%0A%20%20%20%20%20%20%20%20include%3A%20%22*%22%20%23%20%E5%AF%B9%E5%A4%96%E6%9A%B4%E9%9C%B2%E6%89%80%E6%9C%89%E7%9A%84%E7%9B%91%E6%8E%A7%E6%8C%87%E6%A0%87%0A%20%20%20%20%20%20base-path%3A%20%2Fadmin%20%23%20actuator%E6%9A%B4%E9%9C%B2%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%89%8D%E7%BC%80%2C%E9%BB%98%E8%AE%A4%E4%B8%BA%20%2Factuator%0A%20%20endpoint%3A%0A%20%20%20%20prometheus%3A%0A%20%20%20%20%20%20enabled%3A%20true%20%23%20%E6%BF%80%E6%B4%BBprometheus%0A%20%20%20%20health%3A%0A%20%20%20%20%20%20show-details%3A%20always%20%23%20%E4%B8%80%E7%9B%B4%E6%98%BE%E7%A4%BA%E5%81%A5%E5%BA%B7%E8%AF%A6%E7%BB%86%E4%BF%A1%E6%81%AF%0A%20%20metrics%3A%0A%20%20%20%20export%3A%0A%20%20%20%20%20%20prometheus%3A%0A%20%20%20%20%20%20%20%20enabled%3A%20true%20%23%20%E5%85%81%E8%AE%B8%E5%AF%BC%E5%87%BA%20prometheus%20%E4%B8%AD%E7%9A%84%E6%8C%87%E6%A0%87%E4%BF%A1%E6%81%AF%0A%20%20server%3A%0A%20%20%20%20port%3A%208888%0A%60%60%60%0A%0A%23%23%20%E6%B7%BB%E5%8A%A0%E4%B8%9A%E5%8A%A1%E6%96%B9%E6%B3%95%0A%0A%60%60%60java%0A%40RequestMapping(%22%2Fheap%2Ftest%22)%0A%40RestController%0Apublic%20class%20TestController%20%7B%0A%20%20%20%20public%20static%20final%20Map%3CString%2C%20Object%3E%20map%20%3D%20new%20ConcurrentHashMap%3C%3E()%3B%0A%0A%20%20%20%20%40RequestMapping(%22%22)%0A%20%20%20%20public%20String%20testHeapUsed()%20%7B%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%201000000%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20map.put(i%20%2B%20%22%22%2C%20new%20Object())%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%22ok%22%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20http%3A%2F%2Flocalhost%3A8888%2Fadmin%2F%0A%0A!%5B658a1a005aadad11a588236d0d975f11.png%5D(en-resource%3A%2F%2Fdatabase%2F1471%3A1)%0A%0A%0A%23%23%20%E6%94%B9%E5%90%AF%E5%8A%A8%E7%B1%BB%0A%3E%20%E5%9C%A8%E5%90%91prometheus%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%E4%B8%AD%E5%8A%A0%E5%85%A5%E5%BA%94%E7%94%A8%E5%90%8D%E7%A7%B0%E4%BF%A1%E6%81%AF%0A%60%60%60java%0A%40Bean%0AMeterRegistryCustomizer%3CMeterRegistry%3E%20config(%40Value(%22%24%7Bspring.application.name%7D%22)%20String%20applicationName)%20%7B%0A%20%20%20%20return%20(registry)%20-%3E%20registry.config().commonTags(%22fuck%22%2C%20applicationName)%3B%0A%7D%0A%60%60%60%0A%3E%20http%3A%2F%2F192.168.0.104%3A8888%2Fadmin%2Fprometheus%0A%0A!%5B9c6442e04844de6cf600875c70b83929.png%5D(en-resource%3A%2F%2Fdatabase%2F1473%3A0)%0A%0A%0A%0A%23%23%20%E5%AE%89%E8%A3%85prometheus%0A%0A%60%60%60shell%0Amkdir%20%2Fetc%2Fprometheus%0Avi%20%0A%60%60%60%0A%0A%60%60%60yml%0Aglobal%3A%0A%20%20scrape_interval%3A%20%20%20%20%2015s%20%23%20By%20default%2C%20scrape%20targets%20every%2015%20seconds.%0A%20%20evaluation_interval%3A%2015s%20%23%20Evaluate%20rules%20every%2015%20seconds.%0A%0A%20%20%23%20Attach%20these%20extra%20labels%20to%20all%20timeseries%20collected%20by%20this%20Prometheus%20instance.%0A%20%20external_labels%3A%0A%20%20%20%20monitor%3A%20'codelab-monitor'%0Arule_files%3A%0A%20%20-%20'prometheus.rules.yml'%0A%0Ascrape_configs%3A%0A%20%20-%20job_name%3A%20'prometheus'%0A%0A%20%20%20%20%23%20Override%20the%20global%20default%20and%20scrape%20targets%20from%20this%20job%20every%205%20seconds.%0A%20%20%20%20scrape_interval%3A%205s%0A%0A%20%20%20%20static_configs%3A%0A%20%20%20%20%20%20-%20targets%3A%20%5B'localhost%3A9090'%5D%0A%0A%20%20%23%23%20%E4%BB%A5%E4%B8%8B%E5%86%85%E5%AE%B9%E4%B8%BAspringboot%E5%BA%94%E8%AF%A5%E9%85%8D%E7%BD%AE%EF%BC%8C%E6%AF%8F%E9%9A%945s%E5%90%91192.168.0.104%3A8888%E7%9A%84%2Fadmin%2Fprometheus%E7%AB%AF%E7%82%B9%E5%8F%91%E8%B5%B7%E8%AF%B7%E6%B1%82%E8%8E%B7%E5%8F%96%E6%8C%87%E6%A0%87%E6%95%B0%E6%8D%AE%E5%B9%B6%E5%AD%98%E5%82%A8%E5%9C%A8%E6%9C%AC%E5%9C%B0%0A%20%20-%20job_name%3A%20'springboot-prometheus'%0A%20%20%20%20%23%20Override%20the%20global%20default%20and%20scrape%20targets%20from%20this%20job%20every%205%20seconds.%0A%20%20%20%20scrape_interval%3A%205s%0A%20%20%20%20metrics_path%3A%20'%2Fadmin%2Fprometheus'%0A%20%20%20%20static_configs%3A%0A%20%20%20%20%20%20-%20targets%3A%20%5B'192.168.0.104%3A8888'%5D%0A%20%20%20%20%20%20%20%20labels%3A%0A%20%20%20%20%20%20%20%20%20%20group%3A%20'production'%0A%60%60%60%0A%0A%0A%60%60%60shell%0Adocker%20run%20-d%20--name%3Dprometheus%20-p%209090%3A9090%20-v%20%2Fetc%2Fprometheus%2Fprometheus.yml%3A%2Fetc%2Fprometheus%2Fprometheus.yml%20prom%2Fprometheus%0A%60%60%60%0A%3E%20http%3A%2F%2Fmaster%3A9090%0A%0A!%5B8d08b13672cce767c586b7945801170c.png%5D(en-resource%3A%2F%2Fdatabase%2F1475%3A0)%0A!%5B4de0089a1bc25a1ec6b878a736679a29.png%5D(en-resource%3A%2F%2Fdatabase%2F1477%3A0)%0A!%5B7010e4e6a9b9b1a7e3a4575be9692da7.png%5D(en-resource%3A%2F%2Fdatabase%2F1479%3A0)%0A%0A%23%23%20%E5%AE%89%E8%A3%85grafana%0A%0A%60%60%60shell%0Adocker%20run%20-d%20--name%3Dgrafana%20-p%203000%3A3000%20grafana%2Fgrafana%0A%60%60%60%0A%0A%3E%20http%3A%2F%2Fmaster%3A3000%2F%0A%0A%E9%85%8D%E7%BD%AE%E6%95%B0%E6%8D%AE%E6%BA%90%0A!%5B910350ac97bb6693f87ff892ee44673f.png%5D(en-resource%3A%2F%2Fdatabase%2F1481%3A0)%0A!%5Bce9c25b8cb0acd0762b210904ab1c123.png%5D(en-resource%3A%2F%2Fdatabase%2F1483%3A0)%0A%0A%3E%20%E9%85%8D%E7%BD%AEprometheus%E8%AE%BF%E9%97%AE%E5%9C%B0%E5%9D%80%0A%3E%20http%3A%2F%2F192.168.139.127%3A9090%0A%0A!%5B8aa1f9c996a04580129c8c4040f3d409.png%5D(en-resource%3A%2F%2Fdatabase%2F1485%3A0)%0A%0A%0A%3E%20%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF%0A%0A!%5B54772d49b31828574167be9333e96009.png%5D(en-resource%3A%2F%2Fdatabase%2F1487%3A0)%0A%0A%3E%20%E8%BE%93%E5%85%A5%604701%60%EF%BC%8C%20%E5%B9%B6%E9%80%89%E6%8B%A9%E5%88%9A%E6%89%8D%E9%85%8D%E7%BD%AE%E7%9A%84prometheus%E6%95%B0%E6%8D%AE%E6%BA%90%E5%90%8E%E7%82%B9%E5%87%BB%20%60%E5%AF%BC%E5%85%A5%60%0A%0A!%5B8d9a6a14a2f35117f6bdc5d96dfc6390.png%5D(en-resource%3A%2F%2Fdatabase%2F1489%3A0)%0A%0A!%5B15fdfb2bf2cd0808d641434734d6347e.png%5D(en-resource%3A%2F%2Fdatabase%2F1491%3A0)%0A

license

创建时间:2020/9/22 9:00
更新时间:2022/11/5 12:26
作者:Chris
来源:https://www.bilibili.com/video/BV17g4y1v72V/?spm_id_from=333.337.search-card.all.click&vd_source=d5219f7796f600867d78e4b27b0f6350

1. Axure 9 license
Axure 9.0.0.3701,3704,3706,3707,3712,3714,3716版本使用
License:Freecrackdownload.com
Key:5vYpJgQZ431X/G5kp6jpOO8Vi3TySCBnAslTcNcKkszfPH7jaM4eKM8CrALBcEC1
2. VMware-workstation-full-16 license
ZF3R0-FHED2-M80TY-8QYGC-NPKYF
YF390-0HF8P-M81RQ-2DXQE-M2UT6
ZF71R-DMX85-08DQY-8YMNC-PPHV8
%5Btoc%5D%0A%23%23%23%23%23%201.%20Axure%209%20license%0A%60%60%60%0AAxure%209.0.0.3701%EF%BC%8C3704%EF%BC%8C3706%EF%BC%8C3707%EF%BC%8C3712%EF%BC%8C3714%EF%BC%8C3716%E7%89%88%E6%9C%AC%E4%BD%BF%E7%94%A8%0ALicense%EF%BC%9AFreecrackdownload.com%0AKey%EF%BC%9A5vYpJgQZ431X%2FG5kp6jpOO8Vi3TySCBnAslTcNcKkszfPH7jaM4eKM8CrALBcEC1%0A%60%60%60%0A%0A%23%23%23%23%23%202.%20VMware-workstation-full-16%20license%0A%60%60%60%0AZF3R0-FHED2-M80TY-8QYGC-NPKYF%0AYF390-0HF8P-M81RQ-2DXQE-M2UT6%0AZF71R-DMX85-08DQY-8YMNC-PPHV8%0A%60%60%60

common issues

创建时间:2020/10/29 13:50
更新时间:2022/11/5 8:11
作者:Chris
来源:https://www.jianshu.com/p/7d57ce4147d3

1. unable to get local issuer certificate

13622314539@P13622314539 MINGW64 /c/IdeaProjects
$ git clone https://github.com/ChrisLi716/javademo.git
Cloning into 'javademo'...
fatal: unable to access 'https://github.com/ChrisLi716/javademo.git/': SSL certificate problem: unable to get local issuer certificate

解决办法

在windows中打开git bash

ssh-keygen -t rsa -C "lilunlogic@163.com"
ssh-add ~/.ssh/id_rsa  ##此命令是否执行成功不影响最终操作结果

在github中打开配置

刚生成的id_rsa.pub,将里面的内容复制,进入你的github账号,在settings下,SSH and GPG keys下new SSH key,然后将id_rsa.pub里的内容复制到Key中,完成后Add SSH Key。

验证

ssh -T git@github.com 

2. SSL_ERROR_SYSCALL

OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 10054

增大缓存大小
524288000表示增至500兆,1048576000表示增至1G

git config --global http.postBuffer 524288000

利用ssh下载

git clone git://github.com/XX/XXXX.git

安全设置问题

git config http.sslVerify "false"  --在项目目录里面
git config --global http.sslVerify "false" --全局设置

3. Authentication failed

更新密码后更新代码报如下错,但又没有弹窗让重新输入用户名和密码

13622314539@OC136223145391 MINGW64 /c/chris/code/ipd-plm-subtr (feature0930_subtr_sc)
$ git pull origin
fatal: Authentication failed for 'http://alm.adc.com/hardware/IPD/_git/ipd-plm-subtr/'

解决办法

git config --system --unset credential.helper

4. 解决每次更新代码都要输入用户名密码

使用git pull或者git push每次都需要输入用户名和密码很繁琐,耽误时间,
一条命令实现保存用户名和密码不用再输入

git config --global credential.helper store

5. refusing to merge unrelated histories

17:20:29.687: [cloud2022] git -c credential.helper= -c core.quotepath=false -c log.showSignature=false merge origin/master
fatal: refusing to merge unrelated histories

解决方案:

git pull origin master:master --allow-unrelated-histories

6. Support for password authentication was removed

remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.

解决方案:

github->settings-> Developer settings->Personal access tokens

New personal access token
选择过期时间和权限
记得把你的token保存下来,因为你再次刷新网页的时候,你已经没有办法看到它了

7 GITHUB访问慢问题解决

https://tool.chinaz.com/dns?type=1&host=assets-cdn.github.com&ip=

  1. 依次搜索如下域名的IP
github.com
github.global.ssl.fastly.net
assets-cdn.github.com
  1. 修改hosts文件
140.82.113.4  	github.com
199.232.5.194 	github.global.ssl.fastly.net
185.199.108.153 assets-cdn.github.com
185.199.111.153 assets-cdn.github.com
185.199.110.153 assets-cdn.github.com
185.199.109.153 assets-cdn.github.com
  1. 更新DNS
C:\Users\elead>ipconfig/flushdns
Windows IP 配 置
已 成 功 刷 新 DNS 解 析 缓 存 。
%5Btoc%5D%0A%0A%23%23%23%23%201.%20unable%20to%20get%20local%20issuer%20certificate%0A%60%60%60%0A13622314539%40P13622314539%20MINGW64%20%2Fc%2FIdeaProjects%0A%24%20git%20clone%20https%3A%2F%2Fgithub.com%2FChrisLi716%2Fjavademo.git%0ACloning%20into%20'javademo'...%0Afatal%3A%20unable%20to%20access%20'https%3A%2F%2Fgithub.com%2FChrisLi716%2Fjavademo.git%2F'%3A%20SSL%20certificate%20problem%3A%20unable%20to%20get%20local%20issuer%20certificate%0A%60%60%60%0A%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%0A%3E%20%E5%9C%A8windows%E4%B8%AD%E6%89%93%E5%BC%80git%20bash%0A%60%60%60%0Assh-keygen%20-t%20rsa%20-C%20%22lilunlogic%40163.com%22%0Assh-add%20~%2F.ssh%2Fid_rsa%20%20%23%23%E6%AD%A4%E5%91%BD%E4%BB%A4%E6%98%AF%E5%90%A6%E6%89%A7%E8%A1%8C%E6%88%90%E5%8A%9F%E4%B8%8D%E5%BD%B1%E5%93%8D%E6%9C%80%E7%BB%88%E6%93%8D%E4%BD%9C%E7%BB%93%E6%9E%9C%0A%60%60%60%0A%E5%9C%A8github%E4%B8%AD%E6%89%93%E5%BC%80%E9%85%8D%E7%BD%AE%0A%0A%3E%20%E5%88%9A%E7%94%9F%E6%88%90%E7%9A%84id_rsa.pub%EF%BC%8C%E5%B0%86%E9%87%8C%E9%9D%A2%E7%9A%84%E5%86%85%E5%AE%B9%E5%A4%8D%E5%88%B6%EF%BC%8C%E8%BF%9B%E5%85%A5%E4%BD%A0%E7%9A%84github%E8%B4%A6%E5%8F%B7%EF%BC%8C%E5%9C%A8settings%E4%B8%8B%EF%BC%8CSSH%20and%20GPG%20keys%E4%B8%8Bnew%20SSH%20key%EF%BC%8C%E7%84%B6%E5%90%8E%E5%B0%86id_rsa.pub%E9%87%8C%E7%9A%84%E5%86%85%E5%AE%B9%E5%A4%8D%E5%88%B6%E5%88%B0Key%E4%B8%AD%EF%BC%8C%E5%AE%8C%E6%88%90%E5%90%8EAdd%20SSH%20Key%E3%80%82%0A%0A%3E%20%E9%AA%8C%E8%AF%81%0A%60%60%60%0Assh%20-T%20git%40github.com%20%0A%60%60%60%0A%0A%23%23%23%23%202.%20SSL_ERROR_SYSCALL%0A%3E%20OpenSSL%20SSL_read%3A%20SSL_ERROR_SYSCALL%2C%20errno%2010054%0A%0A%3E%20%E5%A2%9E%E5%A4%A7%E7%BC%93%E5%AD%98%E5%A4%A7%E5%B0%8F%20%20%0A%3E%20524288000%E8%A1%A8%E7%A4%BA%E5%A2%9E%E8%87%B3500%E5%85%86%EF%BC%8C1048576000%E8%A1%A8%E7%A4%BA%E5%A2%9E%E8%87%B31G%0A%0A%60%60%60%0Agit%20config%20--global%20http.postBuffer%20524288000%0A%60%60%60%0A%0A%3E%20%E5%88%A9%E7%94%A8ssh%E4%B8%8B%E8%BD%BD%0A%0A%60%60%60%0Agit%20clone%20git%3A%2F%2Fgithub.com%2FXX%2FXXXX.git%0A%60%60%60%0A%0A%3E%20%E5%AE%89%E5%85%A8%E8%AE%BE%E7%BD%AE%E9%97%AE%E9%A2%98%0A%0A%60%60%60%0Agit%20config%20http.sslVerify%20%22false%22%20%20--%E5%9C%A8%E9%A1%B9%E7%9B%AE%E7%9B%AE%E5%BD%95%E9%87%8C%E9%9D%A2%0Agit%20config%20--global%20http.sslVerify%20%22false%22%20--%E5%85%A8%E5%B1%80%E8%AE%BE%E7%BD%AE%0A%60%60%60%0A%0A%0A%23%23%23%23%203.%20Authentication%20failed%0A%3E%20%E6%9B%B4%E6%96%B0%E5%AF%86%E7%A0%81%E5%90%8E%E6%9B%B4%E6%96%B0%E4%BB%A3%E7%A0%81%E6%8A%A5%E5%A6%82%E4%B8%8B%E9%94%99%EF%BC%8C%E4%BD%86%E5%8F%88%E6%B2%A1%E6%9C%89%E5%BC%B9%E7%AA%97%E8%AE%A9%E9%87%8D%E6%96%B0%E8%BE%93%E5%85%A5%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E5%AF%86%E7%A0%81%0A%60%60%60%0A13622314539%40OC136223145391%20MINGW64%20%2Fc%2Fchris%2Fcode%2Fipd-plm-subtr%20(feature0930_subtr_sc)%0A%24%20git%20pull%20origin%0Afatal%3A%20Authentication%20failed%20for%20'http%3A%2F%2Falm.adc.com%2Fhardware%2FIPD%2F_git%2Fipd-plm-subtr%2F'%0A%60%60%60%0A%0A%3E%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%0A%60%60%60%0Agit%20config%20--system%20--unset%20credential.helper%0A%60%60%60%0A%0A%23%23%23%23%204.%20%E8%A7%A3%E5%86%B3%E6%AF%8F%E6%AC%A1%E6%9B%B4%E6%96%B0%E4%BB%A3%E7%A0%81%E9%83%BD%E8%A6%81%E8%BE%93%E5%85%A5%E7%94%A8%E6%88%B7%E5%90%8D%E5%AF%86%E7%A0%81%0A%3E%20%E4%BD%BF%E7%94%A8git%20pull%E6%88%96%E8%80%85git%20push%E6%AF%8F%E6%AC%A1%E9%83%BD%E9%9C%80%E8%A6%81%E8%BE%93%E5%85%A5%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E5%AF%86%E7%A0%81%E5%BE%88%E7%B9%81%E7%90%90%EF%BC%8C%E8%80%BD%E8%AF%AF%E6%97%B6%E9%97%B4%EF%BC%8C%0A%3E%20%E4%B8%80%E6%9D%A1%E5%91%BD%E4%BB%A4%E5%AE%9E%E7%8E%B0%E4%BF%9D%E5%AD%98%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E5%AF%86%E7%A0%81%E4%B8%8D%E7%94%A8%E5%86%8D%E8%BE%93%E5%85%A5%0A%60%60%60%0Agit%20config%20--global%20credential.helper%20store%0A%60%60%60%0A%0A%0A%23%23%23%23%205.%20refusing%20to%20merge%20unrelated%20histories%0A%0A%60%60%60%0A17%3A20%3A29.687%3A%20%5Bcloud2022%5D%20git%20-c%20credential.helper%3D%20-c%20core.quotepath%3Dfalse%20-c%20log.showSignature%3Dfalse%20merge%20origin%2Fmaster%0Afatal%3A%20refusing%20to%20merge%20unrelated%20histories%0A%60%60%60%0A%0A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%EF%BC%9A%0A%0A%60%60%60%0Agit%20pull%20origin%20master%3Amaster%20--allow-unrelated-histories%0A%60%60%60%0A%0A%0A%23%23%23%23%206.%20Support%20for%20password%20authentication%20was%20removed%0A%3E%20remote%3A%20Support%20for%20password%20authentication%20was%20removed%20on%20August%2013%2C%202021.%20Please%20use%20a%20personal%20access%20token%20instead.%0A%0A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%3A%0A%0A%60%60%60%0Agithub-%3Esettings-%3E%20Developer%20settings-%3EPersonal%20access%20tokens%0A%60%60%60%0A%0A%3E%20New%20personal%20access%20token%20%20%0A%3E%20%E9%80%89%E6%8B%A9%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%E5%92%8C%E6%9D%83%E9%99%90%20%20%0A%3E%20%E8%AE%B0%E5%BE%97%E6%8A%8A%E4%BD%A0%E7%9A%84token%E4%BF%9D%E5%AD%98%E4%B8%8B%E6%9D%A5%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%BD%A0%E5%86%8D%E6%AC%A1%E5%88%B7%E6%96%B0%E7%BD%91%E9%A1%B5%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E4%BD%A0%E5%B7%B2%E7%BB%8F%E6%B2%A1%E6%9C%89%E5%8A%9E%E6%B3%95%E7%9C%8B%E5%88%B0%E5%AE%83%E4%BA%86%0A%0A%0A%0A%23%23%23%23%207%20GITHUB%E8%AE%BF%E9%97%AE%E6%85%A2%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3%0Ahttps%3A%2F%2Ftool.chinaz.com%2Fdns%3Ftype%3D1%26host%3Dassets-cdn.github.com%26ip%3D%0A%0A1.%20%E4%BE%9D%E6%AC%A1%E6%90%9C%E7%B4%A2%E5%A6%82%E4%B8%8B%E5%9F%9F%E5%90%8D%E7%9A%84IP%0A%60%60%60%0Agithub.com%0Agithub.global.ssl.fastly.net%0Aassets-cdn.github.com%0A%60%60%60%0A2.%20%E4%BF%AE%E6%94%B9hosts%E6%96%87%E4%BB%B6%0A-%20C%3A%5CWindows%5CSystem32%5Cdrivers%5Cetc%0A%60%60%60%0A140.82.113.4%20%20%09github.com%0A199.232.5.194%20%09github.global.ssl.fastly.net%0A185.199.108.153%20assets-cdn.github.com%0A185.199.111.153%20assets-cdn.github.com%0A185.199.110.153%20assets-cdn.github.com%0A185.199.109.153%20assets-cdn.github.com%0A%60%60%60%0A%0A3.%20%E6%9B%B4%E6%96%B0DNS%0A%60%60%60%0AC%3A%5CUsers%5Celead%3Eipconfig%2Fflushdns%0AWindows%20IP%20%E9%85%8D%20%E7%BD%AE%0A%E5%B7%B2%20%E6%88%90%20%E5%8A%9F%20%E5%88%B7%20%E6%96%B0%20DNS%20%E8%A7%A3%20%E6%9E%90%20%E7%BC%93%20%E5%AD%98%20%E3%80%82%0A%60%60%60

包安装

创建时间:2020/10/5 14:37
更新时间:2022/10/15 11:21
作者:Chris
来源:https://jingyan.baidu.com/article/f79b7cb30d81109144023eba.html

ConvertToUTF8

  1. Ctrl+ shift + P
  2. 然后输入 Install Package,回车
  3. 输入ConvertToUTF8

SFTP/FTP

  1. Ctrl+ shift + P
  2. 然后输入 Install Package,回车
  3. 输入SFTP/FTP

背景半透明设置

Ctrl+shift+P
install package
transparency
依次输入以上命令进行安装,安装完成后可以在菜单View-Window's transparency下进行调节。

Pretty JSON

Sublime,command + shift + p
Install package,搜索 Pretty JSON

sublime菜单栏看到pretty json菜单,所以好像必须利用快捷键来使用pretty json.
Preferences > Key Bindings在右边添加pretty json的快捷键

[
    {"keys": ["ctrl+alt+j"], "command": "pretty_json"}, 
    {"keys": [ "ctrl+alt+m" ], "command": "un_pretty_json" }
]
%5Btoc%5D%0A%0A%23%23%23%23%20ConvertToUTF8%0A%3E1.%20Ctrl%2B%20shift%20%2B%20P%C2%A0%0A%3E2.%20%E7%84%B6%E5%90%8E%E8%BE%93%E5%85%A5%C2%A0Install%20Package%EF%BC%8C%E5%9B%9E%E8%BD%A6%0A%3E3.%20%E8%BE%93%E5%85%A5ConvertToUTF8%0A%0A!%5Bc5f22b20bdbe803bd2a1ed1e1eadfe18.png%5D(en-resource%3A%2F%2Fdatabase%2F709%3A1)%0A%0A%0A%23%23%23%23%20SFTP%2FFTP%0A%3E1.%20Ctrl%2B%20shift%20%2B%20P%C2%A0%0A%3E2.%20%E7%84%B6%E5%90%8E%E8%BE%93%E5%85%A5%C2%A0Install%20Package%EF%BC%8C%E5%9B%9E%E8%BD%A6%0A%3E3.%20%E8%BE%93%E5%85%A5SFTP%2FFTP%0A%0A!%5B7c8282c90dff04cde8476add20486515.png%5D(en-resource%3A%2F%2Fdatabase%2F710%3A1)%0A%0A%23%23%23%23%20%E8%83%8C%E6%99%AF%E5%8D%8A%E9%80%8F%E6%98%8E%E8%AE%BE%E7%BD%AE%0A%0A%3E%20Ctrl%2Bshift%2BP%0Ainstall%20package%0Atransparency%0A%E4%BE%9D%E6%AC%A1%E8%BE%93%E5%85%A5%E4%BB%A5%E4%B8%8A%E5%91%BD%E4%BB%A4%E8%BF%9B%E8%A1%8C%E5%AE%89%E8%A3%85%EF%BC%8C%E5%AE%89%E8%A3%85%E5%AE%8C%E6%88%90%E5%90%8E%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%8F%9C%E5%8D%95View-Window's%20transparency%E4%B8%8B%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%8A%82%E3%80%82%0A%0A%0A%23%23%23%23%20Pretty%20JSON%0A%3E%20Sublime%EF%BC%8Ccommand%20%2B%20shift%20%2B%20p%0AInstall%20package%EF%BC%8C%E6%90%9C%E7%B4%A2%20Pretty%20JSON%0A%0A%3E%20sublime%E8%8F%9C%E5%8D%95%E6%A0%8F%E7%9C%8B%E5%88%B0pretty%20json%E8%8F%9C%E5%8D%95%EF%BC%8C%E6%89%80%E4%BB%A5%E5%A5%BD%E5%83%8F%E5%BF%85%E9%A1%BB%E5%88%A9%E7%94%A8%E5%BF%AB%E6%8D%B7%E9%94%AE%E6%9D%A5%E4%BD%BF%E7%94%A8pretty%20json.%0A%3E%20Preferences%20%3E%20Key%20Bindings%E5%9C%A8%E5%8F%B3%E8%BE%B9%E6%B7%BB%E5%8A%A0pretty%20json%E7%9A%84%E5%BF%AB%E6%8D%B7%E9%94%AE%0A%0A%60%60%60json%0A%5B%0A%20%20%20%20%7B%22keys%22%3A%20%5B%22ctrl%2Balt%2Bj%22%5D%2C%20%22command%22%3A%20%22pretty_json%22%7D%2C%20%0A%20%20%20%20%7B%22keys%22%3A%20%5B%20%22ctrl%2Balt%2Bm%22%20%5D%2C%20%22command%22%3A%20%22un_pretty_json%22%20%7D%0A%5D%0A%60%60%60

EnableAutoConfiguration

创建时间:2022/6/10 17:40
更新时间:2022/10/1 14:18
作者:Chris
来源:https://blog.csdn.net/u014042066/article/details/107134281/

https://blog.csdn.net/u014042066/article/details/107134281/
https://blog.csdn.net/u014042066/article/details/107134281/

EnableAutoConfiguration

1. 在哪

org.springframework.boot.autoconfigure.EnableAutoConfiguration

2. 概述

  1. 开启Spring应该上下文的自动配置,尽可能去加载需要的配置Beans。自动配置类,一般是根据你的classpath路径来应用的。
  2. 当你使用了SpringBootApplication 注解,在context中自动加载配置就已经开启,不需要其他操作。
  3. 可以通过 exclude()传入Class类型;excludeName() 传入名称来排除其他类型的加载。自动加载的配置始终是在普通用户定义的Bean加载之后执行。
  4. 默认EnableAutoConfiguration 扫描的是当前启用注解的Class对象的目录作为root目录。所以这个目录下的所有子目录都会被扫描。
  5. 自动装载的配置类,也是常规的SpringBean(被@Configuration修饰,@Configuration 则被 @Component 修饰, 如果你写的@Configuration在启动类的包名下,开启注解扫描的情况下,也是会把@Configuration注册为Bean对象。
  6. 不在扫描包目录中也可以通过SpringFactoriesLoader的机制来定位到对应的org.springframework.boot.autoconfigure.EnableAutoConfiguration类()。
  7. 一般配合 Conditional、ConditionalOnClass、ConditionalOnMissingBean 一起使用。
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
		return EnableAutoConfiguration.class;
}

会去配置文件F:\mvn_repo\org\springframework\boot\spring-boot-autoconfigure\2.6.3\spring-boot-autoconfigure-2.6.3.jar!\META-INF\spring.factories 中读取 EnableAutoConfiguration下面的所有配置类

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
...
org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames
org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories
java.util.stream.Collectors#collectingAndThen
java.util.Map#computeIfAbsent
org.springframework.context.support.AbstractApplicationContext#refresh
%5Btoc%5D%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2Fu014042066%2Farticle%2Fdetails%2F107134281%2F%0Ahttps%3A%2F%2Fblog.csdn.net%2Fu014042066%2Farticle%2Fdetails%2F107134281%2F%0A%0A%23%23%20EnableAutoConfiguration%0A%23%23%23%23%201.%20%E5%9C%A8%E5%93%AA%0A%60%60%60java%0Aorg.springframework.boot.autoconfigure.EnableAutoConfiguration%0A%60%60%60%0A%23%23%23%23%202.%20%E6%A6%82%E8%BF%B0%0A%0A%3E%201.%20%E5%BC%80%E5%90%AFSpring%E5%BA%94%E8%AF%A5%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%B0%BD%E5%8F%AF%E8%83%BD%E5%8E%BB%E5%8A%A0%E8%BD%BD%E9%9C%80%E8%A6%81%E7%9A%84%E9%85%8D%E7%BD%AEBeans%E3%80%82%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E4%B8%80%E8%88%AC%E6%98%AF%E6%A0%B9%E6%8D%AE%E4%BD%A0%E7%9A%84classpath%E8%B7%AF%E5%BE%84%E6%9D%A5%E5%BA%94%E7%94%A8%E7%9A%84%E3%80%82%0A%3E%202.%20%E5%BD%93%E4%BD%A0%E4%BD%BF%E7%94%A8%E4%BA%86%60SpringBootApplication%60%20%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%9C%A8context%E4%B8%AD%E8%87%AA%E5%8A%A8%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE%E5%B0%B1%E5%B7%B2%E7%BB%8F%E5%BC%80%E5%90%AF%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E5%85%B6%E4%BB%96%E6%93%8D%E4%BD%9C%E3%80%82%0A%3E%203.%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%20%60exclude()%20%60%E4%BC%A0%E5%85%A5Class%E7%B1%BB%E5%9E%8B%EF%BC%9B%60excludeName()%60%20%E4%BC%A0%E5%85%A5%E5%90%8D%E7%A7%B0%E6%9D%A5%E6%8E%92%E9%99%A4%E5%85%B6%E4%BB%96%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8A%A0%E8%BD%BD%E3%80%82%60%E8%87%AA%E5%8A%A8%E5%8A%A0%E8%BD%BD%E7%9A%84%E9%85%8D%E7%BD%AE%E5%A7%8B%E7%BB%88%E6%98%AF%E5%9C%A8%E6%99%AE%E9%80%9A%E7%94%A8%E6%88%B7%E5%AE%9A%E4%B9%89%E7%9A%84Bean%E5%8A%A0%E8%BD%BD%E4%B9%8B%E5%90%8E%E6%89%A7%E8%A1%8C%E3%80%82%60%0A%3E%204.%20%E9%BB%98%E8%AE%A4EnableAutoConfiguration%20%E6%89%AB%E6%8F%8F%E7%9A%84%E6%98%AF%E5%BD%93%E5%89%8D%E5%90%AF%E7%94%A8%E6%B3%A8%E8%A7%A3%E7%9A%84Class%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%9B%AE%E5%BD%95%E4%BD%9C%E4%B8%BAroot%E7%9B%AE%E5%BD%95%E3%80%82%E6%89%80%E4%BB%A5%E8%BF%99%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%89%80%E6%9C%89%E5%AD%90%E7%9B%AE%E5%BD%95%E9%83%BD%E4%BC%9A%E8%A2%AB%E6%89%AB%E6%8F%8F%E3%80%82%0A%3E%205.%20%E8%87%AA%E5%8A%A8%E8%A3%85%E8%BD%BD%E7%9A%84%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E4%B9%9F%E6%98%AF%E5%B8%B8%E8%A7%84%E7%9A%84SpringBean(%E8%A2%AB%40Configuration%E4%BF%AE%E9%A5%B0%EF%BC%8C%60%40Configuration%60%20%E5%88%99%E8%A2%AB%20%60%40Component%60%20%E4%BF%AE%E9%A5%B0%2C%20%E5%A6%82%E6%9E%9C%E4%BD%A0%E5%86%99%E7%9A%84%40Configuration%E5%9C%A8%E5%90%AF%E5%8A%A8%E7%B1%BB%E7%9A%84%E5%8C%85%E5%90%8D%E4%B8%8B%EF%BC%8C%E5%BC%80%E5%90%AF%E6%B3%A8%E8%A7%A3%E6%89%AB%E6%8F%8F%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E4%B9%9F%E6%98%AF%E4%BC%9A%E6%8A%8A%40Configuration%E6%B3%A8%E5%86%8C%E4%B8%BABean%E5%AF%B9%E8%B1%A1%E3%80%82%0A%3E%206.%20%E4%B8%8D%E5%9C%A8%E6%89%AB%E6%8F%8F%E5%8C%85%E7%9B%AE%E5%BD%95%E4%B8%AD%E4%B9%9F%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87SpringFactoriesLoader%E7%9A%84%E6%9C%BA%E5%88%B6%E6%9D%A5%E5%AE%9A%E4%BD%8D%E5%88%B0%E5%AF%B9%E5%BA%94%E7%9A%84org.springframework.boot.autoconfigure.EnableAutoConfiguration%E7%B1%BB()%E3%80%82%0A%3E%207.%20%E4%B8%80%E8%88%AC%E9%85%8D%E5%90%88%20%60Conditional%E3%80%81ConditionalOnClass%E3%80%81ConditionalOnMissingBean%60%20%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8%E3%80%82%0A%0A%0A%60%60%60java%0A%40Import(AutoConfigurationImportSelector.class)%0Apublic%20%40interface%20EnableAutoConfiguration%0A%60%60%60%0A%0A!%5Ba7312459ae46acbd636359deb643aca6.png%5D(en-resource%3A%2F%2Fdatabase%2F1310%3A1)%0A%0A!%5B643d5a5c451c6b402db8bbeb3df279d2.png%5D(en-resource%3A%2F%2Fdatabase%2F1311%3A1)%0A%0A%0A%0A%3E%20org.springframework.boot.autoconfigure.AutoConfigurationImportSelector%23%60getCandidateConfigurations%60%0A%0A%60%60%60java%0Aprotected%20List%3CString%3E%20getCandidateConfigurations(AnnotationMetadata%20metadata%2C%20AnnotationAttributes%20attributes)%20%7B%0A%09List%3CString%3E%20configurations%20%3D%20SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass()%2C%0A%09%09%09%09getBeanClassLoader())%3B%0A%09%09Assert.notEmpty(configurations%2C%20%22No%20auto%20configuration%20classes%20found%20in%20META-INF%2Fspring.factories.%20If%20you%20%22%0A%09%09%09%09%2B%20%22are%20using%20a%20custom%20packaging%2C%20make%20sure%20that%20file%20is%20correct.%22)%3B%0A%09%09return%20configurations%3B%0A%09%7D%0A%0Aprotected%20Class%3C%3F%3E%20getSpringFactoriesLoaderFactoryClass()%20%7B%0A%09%09return%20EnableAutoConfiguration.class%3B%0A%7D%0A%60%60%60%0A%0A%20%E4%BC%9A%E5%8E%BB%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%60F%3A%5Cmvn_repo%5Corg%5Cspringframework%5Cboot%5Cspring-boot-autoconfigure%5C2.6.3%5Cspring-boot-autoconfigure-2.6.3.jar!%5CMETA-INF%5Cspring.factories%60%20%E4%B8%AD%E8%AF%BB%E5%8F%96%20%60EnableAutoConfiguration%60%E4%B8%8B%E9%9D%A2%E7%9A%84%E6%89%80%E6%9C%89%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A%60%60%60java%0A%23%20Auto%20Configure%0Aorg.springframework.boot.autoconfigure.EnableAutoConfiguration%3D%5C%0Aorg.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.aop.AopAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.batch.BatchAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.cache.CacheAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration%2C%5C%0Aorg.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration%2C%5C%0A...%0A%60%60%60%0A%0A%60%60%60java%0Aorg.springframework.core.io.support.SpringFactoriesLoader%23loadFactoryNames%0Aorg.springframework.core.io.support.SpringFactoriesLoader%23loadSpringFactories%0A%60%60%60%0A%0A%60%60%60java%0Ajava.util.stream.Collectors%23collectingAndThen%0Ajava.util.Map%23computeIfAbsent%0A%60%60%60%0A%0A%60%60%60java%0Aorg.springframework.context.support.AbstractApplicationContext%23refresh%0A%60%60%60%0A%0A

Exception

创建时间:2020/9/2 14:47
更新时间:2022/9/19 19:33
作者:Chris
来源:https://www.jianshu.com/p/fe7198e2d635

1. 两种类型

java异常可以分为两种类型:系统错误、异常

1.1 Error 系统错误

系统错误由Java虚拟机抛出,用Error类表示

例如 Java虚拟机崩溃。这种情况仅凭程序自身是无法处理的,在程序中也不会对Error异常进行捕捉和抛出。

1.2 Exception 异常

异常分为:检查异常 CheckedException和非检查异常 UncheckedException

1.2.1 CheckedException

CheckedException 来自于Exception且非运行时异常都是检查异常。
CheckedException 需要声明在方法或者构造器的抛出异常语句部分
public void methodA() throws xxx,从而在方法或构造器执行出现异常时,传播到该方法或构造器之外

编译器会强制检查并通过try-catch块来对其捕获,或者在方法头声明该异常,交给调用者处理。
例如: IOException

1.2.2 Unchecked Exception

UncheckedException 包含 RuntimeException 及其子类。
Unchecked Exception 不需要在方法或构造器上声明异常抛出的原因( public void methodA() {} ),从而在该方法或构造器执行出现异常时,传播到该方法或构造器 之外

RuntimeException 是指程序运行过程中才会被检查的异常

例如:类型错误转换,数组下标访问越界,空指针异常、找不到指定类等等

%5Btoc%5D%0A%23%23%23%23%201.%20%E4%B8%A4%E7%A7%8D%E7%B1%BB%E5%9E%8B%0A%0Ajava%E5%BC%82%E5%B8%B8%E5%8F%AF%E4%BB%A5%E5%88%86%E4%B8%BA%E4%B8%A4%E7%A7%8D%E7%B1%BB%E5%9E%8B%EF%BC%9A%E7%B3%BB%E7%BB%9F%E9%94%99%E8%AF%AF%E3%80%81%E5%BC%82%E5%B8%B8%0A%0A%23%23%23%23%23%201.1%20Error%20%20%E7%B3%BB%E7%BB%9F%E9%94%99%E8%AF%AF%0A%0A%3E%20%E7%B3%BB%E7%BB%9F%E9%94%99%E8%AF%AF%E7%94%B1Java%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%8A%9B%E5%87%BA%EF%BC%8C%E7%94%A8Error%E7%B1%BB%E8%A1%A8%E7%A4%BA%0A%3E%0A%3E%20%E4%BE%8B%E5%A6%82%20Java%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%B4%A9%E6%BA%83%E3%80%82%E8%BF%99%E7%A7%8D%E6%83%85%E5%86%B5%E4%BB%85%E5%87%AD%E7%A8%8B%E5%BA%8F%E8%87%AA%E8%BA%AB%E6%98%AF%E6%97%A0%E6%B3%95%E5%A4%84%E7%90%86%E7%9A%84%EF%BC%8C%E5%9C%A8%E7%A8%8B%E5%BA%8F%E4%B8%AD%E4%B9%9F%E4%B8%8D%E4%BC%9A%E5%AF%B9Error%E5%BC%82%E5%B8%B8%E8%BF%9B%E8%A1%8C%E6%8D%95%E6%8D%89%E5%92%8C%E6%8A%9B%E5%87%BA%E3%80%82%0A%0A%23%23%23%23%23%201.2%20Exception%20%E5%BC%82%E5%B8%B8%0A%0A%3E%20%E5%BC%82%E5%B8%B8%E5%88%86%E4%B8%BA%EF%BC%9A%E6%A3%80%E6%9F%A5%E5%BC%82%E5%B8%B8%20CheckedException%E5%92%8C%E9%9D%9E%E6%A3%80%E6%9F%A5%E5%BC%82%E5%B8%B8%20UncheckedException%0A%0A%23%23%23%23%23%23%201.2.1%20CheckedException%0A%3E%20CheckedException%20%E6%9D%A5%E8%87%AA%E4%BA%8EException%E4%B8%94%E9%9D%9E%E8%BF%90%E8%A1%8C%E6%97%B6%E5%BC%82%E5%B8%B8%E9%83%BD%E6%98%AF%E6%A3%80%E6%9F%A5%E5%BC%82%E5%B8%B8%E3%80%82%0A%3E%20CheckedException%20%E9%9C%80%E8%A6%81%E5%A3%B0%E6%98%8E%E5%9C%A8%E6%96%B9%E6%B3%95%E6%88%96%E8%80%85%E6%9E%84%E9%80%A0%E5%99%A8%E7%9A%84%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E8%AF%AD%E5%8F%A5%E9%83%A8%E5%88%86%20%0A%3E%20public%20%20void%20methodA()%20throws%20xxx%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%9C%A8%E6%96%B9%E6%B3%95%E6%88%96%E6%9E%84%E9%80%A0%E5%99%A8%E6%89%A7%E8%A1%8C%E5%87%BA%E7%8E%B0%E5%BC%82%E5%B8%B8%E6%97%B6%EF%BC%8C%E4%BC%A0%E6%92%AD%E5%88%B0%E8%AF%A5%E6%96%B9%E6%B3%95%E6%88%96%E6%9E%84%E9%80%A0%E5%99%A8%E4%B9%8B%E5%A4%96%0A%3E%20%0A%3E%0A%3E%20%E7%BC%96%E8%AF%91%E5%99%A8%E4%BC%9A%E5%BC%BA%E5%88%B6%E6%A3%80%E6%9F%A5%E5%B9%B6%E9%80%9A%E8%BF%87try-catch%E5%9D%97%E6%9D%A5%E5%AF%B9%E5%85%B6%E6%8D%95%E8%8E%B7%EF%BC%8C%E6%88%96%E8%80%85%E5%9C%A8%E6%96%B9%E6%B3%95%E5%A4%B4%E5%A3%B0%E6%98%8E%E8%AF%A5%E5%BC%82%E5%B8%B8%EF%BC%8C%E4%BA%A4%E7%BB%99%E8%B0%83%E7%94%A8%E8%80%85%E5%A4%84%E7%90%86%E3%80%82%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%9A%20IOException%0A%0A%23%23%23%23%23%23%201.2.2%20%20Unchecked%20Exception%0A%3E%20UncheckedException%20%E5%8C%85%E5%90%AB%20RuntimeException%20%E5%8F%8A%E5%85%B6%E5%AD%90%E7%B1%BB%E3%80%82%0A%3E%20Unchecked%20Exception%20%E4%B8%8D%E9%9C%80%E8%A6%81%E5%9C%A8%E6%96%B9%E6%B3%95%E6%88%96%E6%9E%84%E9%80%A0%E5%99%A8%E4%B8%8A%E5%A3%B0%E6%98%8E%E5%BC%82%E5%B8%B8%E6%8A%9B%E5%87%BA%E7%9A%84%E5%8E%9F%E5%9B%A0(%20public%20void%20methodA()%20%7B%7D%20)%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%9C%A8%E8%AF%A5%E6%96%B9%E6%B3%95%E6%88%96%E6%9E%84%E9%80%A0%E5%99%A8%E6%89%A7%E8%A1%8C%E5%87%BA%E7%8E%B0%E5%BC%82%E5%B8%B8%E6%97%B6%EF%BC%8C%E4%BC%A0%E6%92%AD%E5%88%B0%E8%AF%A5%E6%96%B9%E6%B3%95%E6%88%96%E6%9E%84%E9%80%A0%E5%99%A8%20%E4%B9%8B%E5%A4%96%0A%0A%3E%20RuntimeException%20%E6%98%AF%E6%8C%87%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E8%BF%87%E7%A8%8B%E4%B8%AD%E6%89%8D%E4%BC%9A%E8%A2%AB%E6%A3%80%E6%9F%A5%E7%9A%84%E5%BC%82%E5%B8%B8%0A%3E%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%9A%E7%B1%BB%E5%9E%8B%E9%94%99%E8%AF%AF%E8%BD%AC%E6%8D%A2%EF%BC%8C%E6%95%B0%E7%BB%84%E4%B8%8B%E6%A0%87%E8%AE%BF%E9%97%AE%E8%B6%8A%E7%95%8C%EF%BC%8C%E7%A9%BA%E6%8C%87%E9%92%88%E5%BC%82%E5%B8%B8%E3%80%81%E6%89%BE%E4%B8%8D%E5%88%B0%E6%8C%87%E5%AE%9A%E7%B1%BB%E7%AD%89%E7%AD%89

类加载

创建时间:2022/9/12 16:06
更新时间:2022/9/12 16:06
作者:Chris

类的初始化 
(1)类什么时候才被初始化 
  1)创建类的实例,也就是new一个对象 
  2)访问某个类或接口的静态变量,或者对该静态变量赋值 
  3)调用类的静态方法 
  4)反射(Class.forName(“com.lyj.load”)) 
  5)初始化一个类的子类(会首先初始化子类的父类) 
  6)JVM启动时标明的启动类,即文件名和类名相同的那个类 
(2)类的初始化顺序 
  1)如果这个类还没有被加载和链接,那先进行加载和链接 
  2)假如这个类存在直接父类,并且这个类还没有被初始化(注意:在一个类加载器中,类只能初始化一次),那就初始化直接的父类(不适用于接口) 
  3)加入类中存在初始化语句(如static变量和static块),那就依次执行这些初始化语句。 
  4)总的来说,初始化顺序依次是:(静态变量、静态初始化块)–>(变量、初始化块)–> 构造器;如果有父类,则顺序是:父类static方法 –> 子类static方法 –> 父类构造方法- -> 子类构造方法

基于JDK1.8测试可得

有在代码中被调用的Constructor才会被初始化,没有被调用的Constructor不会被初始化
代码中的静态方法如果没有被调用是不会被初始化

%0A%0A%E7%B1%BB%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%C2%A0%0A%EF%BC%881%EF%BC%89%E7%B1%BB%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E6%89%8D%E8%A2%AB%E5%88%9D%E5%A7%8B%E5%8C%96%C2%A0%0A%E3%80%80%E3%80%801%EF%BC%89%E5%88%9B%E5%BB%BA%E7%B1%BB%E7%9A%84%E5%AE%9E%E4%BE%8B%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AFnew%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%C2%A0%0A%E3%80%80%E3%80%802%EF%BC%89%E8%AE%BF%E9%97%AE%E6%9F%90%E4%B8%AA%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3%E7%9A%84%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%EF%BC%8C%E6%88%96%E8%80%85%E5%AF%B9%E8%AF%A5%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC%C2%A0%0A%E3%80%80%E3%80%803%EF%BC%89%E8%B0%83%E7%94%A8%E7%B1%BB%E7%9A%84%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%C2%A0%0A%E3%80%80%E3%80%804%EF%BC%89%E5%8F%8D%E5%B0%84%EF%BC%88Class.forName(%E2%80%9Ccom.lyj.load%E2%80%9D)%EF%BC%89%C2%A0%0A%E3%80%80%E3%80%805%EF%BC%89%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%80%E4%B8%AA%E7%B1%BB%E7%9A%84%E5%AD%90%E7%B1%BB%EF%BC%88%E4%BC%9A%E9%A6%96%E5%85%88%E5%88%9D%E5%A7%8B%E5%8C%96%E5%AD%90%E7%B1%BB%E7%9A%84%E7%88%B6%E7%B1%BB%EF%BC%89%C2%A0%0A%E3%80%80%E3%80%806%EF%BC%89JVM%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A0%87%E6%98%8E%E7%9A%84%E5%90%AF%E5%8A%A8%E7%B1%BB%EF%BC%8C%E5%8D%B3%E6%96%87%E4%BB%B6%E5%90%8D%E5%92%8C%E7%B1%BB%E5%90%8D%E7%9B%B8%E5%90%8C%E7%9A%84%E9%82%A3%E4%B8%AA%E7%B1%BB%C2%A0%0A%EF%BC%882%EF%BC%89%E7%B1%BB%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E9%A1%BA%E5%BA%8F%C2%A0%0A%E3%80%80%E3%80%801%EF%BC%89%E5%A6%82%E6%9E%9C%E8%BF%99%E4%B8%AA%E7%B1%BB%E8%BF%98%E6%B2%A1%E6%9C%89%E8%A2%AB%E5%8A%A0%E8%BD%BD%E5%92%8C%E9%93%BE%E6%8E%A5%EF%BC%8C%E9%82%A3%E5%85%88%E8%BF%9B%E8%A1%8C%E5%8A%A0%E8%BD%BD%E5%92%8C%E9%93%BE%E6%8E%A5%C2%A0%0A%E3%80%80%E3%80%802%EF%BC%89%E5%81%87%E5%A6%82%E8%BF%99%E4%B8%AA%E7%B1%BB%E5%AD%98%E5%9C%A8%E7%9B%B4%E6%8E%A5%E7%88%B6%E7%B1%BB%EF%BC%8C%E5%B9%B6%E4%B8%94%E8%BF%99%E4%B8%AA%E7%B1%BB%E8%BF%98%E6%B2%A1%E6%9C%89%E8%A2%AB%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%88%E6%B3%A8%E6%84%8F%EF%BC%9A%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E4%B8%AD%EF%BC%8C%E7%B1%BB%E5%8F%AA%E8%83%BD%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%80%E6%AC%A1%EF%BC%89%EF%BC%8C%E9%82%A3%E5%B0%B1%E5%88%9D%E5%A7%8B%E5%8C%96%E7%9B%B4%E6%8E%A5%E7%9A%84%E7%88%B6%E7%B1%BB%EF%BC%88%E4%B8%8D%E9%80%82%E7%94%A8%E4%BA%8E%E6%8E%A5%E5%8F%A3%EF%BC%89%C2%A0%0A%E3%80%80%E3%80%803%EF%BC%89%E5%8A%A0%E5%85%A5%E7%B1%BB%E4%B8%AD%E5%AD%98%E5%9C%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E8%AF%AD%E5%8F%A5%EF%BC%88%E5%A6%82static%E5%8F%98%E9%87%8F%E5%92%8Cstatic%E5%9D%97%EF%BC%89%EF%BC%8C%E9%82%A3%E5%B0%B1%E4%BE%9D%E6%AC%A1%E6%89%A7%E8%A1%8C%E8%BF%99%E4%BA%9B%E5%88%9D%E5%A7%8B%E5%8C%96%E8%AF%AD%E5%8F%A5%E3%80%82%C2%A0%0A%E3%80%80%E3%80%804%EF%BC%89%E6%80%BB%E7%9A%84%E6%9D%A5%E8%AF%B4%EF%BC%8C%E5%88%9D%E5%A7%8B%E5%8C%96%E9%A1%BA%E5%BA%8F%E4%BE%9D%E6%AC%A1%E6%98%AF%EF%BC%9A%EF%BC%88%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E3%80%81%E9%9D%99%E6%80%81%E5%88%9D%E5%A7%8B%E5%8C%96%E5%9D%97%EF%BC%89%E2%80%93%3E%EF%BC%88%E5%8F%98%E9%87%8F%E3%80%81%E5%88%9D%E5%A7%8B%E5%8C%96%E5%9D%97%EF%BC%89%E2%80%93%3E%20%E6%9E%84%E9%80%A0%E5%99%A8%EF%BC%9B%E5%A6%82%E6%9E%9C%E6%9C%89%E7%88%B6%E7%B1%BB%EF%BC%8C%E5%88%99%E9%A1%BA%E5%BA%8F%E6%98%AF%EF%BC%9A%E7%88%B6%E7%B1%BBstatic%E6%96%B9%E6%B3%95%20%E2%80%93%3E%20%E5%AD%90%E7%B1%BBstatic%E6%96%B9%E6%B3%95%20%E2%80%93%3E%20%E7%88%B6%E7%B1%BB%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95-%20-%3E%20%E5%AD%90%E7%B1%BB%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%C2%A0%0A%0A%E5%9F%BA%E4%BA%8EJDK1.8%E6%B5%8B%E8%AF%95%E5%8F%AF%E5%BE%97%0A!%5Be6ba4ee061dd00c78ce5905ca51e2be2.png%5D(en-resource%3A%2F%2Fdatabase%2F1453%3A0)%0A%0A%E6%9C%89%E5%9C%A8%E4%BB%A3%E7%A0%81%E4%B8%AD%E8%A2%AB%E8%B0%83%E7%94%A8%E7%9A%84Constructor%E6%89%8D%E4%BC%9A%E8%A2%AB%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%E6%B2%A1%E6%9C%89%E8%A2%AB%E8%B0%83%E7%94%A8%E7%9A%84Constructor%E4%B8%8D%E4%BC%9A%E8%A2%AB%E5%88%9D%E5%A7%8B%E5%8C%96%0A%E4%BB%A3%E7%A0%81%E4%B8%AD%E7%9A%84%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E8%A2%AB%E8%B0%83%E7%94%A8%E6%98%AF%E4%B8%8D%E4%BC%9A%E8%A2%AB%E5%88%9D%E5%A7%8B%E5%8C%96%0A

final

创建时间:2022/9/12 15:27
更新时间:2022/9/12 16:05
作者:Chris

Final variables:
When a variable is declared with final keyword, its value can’t be modified, essentially, a constant. This also means that you must initialize a final variable. If the final variable is a reference, this means that the variable cannot be re-bound to reference another object, but internal state of the object pointed by that reference variable can be changed i.e. you can add or remove elements from final array or final collection. It is good practice to represent final variables in all uppercase, using underscore to separate words.

Initializing a final variable :
We must initialize a final variable, otherwise compiler will throw compile-time error.A final variable can only be initialized once, either via an initializer or an assignment statement. There are three ways to initialize a final variable :

  1. You can initialize a final variable when it is declared. This approach is the most common. A final variable is called blank final variable,if it is not initialized while declaration. Below are the two ways to initialize a blank final variable.
  2. A blank final variable can be initialized inside instance-initializer block or inside constructor. If you have more than one constructor in your class then it must be initialized in all of them, otherwise compile time error will be thrown.
  3. A blank final static variable can be initialized inside static block.
!%5B9f0f8eeb1f6005dab4f6b6cdfecee3e1.png%5D(en-resource%3A%2F%2Fdatabase%2F1449%3A1)%0A%0AFinal%20variables%3A%0AWhen%20a%20variable%20is%20declared%20with%20final%20keyword%2C%20its%20value%20can%E2%80%99t%20be%20modified%2C%20essentially%2C%20a%20constant.%20This%20also%20means%20that%20you%20must%20initialize%20a%20final%20variable.%20If%20the%20final%20variable%20is%20a%20reference%2C%20this%20means%20that%20the%20variable%20cannot%20be%20re-bound%20to%20reference%20another%20object%2C%20***but%20internal%20state%20of%20the%20object%20pointed%20by%20that%20reference%20variable%20can%20be%20changed***%20i.e.%20you%20can%20add%20or%20remove%20elements%20from%20final%20array%20or%20final%20collection.%20It%20is%20good%20practice%20to%20represent%20final%20variables%20in%20all%20uppercase%2C%20using%20underscore%20to%20separate%20words.%0A%0AInitializing%20a%20final%20variable%20%3A%0AWe%20must%20initialize%20a%20final%20variable%2C%20otherwise%20compiler%20will%20throw%20compile-time%20error.A%20final%20variable%20can%20only%20be%20initialized%20once%2C%20either%20via%20an%20initializer%20or%20an%20assignment%20statement.%20There%20are%20three%20ways%20to%20initialize%20a%20final%20variable%20%3A%0A1.%20You%20can%20initialize%20a%20final%20variable%20when%20it%20is%20declared.%20This%20approach%20is%20the%20most%20common.%20A%20final%20variable%20is%20called%20%3Cu%3E%20blank%20final%20variable%3C%2Fu%3E%2Cif%20it%20is%20not%20initialized%20while%20declaration.%20Below%20are%20the%20two%20ways%20to%20initialize%20a%20blank%20final%20variable.%0A2.%20A%20blank%20final%20variable%20can%20be%20initialized%20inside%20instance-initializer%20block%20or%20inside%20constructor.%20If%20you%20have%20more%20than%20one%20constructor%20in%20your%20class%20then%20it%20must%20be%20initialized%20in%20all%20of%20them%2C%20otherwise%20compile%20time%20error%20will%20be%20thrown.%0A3.%20A%20blank%20final%20static%20variable%20can%20be%20initialized%20inside%20static%20block.

Why having fun is the secret to a healthier life

创建时间:2022/9/11 11:32
更新时间:2022/9/11 11:32
作者:Chris
来源:file:///C:/Users/Dell/Desktop/New%20Microsoft%20Word%20Document.docx

You know what's a lot harder than it seems like it should be? Actually feeling alive. And what I mean by that is that we are all constantly doing, or, at least, we're constantly scrolling. But we're not necessarily living.
00:16
You know, we keep ourselves busy to the point of exhaustion, but we're also languishing. We feel a little bid dead inside. And I think we know that, on some level. I think that's part of the reason we keep ourselves so busy and distracted to begin with. But we don't know what to do about it.
00:32
So I'm here to tell you I figured out what to do about it. We need to have more fun.
00:41
(Laughter)
00:42
(Cheers and applause)
00:46
So you might think that you're already having plenty of fun, and that's because in our everyday speech, we often use the word "fun" to describe anything we do with our leisure time, even if it's not actually enjoyable, and, in fact, a waste of time. So for example, we scroll through social media "for fun," even though doing so often makes us feel bad about, like, kind of everything. Or we'll say, "That was so fun. We should do that again soon" --
01:14
(Laughter)
01:17
... in response to things that weren't that fun and that we don't want to do again, ever.
01:22
(Laughter)
01:25
But it's not really our fault that we're a little bit sloppy about how we use the word "fun," because even the dictionary doesn't get it quite right. It says that fun is amusement or enjoyment, or lighthearted pleasure. It's something for kids to have in play areas. It makes it sound like it's frivolous and optional.
01:44
But if you think back on your own memories that stand out to you as having truly been fun -- and I really encourage you to do this -- the memories that you would describe as -- and forgive me for scientific terminology -- "so fun" -- you're going to notice there's something much deeper going on. I've collected thousands of these stories from people all around the world, and I can tell you it's amazing, because when people recount the memories in which they had the most fun, they tell you about some of the most joyful and treasured memories of their lives.
02:17
So in reality, fun is not just lighthearted pleasure. It's not just for kids, and it is definitely not frivolous. Instead, fun is the secret to feeling alive.
02:31
So today, I want to propose to you a new, more precise definition of what fun is. I want to reveal some of the ways in which it is astonishingly good for us, and I want to give you all some suggestions for things you can do starting right now to experience its power for yourself.
02:48
So the first thing we need to start with is the fact that fun is a feeling, and it's not an activity. And that's important, because a lot of times, when I ask people what's fun, they'll respond with a list of activities that they enjoy. You know, they'll say, "Dancing is fun," or "Skiing is fun," or, I don't know, "Pickleball is fun." Everyone seems to think that pickleball is fun.
03:11
(Cheers and laughter)
03:14
And sure, pickleball can be fun, but we've all had experiences where something's off, and an activity that seems like it would be fun doesn't end up feeling fun. And then on the flip side, we've had experiences where something that doesn't seem like it'll be fun at all ends up feeling ridiculously fun. There's an element of serendipity. But when people do have fun, when they experience this feeling, it's actually very easy to recognize, because people who are having fun look like they're being illuminated from within.
03:42
So, for example, here is me and my husband having fun together. Here are some presidents having fun together.
03:49
(Laughter) Here’s Archbishop Desmond Tutu and the Dalai Lama having fun together.
03:55
(Cheers and laughter)
03:56
Actually, those two seemed like they were very often, even constantly ...
04:01
(Laughter)
04:03
... having fun together.
04:05
(Laughter)
04:08
And as you can see in these photographs, true fun produces this visceral sense of lightness and joy. It's radiant. In fact, when I asked my daughter, when she was about five years old, what color fun would be, she said "sunshine."
04:24
So what is this sunshine? You know? What is this feeling that we call "fun"? When people tell me their stories about fun, it's really interesting, because the details are all different, and often quite mundane, but the energy running through them is the same. There were three factors that are consistently present, to the point that I believe they constitute a new definition, one that is a lot more accurate than what's in the dictionary. And those three factors are playfulness, connection and flow.
04:50
So by playfulness, I do not mean you have to play games, or, God forbid, make believe. I just mean having a lighthearted attitude of doing things for the sake of doing them and not caring too much about the outcome. Letting go of perfectionism. When we have fun, our guard is down, and we're not taking ourselves too seriously.
05:10
Connection refers to the feeling of having a special, shared experience. And I do think it's possible, in some circumstances, to have fun alone, and for this feeling of connection to be with yourself or the surroundings, or the activity. But in the majority of stories that people tell me about their peak fun memories, another person is involved. And that's true even for introverts.
05:31
And then flow is the state where we are so engaged and focused on whatever we're doing that we can even lose track of time. You can think about an athlete in the middle of a game, or a musician playing a piece of music. It's when we're in the zone. It's possible to be in flow and not have fun, like if you're arguing, but you cannot have fun if you're not in flow.
05:51
So playfulness, connection and flow all feel great on their own. But when we experience all three at once, something magical happens. We have fun. And that doesn't just feel good, it is good for us. In fact, fun does so many amazingly good things for us that I personally believe that fun is not just the result of human thriving, it's a cause.
06:13
So, for example, fun is energizing. When people tell me their stories about fun, they glow. It is like a fire has been lit inside of them, and the energy and the warmth that they give off is contagious. You know, so much of life drains us, but fun fills us up. Fun also makes us present. A lot of us put a lot of work into trying to be more present -- we do yoga classes, we meditate, and that is all great, but the fact that fun is a flow state means that when we are having fun, we simply are present. There's no other way for it to happen.
06:47
Fun also unites us. We live in a really polarized world, and as we all know, there's a lot of very serious problems. But when we have fun with people, we don't see them as different political parties, or nationalities or religions. We connect with them as human beings, and it's worth noting that that is the first step in being able to work together to solve those problems.
07:09
Fun also makes us healthier. Being lonely and stressed out, as many of us have been for the past two years, causes hormonal changes in our bodies that increase our risks for disease. But when we have fun, we're relaxed and we're more socially connected, both of which have the opposite effect. So, kind of blows my mind every time I think about it this way, but having fun is a health intervention.
07:34
And then, lastly, fun is joyful. You know, we all so desperately want to be happy. We read books about happiness, we download apps about happiness, but when we are in a moment of having fun, we are happy. So it makes me think that, perhaps, the secret to long-term happiness is just to have more everyday moments of fun.
07:52
So how do we do that? How do we have more fun? Well, to start with, do not take the suggestions you'll find in magazine articles about how to have more fun. I looked at some of these myself, and I found suggestions that include -- and I'm not making these up -- "roast a turkey."
08:07
(Laughter)
08:10
"Put together an altar to loved ones who have passed."
08:13
(Laughter)
08:16
“Watch a documentary about climate change.”
08:19
(Laughter)
08:23
And my personal favorite, "Adorn your table with gourds."
08:26
(Laughter)
08:27
Those are not good suggestions. Instead, the most effective thing you can do to have more fun is to focus on its ingredients, by which I mean, do everything you can to fill your life with more moments of playfulness, connection and flow. So here are some ideas for how to do so. To start with, reduce distractions in order to increase flow. Anything that distracts you is going to kick you out of flow and prevent you from having fun. And what's the number one source of distraction for most of us, these days? Oh, thank you.
08:58
(Laughs)
08:59
It was rhetorical, but yes, your phones.
09:01
(Laughs)
09:02
I wrote a book called "How to Break Up With Your Phone," so I have strong feelings about this, but I can guarantee you that you are not going to have fun if you're constantly on your phone. So today, I want to challenge you to keep your phone out of your hand as much as possible, so you can take me up on my second suggestion, which is to increase connection by interacting more with other human beings in real life. Now, I know that one of the main reasons we're constantly on our phones is specifically to avoid having to spend time and interact with other human beings in real life.
09:33
(Laughter)
09:34
So I want to assure you that it is worth it, and it is not as hard as it might seem. So here's how you do it. You start by making eye contact with someone. Like, look them in the eye, don't look in the middle of their forehead, where the camera would be on a Zoom call.
09:48
(Laughter)
09:49
And you say “Hello.” And if that goes well, you can introduce yourself. And if that goes well, maybe you can ask them a question, something that's thought-provoking, but not overly personal or threatening, like "What's something that fascinates you?" Or "What's one thing that delighted you today?" And you might be amazed by how good just one little moment of connection can make you feel.
10:12
And if you do find someone to connect with, maybe ask them to join you in trying my third suggestion, which is to increase playfulness by finding opportunities to rebel. Now I am not talking about James Dean-level of rebellion. I'm talking about playful deviance. I'm talking about finding ways to break the rules of responsible adulthood, and giving yourself permission to get a kick out of your own life. One person told me that some of the most fun she'd had in recent memory, happened on a Friday morning, when she and some of her friends ditched their work and their childcare responsibilities, tucked flasks into their purses and snuck out to a 10:30am showing of the movie "Bad Moms."
10:52
(Laughter)
10:56
So lastly, here's one more thing that you can do today to start having more fun.
11:02
[Roast a Turkey] I am just kidding.
11:04
(Laughter)
11:05
Prioritize it. That might sound totally obvious, but one of the main reasons we're not having enough fun is that we're not making it a priority. Our fun is always at the bottom of the list, and it can't speak up for itself. So I'm not suggesting that you take out your calendar and make an entry that says: “From 4 to 6pm on Saturday, I shall have fun.” That is a guaranteed way to not have fun. But if you know you consistently have fun when you spend time with a particular person, make a point to spend time with that person. If you know there's an activity that really does often generate playful connected flow for you, carve out time for it in your schedule. Treat fun as if it is important. Because it is. I've been doing this myself for a couple of years now, and it's amazing to see how many areas of my life fun has touched. I'm more creative and more productive, I'm more resilient. I laugh more. Making sure that I'm having enough fun has made me a better partner, a better parent and a better friend. And it has convinced me of something that I very much hope I can convince you of as well, which is that my daughter was right. Fun is sunshine. It's a distillation of life's energy. And the more often we experience it, the more we will feel like we're actually alive.
12:24
Thank you.
12:25
(Cheers and applause)

工具网站

创建时间:2020/9/22 8:57
更新时间:2022/8/28 17:36
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU3NTgyODQ1Nw==&mid=2247522309&idx=1&sn=0d9902bc978175db1a64bed97ace5542&chksm=fd1fe083ca6869953f68dcfb0c82b126de9888e7d36ad1cb69f6e60783eabe09d0945dff6a1c&scene=126&sessionid=1648355412&key=af4c587e24c5aac76dedd64f3c6f625987ade07b04d1fad71de4d4376aa37ce1d808524d5dd9b82b46b4449a73cde6d74bca1d82fb607021687dcc0333f7392c22d6cb536d25a162f30f02dea7afc8e226694f8c7431a1c20732078766b1522f9f3eeb48e45e428a0721fdb9b7bf92b81d87eb824cb3d1f5c625aa574060ed95&ascene=15&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=63060012&lang=en&exportkey=AdVNDZH0OJmXZP5ylKEwmpE%3D&acctmode=0&pass_ticket=PrOVje0uB86IPlXy5NWDBqKMS8BJZqe0Ih3XAW3V%2F9VzM%2BWceSQk%2F94TChhNrsjH&wx_header=0&fontgear=2

1. 国家代码

https://countrycode.org/

2. 在线格式化工具

https://tool.lu/

3. 在线Json工具

https://jsongrid.com/

4. 正则表达式

http://tool.rbtree.cn/regtool/
https://ihateregex.io/

5. Json Path验证

http://jsonpath.com/

6. tabby

https://github.com/Eugeny/tabby/releases/tag/v1.0.183
https://www.zhihu.com/question/64593084

%5Btoc%5D%0A%0A%23%23%23%23%23%201.%20%E5%9B%BD%E5%AE%B6%E4%BB%A3%E7%A0%81%0A%60https%3A%2F%2Fcountrycode.org%2F%60%0A%0A%23%23%23%23%23%202.%20%E5%9C%A8%E7%BA%BF%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%B7%A5%E5%85%B7%0A%60https%3A%2F%2Ftool.lu%2F%60%0A%0A%23%23%23%23%23%203.%20%E5%9C%A8%E7%BA%BFJson%E5%B7%A5%E5%85%B7%0A%60https%3A%2F%2Fjsongrid.com%2F%60%0A%0A%23%23%23%23%23%204.%20%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%0Ahttp%3A%2F%2Ftool.rbtree.cn%2Fregtool%2F%0Ahttps%3A%2F%2Fihateregex.io%2F%0A%0A%23%23%23%23%23%205.%20Json%20Path%E9%AA%8C%E8%AF%81%0Ahttp%3A%2F%2Fjsonpath.com%2F%0A%0A%23%23%23%23%23%206.%20tabby%0Ahttps%3A%2F%2Fgithub.com%2FEugeny%2Ftabby%2Freleases%2Ftag%2Fv1.0.183%0Ahttps%3A%2F%2Fwww.zhihu.com%2Fquestion%2F64593084

MyBatis配置加密、解密

创建时间:2022/8/28 16:38
更新时间:2022/8/28 17:30
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU5NTgzMDYyMA==&mid=2247501591&idx=1&sn=a980d57c5e1e48af391957dfddb0eb4a&chksm=fe697524c91efc3254ee3b6ad0f1b503bf5ca14c438bc3abf624d027b2b4ce988e82a0ad901c&mpshare=1&scene=24&srcid=0807iKmrRoFniiUkxrIpbxRS&sharer_sharetime=1659855343053&sharer_shareid=8f247ffae0fc886917cba955f4d8c07b&key=4287f422ed6aae0cb5bff2bcf733bb534b111b164906209e6312eb11b5f8c8884f9ff12a2a7815947c12fd9337d9ebdda8d73931f50500ac670b7f9e5f4e67005906b745e2aee1061a4fa74aa7d873f23b36970433023325cfcd8678e5cb95906cb9dd9d53de7d75d4bd472903e2ce817a55a0a6488b95c5d0b4d2f0d1eec25d&ascene=14&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=63070517&lang=en&exportkey=ATmDOYwfjOw3a3%2BacaU8Fjs%3D&acctmode=0&pass_ticket=QgVC1BtzsVxVptJEGpukl7%2F9dPzK5E6beXkxqNN9ADp7t3Ii3F7vaMYuQHIBZ8%2By&wx_header=0&fontgear=3

方法1

1. 编写一个实体类,凡是此实体类的数据都表示需要加解密的

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Encrypt {
    private String value;
}

2. 编写一个加解密的TypeHandler

package com.chris.mybatisplus.handler;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.chris.mybatisplus.dto.Encrypt;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * 加解密TypeHandler
 */
@MappedJdbcTypes(JdbcType.VARCHAR) //表示处理器处理的Jdbc类型
@MappedTypes(Encrypt.class) //表示该处理器处理的java类型是什么
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {

    private static final byte[] KEYS = "12345678abcdefgh".getBytes(StandardCharsets.UTF_8);

    /**
     * 设置参数
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Encrypt parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null || parameter.getValue() == null) {
            ps.setString(i, null);
            return;
        }
        AES aes = SecureUtil.aes(KEYS);
        String encrypt = aes.encryptHex(parameter.getValue());
        ps.setString(i, encrypt);
    }

    /**
     * 获取值
     */
    @Override
    public Encrypt getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return decrypt(rs.getString(columnName));
    }

    /**
     * 获取值
     */
    @Override
    public Encrypt getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return decrypt(rs.getString(columnIndex));
    }

    /**
     * 获取值
     */
    @Override
    public Encrypt getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return decrypt(cs.getString(columnIndex));
    }

    public Encrypt decrypt(String value) {
        if (null == value) {
            return null;
        }
        return new Encrypt(SecureUtil.aes(KEYS).decryptStr(value));
    }
}

3. 使用mybatis-plus增强接口

public interface UserMapper extends BaseMapper<User> {

    int addUser(@Param("name") String name, @Param("age") Integer age, @Param("bir") Date bir,
                @Param("phone") Encrypt phone, @Param("address") String address);

    List<User> findUsersByPhone(@Param("phone") Encrypt phone);
}

4. sql语句中写法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chris.mybatisplus.dao.mapper.UserMapper">

    <resultMap id="BaseResultMapper" type="com.chris.mybatisplus.entities.User">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <result column="bir" property="bir"/>
        <result column="phone" property="phone"/>
    </resultMap>

    <insert id="addUser">
        insert into t_user(name, age, bir, phone, address)
        values (#{name}, #{age}, #{bir}, #{phone}, #{address})
    </insert>

    <select id="findUsersByPhone" resultMap="BaseResultMapper">
        select *
        from t_user
        where phone = #{phone}
    </select>

</mapper>

5. application.yml中配置mybais-plus

mybatis-plus:
  mapper-locations: classpath:mappers/*.xml
  global-config:
    db-config:
      #驼峰下划线转换
      #column-underline: true
      #逻辑删除配置
      logic-delete-value: I
      logic-not-delete-value: A
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  #为所有Entity类所在包起默认别名
  type-aliases-package: com.chris.mybatisplus.entities
  #配置文件中指定Typehandler的包路径
  type-handlers-package: com.chris.mybatisplus.handler

测试类

package com.chris.mybatisplus;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.chris.mybatisplus.dao.mapper.UserMapper;
import com.chris.mybatisplus.dto.Encrypt;
import com.chris.mybatisplus.entities.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.security.SecureRandom;
import java.util.*;

@SpringBootTest(classes = MybatisPlusMain.class)
public class TestMybaisPlus {

    @Autowired
    public UserMapper userMapper;


    //写入一条记录,并对phone字段加密
    @Test
    public void testInsertEncrypt() {
        int encrypt = userMapper.addUser("cl", 23, new Date(), new Encrypt("1234454556"), "US");
        System.out.println("insert user account:" + encrypt);
    }

    //查询phone对应的用户信息
    @Test
    public void findUserByPhone() {
        List<User> usersByPhone = userMapper.findUsersByPhone(new Encrypt("1234454556"));
        System.out.println("usersByPhone:" + JSONUtil.toJsonStr(usersByPhone));
    }

}

方法2

对方法1中的entity进行改造

public interface UserCryptoMapper extends BaseMapper<UserCrypto> {

    int addUser(@Param("name") String name, @Param("age") Integer age, @Param("bir") Date bir,
                @Param("phone") Encrypt phone, @Param("address") String address);

    List<User> findUsersByPhone(@Param("phone") Encrypt phone);
}

phone字段类型改为Encrypt并加上 typeHandler="com.chris.mybatisplus.handler.EncryptTypeHandler

@Data
@AllArgsConstructor
@Accessors(chain = true)
@NoArgsConstructor
@TableName("t_user") //在不配置的情况下默认表名与类名一致
public class UserCrypto {

    public UserCrypto(String name, int age, Date bir) {
        this.name = name;
        this.age = age;
        this.bir = bir;
    }


    /**
     * AUTO:数据库自增
     * INPUT:inset前自行设置主键值
     * ASSIGN_ID:分配ID,主键类型为Number(Integer和Long)使用接口IdentifierGenerator的nextId方法(默认实现类为DefaultIdentifierGenerator雪花算法)
     * ASSIGN_UUID:分配UUID,主键类型为String,使用接口IdentifierGenerator的nextId方法(默认default方法)
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /**
     * 表中列名与Java类中属性的映射
     * 如果列名和属性名一致可以不用配置此注解
     */

    @TableField("name")
    private String name;

    private Integer age;
    private Date bir;
    private String address;

    @TableField(jdbcType = JdbcType.VARCHAR, typeHandler = com.chris.mybatisplus.handler.EncryptTypeHandler.class)
    private Encrypt phone;

    // 不映射数据表中的任何字段
    @TableField(exist = false)
    private String notColumn;
}

phone字段加上 typeHandler="com.chris.mybatisplus.handler.EncryptTypeHandler

<mapper namespace="com.chris.mybatisplus.dao.mapper.UserCryptoMapper">

    <resultMap type="com.chris.mybatisplus.entities.UserCrypto">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <result column="bir" property="bir"/>
        <result column="phone" property="phone" typeHandler="com.chris.mybatisplus.handler.EncryptTypeHandler"/>
    </resultMap>

    <insert >
        insert into t_user(name, age, bir, phone, address)
        values (#{name}, #{age}, #{bir}, #{phone}, #{address})
    </insert>

    <select resultMap="BaseResultMapper">
        select *
        from t_user
        where phone = #{phone}
    </select>

</mapper>
@SpringBootTest(classes = MybatisPlusMain.class)
public class EncryptTest {

    @Resource
    private UserCryptoMapper cryptoMapper;

    //写入一条记录,并对phone字段加密
    @Test
    public void testInsertEncrypt() {
        int encrypt = cryptoMapper.addUser("cl", 23, new Date(), new Encrypt("1234454556"), "US");
        System.out.println("insert user account:" + encrypt);
    }

    //查询phone对应的用户信息
    @Test
    public void findUserByPhone() {
        List<User> usersByPhone = cryptoMapper.findUsersByPhone(new Encrypt("1234454556"));
        System.out.println("usersByPhone:" + JSONUtil.toJsonStr(usersByPhone));
    }


    @Test
    public void testEncrypt() {
        UserCrypto user = new UserCrypto();
        user.setAge(21);
        user.setBir(new Date());
        user.setName("Hency");
        user.setPhone(new Encrypt("1263324456677"));
        int i = cryptoMapper.insert(user);
        System.out.println("insert user account:" + i);
    }

}
%5Btoc%5D%0A%0A%23%23%20%E6%96%B9%E6%B3%951%0A%0A%23%23%23%23%201.%20%E7%BC%96%E5%86%99%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BD%93%E7%B1%BB%EF%BC%8C%E5%87%A1%E6%98%AF%E6%AD%A4%E5%AE%9E%E4%BD%93%E7%B1%BB%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E8%A1%A8%E7%A4%BA%E9%9C%80%E8%A6%81%E5%8A%A0%E8%A7%A3%E5%AF%86%E7%9A%84%0A%60%60%60java%0A%40Data%0A%40NoArgsConstructor%0A%40AllArgsConstructor%0Apublic%20class%20Encrypt%20%7B%0A%20%20%20%20private%20String%20value%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202.%20%E7%BC%96%E5%86%99%E4%B8%80%E4%B8%AA%E5%8A%A0%E8%A7%A3%E5%AF%86%E7%9A%84TypeHandler%0A%60%60%60java%0Apackage%20com.chris.mybatisplus.handler%3B%0A%0Aimport%20cn.hutool.crypto.SecureUtil%3B%0Aimport%20cn.hutool.crypto.symmetric.AES%3B%0Aimport%20com.chris.mybatisplus.dto.Encrypt%3B%0Aimport%20org.apache.ibatis.type.BaseTypeHandler%3B%0Aimport%20org.apache.ibatis.type.JdbcType%3B%0Aimport%20org.apache.ibatis.type.MappedJdbcTypes%3B%0Aimport%20org.apache.ibatis.type.MappedTypes%3B%0A%0Aimport%20java.nio.charset.StandardCharsets%3B%0Aimport%20java.sql.CallableStatement%3B%0Aimport%20java.sql.PreparedStatement%3B%0Aimport%20java.sql.ResultSet%3B%0Aimport%20java.sql.SQLException%3B%0A%2F**%0A%20*%20%E5%8A%A0%E8%A7%A3%E5%AF%86TypeHandler%0A%20*%2F%0A%40MappedJdbcTypes(JdbcType.VARCHAR)%20%2F%2F%E8%A1%A8%E7%A4%BA%E5%A4%84%E7%90%86%E5%99%A8%E5%A4%84%E7%90%86%E7%9A%84Jdbc%E7%B1%BB%E5%9E%8B%0A%40MappedTypes(Encrypt.class)%20%2F%2F%E8%A1%A8%E7%A4%BA%E8%AF%A5%E5%A4%84%E7%90%86%E5%99%A8%E5%A4%84%E7%90%86%E7%9A%84java%E7%B1%BB%E5%9E%8B%E6%98%AF%E4%BB%80%E4%B9%88%0Apublic%20class%20EncryptTypeHandler%20extends%20BaseTypeHandler%3CEncrypt%3E%20%7B%0A%0A%20%20%20%20private%20static%20final%20byte%5B%5D%20KEYS%20%3D%20%2212345678abcdefgh%22.getBytes(StandardCharsets.UTF_8)%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%AE%BE%E7%BD%AE%E5%8F%82%E6%95%B0%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20setNonNullParameter(PreparedStatement%20ps%2C%20int%20i%2C%20Encrypt%20parameter%2C%20JdbcType%20jdbcType)%20throws%20SQLException%20%7B%0A%20%20%20%20%20%20%20%20if%20(parameter%20%3D%3D%20null%20%7C%7C%20parameter.getValue()%20%3D%3D%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20ps.setString(i%2C%20null)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20AES%20aes%20%3D%20SecureUtil.aes(KEYS)%3B%0A%20%20%20%20%20%20%20%20String%20encrypt%20%3D%20aes.encryptHex(parameter.getValue())%3B%0A%20%20%20%20%20%20%20%20ps.setString(i%2C%20encrypt)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%8E%B7%E5%8F%96%E5%80%BC%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20Encrypt%20getNullableResult(ResultSet%20rs%2C%20String%20columnName)%20throws%20SQLException%20%7B%0A%20%20%20%20%20%20%20%20return%20decrypt(rs.getString(columnName))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%8E%B7%E5%8F%96%E5%80%BC%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20Encrypt%20getNullableResult(ResultSet%20rs%2C%20int%20columnIndex)%20throws%20SQLException%20%7B%0A%20%20%20%20%20%20%20%20return%20decrypt(rs.getString(columnIndex))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%8E%B7%E5%8F%96%E5%80%BC%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20Encrypt%20getNullableResult(CallableStatement%20cs%2C%20int%20columnIndex)%20throws%20SQLException%20%7B%0A%20%20%20%20%20%20%20%20return%20decrypt(cs.getString(columnIndex))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20Encrypt%20decrypt(String%20value)%20%7B%0A%20%20%20%20%20%20%20%20if%20(null%20%3D%3D%20value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20new%20Encrypt(SecureUtil.aes(KEYS).decryptStr(value))%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%23%23%23%23%203.%20%E4%BD%BF%E7%94%A8mybatis-plus%E5%A2%9E%E5%BC%BA%E6%8E%A5%E5%8F%A3%0A%60%60%60java%0Apublic%20interface%20UserMapper%20extends%20BaseMapper%3CUser%3E%20%7B%0A%0A%20%20%20%20int%20addUser(%40Param(%22name%22)%20String%20name%2C%20%40Param(%22age%22)%20Integer%20age%2C%20%40Param(%22bir%22)%20Date%20bir%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40Param(%22phone%22)%20Encrypt%20phone%2C%20%40Param(%22address%22)%20String%20address)%3B%0A%0A%20%20%20%20List%3CUser%3E%20findUsersByPhone(%40Param(%22phone%22)%20Encrypt%20phone)%3B%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%204.%20sql%E8%AF%AD%E5%8F%A5%E4%B8%AD%E5%86%99%E6%B3%95%0A%60%60%60xml%0A%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3C!DOCTYPE%20mapper%20PUBLIC%20%22-%2F%2Fmybatis.org%2F%2FDTD%20Mapper%203.0%2F%2FEN%22%20%22http%3A%2F%2Fmybatis.org%2Fdtd%2Fmybatis-3-mapper.dtd%22%3E%0A%3Cmapper%20namespace%3D%22com.chris.mybatisplus.dao.mapper.UserMapper%22%3E%0A%0A%20%20%20%20%3CresultMap%20id%3D%22BaseResultMapper%22%20type%3D%22com.chris.mybatisplus.entities.User%22%3E%0A%20%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22name%22%20property%3D%22name%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22age%22%20property%3D%22age%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22bir%22%20property%3D%22bir%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22phone%22%20property%3D%22phone%22%2F%3E%0A%20%20%20%20%3C%2FresultMap%3E%0A%0A%20%20%20%20%3Cinsert%20id%3D%22addUser%22%3E%0A%20%20%20%20%20%20%20%20insert%20into%20t_user(name%2C%20age%2C%20bir%2C%20phone%2C%20address)%0A%20%20%20%20%20%20%20%20values%20(%23%7Bname%7D%2C%20%23%7Bage%7D%2C%20%23%7Bbir%7D%2C%20%23%7Bphone%7D%2C%20%23%7Baddress%7D)%0A%20%20%20%20%3C%2Finsert%3E%0A%0A%20%20%20%20%3Cselect%20id%3D%22findUsersByPhone%22%20resultMap%3D%22BaseResultMapper%22%3E%0A%20%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20%20from%20t_user%0A%20%20%20%20%20%20%20%20where%20phone%20%3D%20%23%7Bphone%7D%0A%20%20%20%20%3C%2Fselect%3E%0A%0A%3C%2Fmapper%3E%0A%60%60%60%0A%0A%23%23%23%23%205.%20application.yml%E4%B8%AD%E9%85%8D%E7%BD%AEmybais-plus%0A%60%60%60yml%0Amybatis-plus%3A%0A%20%20mapper-locations%3A%20classpath%3Amappers%2F*.xml%0A%20%20global-config%3A%0A%20%20%20%20db-config%3A%0A%20%20%20%20%20%20%23%E9%A9%BC%E5%B3%B0%E4%B8%8B%E5%88%92%E7%BA%BF%E8%BD%AC%E6%8D%A2%0A%20%20%20%20%20%20%23column-underline%3A%20true%0A%20%20%20%20%20%20%23%E9%80%BB%E8%BE%91%E5%88%A0%E9%99%A4%E9%85%8D%E7%BD%AE%0A%20%20%20%20%20%20logic-delete-value%3A%20I%0A%20%20%20%20%20%20logic-not-delete-value%3A%20A%0A%20%20configuration%3A%0A%20%20%20%20log-impl%3A%20org.apache.ibatis.logging.stdout.StdOutImpl%0A%20%20%23%E4%B8%BA%E6%89%80%E6%9C%89Entity%E7%B1%BB%E6%89%80%E5%9C%A8%E5%8C%85%E8%B5%B7%E9%BB%98%E8%AE%A4%E5%88%AB%E5%90%8D%0A%20%20type-aliases-package%3A%20com.chris.mybatisplus.entities%0A%20%20%23%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E6%8C%87%E5%AE%9ATypehandler%E7%9A%84%E5%8C%85%E8%B7%AF%E5%BE%84%0A%20%20type-handlers-package%3A%20com.chris.mybatisplus.handler%0A%60%60%60%0A%0A%23%23%23%23%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%60%60%60java%0Apackage%20com.chris.mybatisplus%3B%0A%0Aimport%20cn.hutool.core.util.RandomUtil%3B%0Aimport%20cn.hutool.json.JSONUtil%3B%0Aimport%20com.baomidou.mybatisplus.core.conditions.query.QueryWrapper%3B%0Aimport%20com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper%3B%0Aimport%20com.chris.mybatisplus.dao.mapper.UserMapper%3B%0Aimport%20com.chris.mybatisplus.dto.Encrypt%3B%0Aimport%20com.chris.mybatisplus.entities.User%3B%0Aimport%20org.junit.jupiter.api.Test%3B%0Aimport%20org.springframework.beans.factory.annotation.Autowired%3B%0Aimport%20org.springframework.boot.test.context.SpringBootTest%3B%0A%0Aimport%20java.security.SecureRandom%3B%0Aimport%20java.util.*%3B%0A%0A%40SpringBootTest(classes%20%3D%20MybatisPlusMain.class)%0Apublic%20class%20TestMybaisPlus%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20public%20UserMapper%20userMapper%3B%0A%0A%0A%20%20%20%20%2F%2F%E5%86%99%E5%85%A5%E4%B8%80%E6%9D%A1%E8%AE%B0%E5%BD%95%EF%BC%8C%E5%B9%B6%E5%AF%B9phone%E5%AD%97%E6%AE%B5%E5%8A%A0%E5%AF%86%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20testInsertEncrypt()%20%7B%0A%20%20%20%20%20%20%20%20int%20encrypt%20%3D%20userMapper.addUser(%22cl%22%2C%2023%2C%20new%20Date()%2C%20new%20Encrypt(%221234454556%22)%2C%20%22US%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22insert%20user%20account%3A%22%20%2B%20encrypt)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%E6%9F%A5%E8%AF%A2phone%E5%AF%B9%E5%BA%94%E7%9A%84%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20findUserByPhone()%20%7B%0A%20%20%20%20%20%20%20%20List%3CUser%3E%20usersByPhone%20%3D%20userMapper.findUsersByPhone(new%20Encrypt(%221234454556%22))%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22usersByPhone%3A%22%20%2B%20JSONUtil.toJsonStr(usersByPhone))%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%0A%60%60%60%0A%0A%23%23%20%E6%96%B9%E6%B3%952%0A%3E%20%E5%AF%B9%E6%96%B9%E6%B3%951%E4%B8%AD%E7%9A%84entity%E8%BF%9B%E8%A1%8C%E6%94%B9%E9%80%A0%0A%0A%0A%0A%60%60%60java%0Apublic%20interface%20UserCryptoMapper%20extends%20BaseMapper%3CUserCrypto%3E%20%7B%0A%0A%20%20%20%20int%20addUser(%40Param(%22name%22)%20String%20name%2C%20%40Param(%22age%22)%20Integer%20age%2C%20%40Param(%22bir%22)%20Date%20bir%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40Param(%22phone%22)%20Encrypt%20phone%2C%20%40Param(%22address%22)%20String%20address)%3B%0A%0A%20%20%20%20List%3CUser%3E%20findUsersByPhone(%40Param(%22phone%22)%20Encrypt%20phone)%3B%0A%7D%0A%60%60%60%0A%0A%3E%20phone%E5%AD%97%E6%AE%B5%E7%B1%BB%E5%9E%8B%E6%94%B9%E4%B8%BAEncrypt%E5%B9%B6%E5%8A%A0%E4%B8%8A%20%60typeHandler%3D%22com.chris.mybatisplus.handler.EncryptTypeHandler%60%0A%60%60%60java%0A%40Data%0A%40AllArgsConstructor%0A%40Accessors(chain%20%3D%20true)%0A%40NoArgsConstructor%0A%40TableName(%22t_user%22)%20%2F%2F%E5%9C%A8%E4%B8%8D%E9%85%8D%E7%BD%AE%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E9%BB%98%E8%AE%A4%E8%A1%A8%E5%90%8D%E4%B8%8E%E7%B1%BB%E5%90%8D%E4%B8%80%E8%87%B4%0Apublic%20class%20UserCrypto%20%7B%0A%0A%20%20%20%20public%20UserCrypto(String%20name%2C%20int%20age%2C%20Date%20bir)%20%7B%0A%20%20%20%20%20%20%20%20this.name%20%3D%20name%3B%0A%20%20%20%20%20%20%20%20this.age%20%3D%20age%3B%0A%20%20%20%20%20%20%20%20this.bir%20%3D%20bir%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20AUTO%3A%E6%95%B0%E6%8D%AE%E5%BA%93%E8%87%AA%E5%A2%9E%0A%20%20%20%20%20*%20INPUT%3Ainset%E5%89%8D%E8%87%AA%E8%A1%8C%E8%AE%BE%E7%BD%AE%E4%B8%BB%E9%94%AE%E5%80%BC%0A%20%20%20%20%20*%20ASSIGN_ID%3A%E5%88%86%E9%85%8DID%EF%BC%8C%E4%B8%BB%E9%94%AE%E7%B1%BB%E5%9E%8B%E4%B8%BANumber(Integer%E5%92%8CLong)%E4%BD%BF%E7%94%A8%E6%8E%A5%E5%8F%A3IdentifierGenerator%E7%9A%84nextId%E6%96%B9%E6%B3%95%EF%BC%88%E9%BB%98%E8%AE%A4%E5%AE%9E%E7%8E%B0%E7%B1%BB%E4%B8%BADefaultIdentifierGenerator%E9%9B%AA%E8%8A%B1%E7%AE%97%E6%B3%95%EF%BC%89%0A%20%20%20%20%20*%20ASSIGN_UUID%3A%E5%88%86%E9%85%8DUUID%EF%BC%8C%E4%B8%BB%E9%94%AE%E7%B1%BB%E5%9E%8B%E4%B8%BAString%2C%E4%BD%BF%E7%94%A8%E6%8E%A5%E5%8F%A3IdentifierGenerator%E7%9A%84nextId%E6%96%B9%E6%B3%95%EF%BC%88%E9%BB%98%E8%AE%A4default%E6%96%B9%E6%B3%95%EF%BC%89%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40TableId(value%20%3D%20%22id%22%2C%20type%20%3D%20IdType.AUTO)%0A%20%20%20%20private%20Integer%20id%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%A1%A8%E4%B8%AD%E5%88%97%E5%90%8D%E4%B8%8EJava%E7%B1%BB%E4%B8%AD%E5%B1%9E%E6%80%A7%E7%9A%84%E6%98%A0%E5%B0%84%0A%20%20%20%20%20*%20%E5%A6%82%E6%9E%9C%E5%88%97%E5%90%8D%E5%92%8C%E5%B1%9E%E6%80%A7%E5%90%8D%E4%B8%80%E8%87%B4%E5%8F%AF%E4%BB%A5%E4%B8%8D%E7%94%A8%E9%85%8D%E7%BD%AE%E6%AD%A4%E6%B3%A8%E8%A7%A3%0A%20%20%20%20%20*%2F%0A%0A%20%20%20%20%40TableField(%22name%22)%0A%20%20%20%20private%20String%20name%3B%0A%0A%20%20%20%20private%20Integer%20age%3B%0A%20%20%20%20private%20Date%20bir%3B%0A%20%20%20%20private%20String%20address%3B%0A%0A%20%20%20%20%40TableField(jdbcType%20%3D%20JdbcType.VARCHAR%2C%20typeHandler%20%3D%20com.chris.mybatisplus.handler.EncryptTypeHandler.class)%0A%20%20%20%20private%20Encrypt%20phone%3B%0A%0A%20%20%20%20%2F%2F%20%E4%B8%8D%E6%98%A0%E5%B0%84%E6%95%B0%E6%8D%AE%E8%A1%A8%E4%B8%AD%E7%9A%84%E4%BB%BB%E4%BD%95%E5%AD%97%E6%AE%B5%0A%20%20%20%20%40TableField(exist%20%3D%20false)%0A%20%20%20%20private%20String%20notColumn%3B%0A%7D%0A%0A%60%60%60%0A%0A%3E%20phone%E5%AD%97%E6%AE%B5%E5%8A%A0%E4%B8%8A%20%60typeHandler%3D%22com.chris.mybatisplus.handler.EncryptTypeHandler%60%0A%60%60%60%0A%3Cmapper%20namespace%3D%22com.chris.mybatisplus.dao.mapper.UserCryptoMapper%22%3E%0A%0A%20%20%20%20%3CresultMap%20id%3D%22BaseResultMapper%22%20type%3D%22com.chris.mybatisplus.entities.UserCrypto%22%3E%0A%20%20%20%20%20%20%20%20%3Cid%20column%3D%22id%22%20property%3D%22id%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22name%22%20property%3D%22name%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22age%22%20property%3D%22age%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22bir%22%20property%3D%22bir%22%2F%3E%0A%20%20%20%20%20%20%20%20%3Cresult%20column%3D%22phone%22%20property%3D%22phone%22%20typeHandler%3D%22com.chris.mybatisplus.handler.EncryptTypeHandler%22%2F%3E%0A%20%20%20%20%3C%2FresultMap%3E%0A%0A%20%20%20%20%3Cinsert%20id%3D%22addUser%22%3E%0A%20%20%20%20%20%20%20%20insert%20into%20t_user(name%2C%20age%2C%20bir%2C%20phone%2C%20address)%0A%20%20%20%20%20%20%20%20values%20(%23%7Bname%7D%2C%20%23%7Bage%7D%2C%20%23%7Bbir%7D%2C%20%23%7Bphone%7D%2C%20%23%7Baddress%7D)%0A%20%20%20%20%3C%2Finsert%3E%0A%0A%20%20%20%20%3Cselect%20id%3D%22findUsersByPhone%22%20resultMap%3D%22BaseResultMapper%22%3E%0A%20%20%20%20%20%20%20%20select%20*%0A%20%20%20%20%20%20%20%20from%20t_user%0A%20%20%20%20%20%20%20%20where%20phone%20%3D%20%23%7Bphone%7D%0A%20%20%20%20%3C%2Fselect%3E%0A%0A%3C%2Fmapper%3E%0A%60%60%60%0A%0A%60%60%60java%0A%40SpringBootTest(classes%20%3D%20MybatisPlusMain.class)%0Apublic%20class%20EncryptTest%20%7B%0A%0A%20%20%20%20%40Resource%0A%20%20%20%20private%20UserCryptoMapper%20cryptoMapper%3B%0A%0A%20%20%20%20%2F%2F%E5%86%99%E5%85%A5%E4%B8%80%E6%9D%A1%E8%AE%B0%E5%BD%95%EF%BC%8C%E5%B9%B6%E5%AF%B9phone%E5%AD%97%E6%AE%B5%E5%8A%A0%E5%AF%86%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20testInsertEncrypt()%20%7B%0A%20%20%20%20%20%20%20%20int%20encrypt%20%3D%20cryptoMapper.addUser(%22cl%22%2C%2023%2C%20new%20Date()%2C%20new%20Encrypt(%221234454556%22)%2C%20%22US%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22insert%20user%20account%3A%22%20%2B%20encrypt)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%E6%9F%A5%E8%AF%A2phone%E5%AF%B9%E5%BA%94%E7%9A%84%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20findUserByPhone()%20%7B%0A%20%20%20%20%20%20%20%20List%3CUser%3E%20usersByPhone%20%3D%20cryptoMapper.findUsersByPhone(new%20Encrypt(%221234454556%22))%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22usersByPhone%3A%22%20%2B%20JSONUtil.toJsonStr(usersByPhone))%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20testEncrypt()%20%7B%0A%20%20%20%20%20%20%20%20UserCrypto%20user%20%3D%20new%20UserCrypto()%3B%0A%20%20%20%20%20%20%20%20user.setAge(21)%3B%0A%20%20%20%20%20%20%20%20user.setBir(new%20Date())%3B%0A%20%20%20%20%20%20%20%20user.setName(%22Hency%22)%3B%0A%20%20%20%20%20%20%20%20user.setPhone(new%20Encrypt(%221263324456677%22))%3B%0A%20%20%20%20%20%20%20%20int%20i%20%3D%20cryptoMapper.insert(user)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22insert%20user%20account%3A%22%20%2B%20i)%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%60%60%60

自定义类型处理器 Typehandler

创建时间:2022/8/28 13:58
更新时间:2022/8/28 13:58
作者:Chris

https://blog.csdn.net/lmb55/article/details/90380309

%0Ahttps%3A%2F%2Fblog.csdn.net%2Flmb55%2Farticle%2Fdetails%2F90380309

面向切面编程

创建时间:2020/11/16 16:29
更新时间:2024/2/14 12:56
作者:Chris
来源:https://www.cnblogs.com/wangshen31/p/9379197.html

  • 1 是什么
    • 1.1 应用场景
    • 1.2 切面
    • 1.3 描述切面的常用术语有
      • 1.3.1 切点(pointcut)
      • 1.3.2 通知(advice)
      • 1.3.3 连接点(join point)
    • 1.4 原理
    • 1.5 切点表达式
      • 1.5.1 execution()指示器
      • 1.5.2 bean()指示器
  • 2 怎么玩
  • 3 总结
https://www.cnblogs.com/wangshen31/p/9379197.html

1 是什么

1.1 应用场景

切面所适用的多个场景,包括日志,声明式事务、安全和缓存

1.2 切面

切面 是通知和切点的结合。
通知和切点共同定义了切面的全部内容——它是什么,在何时和何处完成其功能.
织入 是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。

1.3 描述切面的常用术语有

切点(pointcut)、 通知(advice)和连接点(join point)
1.3.1 切点(pointcut)
切点定义了通知被应用到的具体位置
@Pointcut注解能够在一个@AspectJ切面内定义可重用的切点
@Pointcut("(execution(public * com.chris.demo..*.service..*.*(..))" +
"|| execution(public * com.chris.demo..*.app..*.*(..))" +
"|| execution(public * com.chris.demo..*.api..*.*(..)))" +
"|| execution(public * com.chris.demo..*.web..*Controller.*(..)))")
private void check() {
}

@Pointcut("@annotation(com.chris.demo.common.annotation.LogIgnoreFilter)")
public void ignoreLog() {
}

@Pointcut("(execution(public * com.chris.demo.report.*.*.*(..))" +
"|| execution(public * com.chris.demo.file..*.*.*(..))" +
"|| execution(public * com.chris.demo..*.FileAction.*(..)))")
private void uncheck() {
}

/**
* 定义复合切点
*/
@Pointcut("check() && !uncheck()")
public void serviceLog() {
}
切入点表达式可以用逻辑符号&&, ||, ! 来描述
1.3.2 通知(advice)
Spring切面可以应用5种类型的通知:
  • 前置通知(Before):在目标方法被调用之前调用通知功能;
  • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
  • 返回通知(After-returning):在目标方法成功执行之后调用通知;
  • 异常通知(After-throwing):在目标方法抛出异常后调用通知;
  • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
  • @Before
    切入点表达式可以用逻辑符号 &&, ||, !来描述
// 在切入点的方法run之前要干的
@Before("check() || uiControllerLog()")
public void logBeforeController(JoinPoint joinPoint) {
  • @After
    这个注解就是在切入的方法运行完之后把我们的advice增强加进去。
    一样方法中可以添加JoinPoint。
  • @Around
    这个注解可以简单地看作@Before和@After的结合。这个注解和其他的比比较特别,它的方法的参数一定要是ProceedingJoinPoint,这个对象是JoinPoint的子类。我们可以把这个看作是切入点的那个方法的替身
    ProceedingJoinPoint 有个proceed() 方法,相当于就是那切入点的那个方法执行,简单地说就是让目标方法执行,然后这个方法会返回一个对象,这个对象就是那个切入点所在位置的方法所返回的对象。
    除了这个Proceed方法(很重要的方法),其他和那几个注解一样。
  • @AfterReturning
    这个注解可以指定两个属性,
    returning属性,表明可以在Advice的方法中有目标方法返回值的形参
@AfterReturning(returning = "returnOb", pointcut = "controllerLog() || uiControllerLog()")
public void doAfterReturning(JoinPoint joinPoint, Object returnOb) {
System.out.println("##################### the return of the method is : " + returnOb);
}
  • @AfterThrowing
    异常抛出增强,在异常抛出后织入的增强。有点像上面的@AfterReturning
    这个注解也是有两个属性,pointcut和throwing。
@AfterThrowing(pointcut = "controllerLog() || uiControllerLog()", throwing = "ex")
public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = point.getSignature().getName();
List<Object> args = Arrays.asList(point.getArgs());
System.out.println("连接点方法为:" + methodName + ",参数为:" + args + ",异常为:" + ex);
}
1.3.3 连接点(join point)
连接点是程序执行过程中能够应用通知的所有点
JoinPoint : 代表着织入增强处理的连接点。
JoinPoint包含了几个很有用的参数:
Object[] getArgs:返回目标方法的参数
Signature getSignature:返回目标方法的签名
Object getTarget:返回被织入增强处理的目标对象
Object getThis:返回AOP框架为目标对象生成的代理对象

1.4 原理

Spring提供了4种类型的AOP支持
  • 基于代理的经典Spring AOP;
  • 纯POJO切面;
  • @AspectJ注解驱动的切面;
  • 注入式AspectJ切面(适用于Spring各版本)。
前三种都是AOP实现的变体,
Spring AOP构建在动态代理 基础之上,因此,Spring对AOP的支持局限于方法拦截
Spring在运行时通过在代理类中包裹切面,把切面织入到Spring管理的bean中。
代理类封装了目标类, 先拦截被通知方法的调用,再把方法调用转发给真正目标bean。当代理拦截到方法调用时,在调用目标bean方法之前,会执行切面逻辑。

Spring的切面由包裹了目标对象的代理类实现。代理类处理方法的调用,执行额外的切面逻辑,并调用目标方法.

1.5 切点表达式

在Spring AOP中,要使用AspectJ的 切点表达式语言 来定义切点.
Spring AOP仅支持AspectJ 切点指示器(pointcut designator) 的一个子集。
Spring借助AspectJ的 切点表达式语言 来定义Spring切面
在Spring中尝试使用AspectJ其他指示器时,将会抛出IllegalArgument-Exception异常
只有 execution指示器 是实际执行匹配的,而其他的指示器都是用来限制匹配的.
1.5.1 execution()指示器
execution(方法修饰符(可选) 返回类型 类路径 方法名 参数 异常模式(可选))
例如:
execution()指示器选择Performance的perform()方法。方法表达式以“*”号开始,表明了我们不关心方法返回值的类型。然后,我们指定了全限定类名和方法名。
对于方法参数列表,我们使用两个(..)表明切点要选择任意的perform()方法,不论该方法的入参是什么。

expression="execution(* com.loongshawn.method.ces..*.*(..))"

1)execution(public * *(..)): 表示匹配所有public方法
2)execution(* set*(..)): 表示所有以“set”开头的方法
3)execution(* com.xyz.service.AccountService.*(..)): 表示匹配所有AccountService接口的方法
4)execution(* com.xyz.service.*.*(..)): 表示匹配service包下所有的方法
5)execution(* com.xyz.service..*.*(..)): 表示匹配service包和它的子包下的方法
1.5.2 bean()指示器
Spring还引入了一个新的bean()指示器,它允许我们在切点表达式中使用bean的ID来标识bean.
execution(* concert.Performance.perform()) and bean('woodstock')
在执行Performance的perform()方法时应用通知,但限定bean的ID为woodstock

2 怎么玩

3 总结

使用JavaConfig的话,可以在配置类的类级别上通过使用EnableAspectJ-AutoProxy注解启用自动代理功能。
使用XML来装配bean的话,那么需要使用Springaop命名空间中的aop:aspectj-autoproxy元素
不管你是使用JavaConfig还是XML,AspectJ自动代理都会为使用@Aspect注解的bean创建一个代理,这个代理会围绕着所有该切面的切点所匹配的bean。
我们需要记住的是,Spring的AspectJ自动代理仅仅使用@AspectJ作为创建切面的指导,切面依然是基于代理的。在本质上,它依然是Spring基于代理的切面。这一点非常重要,因为这意味着尽管使用的是@AspectJ注解,但我们仍然限于代理方法的调用。如果想利用AspectJ的所有能力,我们必须在运行时使用AspectJ并且不依赖Spring来创建基于代理的切面。
%5Btoc%5D%0A%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fwangshen31%2Fp%2F9379197.html%0A%0A%23%23%201%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%23%23%23%23%201.1%20%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%20%20%0A%3E%20%E5%88%87%E9%9D%A2%E6%89%80%E9%80%82%E7%94%A8%E7%9A%84%E5%A4%9A%E4%B8%AA%E5%9C%BA%E6%99%AF%EF%BC%8C%E5%8C%85%E6%8B%AC%E6%97%A5%E5%BF%97%EF%BC%8C%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E3%80%81%E5%AE%89%E5%85%A8%E5%92%8C%E7%BC%93%E5%AD%98%0A%0A%23%23%23%23%201.2%20%E5%88%87%E9%9D%A2%0A%3E%20%60%E5%88%87%E9%9D%A2%60%20%E6%98%AF%E9%80%9A%E7%9F%A5%E5%92%8C%E5%88%87%E7%82%B9%E7%9A%84%E7%BB%93%E5%90%88%E3%80%82%0A%3E%20%E9%80%9A%E7%9F%A5%E5%92%8C%E5%88%87%E7%82%B9%E5%85%B1%E5%90%8C%E5%AE%9A%E4%B9%89%E4%BA%86%E5%88%87%E9%9D%A2%E7%9A%84%E5%85%A8%E9%83%A8%E5%86%85%E5%AE%B9%E2%80%94%E2%80%94%E5%AE%83%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%8C%E5%9C%A8%E4%BD%95%E6%97%B6%E5%92%8C%E4%BD%95%E5%A4%84%E5%AE%8C%E6%88%90%E5%85%B6%E5%8A%9F%E8%83%BD.%0A%0A%3E%20%60%E7%BB%87%E5%85%A5%60%20%20%E6%98%AF%E6%8A%8A%E5%88%87%E9%9D%A2%E5%BA%94%E7%94%A8%E5%88%B0%E7%9B%AE%E6%A0%87%E5%AF%B9%E8%B1%A1%E5%B9%B6%E5%88%9B%E5%BB%BA%E6%96%B0%E7%9A%84%E4%BB%A3%E7%90%86%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%BF%87%E7%A8%8B%E3%80%82%E5%88%87%E9%9D%A2%E5%9C%A8%E6%8C%87%E5%AE%9A%E7%9A%84%E8%BF%9E%E6%8E%A5%E7%82%B9%E8%A2%AB%E7%BB%87%E5%85%A5%E5%88%B0%E7%9B%AE%E6%A0%87%E5%AF%B9%E8%B1%A1%E4%B8%AD%E3%80%82%0A%0A%0A%23%23%23%23%201.3%20%E6%8F%8F%E8%BF%B0%E5%88%87%E9%9D%A2%E7%9A%84%E5%B8%B8%E7%94%A8%E6%9C%AF%E8%AF%AD%E6%9C%89%0A%3E%E5%88%87%E7%82%B9%EF%BC%88pointcut%EF%BC%89%E3%80%81%20%E9%80%9A%E7%9F%A5%EF%BC%88advice%EF%BC%89%E5%92%8C%E8%BF%9E%E6%8E%A5%E7%82%B9%EF%BC%88join%20point%EF%BC%89%0A%0A%23%23%23%23%23%201.3.1%20%20%E5%88%87%E7%82%B9%EF%BC%88pointcut%EF%BC%89%0A%3E%20%E5%88%87%E7%82%B9%E5%AE%9A%E4%B9%89%E4%BA%86%E9%80%9A%E7%9F%A5%E8%A2%AB%E5%BA%94%E7%94%A8%E5%88%B0%E7%9A%84%E5%85%B7%E4%BD%93%E4%BD%8D%E7%BD%AE%0A%3E%20%40Pointcut%E6%B3%A8%E8%A7%A3%E8%83%BD%E5%A4%9F%E5%9C%A8%E4%B8%80%E4%B8%AA%40AspectJ%E5%88%87%E9%9D%A2%E5%86%85%E5%AE%9A%E4%B9%89%E5%8F%AF%E9%87%8D%E7%94%A8%E7%9A%84%E5%88%87%E7%82%B9%0A%0A%60%60%60java%0A%40Pointcut(%22(execution(public%20*%20com.chris.demo..*.service..*.*(..))%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%7C%20execution(public%20*%20com.chris.demo..*.app..*.*(..))%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%7C%20execution(public%20*%20com.chris.demo..*.api..*.*(..)))%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%7C%20execution(public%20*%20com.chris.demo..*.web..*Controller.*(..)))%22)%0Aprivate%20void%20check()%20%7B%0A%7D%0A%0A%40Pointcut(%22%40annotation(com.chris.demo.common.annotation.LogIgnoreFilter)%22)%0Apublic%20void%20ignoreLog()%20%7B%0A%7D%0A%0A%40Pointcut(%22(execution(public%20*%20com.chris.demo.report.*.*.*(..))%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%7C%20execution(public%20*%20com.chris.demo.file..*.*.*(..))%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%7C%20execution(public%20*%20com.chris.demo..*.FileAction.*(..)))%22)%0Aprivate%20void%20uncheck()%20%7B%0A%7D%0A%0A%20%2F**%0A%20%20*%20%E5%AE%9A%E4%B9%89%E5%A4%8D%E5%90%88%E5%88%87%E7%82%B9%0A%20%20*%2F%0A%40Pointcut(%22check()%20%26%26%20!uncheck()%22)%0Apublic%20void%20serviceLog()%20%7B%0A%7D%0A%60%60%60%0A%3E%20%E5%88%87%E5%85%A5%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8F%AF%E4%BB%A5%E7%94%A8%E9%80%BB%E8%BE%91%E7%AC%A6%E5%8F%B7%60%26%26%2C%20%7C%7C%2C%20!%60%20%E6%9D%A5%E6%8F%8F%E8%BF%B0%0A%0A%23%23%23%23%23%201.3.2%20%20%E9%80%9A%E7%9F%A5%EF%BC%88advice%EF%BC%89%0A%3E%20Spring%E5%88%87%E9%9D%A2%E5%8F%AF%E4%BB%A5%E5%BA%94%E7%94%A85%E7%A7%8D%E7%B1%BB%E5%9E%8B%E7%9A%84%E9%80%9A%E7%9F%A5%EF%BC%9A%0A%3E%20-%20%E5%89%8D%E7%BD%AE%E9%80%9A%E7%9F%A5%EF%BC%88Before%EF%BC%89%EF%BC%9A%E5%9C%A8%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E8%A2%AB%E8%B0%83%E7%94%A8%E4%B9%8B%E5%89%8D%E8%B0%83%E7%94%A8%E9%80%9A%E7%9F%A5%E5%8A%9F%E8%83%BD%EF%BC%9B%0A%3E%20-%20%E5%90%8E%E7%BD%AE%E9%80%9A%E7%9F%A5%EF%BC%88After%EF%BC%89%EF%BC%9A%E5%9C%A8%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E5%AE%8C%E6%88%90%E4%B9%8B%E5%90%8E%E8%B0%83%E7%94%A8%E9%80%9A%E7%9F%A5%EF%BC%8C%E6%AD%A4%E6%97%B6%E4%B8%8D%E4%BC%9A%E5%85%B3%E5%BF%83%E6%96%B9%E6%B3%95%E7%9A%84%E8%BE%93%E5%87%BA%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9B%0A%3E%20-%20%E8%BF%94%E5%9B%9E%E9%80%9A%E7%9F%A5%EF%BC%88After-returning%EF%BC%89%EF%BC%9A%E5%9C%A8%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E6%88%90%E5%8A%9F%E6%89%A7%E8%A1%8C%E4%B9%8B%E5%90%8E%E8%B0%83%E7%94%A8%E9%80%9A%E7%9F%A5%EF%BC%9B%0A%3E%20-%20%E5%BC%82%E5%B8%B8%E9%80%9A%E7%9F%A5%EF%BC%88After-throwing%EF%BC%89%EF%BC%9A%E5%9C%A8%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E5%90%8E%E8%B0%83%E7%94%A8%E9%80%9A%E7%9F%A5%EF%BC%9B%0A%3E%20-%20%E7%8E%AF%E7%BB%95%E9%80%9A%E7%9F%A5%EF%BC%88Around%EF%BC%89%EF%BC%9A%E9%80%9A%E7%9F%A5%E5%8C%85%E8%A3%B9%E4%BA%86%E8%A2%AB%E9%80%9A%E7%9F%A5%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%9C%A8%E8%A2%AB%E9%80%9A%E7%9F%A5%E7%9A%84%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%E4%B9%8B%E5%89%8D%E5%92%8C%E8%B0%83%E7%94%A8%E4%B9%8B%E5%90%8E%E6%89%A7%E8%A1%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E8%A1%8C%E4%B8%BA%E3%80%82%0A%0A%3E%20-%20%40Before%0A%3E%20%E5%88%87%E5%85%A5%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8F%AF%E4%BB%A5%E7%94%A8%E9%80%BB%E8%BE%91%E7%AC%A6%E5%8F%B7%20%60%26%26%2C%20%7C%7C%2C%20!%60%E6%9D%A5%E6%8F%8F%E8%BF%B0%0A%60%60%60java%0A%2F%2F%20%E5%9C%A8%E5%88%87%E5%85%A5%E7%82%B9%E7%9A%84%E6%96%B9%E6%B3%95run%E4%B9%8B%E5%89%8D%E8%A6%81%E5%B9%B2%E7%9A%84%0A%40Before(%22check()%20%7C%7C%20uiControllerLog()%22)%20%0A%20public%20void%20logBeforeController(JoinPoint%20joinPoint)%20%7B%0A%60%60%60%0A%0A%3E%20-%20%40After%0A%3E%20%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E5%B0%B1%E6%98%AF%E5%9C%A8%E5%88%87%E5%85%A5%E7%9A%84%E6%96%B9%E6%B3%95%E8%BF%90%E8%A1%8C%E5%AE%8C%E4%B9%8B%E5%90%8E%E6%8A%8A%E6%88%91%E4%BB%AC%E7%9A%84advice%E5%A2%9E%E5%BC%BA%E5%8A%A0%E8%BF%9B%E5%8E%BB%E3%80%82%0A%3E%20%E4%B8%80%E6%A0%B7%E6%96%B9%E6%B3%95%E4%B8%AD%E5%8F%AF%E4%BB%A5%E6%B7%BB%E5%8A%A0JoinPoint%E3%80%82%0A%0A%3E%20-%20%40Around%0A%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E5%8F%AF%E4%BB%A5%E7%AE%80%E5%8D%95%E5%9C%B0%E7%9C%8B%E4%BD%9C%40Before%E5%92%8C%40After%E7%9A%84%E7%BB%93%E5%90%88%E3%80%82%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E5%92%8C%E5%85%B6%E4%BB%96%E7%9A%84%E6%AF%94%E6%AF%94%E8%BE%83%E7%89%B9%E5%88%AB%EF%BC%8C%E5%AE%83%E7%9A%84%E6%96%B9%E6%B3%95%E7%9A%84%E5%8F%82%E6%95%B0%E4%B8%80%E5%AE%9A%E8%A6%81%E6%98%AF%60ProceedingJoinPoint%60%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E6%98%AFJoinPoint%E7%9A%84%E5%AD%90%E7%B1%BB%E3%80%82%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E6%8A%8A%E8%BF%99%E4%B8%AA%E7%9C%8B%E4%BD%9C%E6%98%AF%E5%88%87%E5%85%A5%E7%82%B9%E7%9A%84%E9%82%A3%E4%B8%AA%E6%96%B9%E6%B3%95%E7%9A%84%E6%9B%BF%E8%BA%AB%0A%60ProceedingJoinPoint%60%20%E6%9C%89%E4%B8%AA%60proceed()%60%20%E6%96%B9%E6%B3%95%EF%BC%8C%E7%9B%B8%E5%BD%93%E4%BA%8E%E5%B0%B1%E6%98%AF%E9%82%A3%E5%88%87%E5%85%A5%E7%82%B9%E7%9A%84%E9%82%A3%E4%B8%AA%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%EF%BC%8C%E7%AE%80%E5%8D%95%E5%9C%B0%E8%AF%B4%E5%B0%B1%E6%98%AF%E8%AE%A9%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%EF%BC%8C%E7%84%B6%E5%90%8E%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E4%BC%9A%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%B0%B1%E6%98%AF%E9%82%A3%E4%B8%AA%E5%88%87%E5%85%A5%E7%82%B9%E6%89%80%E5%9C%A8%E4%BD%8D%E7%BD%AE%E7%9A%84%E6%96%B9%E6%B3%95%E6%89%80%E8%BF%94%E5%9B%9E%E7%9A%84%E5%AF%B9%E8%B1%A1%E3%80%82%0A%E9%99%A4%E4%BA%86%E8%BF%99%E4%B8%AAProceed%E6%96%B9%E6%B3%95%EF%BC%88%E5%BE%88%E9%87%8D%E8%A6%81%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%89%EF%BC%8C%E5%85%B6%E4%BB%96%E5%92%8C%E9%82%A3%E5%87%A0%E4%B8%AA%E6%B3%A8%E8%A7%A3%E4%B8%80%E6%A0%B7%E3%80%82%0A%0A%3E%20-%20%40AfterReturning%0A%3E%20%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E4%B8%A4%E4%B8%AA%E5%B1%9E%E6%80%A7%2C%0A%3E%20returning%E5%B1%9E%E6%80%A7%EF%BC%8C%E8%A1%A8%E6%98%8E%E5%8F%AF%E4%BB%A5%E5%9C%A8Advice%E7%9A%84%E6%96%B9%E6%B3%95%E4%B8%AD%E6%9C%89%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%80%BC%E7%9A%84%E5%BD%A2%E5%8F%82%0A%60%60%60java%0A%40AfterReturning(returning%20%3D%20%22returnOb%22%2C%20pointcut%20%3D%20%22controllerLog()%20%7C%7C%20uiControllerLog()%22)%0Apublic%20void%20doAfterReturning(JoinPoint%20joinPoint%2C%20Object%20returnOb)%20%7B%0A%20%20%20%20System.out.println(%22%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%20the%20return%20of%20the%20method%20is%20%3A%20%22%20%2B%20returnOb)%3B%0A%7D%0A%60%60%60%0A%0A%3E%20-%20%40AfterThrowing%0A%3E%20%E5%BC%82%E5%B8%B8%E6%8A%9B%E5%87%BA%E5%A2%9E%E5%BC%BA%EF%BC%8C%E5%9C%A8%E5%BC%82%E5%B8%B8%E6%8A%9B%E5%87%BA%E5%90%8E%E7%BB%87%E5%85%A5%E7%9A%84%E5%A2%9E%E5%BC%BA%E3%80%82%E6%9C%89%E7%82%B9%E5%83%8F%E4%B8%8A%E9%9D%A2%E7%9A%84%40AfterReturning%0A%3E%20%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E4%B9%9F%E6%98%AF%E6%9C%89%E4%B8%A4%E4%B8%AA%E5%B1%9E%E6%80%A7%EF%BC%8Cpointcut%E5%92%8Cthrowing%E3%80%82%0A%60%60%60java%0A%40AfterThrowing(pointcut%20%3D%20%22controllerLog()%20%7C%7C%20uiControllerLog()%22%2C%20throwing%20%3D%20%22ex%22)%0Apublic%20void%20doAfterThrowing(JoinPoint%20joinPoint%2C%20Exception%20ex)%20%7B%0A%20%20%20%20%20%20%20%20String%20methodName%20%3D%20point.getSignature().getName()%3B%0A%20%20%20%20%20%20%20%20List%3CObject%3E%20args%20%3D%20Arrays.asList(point.getArgs())%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E8%BF%9E%E6%8E%A5%E7%82%B9%E6%96%B9%E6%B3%95%E4%B8%BA%EF%BC%9A%22%20%2B%20methodName%20%2B%20%22%2C%E5%8F%82%E6%95%B0%E4%B8%BA%EF%BC%9A%22%20%2B%20args%20%2B%20%22%2C%E5%BC%82%E5%B8%B8%E4%B8%BA%EF%BC%9A%22%20%2B%20ex)%3B%0A%20%20%20%20%20%20%20%20%20%20%0A%7D%20%0A%60%60%60%0A%0A%23%23%23%23%23%201.3.3%20%20%E8%BF%9E%E6%8E%A5%E7%82%B9%EF%BC%88join%20point%EF%BC%89%0A%3E%20%E8%BF%9E%E6%8E%A5%E7%82%B9%E6%98%AF%E7%A8%8B%E5%BA%8F%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%E4%B8%AD%E8%83%BD%E5%A4%9F%E5%BA%94%E7%94%A8%E9%80%9A%E7%9F%A5%E7%9A%84%E6%89%80%E6%9C%89%E7%82%B9%0A%0A%3E%20JoinPoint%20%3A%20%E4%BB%A3%E8%A1%A8%E7%9D%80%E7%BB%87%E5%85%A5%E5%A2%9E%E5%BC%BA%E5%A4%84%E7%90%86%E7%9A%84%E8%BF%9E%E6%8E%A5%E7%82%B9%E3%80%82%0A%3E%20JoinPoint%E5%8C%85%E5%90%AB%E4%BA%86%E5%87%A0%E4%B8%AA%E5%BE%88%E6%9C%89%E7%94%A8%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%9A%0A%60%60%60java%0AObject%5B%5D%20getArgs%EF%BC%9A%E8%BF%94%E5%9B%9E%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E7%9A%84%E5%8F%82%E6%95%B0%0ASignature%20getSignature%EF%BC%9A%E8%BF%94%E5%9B%9E%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%E7%9A%84%E7%AD%BE%E5%90%8D%0AObject%20getTarget%EF%BC%9A%E8%BF%94%E5%9B%9E%E8%A2%AB%E7%BB%87%E5%85%A5%E5%A2%9E%E5%BC%BA%E5%A4%84%E7%90%86%E7%9A%84%E7%9B%AE%E6%A0%87%E5%AF%B9%E8%B1%A1%0AObject%20getThis%EF%BC%9A%E8%BF%94%E5%9B%9EAOP%E6%A1%86%E6%9E%B6%E4%B8%BA%E7%9B%AE%E6%A0%87%E5%AF%B9%E8%B1%A1%E7%94%9F%E6%88%90%E7%9A%84%E4%BB%A3%E7%90%86%E5%AF%B9%E8%B1%A1%0A%60%60%60%0A%0A%0A%23%23%23%23%201.4%20%E5%8E%9F%E7%90%86%0A%3E%20Spring%E6%8F%90%E4%BE%9B%E4%BA%864%E7%A7%8D%E7%B1%BB%E5%9E%8B%E7%9A%84AOP%E6%94%AF%E6%8C%81%0A-%20%E5%9F%BA%E4%BA%8E%E4%BB%A3%E7%90%86%E7%9A%84%E7%BB%8F%E5%85%B8Spring%20AOP%EF%BC%9B%0A-%20%E7%BA%AFPOJO%E5%88%87%E9%9D%A2%EF%BC%9B%0A-%20%40AspectJ%E6%B3%A8%E8%A7%A3%E9%A9%B1%E5%8A%A8%E7%9A%84%E5%88%87%E9%9D%A2%EF%BC%9B%0A-%20%E6%B3%A8%E5%85%A5%E5%BC%8FAspectJ%E5%88%87%E9%9D%A2%EF%BC%88%E9%80%82%E7%94%A8%E4%BA%8ESpring%E5%90%84%E7%89%88%E6%9C%AC%EF%BC%89%E3%80%82%0A%3E%20%E5%89%8D%E4%B8%89%E7%A7%8D%E9%83%BD%E6%98%AFAOP%E5%AE%9E%E7%8E%B0%E7%9A%84%E5%8F%98%E4%BD%93%EF%BC%8C%0A%3E%20Spring%20AOP%E6%9E%84%E5%BB%BA%E5%9C%A8%60%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%60%20%E5%9F%BA%E7%A1%80%E4%B9%8B%E4%B8%8A%EF%BC%8C%E5%9B%A0%E6%AD%A4%EF%BC%8CSpring%E5%AF%B9AOP%E7%9A%84%E6%94%AF%E6%8C%81%E5%B1%80%E9%99%90%E4%BA%8E%60%E6%96%B9%E6%B3%95%E6%8B%A6%E6%88%AA%60%0A%0A%3E%20Spring%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E9%80%9A%E8%BF%87%E5%9C%A8%E4%BB%A3%E7%90%86%E7%B1%BB%E4%B8%AD%E5%8C%85%E8%A3%B9%E5%88%87%E9%9D%A2%EF%BC%8C%E6%8A%8A%E5%88%87%E9%9D%A2%E7%BB%87%E5%85%A5%E5%88%B0Spring%E7%AE%A1%E7%90%86%E7%9A%84bean%E4%B8%AD%E3%80%82%0A%3E%20%E4%BB%A3%E7%90%86%E7%B1%BB%E5%B0%81%E8%A3%85%E4%BA%86%E7%9B%AE%E6%A0%87%E7%B1%BB%2C%20%E5%85%88%E6%8B%A6%E6%88%AA%E8%A2%AB%E9%80%9A%E7%9F%A5%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%EF%BC%8C%E5%86%8D%E6%8A%8A%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%E8%BD%AC%E5%8F%91%E7%BB%99%E7%9C%9F%E6%AD%A3%E7%9B%AE%E6%A0%87bean%E3%80%82%E5%BD%93%E4%BB%A3%E7%90%86%E6%8B%A6%E6%88%AA%E5%88%B0%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%E6%97%B6%EF%BC%8C%E5%9C%A8%E8%B0%83%E7%94%A8%E7%9B%AE%E6%A0%87bean%E6%96%B9%E6%B3%95%E4%B9%8B%E5%89%8D%EF%BC%8C%E4%BC%9A%E6%89%A7%E8%A1%8C%E5%88%87%E9%9D%A2%E9%80%BB%E8%BE%91%E3%80%82%0A%0A!%5B64c53f639ea3b50a6cdbfb751bbe43b7.png%5D(en-resource%3A%2F%2Fdatabase%2F1312%3A1)%0A%0A%3E%20Spring%E7%9A%84%E5%88%87%E9%9D%A2%E7%94%B1%E5%8C%85%E8%A3%B9%E4%BA%86%E7%9B%AE%E6%A0%87%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%BB%A3%E7%90%86%E7%B1%BB%E5%AE%9E%E7%8E%B0%E3%80%82%E4%BB%A3%E7%90%86%E7%B1%BB%E5%A4%84%E7%90%86%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%EF%BC%8C%E6%89%A7%E8%A1%8C%E9%A2%9D%E5%A4%96%E7%9A%84%E5%88%87%E9%9D%A2%E9%80%BB%E8%BE%91%EF%BC%8C%E5%B9%B6%E8%B0%83%E7%94%A8%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95.%0A%0A%23%23%23%23%201.5%20%E5%88%87%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%3E%20%E5%9C%A8Spring%20AOP%E4%B8%AD%EF%BC%8C%E8%A6%81%E4%BD%BF%E7%94%A8AspectJ%E7%9A%84%20%60%E5%88%87%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E8%A8%80%60%20%E6%9D%A5%E5%AE%9A%E4%B9%89%E5%88%87%E7%82%B9.%0A%3E%20Spring%20AOP%E4%BB%85%E6%94%AF%E6%8C%81AspectJ%20%60%E5%88%87%E7%82%B9%E6%8C%87%E7%A4%BA%E5%99%A8%EF%BC%88pointcut%20designator%EF%BC%89%60%20%E7%9A%84%E4%B8%80%E4%B8%AA%E5%AD%90%E9%9B%86%E3%80%82%0A%3E%20Spring%E5%80%9F%E5%8A%A9AspectJ%E7%9A%84%20%60%E5%88%87%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E8%A8%80%60%20%E6%9D%A5%E5%AE%9A%E4%B9%89Spring%E5%88%87%E9%9D%A2%0A%0A%3E%20%E5%9C%A8Spring%E4%B8%AD%E5%B0%9D%E8%AF%95%E4%BD%BF%E7%94%A8AspectJ%E5%85%B6%E4%BB%96%E6%8C%87%E7%A4%BA%E5%99%A8%E6%97%B6%EF%BC%8C%E5%B0%86%E4%BC%9A%E6%8A%9B%E5%87%BAIllegalArgument-Exception%E5%BC%82%E5%B8%B8%0A%3E%20%E5%8F%AA%E6%9C%89%20%60execution%E6%8C%87%E7%A4%BA%E5%99%A8%60%20%E6%98%AF%E5%AE%9E%E9%99%85%E6%89%A7%E8%A1%8C%E5%8C%B9%E9%85%8D%E7%9A%84%EF%BC%8C%E8%80%8C%E5%85%B6%E4%BB%96%E7%9A%84%E6%8C%87%E7%A4%BA%E5%99%A8%E9%83%BD%E6%98%AF%E7%94%A8%E6%9D%A5%E9%99%90%E5%88%B6%E5%8C%B9%E9%85%8D%E7%9A%84.%0A%0A%23%23%23%23%23%201.5.1%20execution()%E6%8C%87%E7%A4%BA%E5%99%A8%0A%3E%20execution(%E6%96%B9%E6%B3%95%E4%BF%AE%E9%A5%B0%E7%AC%A6(%E5%8F%AF%E9%80%89)%20%20%E8%BF%94%E5%9B%9E%E7%B1%BB%E5%9E%8B%20%20%E7%B1%BB%E8%B7%AF%E5%BE%84%20%E6%96%B9%E6%B3%95%E5%90%8D%20%20%E5%8F%82%E6%95%B0%20%20%E5%BC%82%E5%B8%B8%E6%A8%A1%E5%BC%8F(%E5%8F%AF%E9%80%89))%20%0A%0A%E4%BE%8B%E5%A6%82%EF%BC%9A%0A%3E%20execution()%E6%8C%87%E7%A4%BA%E5%99%A8%E9%80%89%E6%8B%A9Performance%E7%9A%84perform()%E6%96%B9%E6%B3%95%E3%80%82%E6%96%B9%E6%B3%95%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%BB%A5%E2%80%9C%5C*%E2%80%9D%E5%8F%B7%E5%BC%80%E5%A7%8B%EF%BC%8C%E8%A1%A8%E6%98%8E%E4%BA%86%E6%88%91%E4%BB%AC%E4%B8%8D%E5%85%B3%E5%BF%83%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%80%BC%E7%9A%84%E7%B1%BB%E5%9E%8B%E3%80%82%E7%84%B6%E5%90%8E%EF%BC%8C%E6%88%91%E4%BB%AC%E6%8C%87%E5%AE%9A%E4%BA%86%E5%85%A8%E9%99%90%E5%AE%9A%E7%B1%BB%E5%90%8D%E5%92%8C%E6%96%B9%E6%B3%95%E5%90%8D%E3%80%82%0A%3E%20%E5%AF%B9%E4%BA%8E%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E5%88%97%E8%A1%A8%EF%BC%8C%E6%88%91%E4%BB%AC%E4%BD%BF%E7%94%A8%E4%B8%A4%E4%B8%AA%EF%BC%88..%EF%BC%89%E8%A1%A8%E6%98%8E%E5%88%87%E7%82%B9%E8%A6%81%E9%80%89%E6%8B%A9%E4%BB%BB%E6%84%8F%E7%9A%84perform()%E6%96%B9%E6%B3%95%EF%BC%8C%E4%B8%8D%E8%AE%BA%E8%AF%A5%E6%96%B9%E6%B3%95%E7%9A%84%E5%85%A5%E5%8F%82%E6%98%AF%E4%BB%80%E4%B9%88%E3%80%82%0A%0A!%5B75354077912fb32536285c3d21e10ad5.png%5D(en-resource%3A%2F%2Fdatabase%2F1314%3A1)%0A%0A%60%60%60java%0Aexpression%3D%22execution(*%20com.loongshawn.method.ces..*.*(..))%22%0A%60%60%60%0A!%5B2e319267f2859cc29d92422e7c14bd40.png%5D(en-resource%3A%2F%2Fdatabase%2F1316%3A1)%0A%60%60%60%0A1%EF%BC%89execution(public%20*%20*(..))%3A%20%E8%A1%A8%E7%A4%BA%E5%8C%B9%E9%85%8D%E6%89%80%E6%9C%89public%E6%96%B9%E6%B3%95%0A2%EF%BC%89execution(*%20set*(..))%3A%20%E8%A1%A8%E7%A4%BA%E6%89%80%E6%9C%89%E4%BB%A5%E2%80%9Cset%E2%80%9D%E5%BC%80%E5%A4%B4%E7%9A%84%E6%96%B9%E6%B3%95%0A3%EF%BC%89execution(*%20com.xyz.service.AccountService.*(..))%3A%20%E8%A1%A8%E7%A4%BA%E5%8C%B9%E9%85%8D%E6%89%80%E6%9C%89AccountService%E6%8E%A5%E5%8F%A3%E7%9A%84%E6%96%B9%E6%B3%95%0A4%EF%BC%89execution(*%20com.xyz.service.*.*(..))%3A%20%E8%A1%A8%E7%A4%BA%E5%8C%B9%E9%85%8Dservice%E5%8C%85%E4%B8%8B%E6%89%80%E6%9C%89%E7%9A%84%E6%96%B9%E6%B3%95%0A5%EF%BC%89execution(*%20com.xyz.service..*.*(..))%3A%20%E8%A1%A8%E7%A4%BA%E5%8C%B9%E9%85%8Dservice%E5%8C%85%E5%92%8C%E5%AE%83%E7%9A%84%E5%AD%90%E5%8C%85%E4%B8%8B%E7%9A%84%E6%96%B9%E6%B3%95%0A%60%60%60%0A%0A%23%23%23%23%23%201.5.2%20bean()%E6%8C%87%E7%A4%BA%E5%99%A8%0A%3E%20Spring%E8%BF%98%E5%BC%95%E5%85%A5%E4%BA%86%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84bean()%E6%8C%87%E7%A4%BA%E5%99%A8%EF%BC%8C%E5%AE%83%E5%85%81%E8%AE%B8%E6%88%91%E4%BB%AC%E5%9C%A8%E5%88%87%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%AD%E4%BD%BF%E7%94%A8bean%E7%9A%84ID%E6%9D%A5%E6%A0%87%E8%AF%86bean.%0A%60%60%60java%0Aexecution(*%20concert.Performance.perform())%20and%20bean('woodstock')%0A%60%60%60%0A%3E%20%E5%9C%A8%E6%89%A7%E8%A1%8CPerformance%E7%9A%84perform()%E6%96%B9%E6%B3%95%E6%97%B6%E5%BA%94%E7%94%A8%E9%80%9A%E7%9F%A5%EF%BC%8C%E4%BD%86%E9%99%90%E5%AE%9Abean%E7%9A%84ID%E4%B8%BAwoodstock%0A%0A%0A%23%23%202%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%0A%23%23%203%20%E6%80%BB%E7%BB%93%0A%E4%BD%BF%E7%94%A8JavaConfig%E7%9A%84%E8%AF%9D%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%9C%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%9A%84%E7%B1%BB%E7%BA%A7%E5%88%AB%E4%B8%8A%E9%80%9A%E8%BF%87%E4%BD%BF%E7%94%A8EnableAspectJ-AutoProxy%E6%B3%A8%E8%A7%A3%E5%90%AF%E7%94%A8%E8%87%AA%E5%8A%A8%E4%BB%A3%E7%90%86%E5%8A%9F%E8%83%BD%E3%80%82%0A%E4%BD%BF%E7%94%A8XML%E6%9D%A5%E8%A3%85%E9%85%8Dbean%E7%9A%84%E8%AF%9D%EF%BC%8C%E9%82%A3%E4%B9%88%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8Springaop%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E4%B8%AD%E7%9A%84%3Caop%3Aaspectj-autoproxy%3E%E5%85%83%E7%B4%A0%0A%0A%E4%B8%8D%E7%AE%A1%E4%BD%A0%E6%98%AF%E4%BD%BF%E7%94%A8JavaConfig%E8%BF%98%E6%98%AFXML%EF%BC%8CAspectJ%E8%87%AA%E5%8A%A8%E4%BB%A3%E7%90%86%E9%83%BD%E4%BC%9A%E4%B8%BA%E4%BD%BF%E7%94%A8%40Aspect%E6%B3%A8%E8%A7%A3%E7%9A%84bean%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E4%BB%A3%E7%90%86%EF%BC%8C%E8%BF%99%E4%B8%AA%E4%BB%A3%E7%90%86%E4%BC%9A%E5%9B%B4%E7%BB%95%E7%9D%80%E6%89%80%E6%9C%89%E8%AF%A5%E5%88%87%E9%9D%A2%E7%9A%84%E5%88%87%E7%82%B9%E6%89%80%E5%8C%B9%E9%85%8D%E7%9A%84bean%E3%80%82%0A%0A%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E8%AE%B0%E4%BD%8F%E7%9A%84%E6%98%AF%EF%BC%8CSpring%E7%9A%84AspectJ%E8%87%AA%E5%8A%A8%E4%BB%A3%E7%90%86%E4%BB%85%E4%BB%85%E4%BD%BF%E7%94%A8%40AspectJ%E4%BD%9C%E4%B8%BA%E5%88%9B%E5%BB%BA%E5%88%87%E9%9D%A2%E7%9A%84%E6%8C%87%E5%AF%BC%EF%BC%8C%E5%88%87%E9%9D%A2%E4%BE%9D%E7%84%B6%E6%98%AF%E5%9F%BA%E4%BA%8E%E4%BB%A3%E7%90%86%E7%9A%84%E3%80%82%E5%9C%A8%E6%9C%AC%E8%B4%A8%E4%B8%8A%EF%BC%8C%E5%AE%83%E4%BE%9D%E7%84%B6%E6%98%AFSpring%E5%9F%BA%E4%BA%8E%E4%BB%A3%E7%90%86%E7%9A%84%E5%88%87%E9%9D%A2%E3%80%82%E8%BF%99%E4%B8%80%E7%82%B9%E9%9D%9E%E5%B8%B8%E9%87%8D%E8%A6%81%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%BF%99%E6%84%8F%E5%91%B3%E7%9D%80%E5%B0%BD%E7%AE%A1%E4%BD%BF%E7%94%A8%E7%9A%84%E6%98%AF%40AspectJ%E6%B3%A8%E8%A7%A3%EF%BC%8C%E4%BD%86%E6%88%91%E4%BB%AC%E4%BB%8D%E7%84%B6%E9%99%90%E4%BA%8E%E4%BB%A3%E7%90%86%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%E3%80%82%E5%A6%82%E6%9E%9C%E6%83%B3%E5%88%A9%E7%94%A8AspectJ%E7%9A%84%E6%89%80%E6%9C%89%E8%83%BD%E5%8A%9B%EF%BC%8C%E6%88%91%E4%BB%AC%E5%BF%85%E9%A1%BB%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E4%BD%BF%E7%94%A8AspectJ%E5%B9%B6%E4%B8%94%E4%B8%8D%E4%BE%9D%E8%B5%96Spring%E6%9D%A5%E5%88%9B%E5%BB%BA%E5%9F%BA%E4%BA%8E%E4%BB%A3%E7%90%86%E7%9A%84%E5%88%87%E9%9D%A2%E3%80%82%0A

es

创建时间:2022/4/6 9:34
更新时间:2022/8/14 18:55
作者:Chris
来源:https://www.cnblogs.com/taozi32/p/10238568.html

SpringBoot 检索篇 - 整合Elasticsearch7.6.2

概述

ES 是基于Apache Lucene 构建的开源搜索引擎,Lucene是迄今为止最好的一款搜索引擎工具包,但是Lucene的API相对复杂,很难集成到实际的应用中去。同时ES基于java编写,提供简单易用的RestFul API,开发者可以使用简单的API开发相关搜索功能

全文检索[Full-Text Retrival]

计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的位置和次数,当用户查询时再根据建立的索引查找,类似于通过字典查字的过程。

只处理文本,不处理语义

比如 ‘你今年多大了’如果处理语义就会告诉你实际年龄,
如果不处理语意则会把这句话做为搜索关键字来查询出包含它的结果

特点

比数据库查询效率高
搜索结果存在相关度排序
搜索时关键词不区分大小写,mysql只能统一转大写或者统一转小写

数据存储

ES主要以轻量级的json格式存储数据,同时也支持地理位置查询,也支持地理位置和文本混合查询
在统计,日志数据处理和分析,可视化方面是引领者
wikipedia,stackoverflow,baidu,ali都在使用es做检索
使用比较广泛的平台ELK(ElasticSearch, Logstash, Kibana)

安装

  1. jdk8
  2. centos7

下载 https://www.elastic.co/start
ES默认不能使用root用户启动,创建普通用户es

[root@master home]# groupadd es
[root@master home]# cat /etc/group|grep es
games:x:20:
setroubleshoot:x:987:
pulse-access:x:986:
es:x:1001:
[root@master home]# useradd -m -d /home/es -s /bin/bash -g es es
[root@master home]# passwd es
[root@master home]# id es
uid=1001(es) gid=1001(es) groups=1001(es)
[root@master home]#su es

上传 elasticsearch-7.13.4-linux-x86_64.tar.gz

[root@master opt] wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.13.4-linux-x86_64.tar.gz
[root@master opt]# tar -zxvf elasticsearch-7.13.4-linux-x86_64.tar.gz
[root@master opt]# cd elasticsearch-7.13.4/
[root@master opt]# ll
drwxr-xr-x.  2 root root   4096 Jul 15 02:37 bin
drwxr-xr-x.  3 root root    169 Jul 30 09:52 config
drwxr-xr-x.  9 root root    107 Jul 15 02:37 jdk
drwxr-xr-x.  3 root root   4096 Jul 15 02:37 lib
-rw-r--r--.  1 root root   3860 Jul 15 02:31 LICENSE.txt
drwxr-xr-x.  2 root root      6 Jul 15 02:35 logs
drwxr-xr-x. 59 root root   4096 Jul 15 02:38 modules
-rw-r--r--.  1 root root 594150 Jul 15 02:35 NOTICE.txt
drwxr-xr-x.  2 root root      6 Jul 15 02:35 plugins
-rw-r--r--.  1 root root   2710 Jul 15 02:31 README.asciidoc

bin 可执行脚本目录,启动脚本 elasticsearch
config 存放配置文件目录,核心配置文件 elasticsearch.yml
logs 存放日志目录
plugins 用来扩展ES的插件目录

启动
cd bin/
./elasticsearch 
# 后台启动不会占用窗口
./elasticsearch -d

测试es是否启动成功

curl http://localhost:9200

[root@master ~]# curl http://localhost:9200
{
  "name" : "master",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "OE2K0TcwT9SIRuEHmI95Tg",
  "version" : {
    "number" : "7.13.4",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "c5f60e894ca0c61cdbae4f5a686d9f08bcefc942",
    "build_date" : "2021-07-14T18:33:36.673943207Z",
    "build_snapshot" : false,
    "lucene_version" : "8.8.2",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

修改启动内存大小

es最小内存为512m, 不能再小

[root@master config]# vi jvm.options
-Xms512m
-Xmx512m
重启ES
[es@master bin]$ ps -ef | grep elastic
[es@master bin]$ kill -9 10965
[es@master bin]$ ./elasticsearch
开启es远程链接权限

es默认只允许本地访问,如果需要远程访问则需要开启远程访问链接

  1. 修改es配置文件
[es@master config]$ vi elasticsearch.yml
#network.host: 192.168.0.1 
修改为: 
network.host: 0.0.0.0
  1. 启动es时会出现3个问题
ERROR: [3] bootstrap checks failed. You must address the points described in the following [3] lines before starting Elasticsearch.
bootstrap check failure [1] of [3]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]
bootstrap check failure [2] of [3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
bootstrap check failure [3] of [3]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
解决错误1

切换到root

vi /etc/security/limits.conf
*               soft    nofile           65536
*               hard    nofile           65536
*               soft    nproc            4096
*               hard    nproc            4096

退出重新登录检查配置是否生效
粘贴以下命令

ulimit -Hn
ulimit -Sn
ulimit -Hu
ulimit -Sn

[root@master ~]# ulimit -Hn
65536
[root@master ~]# ulimit -Sn
65536
[root@master ~]# ulimit -Hu
4096
[root@master ~]# ulimit -Sn
65536
解决错误2

切换到root
在文件中加入如下内容

启动es的用户名 soft nproc 4096

[root@master ~]# vi /etc/security/limits.d/20-nproc.conf
es         soft    nproc     4096

解决错误3

切换到root

[root@master ~]# vi /etc/sysctl.conf
vm.max_map_count=655360
[root@master ~]# sysctl -p
vm.max_map_count = 655360
[es@master config]$ cd /config/
[es@master config]$ vi elasticsearch.yml
# 修改被注释的如下信息为
node.name: node-1
cluster.initial_master_nodes: ["node-1"]
关闭firewall
[root@master config]# firewall-cmd --state 
running
[root@master config]# systemctl disable firewalld.service
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@master config]# firewall-cmd --state 
running
[root@master config]# systemctl stop firewalld.service 
[root@master config]# firewall-cmd --state 
not running

重要概念

1. 接近实时 Near Real Time [NRT]

从将文档增加到es中到检索文档中的内容全过程仅需要1s

2. 索引

一个索引是一个拥有相似特征的文档的集合,类似于mysql中的database.
用户索引 ,订单索引,商品索引,分类索引
一个索引由一个名字标识,标识必须全为小写字母,在对索引中的文档进行crud时需要用到这个索引名称.
数据库中的database一般是根据应用来创建,但是索引是一组具有相似特征的文档集合,所以实际中一个应用一个database,但可能对应多个索引。

3. 类型[type]

一个类型是索引的一个逻辑上的分类,其语意由个人来定,类型类似于数据库中的表的概念

注意:
将索引比作一个database,将类型比作一个表其实是一个坏的比喻。
在es5.x之前的版本中一个索引可以创建一个或多个类型。
在es6.x版本兼容之前的版本中一个索引创建的一个或多个类型,便是不能在一个索引下再创建多个类型。
在es7.x之后的版本中一个索引仅可以创建一个类型。

官方文档:
Learn -> Docs
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html

4. 映射[mapping]

类似于关系性数据库中表的schema,用于定义一个索引[index]中类型[type]的数据结构,mapping中包含字段名,字段数据类型和字段索引类型
在默认情况下,es可以根据插入的数据自动地创建type及其mapping。

5. 文档[document]

一个文档是一个可被索引的基础信息单元,类似于关系型数据库中的一条记录。
例如你可以拥有一个员工的文档,也可以拥有某个商品的一个文档
文档采用了轻量级的数据交互格式Json来表示。

kibana

安装

ES的客户端工具
当前使用的ES版本与kibana版本一致
上传到es用户的家目录下

[es@master]tar -zxvf kibana-7.13.4-linux-x86_64.tar.gz
[es@master]/home/es/kibana-7.13.4/config
[es@master config]$ vi kibana.yml
server.host: "192.168.80.180"
elasticsearch.hosts: ["http://192.168.80.180:9200"]

kibana 默认端口号为5601

启动
cd bin/
[es@master bin]$ ./kibana
访问

http://master:5601

基本操作

1 索引
创建
PUT /ems

结果:
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "ems"
}

查看
GET /_cat/health --查看健康状况
GET /_cat/nodes  --查看所有节点
GET /_cat/master --查看主节点 
GET _cat/indices --查看所有索引
GET /_cat/indices/v --显示表头查看所有索引

health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .apm-custom-link                wk57k9ydRfalb-vx5Zon7w   1   0          0            0       208b           208b
green  open   .kibana-event-log-7.13.4-000001 vf4JjMfEQjGqOlnYz0HQww   1   0          1            0      5.6kb          5.6kb
green  open   .apm-agent-configuration        tCHpjuNmSwq2PiwBadMVeg   1   0          0            0       208b           208b
yellow open   ems                             ysfFkjV5RNOPgNQ68CFK1g   1   1          0            0       208b           208b
green  open   .kibana_7.13.4_001              HyDQ5FmdRTiQPWjVkqzPsw   1   0         29            5      2.1mb          2.1mb
yellow open   dangdang                        yzm7GHk9RKSA93RA7HzGoQ   1   1          0            0       208b           208b
green  open   .kibana_task_manager_7.13.4_001 ipMKJ-PaQnWGVYifkpEW-A   1   0         10         1297    243.1kb        243.1kb

health -- 健康状态, GREEN -> YELLOW -> RED
pri --主分片数  
rep --副本分片数  
docs.count --文档数  
docs.deleted --文档是否被删除过  
store.size --存储大小  
pri.store.size -- 主分片存储大小 
GET /dangdang

{
  "dangdang" : {
    "aliases" : { },
    "mappings" : { },
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "1",
        "provided_name" : "dangdang",
        "creation_date" : "1627636773007",
        "number_of_replicas" : "1",
        "uuid" : "yzm7GHk9RKSA93RA7HzGoQ",
        "version" : {
          "created" : "7130499"
        }
      }
    }
  }
}
删除
DELETE /dangdang --删除单个索引
DELETE /*    -- 删除所有索引
2 索引和映射
mapping type 数据类型

text, keyword, data, integer, long, double, boolean, ip

创建
PUT /dangdang_2
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "name":{
        "type": "keyword"
      },
      "age":{
        "type": "integer"
      },
      "bir":{
        "type": "date"
      }
    }
  }
}

结果:
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "dangdang_2"
}
查看
GET /dangdang2/_mapping
3 文档
创建时指定 _id

以下命令会自动创建一个索引为tianmao类型为order的文档_id=1

PUT /tianmao/order/1 或者 PUT /tianmao/_doc/1
{
  "id":"21",
  "name":"chris",
  "prvice":23.13,
  "amount":23
}
创建时不指定 _id
POST /tianmao/order 或者 POST /tianmoa/_doc
{
  "id":"12",
  "name":"海苔",
  "prvice":3.13,
  "amount":24
}

-- 会自动生成_id
{
  "_index" : "tianmao",
  "_type" : "order",
  "_id" : "F5I6-noB9Y4OLXrN27h2",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}
查询
GET /tianmao/order/1
或者 GET/tianmao/_doc/1

{
  "_index" : "tianmao",
  "_type" : "order",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "id" : "21",
    "name" : "chris",
    "prvice" : 23.13,
    "amount" : 23
  }
}
更新

新增索引映射

PUT /dangdang/
{
  "mappings": {
    "properties": {
      "name":{"type": "keyword"},
      "content":{"type": "text"},
      "price":{"type": "float"},
      "update":{"type": "date"}
    }
  }
}

GET /dangdang/_mapping

PUT /dangdang/_doc/1
{
  "name": "一只小白羊的故事",
  "content":"我是一只小白羊,每天吃草都很忙",
  "price":23.4,
  "date":"2018-02-23"
}

GET /dangdang/_doc/1
  1. 覆盖式更新

更新之后只剩下name字段, 相当于把原来的文档删除后再添加

POST /dangdang/_doc/1
{
  "name":"小白羊多利的故事"
}

GET /dangdang/_doc/1
{
  "_index" : "dangdang",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "小白羊多利的故事"
  }
}
  1. 更新原始文档的指定字段
POST /dangdang/_doc/1/_update
{
  "doc":{
    "name":"小白羊多利的故事"
  }
}
  1. 更新原始文档的指定字段时添加新的字段
POST /dangdang/_doc/1/_update
{
  "doc":{
    "name":"小白羊多利的故事",
    "category":"少儿故事类"
  }
}

GET /dangdang/_doc/1

{
  "_index" : "dangdang",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 5,
  "_seq_no" : 5,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "小白羊多利的故事",
    "content" : "我是一只小白羊,每天吃草都很忙",
    "price" : 23.4,
    "date" : "2018-02-23",
    "category" : "少儿故事类"
  }
}

GET /dangdang/_mapping

{
  "dangdang" : {
    "mappings" : {
      "properties" : {
        "category" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "content" : {
          "type" : "text"
        },
        "date" : {
          "type" : "date"
        },
        "name" : {
          "type" : "keyword"
        },
        "price" : {
          "type" : "float"
        },
        "update" : {
          "type" : "date"
        }
      }
    }
  }
}

  1. 通过脚本对更新指定字段

更新price字段,在原来基础上增加1.3

POST /dangdang/_doc/1/_update
{
  "script":"ctx._source.price+=1.3"
}
删除
DELETE /dangdang/_doc/1
4 文档批量操作

https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html

批量更新不会因为其中一条的失败而所有失败
{ "index" : {}} 如是不指定_id则会自动生成_id

POST /dangdang/_doc/_bulk
{ "index" : {"_id" : "11" } }
{ "id" : "11", "name":"c++ dev principles", "price":52.3, "amount":"32"}
{ "index" : {"_id" : "12" } }
{ "id" : "12", "name":"java dev principles", "price":392.3, "amount":"23"}
{ "index" : {}}
{ "id" : "13", "name":"python dev principles", "price":33.3, "amount":"45"}
{ "create" : {"_id" : "14" } }
{ "id" : "14", "name":"devops 实战指南", "price":110.4, "amount":"43"}
{ "delete" : {"_id" : "1" } }
{ "update" : {"_id" : "2" } }
{"doc":{"name":"一只小黑羊的故事-2"}}

ES中的检索方式

es提供了两种数据的检索方式

  1. 使用url参数方式即query string进行检索
  2. 使用DSL[domain specified language]方式即request body进行检索

准备数据

PUT /ems/
{
  "mappings": {
    "properties": {
      "name":{"type": "keyword"},
      "age":{"type": "integer"},
      "bir":{"type": "date"},
      "content":{"type": "text"},
      "address":{"type": "keyword"}
    }
  }
}

GET /ems/_mapping

POST /ems/_doc/_bulk
{ "index" :{}}
{ "name":"chris", "age":23, "bir":"2016-12-21", "content":"A search query, or query, is a request for information about data in Elasticsearch data streams or indices.", "address":"China"}
{ "index" : {} }
{ "name":"john", "age":33, "bir":"2018-09-12", "content":"What processes on my server take longer than 500 milliseconds to respond?", "address":"US"}
{ "index" : {}}
{ "name":"petter", "age":13, "bir":"2001-11-09", "content":"A search consists of one or more queries that are combined and sent to Elasticsearch. Documents that match a search’s queries are returned in the hits, or search results, of the response.", "address":"Franch"}
{ "create" : {} }
{ "name":"Ethen",  "age":43, "bir":"2019-09-01", "content":"You can use the search API to search and aggregate data stored in Elasticsearch data streams or indices. The API’s query request body parameter accepts queries written in Query DSL.", "address":"China"}

1 使用url参数方式即query string进行检索

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html

  1. 查询所有

GET /ems/_doc/_search?q=*

  1. 查询并排序

GET /ems/_doc/_search?q=*&sort=age:desc&size=2

  1. 查询并排序且指定返回结果个数

GET /ems/_doc/_search?q=*&sort=age:desc&size=2

2 使用DSL方式即requestbody进行检索
2.1. 查询所有,按指定字段排序并返回指定结果数
GET ems/_doc/_search
{
  "query":{
    "match_all":{}
  },
  "sort":[{
    "age":{
      "order":"desc"
    }
  }],
  "size":2
}
2.2. 查询结果中返回指定字段(_source)
GET ems/_doc/_search
{
  "query":{
    "match_all":{}
  },
  "_source":["name", "content"],
  "sort":[{
    "age":{
      "order":"desc"
    }
  }],
  "size":2
}
2.3. 精准查询(term)

term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇,不会参与ES分词查询

GET ems/_doc/_search
{
  "query":{
    "term":{
      "content":{
        "value":"consists"
      }
    }
  }
}
2.4. terms 查询是term的扩展

可以支持多个vlaue匹配,只需要一个匹配就可以了

GET ems/_doc/_search
{
  "query":{
    "terms":{
      "content":["consists","query"]
    }
  }
}
2.5. 范围查询(range)

检索年龄大于等13且小于等于33的相关文档

POST /ems/_doc/_search 
{
  "query":{
    "range":{
      "age":{
        "gte":13,
        "lte": 33
      }
    }
  },
  "sort":[{
    "age":{
      "order":"asc"
    }
  }]
}
2.6. 前缀查询(prefix)

检索含有指定前缀的关键字相关文档
使用大写字母不会检索到文档,因为ES在对每一个词建立索引时会将词统一转成小写

POST /ems/_doc/_search 
{
  "query":{
    "prefix":{
      "content":{
        "value":"or"
      }
    }
  },
  "sort":[{
    "age":{
      "order":"asc"
    }
  }]
}
2.7. 通配符查询(wildcard)

? 表未任意一个字符
* 表示零个或多个字符

POST /ems/_doc/_search 
{
  "query":{
    "wildcard":{
      "content":{
        "value":"*ill*"
      }
    }
  },
  "_source":["name", "content"],
  "sort":[{
    "age":{
      "order":"asc"
    }
  }]
}
2.8. 多id查询(ids)

值为数组类型,用来获得一组id对应的多个文档

POST /ems/_doc/_search 
{
  "query":{
    "ids":{
      "values":["sPWeBHsBjA6v-uGtRIg5", "sfWeBHsBjA6v-uGtRIg5"]
    }
  },
  "_source":["name", "content"],
  "sort":[{
    "age":{
      "order":"asc"
    }
  }]
}
2.9. 模糊查询(fuzzy)

用来模糊查询含有指定关键字的文档
注意:最大编辑距离为0 1 2
如果关键词的长度为2,则不允许有错误,必须完全配置
如果关键词的长度为3到5,则允许有一个错误
如果关键词的长度为大于5,则最多允许有两个错误

-- 可以查询到name 为Ethan的文档

POST /ems/_doc/_search 
{
  "query":{
    "fuzzy":{
      "name":"Ethxxn"
    }
  }
}

-- 查询不到name 为Ethan的文档,因为不配置尾

POST /ems/_doc/_search 
{
  "query":{
    "fuzzy":{
      "name":"Ethxx"
    }
  }
}
2.8. 布尔查询(bool)

用于组合多条件实现复杂查询
must 相当于 &&
should 相当于 ||
must_not 相当于!

查询elasticsearch关键字同时id不是"sfWeBHsBjA6v-uGtRIg5", "rvWeBHsBjA6v-uGtRIg5"的文档

POST /ems/_doc/_search 
{
  "query":{
    "bool":{
      "must":[
        {
          "term":{
            "content":{
              "value":"elasticsearch"
            }
          }
        }],
      "must_not":[{
        "ids":{
          "values":["sfWeBHsBjA6v-uGtRIg5", "rvWeBHsBjA6v-uGtRIg5"]
        }
      }]
    }
  }
}
2.9. 多字段查询(multi_match)

在查询过程中会先将查询条件根据当前分词器分词后再进行查询
ES会跟据mapping type中的类型来判断是否需要分词处理,只有text类型会分词处理,其它类型均不分词。
不需要分词的字段会将查询条件进行全匹配
需要分词的字段是将查询条件分词后再逐个匹配

GET /ems/_doc/_search
{
  "query":{
    "multi_match":{
      "query":"query request",
      "fields":["name","content"]
    }
  }
}
2.10. 多字段分词查询(query_string)

在查询过程中会先将查询条件根据当前分词器分词后再进行查询
与multi_match相比,最大的好处就是在查询中可以指定分词器

GET /ems/_doc/_search
{
  "query": {
    "query_string": {
      "query": "query request",
      "fields": ["name","content"],
      "analyzer":"standard"
    }
  }
}

GET _analyze
{
  "analyzer": "standard",  -- simple
  "text": ["query request"]
}
2.11. 高亮显示

原理: 将原始的检索结果与检索关键词的分词作匹配,如果能对应上则对在该词的前后默认加上<em>

多字段查询并对content字段中的查询分词高亮显示

GET /ems/_doc/_search
{
  "query":{
    "multi_match":{
      "query":"query request",
      "fields":["name","content"]
    }
  },
  "highlight":{
    "fields":{"content":{}}
  }
}

自定义高亮显示标签

GET /ems/_doc/_search
{
  "query":{
    "multi_match":{
      "query":"query request",
      "fields":["name","content"]
    }
  },
  "highlight":{
    "fields":{"content":{}},
    "pre_tags":"<span style='color:red'>",
    "post_tags":"<span>"
  }
}

对所有查询字段高亮显示标签
require_field_match:false

GET /ems/_doc/_search
{
  "query":{
    "multi_match":{
      "query":"query",
      "fields":["content"]
    }
  },
  "highlight":{
    "fields":{"*":{}},
    "pre_tags":"<span style='color:red'>",
    "post_tags":"<span>",
    "require_field_match":false
  }
}

{
    "_index" : "ems",
    "_type" : "_doc",
    "_id" : "svXPBXsBjA6v-uGtDIi2",
    "_score" : 0.89701396,
    "_source" : {
      "name" : "query",
      "age" : 39,
      "bir" : "2008-12-21",
      "content" : "it's operation for query the result your wannt",
      "address" : "Australia"
    },
    "highlight" : {
      "name" : [
        "<span style='color:red'>query<span>"
      ],
      "content" : [
        "it's operation for <span style='color:red'>query<span> the result your wannt"
      ]
}

索引库原理

创建索引
1.通过扫描数据,按索引中的mapping定义判断是否需要分词
2.对每一个字段中的分词结果在索引区创建索引,索引中包含该词在文章中出现的位置和次数
3.元数据区存储了以_id打头文档的原始数据

检索索引
1.根据关键词定位索引
2.根据索引定位文档

分词器

1 定义:

就是将一个文本里面的关键词拆分出来
例如:我是中国人
拆分出: 中国|中国人
去掉停用词和语气词

2 ES提供的分词器:
  1. 默认标准分词器:standard

对英文进行单词分词,对中文进行单字分词。

GET _analyze
{
  "analyzer": "standard",
  "text":"redis 非常好用 111"
}

{
  "tokens" : [
    {
      "token" : "redis",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "非",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "常",
      "start_offset" : 7,
      "end_offset" : 8,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "好",
      "start_offset" : 8,
      "end_offset" : 9,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "用",
      "start_offset" : 9,
      "end_offset" : 10,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    },
    {
      "token" : "111",
      "start_offset" : 11,
      "end_offset" : 14,
      "type" : "<NUM>",
      "position" : 5
    }
  ]
}
  1. 简单分词器simple

英文单词分词去掉数字,中文不分词

GET _analyze
{
  "analyzer": "simple",
  "text":"redis 非常好用 111"
}

{
  "tokens" : [
    {
      "token" : "redis",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "非常好用",
      "start_offset" : 6,
      "end_offset" : 10,
      "type" : "word",
      "position" : 1
    }
  ]
}
3 ik分词器

https://github.com/medcl/elasticsearch-analysis-ik

要求使用的ik分词器的版本必须与ES版本严格一致

  1. 在线安装

会把plugin安装在elasticsearch-7.13.4/plugins目录下

cd /home/es/elasticsearch-7.13.4/bin
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.0/elasticsearch-analysis-ik-7.13.4.zip
  1. 本地安装

下载zip包: https://github.com/medcl/elasticsearch-analysis-ik/releases

[es@master ~]$ unzip  elasticsearch-analysis-ik-7.13.4.zip  -d ./elasticsearch-ik
[es@master ~]$ mv elasticsearch-ik/ elasticsearch-7.13.4/plugins/

重启ES

[es@master bin]$ ps -ef | grep elastic
[es@master bin]$ kill -9 10965
[es@master bin]$ ./elasticsearch

  1. ik_max_word 和 ik_smart 什么区别?

ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query;

ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询。

  1. 使用

"content":{"type": "text", "analyzer": "ik_max_word"},

PUT /ems/
{
  "mappings": {
    "properties": {
      "name":{"type": "keyword"},
      "age":{"type": "integer"},
      "bir":{"type": "date"},
      "content":{"type": "text", "analyzer": "ik_max_word"},
      "address":{"type": "keyword"}
    }
  }
}

GET /ems/_mapping

POST /ems/_doc/_bulk
{ "index" :{}}
{ "name":"chris", "age":23, "bir":"2016-12-21", "content":"美国留给伊拉克的是个烂摊子吗.", "address":"China"}
{ "index" : {} }
{ "name":"john", "age":33, "bir":"2018-09-12", "content":"公安部:各地校车将享最高路权", "address":"US"}
{ "index" : {}}
{ "name":"petter", "age":13, "bir":"2001-11-09", "content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船", "address":"Franch"}
{ "create" : {} }
{ "name":"Ethen",  "age":43, "bir":"2019-09-01", "content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首", "address":"China"}


POST /ems/_doc/_search 
{
  "query":{
    "term":{
      "content":{
        "value":"中国"
      }
    }
  }
}
4 ik扩展词和停用词
4.1. 扩展词
  1. 修改IKAnalyzer.cfg.xml
[es@master config]$ vi IKAnalyzer.cfg.xml
-- 修改为:
<entry key="ext_dict">ext.dic</entry>
  1. 创建ext.dict文件
[es@master config]$ cp extra_main.dic ext.dict
vi ext.dict
碰瓷
李毛毛
  1. 重启es
4.2. 停用词
  1. 修改IKAnalyzer.cfg.xml
[es@master config]$ vi IKAnalyzer.cfg.xml
-- 修改为:
<entry key="ext_stopwords">stopext.dic</entry>
  1. 创建ext.dict文件
[es@master config]$ cp ext.dic stopext.dict
vi ext.dict
遇到
  1. 重启es
4.3. 启用远程扩展词和停用词

注意:

  1. 更新远程词库的热词后不会对已生成的索引的文档数据产生影响, 只能对后续新加入的文档数据生效
  2. 所以更新远程词库后需要把原来的文档数据重新录入
%5Btoc%5D%0A%0A%5BSpringBoot%20%E6%A3%80%E7%B4%A2%E7%AF%87%20-%20%E6%95%B4%E5%90%88Elasticsearch7.6.2%5D(https%3A%2F%2Fblog.csdn.net%2Fweixin_41105242%2Farticle%2Fdetails%2F107711634)%0A%0A%23%23%23%23%20%E6%A6%82%E8%BF%B0%0AES%20%E6%98%AF%E5%9F%BA%E4%BA%8EApache%20Lucene%20%E6%9E%84%E5%BB%BA%E7%9A%84%E5%BC%80%E6%BA%90%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%EF%BC%8CLucene%E6%98%AF%E8%BF%84%E4%BB%8A%E4%B8%BA%E6%AD%A2%E6%9C%80%E5%A5%BD%E7%9A%84%E4%B8%80%E6%AC%BE%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E5%B7%A5%E5%85%B7%E5%8C%85%EF%BC%8C%E4%BD%86%E6%98%AFLucene%E7%9A%84API%E7%9B%B8%E5%AF%B9%E5%A4%8D%E6%9D%82%EF%BC%8C%E5%BE%88%E9%9A%BE%E9%9B%86%E6%88%90%E5%88%B0%E5%AE%9E%E9%99%85%E7%9A%84%E5%BA%94%E7%94%A8%E4%B8%AD%E5%8E%BB%E3%80%82%E5%90%8C%E6%97%B6ES%E5%9F%BA%E4%BA%8Ejava%E7%BC%96%E5%86%99%EF%BC%8C%E6%8F%90%E4%BE%9B%E7%AE%80%E5%8D%95%E6%98%93%E7%94%A8%E7%9A%84RestFul%20API%EF%BC%8C%E5%BC%80%E5%8F%91%E8%80%85%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E7%AE%80%E5%8D%95%E7%9A%84API%E5%BC%80%E5%8F%91%E7%9B%B8%E5%85%B3%E6%90%9C%E7%B4%A2%E5%8A%9F%E8%83%BD%0A%0A%23%23%23%23%20%E5%85%A8%E6%96%87%E6%A3%80%E7%B4%A2%5BFull-Text%20Retrival%5D%20%20%0A%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A8%8B%E5%BA%8F%E9%80%9A%E8%BF%87%E6%89%AB%E6%8F%8F%E6%96%87%E7%AB%A0%E4%B8%AD%E7%9A%84%E6%AF%8F%E4%B8%80%E4%B8%AA%E8%AF%8D%EF%BC%8C%E5%AF%B9%E6%AF%8F%E4%B8%80%E4%B8%AA%E8%AF%8D%E5%BB%BA%E7%AB%8B%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%EF%BC%8C%E6%8C%87%E6%98%8E%E8%AF%A5%E8%AF%8D%E5%9C%A8%E6%96%87%E7%AB%A0%E4%B8%AD%E5%87%BA%E7%8E%B0%E7%9A%84%E4%BD%8D%E7%BD%AE%E5%92%8C%E6%AC%A1%E6%95%B0%EF%BC%8C%E5%BD%93%E7%94%A8%E6%88%B7%E6%9F%A5%E8%AF%A2%E6%97%B6%E5%86%8D%E6%A0%B9%E6%8D%AE%E5%BB%BA%E7%AB%8B%E7%9A%84%E7%B4%A2%E5%BC%95%E6%9F%A5%E6%89%BE%EF%BC%8C%E7%B1%BB%E4%BC%BC%E4%BA%8E%E9%80%9A%E8%BF%87%E5%AD%97%E5%85%B8%E6%9F%A5%E5%AD%97%E7%9A%84%E8%BF%87%E7%A8%8B%E3%80%82%0A!%5Bec8ee37e2c9fec701f936321d60f5a2b.png%5D(en-resource%3A%2F%2Fdatabase%2F583%3A1)%0A%0A%0A%E5%8F%AA%E5%A4%84%E7%90%86%E6%96%87%E6%9C%AC%EF%BC%8C%E4%B8%8D%E5%A4%84%E7%90%86%E8%AF%AD%E4%B9%89%0A%3E%20%E6%AF%94%E5%A6%82%20%E2%80%98%E4%BD%A0%E4%BB%8A%E5%B9%B4%E5%A4%9A%E5%A4%A7%E4%BA%86%E2%80%99%E5%A6%82%E6%9E%9C%E5%A4%84%E7%90%86%E8%AF%AD%E4%B9%89%E5%B0%B1%E4%BC%9A%E5%91%8A%E8%AF%89%E4%BD%A0%E5%AE%9E%E9%99%85%E5%B9%B4%E9%BE%84%EF%BC%8C%0A%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%A4%84%E7%90%86%E8%AF%AD%E6%84%8F%E5%88%99%E4%BC%9A%E6%8A%8A%E8%BF%99%E5%8F%A5%E8%AF%9D%E5%81%9A%E4%B8%BA%E6%90%9C%E7%B4%A2%E5%85%B3%E9%94%AE%E5%AD%97%E6%9D%A5%E6%9F%A5%E8%AF%A2%E5%87%BA%E5%8C%85%E5%90%AB%E5%AE%83%E7%9A%84%E7%BB%93%E6%9E%9C%0A%0A%23%23%23%23%20%E7%89%B9%E7%82%B9%0A%3E%20%E6%AF%94%E6%95%B0%E6%8D%AE%E5%BA%93%E6%9F%A5%E8%AF%A2%E6%95%88%E7%8E%87%E9%AB%98%20%20%0A%3E%20%E6%90%9C%E7%B4%A2%E7%BB%93%E6%9E%9C%E5%AD%98%E5%9C%A8%E7%9B%B8%E5%85%B3%E5%BA%A6%E6%8E%92%E5%BA%8F%20%20%0A%3E%20%E6%90%9C%E7%B4%A2%E6%97%B6%E5%85%B3%E9%94%AE%E8%AF%8D%E4%B8%8D%E5%8C%BA%E5%88%86%E5%A4%A7%E5%B0%8F%E5%86%99%EF%BC%8Cmysql%E5%8F%AA%E8%83%BD%E7%BB%9F%E4%B8%80%E8%BD%AC%E5%A4%A7%E5%86%99%E6%88%96%E8%80%85%E7%BB%9F%E4%B8%80%E8%BD%AC%E5%B0%8F%E5%86%99%0A%0A%0A%23%23%23%23%20%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8%0A%3E%20ES%E4%B8%BB%E8%A6%81%E4%BB%A5%E8%BD%BB%E9%87%8F%E7%BA%A7%E7%9A%84json%E6%A0%BC%E5%BC%8F%E5%AD%98%E5%82%A8%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%90%8C%E6%97%B6%E4%B9%9F%E6%94%AF%E6%8C%81%E5%9C%B0%E7%90%86%E4%BD%8D%E7%BD%AE%E6%9F%A5%E8%AF%A2%EF%BC%8C%E4%B9%9F%E6%94%AF%E6%8C%81%E5%9C%B0%E7%90%86%E4%BD%8D%E7%BD%AE%E5%92%8C%E6%96%87%E6%9C%AC%E6%B7%B7%E5%90%88%E6%9F%A5%E8%AF%A2%20%20%20%0A%3E%20%E5%9C%A8%E7%BB%9F%E8%AE%A1%EF%BC%8C%E6%97%A5%E5%BF%97%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86%E5%92%8C%E5%88%86%E6%9E%90%EF%BC%8C%E5%8F%AF%E8%A7%86%E5%8C%96%E6%96%B9%E9%9D%A2%E6%98%AF%E5%BC%95%E9%A2%86%E8%80%85%20%20%0A%3E%20wikipedia%2Cstackoverflow%2Cbaidu%2Cali%E9%83%BD%E5%9C%A8%E4%BD%BF%E7%94%A8es%E5%81%9A%E6%A3%80%E7%B4%A2%20%20%20%20%0A%3E%20%E4%BD%BF%E7%94%A8%E6%AF%94%E8%BE%83%E5%B9%BF%E6%B3%9B%E7%9A%84%E5%B9%B3%E5%8F%B0ELK(ElasticSearch%2C%20Logstash%2C%20Kibana)%0A%0A%23%23%23%23%20%E5%AE%89%E8%A3%85%0A1.%20jdk8%0A2.%20centos7%0A%0A%3E%20%E4%B8%8B%E8%BD%BD%20https%3A%2F%2Fwww.elastic.co%2Fstart%20%20%0A%3E%20ES%E9%BB%98%E8%AE%A4%E4%B8%8D%E8%83%BD%E4%BD%BF%E7%94%A8root%E7%94%A8%E6%88%B7%E5%90%AF%E5%8A%A8%2C%E5%88%9B%E5%BB%BA%E6%99%AE%E9%80%9A%E7%94%A8%E6%88%B7es%0A%0A%60%60%60%0A%5Broot%40master%20home%5D%23%20groupadd%20es%0A%5Broot%40master%20home%5D%23%20cat%20%2Fetc%2Fgroup%7Cgrep%20es%0Agames%3Ax%3A20%3A%0Asetroubleshoot%3Ax%3A987%3A%0Apulse-access%3Ax%3A986%3A%0Aes%3Ax%3A1001%3A%0A%5Broot%40master%20home%5D%23%20useradd%20-m%20-d%20%2Fhome%2Fes%20-s%20%2Fbin%2Fbash%20-g%20es%20es%0A%5Broot%40master%20home%5D%23%20passwd%20es%0A%5Broot%40master%20home%5D%23%20id%20es%0Auid%3D1001(es)%20gid%3D1001(es)%20groups%3D1001(es)%0A%5Broot%40master%20home%5D%23su%20es%0A%60%60%60%0A%0A%E4%B8%8A%E4%BC%A0%20elasticsearch-7.13.4-linux-x86_64.tar.gz%0A%0A%0A%60%60%60%0A%5Broot%40master%20opt%5D%20wget%20https%3A%2F%2Fartifacts.elastic.co%2Fdownloads%2Felasticsearch%2Felasticsearch-7.13.4-linux-x86_64.tar.gz%0A%5Broot%40master%20opt%5D%23%20tar%20-zxvf%20elasticsearch-7.13.4-linux-x86_64.tar.gz%0A%5Broot%40master%20opt%5D%23%20cd%20elasticsearch-7.13.4%2F%0A%5Broot%40master%20opt%5D%23%20ll%0Adrwxr-xr-x.%20%202%20root%20root%20%20%204096%20Jul%2015%2002%3A37%20bin%0Adrwxr-xr-x.%20%203%20root%20root%20%20%20%20169%20Jul%2030%2009%3A52%20config%0Adrwxr-xr-x.%20%209%20root%20root%20%20%20%20107%20Jul%2015%2002%3A37%20jdk%0Adrwxr-xr-x.%20%203%20root%20root%20%20%204096%20Jul%2015%2002%3A37%20lib%0A-rw-r--r--.%20%201%20root%20root%20%20%203860%20Jul%2015%2002%3A31%20LICENSE.txt%0Adrwxr-xr-x.%20%202%20root%20root%20%20%20%20%20%206%20Jul%2015%2002%3A35%20logs%0Adrwxr-xr-x.%2059%20root%20root%20%20%204096%20Jul%2015%2002%3A38%20modules%0A-rw-r--r--.%20%201%20root%20root%20594150%20Jul%2015%2002%3A35%20NOTICE.txt%0Adrwxr-xr-x.%20%202%20root%20root%20%20%20%20%20%206%20Jul%2015%2002%3A35%20plugins%0A-rw-r--r--.%20%201%20root%20root%20%20%202710%20Jul%2015%2002%3A31%20README.asciidoc%0A%60%60%60%0A%3E%20bin%20%20%20%E5%8F%AF%E6%89%A7%E8%A1%8C%E8%84%9A%E6%9C%AC%E7%9B%AE%E5%BD%95%EF%BC%8C%E5%90%AF%E5%8A%A8%E8%84%9A%E6%9C%AC%20elasticsearch%20%20%0Aconfig%20%20%E5%AD%98%E6%94%BE%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%EF%BC%8C%E6%A0%B8%E5%BF%83%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%20elasticsearch.yml%20%20%0Alogs%20%20%20%20%E5%AD%98%E6%94%BE%E6%97%A5%E5%BF%97%E7%9B%AE%E5%BD%95%20%20%0Aplugins%20%E7%94%A8%E6%9D%A5%E6%89%A9%E5%B1%95ES%E7%9A%84%E6%8F%92%E4%BB%B6%E7%9B%AE%E5%BD%95%20%20%0A%0A%23%23%23%23%23%20%E5%90%AF%E5%8A%A8%0A%0A%60%60%60%0Acd%20bin%2F%0A.%2Felasticsearch%20%0A%23%20%E5%90%8E%E5%8F%B0%E5%90%AF%E5%8A%A8%E4%B8%8D%E4%BC%9A%E5%8D%A0%E7%94%A8%E7%AA%97%E5%8F%A3%0A.%2Felasticsearch%20-d%0A%60%60%60%0A!%5Ba1ac283b06d64432ad9aa705fa9db2b3.png%5D(en-resource%3A%2F%2Fdatabase%2F587%3A1)%0A%0A%0A%E6%B5%8B%E8%AF%95es%E6%98%AF%E5%90%A6%E5%90%AF%E5%8A%A8%E6%88%90%E5%8A%9F%0A%3E%20curl%20http%3A%2F%2Flocalhost%3A9200%20%20%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20curl%20http%3A%2F%2Flocalhost%3A9200%0A%7B%0A%20%20%22name%22%20%3A%20%22master%22%2C%0A%20%20%22cluster_name%22%20%3A%20%22elasticsearch%22%2C%0A%20%20%22cluster_uuid%22%20%3A%20%22OE2K0TcwT9SIRuEHmI95Tg%22%2C%0A%20%20%22version%22%20%3A%20%7B%0A%20%20%20%20%22number%22%20%3A%20%227.13.4%22%2C%0A%20%20%20%20%22build_flavor%22%20%3A%20%22default%22%2C%0A%20%20%20%20%22build_type%22%20%3A%20%22tar%22%2C%0A%20%20%20%20%22build_hash%22%20%3A%20%22c5f60e894ca0c61cdbae4f5a686d9f08bcefc942%22%2C%0A%20%20%20%20%22build_date%22%20%3A%20%222021-07-14T18%3A33%3A36.673943207Z%22%2C%0A%20%20%20%20%22build_snapshot%22%20%3A%20false%2C%0A%20%20%20%20%22lucene_version%22%20%3A%20%228.8.2%22%2C%0A%20%20%20%20%22minimum_wire_compatibility_version%22%20%3A%20%226.8.0%22%2C%0A%20%20%20%20%22minimum_index_compatibility_version%22%20%3A%20%226.0.0-beta1%22%0A%20%20%7D%2C%0A%20%20%22tagline%22%20%3A%20%22You%20Know%2C%20for%20Search%22%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%23%20%E4%BF%AE%E6%94%B9%E5%90%AF%E5%8A%A8%E5%86%85%E5%AD%98%E5%A4%A7%E5%B0%8F%0A%3E%20es%E6%9C%80%E5%B0%8F%E5%86%85%E5%AD%98%E4%B8%BA512m%2C%20%E4%B8%8D%E8%83%BD%E5%86%8D%E5%B0%8F%0A%0A%60%60%60%0A%5Broot%40master%20config%5D%23%20vi%20jvm.options%0A-Xms512m%0A-Xmx512m%0A%60%60%60%0A%0A%23%23%23%23%23%20%E9%87%8D%E5%90%AFES%0A%60%60%60%0A%5Bes%40master%20bin%5D%24%20ps%20-ef%20%7C%20grep%20elastic%0A%5Bes%40master%20bin%5D%24%20kill%20-9%2010965%0A%5Bes%40master%20bin%5D%24%20.%2Felasticsearch%0A%60%60%60%0A%0A%23%23%23%23%23%20%E5%BC%80%E5%90%AFes%E8%BF%9C%E7%A8%8B%E9%93%BE%E6%8E%A5%E6%9D%83%E9%99%90%0A%3E%20es%E9%BB%98%E8%AE%A4%E5%8F%AA%E5%85%81%E8%AE%B8%E6%9C%AC%E5%9C%B0%E8%AE%BF%E9%97%AE%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E8%BF%9C%E7%A8%8B%E8%AE%BF%E9%97%AE%E5%88%99%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AF%E8%BF%9C%E7%A8%8B%E8%AE%BF%E9%97%AE%E9%93%BE%E6%8E%A5%0A1.%20%E4%BF%AE%E6%94%B9es%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%20%0A%0A%60%60%60%0A%5Bes%40master%20config%5D%24%20vi%20elasticsearch.yml%0A%23network.host%3A%20192.168.0.1%20%0A%E4%BF%AE%E6%94%B9%E4%B8%BA%3A%20%0Anetwork.host%3A%200.0.0.0%0A%60%60%60%0A2.%20%E5%90%AF%E5%8A%A8es%E6%97%B6%E4%BC%9A%E5%87%BA%E7%8E%B03%E4%B8%AA%E9%97%AE%E9%A2%98%0A%60%60%60%0AERROR%3A%20%5B3%5D%20bootstrap%20checks%20failed.%20You%20must%20address%20the%20points%20described%20in%20the%20following%20%5B3%5D%20lines%20before%20starting%20Elasticsearch.%0Abootstrap%20check%20failure%20%5B1%5D%20of%20%5B3%5D%3A%20max%20file%20descriptors%20%5B4096%5D%20for%20elasticsearch%20process%20is%20too%20low%2C%20increase%20to%20at%20least%20%5B65535%5D%0Abootstrap%20check%20failure%20%5B2%5D%20of%20%5B3%5D%3A%20max%20virtual%20memory%20areas%20vm.max_map_count%20%5B65530%5D%20is%20too%20low%2C%20increase%20to%20at%20least%20%5B262144%5D%0Abootstrap%20check%20failure%20%5B3%5D%20of%20%5B3%5D%3A%20the%20default%20discovery%20settings%20are%20unsuitable%20for%20production%20use%3B%20at%20least%20one%20of%20%5Bdiscovery.seed_hosts%2C%20discovery.seed_providers%2C%20cluster.initial_master_nodes%5D%20must%20be%20configured%0A%60%60%60%0A%23%23%23%23%23%23%20%E8%A7%A3%E5%86%B3%E9%94%99%E8%AF%AF1%0A%E5%88%87%E6%8D%A2%E5%88%B0root%0A%0A%60%60%60%0Avi%20%2Fetc%2Fsecurity%2Flimits.conf%0A*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20soft%20%20%20%20nofile%20%20%20%20%20%20%20%20%20%20%2065536%0A*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hard%20%20%20%20nofile%20%20%20%20%20%20%20%20%20%20%2065536%0A*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20soft%20%20%20%20nproc%20%20%20%20%20%20%20%20%20%20%20%204096%0A*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hard%20%20%20%20nproc%20%20%20%20%20%20%20%20%20%20%20%204096%0A%60%60%60%0A%3E%20%E9%80%80%E5%87%BA%E9%87%8D%E6%96%B0%E7%99%BB%E5%BD%95%E6%A3%80%E6%9F%A5%E9%85%8D%E7%BD%AE%E6%98%AF%E5%90%A6%E7%94%9F%E6%95%88%0A%3E%20%E7%B2%98%E8%B4%B4%E4%BB%A5%E4%B8%8B%E5%91%BD%E4%BB%A4%0A%60%60%60%0Aulimit%20-Hn%0Aulimit%20-Sn%0Aulimit%20-Hu%0Aulimit%20-Sn%0A%0A%5Broot%40master%20~%5D%23%20ulimit%20-Hn%0A65536%0A%5Broot%40master%20~%5D%23%20ulimit%20-Sn%0A65536%0A%5Broot%40master%20~%5D%23%20ulimit%20-Hu%0A4096%0A%5Broot%40master%20~%5D%23%20ulimit%20-Sn%0A65536%0A%60%60%60%0A%23%23%23%23%23%23%20%E8%A7%A3%E5%86%B3%E9%94%99%E8%AF%AF2%0A%E5%88%87%E6%8D%A2%E5%88%B0root%0A%E5%9C%A8%E6%96%87%E4%BB%B6%E4%B8%AD%E5%8A%A0%E5%85%A5%E5%A6%82%E4%B8%8B%E5%86%85%E5%AE%B9%20%20%0A%3E%20%E5%90%AF%E5%8A%A8es%E7%9A%84%E7%94%A8%E6%88%B7%E5%90%8D%20soft%20%20%20%20nproc%20%20%20%20%204096%0A%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20vi%20%2Fetc%2Fsecurity%2Flimits.d%2F20-nproc.conf%0Aes%20%20%20%20%20%20%20%20%20soft%20%20%20%20nproc%20%20%20%20%204096%0A%60%60%60%0A!%5Be6cafe96afe1057fbc942618e84a969e.png%5D(en-resource%3A%2F%2Fdatabase%2F582%3A1)%0A%0A%0A%23%23%23%23%23%23%20%E8%A7%A3%E5%86%B3%E9%94%99%E8%AF%AF3%0A%0A%E5%88%87%E6%8D%A2%E5%88%B0root%0A%60%60%60%0A%5Broot%40master%20~%5D%23%20vi%20%2Fetc%2Fsysctl.conf%0Avm.max_map_count%3D655360%0A%5Broot%40master%20~%5D%23%20sysctl%20-p%0Avm.max_map_count%20%3D%20655360%0A%60%60%60%0A%0A%60%60%60%0A%5Bes%40master%20config%5D%24%20cd%20%2Fconfig%2F%0A%5Bes%40master%20config%5D%24%20vi%20elasticsearch.yml%0A%23%20%E4%BF%AE%E6%94%B9%E8%A2%AB%E6%B3%A8%E9%87%8A%E7%9A%84%E5%A6%82%E4%B8%8B%E4%BF%A1%E6%81%AF%E4%B8%BA%0Anode.name%3A%20node-1%0Acluster.initial_master_nodes%3A%20%5B%22node-1%22%5D%0A%60%60%60%0A%23%23%23%23%23%23%20%E5%85%B3%E9%97%ADfirewall%0A%0A%60%60%60%0A%5Broot%40master%20config%5D%23%20firewall-cmd%20--state%20%0Arunning%0A%5Broot%40master%20config%5D%23%20systemctl%20disable%20firewalld.service%0ARemoved%20symlink%20%2Fetc%2Fsystemd%2Fsystem%2Fmulti-user.target.wants%2Ffirewalld.service.%0ARemoved%20symlink%20%2Fetc%2Fsystemd%2Fsystem%2Fdbus-org.fedoraproject.FirewallD1.service.%0A%5Broot%40master%20config%5D%23%20firewall-cmd%20--state%20%0Arunning%0A%5Broot%40master%20config%5D%23%20systemctl%20stop%20firewalld.service%20%0A%5Broot%40master%20config%5D%23%20firewall-cmd%20--state%20%0Anot%20running%0A%60%60%60%0A!%5B4d842e78b8bf67ce0771ef8d870b3ece.png%5D(en-resource%3A%2F%2Fdatabase%2F585%3A1)%0A%0A%23%23%23%23%20%E9%87%8D%E8%A6%81%E6%A6%82%E5%BF%B5%0A%23%23%23%23%23%201.%20%E6%8E%A5%E8%BF%91%E5%AE%9E%E6%97%B6%20Near%20Real%20Time%20%5BNRT%5D%0A%3E%20%E4%BB%8E%E5%B0%86%E6%96%87%E6%A1%A3%E5%A2%9E%E5%8A%A0%E5%88%B0es%E4%B8%AD%E5%88%B0%E6%A3%80%E7%B4%A2%E6%96%87%E6%A1%A3%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%E5%85%A8%E8%BF%87%E7%A8%8B%E4%BB%85%E9%9C%80%E8%A6%811s%0A%0A%23%23%23%23%23%202.%20%E7%B4%A2%E5%BC%95%0A%3E%20%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%E6%98%AF%E4%B8%80%E4%B8%AA%E6%8B%A5%E6%9C%89%E7%9B%B8%E4%BC%BC%E7%89%B9%E5%BE%81%E7%9A%84%E6%96%87%E6%A1%A3%E7%9A%84%E9%9B%86%E5%90%88%EF%BC%8C%E7%B1%BB%E4%BC%BC%E4%BA%8Emysql%E4%B8%AD%E7%9A%84database.%20%20%0A%E7%94%A8%E6%88%B7%E7%B4%A2%E5%BC%95%20%EF%BC%8C%E8%AE%A2%E5%8D%95%E7%B4%A2%E5%BC%95%EF%BC%8C%E5%95%86%E5%93%81%E7%B4%A2%E5%BC%95%EF%BC%8C%E5%88%86%E7%B1%BB%E7%B4%A2%E5%BC%95%20%20%0A%3E%20%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%E7%94%B1%E4%B8%80%E4%B8%AA%E5%90%8D%E5%AD%97%E6%A0%87%E8%AF%86%EF%BC%8C%E6%A0%87%E8%AF%86%E5%BF%85%E9%A1%BB%E5%85%A8%E4%B8%BA**%E5%B0%8F%E5%86%99%E5%AD%97%E6%AF%8D**%EF%BC%8C%E5%9C%A8%E5%AF%B9%E7%B4%A2%E5%BC%95%E4%B8%AD%E7%9A%84%E6%96%87%E6%A1%A3%E8%BF%9B%E8%A1%8Ccrud%E6%97%B6%E9%9C%80%E8%A6%81%E7%94%A8%E5%88%B0%E8%BF%99%E4%B8%AA%E7%B4%A2%E5%BC%95%E5%90%8D%E7%A7%B0.%20%20%0A%3E%20%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E7%9A%84database%E4%B8%80%E8%88%AC%E6%98%AF%E6%A0%B9%E6%8D%AE%E5%BA%94%E7%94%A8%E6%9D%A5%E5%88%9B%E5%BB%BA%EF%BC%8C%E4%BD%86%E6%98%AF%E7%B4%A2%E5%BC%95%E6%98%AF%E4%B8%80%E7%BB%84%E5%85%B7%E6%9C%89%E7%9B%B8%E4%BC%BC%E7%89%B9%E5%BE%81%E7%9A%84%E6%96%87%E6%A1%A3%E9%9B%86%E5%90%88%EF%BC%8C%E6%89%80%E4%BB%A5%E5%AE%9E%E9%99%85%E4%B8%AD%E4%B8%80%E4%B8%AA%E5%BA%94%E7%94%A8%E4%B8%80%E4%B8%AAdatabase%EF%BC%8C%E4%BD%86%E5%8F%AF%E8%83%BD%E5%AF%B9%E5%BA%94%E5%A4%9A%E4%B8%AA%E7%B4%A2%E5%BC%95%E3%80%82%0A%0A!%5B99565c8425741984b96e1820c7c7f730.png%5D(en-resource%3A%2F%2Fdatabase%2F589%3A1)%0A%0A%0A%0A%23%23%23%23%23%203.%20%E7%B1%BB%E5%9E%8B%5Btype%5D%0A%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%9E%8B%E6%98%AF%E7%B4%A2%E5%BC%95%E7%9A%84%E4%B8%80%E4%B8%AA%E9%80%BB%E8%BE%91%E4%B8%8A%E7%9A%84%E5%88%86%E7%B1%BB%EF%BC%8C%E5%85%B6%E8%AF%AD%E6%84%8F%E7%94%B1%E4%B8%AA%E4%BA%BA%E6%9D%A5%E5%AE%9A%EF%BC%8C%E7%B1%BB%E5%9E%8B%E7%B1%BB%E4%BC%BC%E4%BA%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E7%9A%84%E8%A1%A8%E7%9A%84%E6%A6%82%E5%BF%B5%0A%3E%20%E6%B3%A8%E6%84%8F%EF%BC%9A%20%0A%E5%B0%86%E7%B4%A2%E5%BC%95%E6%AF%94%E4%BD%9C%E4%B8%80%E4%B8%AAdatabase%EF%BC%8C%E5%B0%86%E7%B1%BB%E5%9E%8B%E6%AF%94%E4%BD%9C%E4%B8%80%E4%B8%AA%E8%A1%A8%E5%85%B6%E5%AE%9E%E6%98%AF%E4%B8%80%E4%B8%AA%E5%9D%8F%E7%9A%84%E6%AF%94%E5%96%BB%E3%80%82%20%20%0A%E5%9C%A8es5.x%E4%B9%8B%E5%89%8D%E7%9A%84%E7%89%88%E6%9C%AC%E4%B8%AD%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E7%B1%BB%E5%9E%8B%E3%80%82%20%20%20%20%0A%E5%9C%A8es6.x%E7%89%88%E6%9C%AC%E5%85%BC%E5%AE%B9%E4%B9%8B%E5%89%8D%E7%9A%84%E7%89%88%E6%9C%AC%E4%B8%AD%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%E5%88%9B%E5%BB%BA%E7%9A%84%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E7%B1%BB%E5%9E%8B%EF%BC%8C%E4%BE%BF%E6%98%AF%E4%B8%8D%E8%83%BD%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%E4%B8%8B%E5%86%8D%E5%88%9B%E5%BB%BA%E5%A4%9A%E4%B8%AA%E7%B1%BB%E5%9E%8B%E3%80%82%20%20%20%20%0A%E5%9C%A8es7.x%E4%B9%8B%E5%90%8E%E7%9A%84%E7%89%88%E6%9C%AC%E4%B8%AD%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%E4%BB%85%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%9E%8B%E3%80%82%20%20%0A%0A%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%3A%20%20%0ALearn%20-%3E%20Docs%20%20%0Ahttps%3A%2F%2Fwww.elastic.co%2Fguide%2Fen%2Felasticsearch%2Freference%2Fcurrent%2Fmapping.html%0Ahttps%3A%2F%2Fwww.elastic.co%2Fguide%2Fen%2Felasticsearch%2Freference%2Fcurrent%2Fremoval-of-types.html%0A%0A%23%23%23%23%23%204.%20%E6%98%A0%E5%B0%84%5Bmapping%5D%0A%3E%20%E7%B1%BB%E4%BC%BC%E4%BA%8E%E5%85%B3%E7%B3%BB%E6%80%A7%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E8%A1%A8%E7%9A%84schema%2C%E7%94%A8%E4%BA%8E%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%5Bindex%5D%E4%B8%AD%E7%B1%BB%E5%9E%8B%5Btype%5D%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%EF%BC%8Cmapping%E4%B8%AD%E5%8C%85%E5%90%AB%E5%AD%97%E6%AE%B5%E5%90%8D%EF%BC%8C%E5%AD%97%E6%AE%B5%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%AD%97%E6%AE%B5%E7%B4%A2%E5%BC%95%E7%B1%BB%E5%9E%8B%20%20%0A%E5%9C%A8%E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8Ces%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E6%8F%92%E5%85%A5%E7%9A%84%E6%95%B0%E6%8D%AE%E8%87%AA%E5%8A%A8%E5%9C%B0%E5%88%9B%E5%BB%BAtype%E5%8F%8A%E5%85%B6mapping%E3%80%82%0A%0A%23%23%23%23%23%205.%20%E6%96%87%E6%A1%A3%5Bdocument%5D%0A%3E%20%E4%B8%80%E4%B8%AA%E6%96%87%E6%A1%A3%E6%98%AF%E4%B8%80%E4%B8%AA%E5%8F%AF%E8%A2%AB%E7%B4%A2%E5%BC%95%E7%9A%84%E5%9F%BA%E7%A1%80%E4%BF%A1%E6%81%AF%E5%8D%95%E5%85%83%EF%BC%8C%E7%B1%BB%E4%BC%BC%E4%BA%8E%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E7%9A%84%E4%B8%80%E6%9D%A1%E8%AE%B0%E5%BD%95%E3%80%82%20%20%0A%E4%BE%8B%E5%A6%82%E4%BD%A0%E5%8F%AF%E4%BB%A5%E6%8B%A5%E6%9C%89%E4%B8%80%E4%B8%AA%E5%91%98%E5%B7%A5%E7%9A%84%E6%96%87%E6%A1%A3%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%8B%A5%E6%9C%89%E6%9F%90%E4%B8%AA%E5%95%86%E5%93%81%E7%9A%84%E4%B8%80%E4%B8%AA%E6%96%87%E6%A1%A3%20%20%0A%E6%96%87%E6%A1%A3%E9%87%87%E7%94%A8%E4%BA%86%E8%BD%BB%E9%87%8F%E7%BA%A7%E7%9A%84%E6%95%B0%E6%8D%AE%E4%BA%A4%E4%BA%92%E6%A0%BC%E5%BC%8FJson%E6%9D%A5%E8%A1%A8%E7%A4%BA%E3%80%82%0A%0A%23%23%23%23%20kibana%0A%0A%23%23%23%23%23%20%E5%AE%89%E8%A3%85%0A%3E%20ES%E7%9A%84%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%B7%A5%E5%85%B7%20%20%0A%3E%20%E5%BD%93%E5%89%8D%E4%BD%BF%E7%94%A8%E7%9A%84ES%E7%89%88%E6%9C%AC%E4%B8%8Ekibana%E7%89%88%E6%9C%AC%E4%B8%80%E8%87%B4%20%20%0A%3E%20%E4%B8%8A%E4%BC%A0%E5%88%B0es%E7%94%A8%E6%88%B7%E7%9A%84%E5%AE%B6%E7%9B%AE%E5%BD%95%E4%B8%8B%0A%0A%60%60%60%0A%5Bes%40master%5Dtar%20-zxvf%20kibana-7.13.4-linux-x86_64.tar.gz%0A%5Bes%40master%5D%2Fhome%2Fes%2Fkibana-7.13.4%2Fconfig%0A%5Bes%40master%20config%5D%24%20vi%20kibana.yml%0Aserver.host%3A%20%22192.168.80.180%22%0Aelasticsearch.hosts%3A%20%5B%22http%3A%2F%2F192.168.80.180%3A9200%22%5D%0A%60%60%60%0A%3E%20kibana%20%E9%BB%98%E8%AE%A4%E7%AB%AF%E5%8F%A3%E5%8F%B7%E4%B8%BA5601%0A%0A%23%23%23%23%23%20%E5%90%AF%E5%8A%A8%0A%0A%60%60%60%0Acd%20bin%2F%0A%5Bes%40master%20bin%5D%24%20.%2Fkibana%0A%60%60%60%0A%0A%23%23%23%23%23%20%E8%AE%BF%E9%97%AE%0A%3E%20http%3A%2F%2Fmaster%3A5601%0A%0A!%5B26cc560d9838ada8f1952daf112f953d.png%5D(en-resource%3A%2F%2Fdatabase%2F588%3A1)%0A%0A%0A%23%23%23%23%20%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C%0A%23%23%23%23%23%201%20%E7%B4%A2%E5%BC%95%0A%23%23%23%23%23%23%20%E5%88%9B%E5%BB%BA%0A%0A%60%60%60%0APUT%20%2Fems%0A%0A%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%7B%0A%20%20%22acknowledged%22%20%3A%20true%2C%0A%20%20%22shards_acknowledged%22%20%3A%20true%2C%0A%20%20%22index%22%20%3A%20%22ems%22%0A%7D%0A%0A%60%60%60%0A%23%23%23%23%23%23%20%E6%9F%A5%E7%9C%8B%0A%60%60%60%0AGET%20%2F_cat%2Fhealth%20--%E6%9F%A5%E7%9C%8B%E5%81%A5%E5%BA%B7%E7%8A%B6%E5%86%B5%0AGET%20%2F_cat%2Fnodes%20%20--%E6%9F%A5%E7%9C%8B%E6%89%80%E6%9C%89%E8%8A%82%E7%82%B9%0AGET%20%2F_cat%2Fmaster%20--%E6%9F%A5%E7%9C%8B%E4%B8%BB%E8%8A%82%E7%82%B9%20%0AGET%20_cat%2Findices%20--%E6%9F%A5%E7%9C%8B%E6%89%80%E6%9C%89%E7%B4%A2%E5%BC%95%0AGET%20%2F_cat%2Findices%2Fv%20--%E6%98%BE%E7%A4%BA%E8%A1%A8%E5%A4%B4%E6%9F%A5%E7%9C%8B%E6%89%80%E6%9C%89%E7%B4%A2%E5%BC%95%0A%0Ahealth%20status%20index%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20uuid%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pri%20rep%20docs.count%20docs.deleted%20store.size%20pri.store.size%0Agreen%20%20open%20%20%20.apm-custom-link%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20wk57k9ydRfalb-vx5Zon7w%20%20%201%20%20%200%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%20%20208b%20%20%20%20%20%20%20%20%20%20%20208b%0Agreen%20%20open%20%20%20.kibana-event-log-7.13.4-000001%20vf4JjMfEQjGqOlnYz0HQww%20%20%201%20%20%200%20%20%20%20%20%20%20%20%20%201%20%20%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%205.6kb%20%20%20%20%20%20%20%20%20%205.6kb%0Agreen%20%20open%20%20%20.apm-agent-configuration%20%20%20%20%20%20%20%20tCHpjuNmSwq2PiwBadMVeg%20%20%201%20%20%200%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%20%20208b%20%20%20%20%20%20%20%20%20%20%20208b%0Ayellow%20open%20%20%20ems%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ysfFkjV5RNOPgNQ68CFK1g%20%20%201%20%20%201%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%20%20208b%20%20%20%20%20%20%20%20%20%20%20208b%0Agreen%20%20open%20%20%20.kibana_7.13.4_001%20%20%20%20%20%20%20%20%20%20%20%20%20%20HyDQ5FmdRTiQPWjVkqzPsw%20%20%201%20%20%200%20%20%20%20%20%20%20%20%2029%20%20%20%20%20%20%20%20%20%20%20%205%20%20%20%20%20%202.1mb%20%20%20%20%20%20%20%20%20%202.1mb%0Ayellow%20open%20%20%20dangdang%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20yzm7GHk9RKSA93RA7HzGoQ%20%20%201%20%20%201%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%20%20208b%20%20%20%20%20%20%20%20%20%20%20208b%0Agreen%20%20open%20%20%20.kibana_task_manager_7.13.4_001%20ipMKJ-PaQnWGVYifkpEW-A%20%20%201%20%20%200%20%20%20%20%20%20%20%20%2010%20%20%20%20%20%20%20%20%201297%20%20%20%20243.1kb%20%20%20%20%20%20%20%20243.1kb%0A%0Ahealth%20--%20%E5%81%A5%E5%BA%B7%E7%8A%B6%E6%80%81%2C%20GREEN%20-%3E%20YELLOW%20-%3E%20RED%0Apri%20--%E4%B8%BB%E5%88%86%E7%89%87%E6%95%B0%20%20%0Arep%20--%E5%89%AF%E6%9C%AC%E5%88%86%E7%89%87%E6%95%B0%20%20%0Adocs.count%20--%E6%96%87%E6%A1%A3%E6%95%B0%20%20%0Adocs.deleted%20--%E6%96%87%E6%A1%A3%E6%98%AF%E5%90%A6%E8%A2%AB%E5%88%A0%E9%99%A4%E8%BF%87%20%20%0Astore.size%20--%E5%AD%98%E5%82%A8%E5%A4%A7%E5%B0%8F%20%20%0Apri.store.size%20--%20%E4%B8%BB%E5%88%86%E7%89%87%E5%AD%98%E5%82%A8%E5%A4%A7%E5%B0%8F%20%0A%60%60%60%0A%20%0A%20%0A%60%60%60%0AGET%20%2Fdangdang%0A%0A%7B%0A%20%20%22dangdang%22%20%3A%20%7B%0A%20%20%20%20%22aliases%22%20%3A%20%7B%20%7D%2C%0A%20%20%20%20%22mappings%22%20%3A%20%7B%20%7D%2C%0A%20%20%20%20%22settings%22%20%3A%20%7B%0A%20%20%20%20%20%20%22index%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%22routing%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22allocation%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22include%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22_tier_preference%22%20%3A%20%22data_content%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22number_of_shards%22%20%3A%20%221%22%2C%0A%20%20%20%20%20%20%20%20%22provided_name%22%20%3A%20%22dangdang%22%2C%0A%20%20%20%20%20%20%20%20%22creation_date%22%20%3A%20%221627636773007%22%2C%0A%20%20%20%20%20%20%20%20%22number_of_replicas%22%20%3A%20%221%22%2C%0A%20%20%20%20%20%20%20%20%22uuid%22%20%3A%20%22yzm7GHk9RKSA93RA7HzGoQ%22%2C%0A%20%20%20%20%20%20%20%20%22version%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22created%22%20%3A%20%227130499%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%20%E5%88%A0%E9%99%A4%0A%0A%60%60%60%0ADELETE%20%2Fdangdang%20--%E5%88%A0%E9%99%A4%E5%8D%95%E4%B8%AA%E7%B4%A2%E5%BC%95%0ADELETE%20%2F*%20%20%20%20--%20%E5%88%A0%E9%99%A4%E6%89%80%E6%9C%89%E7%B4%A2%E5%BC%95%0A%60%60%60%0A%0A%23%23%23%23%23%202%20%E7%B4%A2%E5%BC%95%E5%92%8C%E6%98%A0%E5%B0%84%0A%23%23%23%23%23%23%20mapping%20type%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%0A%3E%20text%2C%20keyword%2C%20data%2C%20integer%2C%20long%2C%20double%2C%20boolean%2C%20ip%0A%0A%23%23%23%23%23%23%20%E5%88%9B%E5%BB%BA%0A%0A%60%60%60%0APUT%20%2Fdangdang_2%0A%7B%0A%20%20%22mappings%22%3A%20%7B%0A%20%20%20%20%22properties%22%3A%20%7B%0A%20%20%20%20%20%20%22id%22%3A%7B%0A%20%20%20%20%20%20%20%20%22type%22%3A%20%22keyword%22%0A%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%22name%22%3A%7B%0A%20%20%20%20%20%20%20%20%22type%22%3A%20%22keyword%22%0A%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%22age%22%3A%7B%0A%20%20%20%20%20%20%20%20%22type%22%3A%20%22integer%22%0A%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%22bir%22%3A%7B%0A%20%20%20%20%20%20%20%20%22type%22%3A%20%22date%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0A%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%7B%0A%20%20%22acknowledged%22%20%3A%20true%2C%0A%20%20%22shards_acknowledged%22%20%3A%20true%2C%0A%20%20%22index%22%20%3A%20%22dangdang_2%22%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%20%E6%9F%A5%E7%9C%8B%0A%60%60%60%0AGET%20%2Fdangdang2%2F_mapping%0A%60%60%60%0A%0A%23%23%23%23%23%203%20%E6%96%87%E6%A1%A3%0A%0A%23%23%23%23%23%23%20%E5%88%9B%E5%BB%BA%E6%97%B6%E6%8C%87%E5%AE%9A%20_id%0A%3E%20%E4%BB%A5%E4%B8%8B%E5%91%BD%E4%BB%A4%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%E4%B8%BAtianmao%E7%B1%BB%E5%9E%8B%E4%B8%BAorder%E7%9A%84%E6%96%87%E6%A1%A3_id%3D1%0A%60%60%60%0APUT%20%2Ftianmao%2Forder%2F1%20%E6%88%96%E8%80%85%20PUT%20%2Ftianmao%2F_doc%2F1%0A%7B%0A%20%20%22id%22%3A%2221%22%2C%0A%20%20%22name%22%3A%22chris%22%2C%0A%20%20%22prvice%22%3A23.13%2C%0A%20%20%22amount%22%3A23%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%20%E5%88%9B%E5%BB%BA%E6%97%B6%E4%B8%8D%E6%8C%87%E5%AE%9A%20_id%0A%60%60%60%0APOST%20%2Ftianmao%2Forder%20%E6%88%96%E8%80%85%20POST%20%2Ftianmoa%2F_doc%0A%7B%0A%20%20%22id%22%3A%2212%22%2C%0A%20%20%22name%22%3A%22%E6%B5%B7%E8%8B%94%22%2C%0A%20%20%22prvice%22%3A3.13%2C%0A%20%20%22amount%22%3A24%0A%7D%0A%0A--%20%E4%BC%9A%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90_id%0A%7B%0A%20%20%22_index%22%20%3A%20%22tianmao%22%2C%0A%20%20%22_type%22%20%3A%20%22order%22%2C%0A%20%20%22_id%22%20%3A%20%22F5I6-noB9Y4OLXrN27h2%22%2C%0A%20%20%22_version%22%20%3A%201%2C%0A%20%20%22result%22%20%3A%20%22created%22%2C%0A%20%20%22_shards%22%20%3A%20%7B%0A%20%20%20%20%22total%22%20%3A%202%2C%0A%20%20%20%20%22successful%22%20%3A%201%2C%0A%20%20%20%20%22failed%22%20%3A%200%0A%20%20%7D%2C%0A%20%20%22_seq_no%22%20%3A%201%2C%0A%20%20%22_primary_term%22%20%3A%201%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%20%E6%9F%A5%E8%AF%A2%0A%0A%60%60%60%0AGET%20%2Ftianmao%2Forder%2F1%0A%E6%88%96%E8%80%85%20GET%2Ftianmao%2F_doc%2F1%0A%0A%7B%0A%20%20%22_index%22%20%3A%20%22tianmao%22%2C%0A%20%20%22_type%22%20%3A%20%22order%22%2C%0A%20%20%22_id%22%20%3A%20%221%22%2C%0A%20%20%22_version%22%20%3A%201%2C%0A%20%20%22_seq_no%22%20%3A%200%2C%0A%20%20%22_primary_term%22%20%3A%201%2C%0A%20%20%22found%22%20%3A%20true%2C%0A%20%20%22_source%22%20%3A%20%7B%0A%20%20%20%20%22id%22%20%3A%20%2221%22%2C%0A%20%20%20%20%22name%22%20%3A%20%22chris%22%2C%0A%20%20%20%20%22prvice%22%20%3A%2023.13%2C%0A%20%20%20%20%22amount%22%20%3A%2023%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%20%E6%9B%B4%E6%96%B0%0A%3E%20%E6%96%B0%E5%A2%9E%E7%B4%A2%E5%BC%95%E6%98%A0%E5%B0%84%0A%60%60%60%0APUT%20%2Fdangdang%2F%0A%7B%0A%20%20%22mappings%22%3A%20%7B%0A%20%20%20%20%22properties%22%3A%20%7B%0A%20%20%20%20%20%20%22name%22%3A%7B%22type%22%3A%20%22keyword%22%7D%2C%0A%20%20%20%20%20%20%22content%22%3A%7B%22type%22%3A%20%22text%22%7D%2C%0A%20%20%20%20%20%20%22price%22%3A%7B%22type%22%3A%20%22float%22%7D%2C%0A%20%20%20%20%20%20%22update%22%3A%7B%22type%22%3A%20%22date%22%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0AGET%20%2Fdangdang%2F_mapping%0A%0APUT%20%2Fdangdang%2F_doc%2F1%0A%7B%0A%20%20%22name%22%3A%20%22%E4%B8%80%E5%8F%AA%E5%B0%8F%E7%99%BD%E7%BE%8A%E7%9A%84%E6%95%85%E4%BA%8B%22%2C%0A%20%20%22content%22%3A%22%E6%88%91%E6%98%AF%E4%B8%80%E5%8F%AA%E5%B0%8F%E7%99%BD%E7%BE%8A%EF%BC%8C%E6%AF%8F%E5%A4%A9%E5%90%83%E8%8D%89%E9%83%BD%E5%BE%88%E5%BF%99%22%2C%0A%20%20%22price%22%3A23.4%2C%0A%20%20%22date%22%3A%222018-02-23%22%0A%7D%0A%0AGET%20%2Fdangdang%2F_doc%2F1%0A%60%60%60%0A%0A1.%20%E8%A6%86%E7%9B%96%E5%BC%8F%E6%9B%B4%E6%96%B0%20%20%0A%3E%20%E6%9B%B4%E6%96%B0%E4%B9%8B%E5%90%8E%E5%8F%AA%E5%89%A9%E4%B8%8Bname%E5%AD%97%E6%AE%B5%2C%20%E7%9B%B8%E5%BD%93%E4%BA%8E%E6%8A%8A%E5%8E%9F%E6%9D%A5%E7%9A%84%E6%96%87%E6%A1%A3%E5%88%A0%E9%99%A4%E5%90%8E%E5%86%8D%E6%B7%BB%E5%8A%A0%0A%60%60%60%0APOST%20%2Fdangdang%2F_doc%2F1%0A%7B%0A%20%20%22name%22%3A%22%E5%B0%8F%E7%99%BD%E7%BE%8A%E5%A4%9A%E5%88%A9%E7%9A%84%E6%95%85%E4%BA%8B%22%0A%7D%0A%0AGET%20%2Fdangdang%2F_doc%2F1%0A%7B%0A%20%20%22_index%22%20%3A%20%22dangdang%22%2C%0A%20%20%22_type%22%20%3A%20%22_doc%22%2C%0A%20%20%22_id%22%20%3A%20%221%22%2C%0A%20%20%22_version%22%20%3A%202%2C%0A%20%20%22_seq_no%22%20%3A%202%2C%0A%20%20%22_primary_term%22%20%3A%201%2C%0A%20%20%22found%22%20%3A%20true%2C%0A%20%20%22_source%22%20%3A%20%7B%0A%20%20%20%20%22name%22%20%3A%20%22%E5%B0%8F%E7%99%BD%E7%BE%8A%E5%A4%9A%E5%88%A9%E7%9A%84%E6%95%85%E4%BA%8B%22%0A%20%20%7D%0A%7D%0A%60%60%60%0A2.%20%E6%9B%B4%E6%96%B0%E5%8E%9F%E5%A7%8B%E6%96%87%E6%A1%A3%E7%9A%84%E6%8C%87%E5%AE%9A%E5%AD%97%E6%AE%B5%0A%0A%60%60%60%0APOST%20%2Fdangdang%2F_doc%2F1%2F_update%0A%7B%0A%20%20%22doc%22%3A%7B%0A%20%20%20%20%22name%22%3A%22%E5%B0%8F%E7%99%BD%E7%BE%8A%E5%A4%9A%E5%88%A9%E7%9A%84%E6%95%85%E4%BA%8B%22%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A3.%20%E6%9B%B4%E6%96%B0%E5%8E%9F%E5%A7%8B%E6%96%87%E6%A1%A3%E7%9A%84%E6%8C%87%E5%AE%9A%E5%AD%97%E6%AE%B5%E6%97%B6%E6%B7%BB%E5%8A%A0%E6%96%B0%E7%9A%84%E5%AD%97%E6%AE%B5%0A%0A%60%60%60%0APOST%20%2Fdangdang%2F_doc%2F1%2F_update%0A%7B%0A%20%20%22doc%22%3A%7B%0A%20%20%20%20%22name%22%3A%22%E5%B0%8F%E7%99%BD%E7%BE%8A%E5%A4%9A%E5%88%A9%E7%9A%84%E6%95%85%E4%BA%8B%22%2C%0A%20%20%20%20%22category%22%3A%22%E5%B0%91%E5%84%BF%E6%95%85%E4%BA%8B%E7%B1%BB%22%0A%20%20%7D%0A%7D%0A%0AGET%20%2Fdangdang%2F_doc%2F1%0A%0A%7B%0A%20%20%22_index%22%20%3A%20%22dangdang%22%2C%0A%20%20%22_type%22%20%3A%20%22_doc%22%2C%0A%20%20%22_id%22%20%3A%20%221%22%2C%0A%20%20%22_version%22%20%3A%205%2C%0A%20%20%22_seq_no%22%20%3A%205%2C%0A%20%20%22_primary_term%22%20%3A%201%2C%0A%20%20%22found%22%20%3A%20true%2C%0A%20%20%22_source%22%20%3A%20%7B%0A%20%20%20%20%22name%22%20%3A%20%22%E5%B0%8F%E7%99%BD%E7%BE%8A%E5%A4%9A%E5%88%A9%E7%9A%84%E6%95%85%E4%BA%8B%22%2C%0A%20%20%20%20%22content%22%20%3A%20%22%E6%88%91%E6%98%AF%E4%B8%80%E5%8F%AA%E5%B0%8F%E7%99%BD%E7%BE%8A%EF%BC%8C%E6%AF%8F%E5%A4%A9%E5%90%83%E8%8D%89%E9%83%BD%E5%BE%88%E5%BF%99%22%2C%0A%20%20%20%20%22price%22%20%3A%2023.4%2C%0A%20%20%20%20%22date%22%20%3A%20%222018-02-23%22%2C%0A%20%20%20%20%22category%22%20%3A%20%22%E5%B0%91%E5%84%BF%E6%95%85%E4%BA%8B%E7%B1%BB%22%0A%20%20%7D%0A%7D%0A%0AGET%20%2Fdangdang%2F_mapping%0A%0A%7B%0A%20%20%22dangdang%22%20%3A%20%7B%0A%20%20%20%20%22mappings%22%20%3A%20%7B%0A%20%20%20%20%20%20%22properties%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%22category%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22type%22%20%3A%20%22text%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22fields%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22keyword%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%20%3A%20%22keyword%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22ignore_above%22%20%3A%20256%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22content%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22type%22%20%3A%20%22text%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22date%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22type%22%20%3A%20%22date%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22name%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22type%22%20%3A%20%22keyword%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22price%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22type%22%20%3A%20%22float%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22update%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22type%22%20%3A%20%22date%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A4.%20%E9%80%9A%E8%BF%87%E8%84%9A%E6%9C%AC%E5%AF%B9%E6%9B%B4%E6%96%B0%E6%8C%87%E5%AE%9A%E5%AD%97%E6%AE%B5%0A%3E%20%E6%9B%B4%E6%96%B0price%E5%AD%97%E6%AE%B5%EF%BC%8C%E5%9C%A8%E5%8E%9F%E6%9D%A5%E5%9F%BA%E7%A1%80%E4%B8%8A%E5%A2%9E%E5%8A%A01.3%0A%60%60%60%0APOST%20%2Fdangdang%2F_doc%2F1%2F_update%0A%7B%0A%20%20%22script%22%3A%22ctx._source.price%2B%3D1.3%22%0A%7D%0A%60%60%60%0A%0A%0A%23%23%23%23%23%23%20%E5%88%A0%E9%99%A4%0A%60%60%60%0ADELETE%20%2Fdangdang%2F_doc%2F1%0A%60%60%60%0A%0A%23%23%23%23%23%204%20%E6%96%87%E6%A1%A3%E6%89%B9%E9%87%8F%E6%93%8D%E4%BD%9C%0A%0Ahttps%3A%2F%2Fwww.elastic.co%2Fguide%2Fen%2Felasticsearch%2Freference%2Fcurrent%2Fdocs-bulk.html%0A%0A%3E%20%E6%89%B9%E9%87%8F%E6%9B%B4%E6%96%B0%E4%B8%8D%E4%BC%9A%E5%9B%A0%E4%B8%BA%E5%85%B6%E4%B8%AD%E4%B8%80%E6%9D%A1%E7%9A%84%E5%A4%B1%E8%B4%A5%E8%80%8C%E6%89%80%E6%9C%89%E5%A4%B1%E8%B4%A5%20%20%0A%7B%20%22index%22%20%3A%20%7B%7D%7D%20%E5%A6%82%E6%98%AF%E4%B8%8D%E6%8C%87%E5%AE%9A_id%E5%88%99%E4%BC%9A%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90_id%0A%60%60%60%0APOST%20%2Fdangdang%2F_doc%2F_bulk%0A%7B%20%22index%22%20%3A%20%7B%22_id%22%20%3A%20%2211%22%20%7D%20%7D%0A%7B%20%22id%22%20%3A%20%2211%22%2C%20%22name%22%3A%22c%2B%2B%20dev%20principles%22%2C%20%22price%22%3A52.3%2C%20%22amount%22%3A%2232%22%7D%0A%7B%20%22index%22%20%3A%20%7B%22_id%22%20%3A%20%2212%22%20%7D%20%7D%0A%7B%20%22id%22%20%3A%20%2212%22%2C%20%22name%22%3A%22java%20dev%20principles%22%2C%20%22price%22%3A392.3%2C%20%22amount%22%3A%2223%22%7D%0A%7B%20%22index%22%20%3A%20%7B%7D%7D%0A%7B%20%22id%22%20%3A%20%2213%22%2C%20%22name%22%3A%22python%20dev%20principles%22%2C%20%22price%22%3A33.3%2C%20%22amount%22%3A%2245%22%7D%0A%7B%20%22create%22%20%3A%20%7B%22_id%22%20%3A%20%2214%22%20%7D%20%7D%0A%7B%20%22id%22%20%3A%20%2214%22%2C%20%22name%22%3A%22devops%20%E5%AE%9E%E6%88%98%E6%8C%87%E5%8D%97%22%2C%20%22price%22%3A110.4%2C%20%22amount%22%3A%2243%22%7D%0A%7B%20%22delete%22%20%3A%20%7B%22_id%22%20%3A%20%221%22%20%7D%20%7D%0A%7B%20%22update%22%20%3A%20%7B%22_id%22%20%3A%20%222%22%20%7D%20%7D%0A%7B%22doc%22%3A%7B%22name%22%3A%22%E4%B8%80%E5%8F%AA%E5%B0%8F%E9%BB%91%E7%BE%8A%E7%9A%84%E6%95%85%E4%BA%8B-2%22%7D%7D%0A%60%60%60%0A%23%23%23%23%20ES%E4%B8%AD%E7%9A%84%E6%A3%80%E7%B4%A2%E6%96%B9%E5%BC%8F%0Aes%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%A4%E7%A7%8D%E6%95%B0%E6%8D%AE%E7%9A%84%E6%A3%80%E7%B4%A2%E6%96%B9%E5%BC%8F%0A%3E%201.%20%E4%BD%BF%E7%94%A8url%E5%8F%82%E6%95%B0%E6%96%B9%E5%BC%8F%E5%8D%B3query%20string%E8%BF%9B%E8%A1%8C%E6%A3%80%E7%B4%A2%0A%3E%202.%20%E4%BD%BF%E7%94%A8DSL%5Bdomain%20specified%20language%5D%E6%96%B9%E5%BC%8F%E5%8D%B3request%20body%E8%BF%9B%E8%A1%8C%E6%A3%80%E7%B4%A2%0A%0A%E5%87%86%E5%A4%87%E6%95%B0%E6%8D%AE%0A%0A%60%60%60%0APUT%20%2Fems%2F%0A%7B%0A%20%20%22mappings%22%3A%20%7B%0A%20%20%20%20%22properties%22%3A%20%7B%0A%20%20%20%20%20%20%22name%22%3A%7B%22type%22%3A%20%22keyword%22%7D%2C%0A%20%20%20%20%20%20%22age%22%3A%7B%22type%22%3A%20%22integer%22%7D%2C%0A%20%20%20%20%20%20%22bir%22%3A%7B%22type%22%3A%20%22date%22%7D%2C%0A%20%20%20%20%20%20%22content%22%3A%7B%22type%22%3A%20%22text%22%7D%2C%0A%20%20%20%20%20%20%22address%22%3A%7B%22type%22%3A%20%22keyword%22%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0AGET%20%2Fems%2F_mapping%0A%0APOST%20%2Fems%2F_doc%2F_bulk%0A%7B%20%22index%22%20%3A%7B%7D%7D%0A%7B%20%22name%22%3A%22chris%22%2C%20%22age%22%3A23%2C%20%22bir%22%3A%222016-12-21%22%2C%20%22content%22%3A%22A%20search%20query%2C%20or%20query%2C%20is%20a%20request%20for%20information%20about%20data%20in%20Elasticsearch%20data%20streams%20or%20indices.%22%2C%20%22address%22%3A%22China%22%7D%0A%7B%20%22index%22%20%3A%20%7B%7D%20%7D%0A%7B%20%22name%22%3A%22john%22%2C%20%22age%22%3A33%2C%20%22bir%22%3A%222018-09-12%22%2C%20%22content%22%3A%22What%20processes%20on%20my%20server%20take%20longer%20than%20500%20milliseconds%20to%20respond%3F%22%2C%20%22address%22%3A%22US%22%7D%0A%7B%20%22index%22%20%3A%20%7B%7D%7D%0A%7B%20%22name%22%3A%22petter%22%2C%20%22age%22%3A13%2C%20%22bir%22%3A%222001-11-09%22%2C%20%22content%22%3A%22A%20search%20consists%20of%20one%20or%20more%20queries%20that%20are%20combined%20and%20sent%20to%20Elasticsearch.%20Documents%20that%20match%20a%20search%E2%80%99s%20queries%20are%20returned%20in%20the%20hits%2C%20or%20search%20results%2C%20of%20the%20response.%22%2C%20%22address%22%3A%22Franch%22%7D%0A%7B%20%22create%22%20%3A%20%7B%7D%20%7D%0A%7B%20%22name%22%3A%22Ethen%22%2C%20%20%22age%22%3A43%2C%20%22bir%22%3A%222019-09-01%22%2C%20%22content%22%3A%22You%20can%20use%20the%20search%20API%20to%20search%20and%20aggregate%20data%20stored%20in%20Elasticsearch%20data%20streams%20or%20indices.%20The%20API%E2%80%99s%20query%20request%20body%20parameter%20accepts%20queries%20written%20in%20Query%20DSL.%22%2C%20%22address%22%3A%22China%22%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%23%201%20%E4%BD%BF%E7%94%A8url%E5%8F%82%E6%95%B0%E6%96%B9%E5%BC%8F%E5%8D%B3query%20string%E8%BF%9B%E8%A1%8C%E6%A3%80%E7%B4%A2%0Ahttps%3A%2F%2Fwww.elastic.co%2Fguide%2Fen%2Felasticsearch%2Freference%2Fcurrent%2Fsearch-search.html%0A1.%20%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%0A%3E%20GET%20%2Fems%2F_doc%2F_search%3Fq%3D*%0A%0A2.%20%E6%9F%A5%E8%AF%A2%E5%B9%B6%E6%8E%92%E5%BA%8F%0A%3E%20GET%20%2Fems%2F_doc%2F_search%3Fq%3D*%26sort%3Dage%3Adesc%26size%3D2%0A%0A3.%20%E6%9F%A5%E8%AF%A2%E5%B9%B6%E6%8E%92%E5%BA%8F%E4%B8%94%E6%8C%87%E5%AE%9A%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E4%B8%AA%E6%95%B0%0A%3E%20GET%20%2Fems%2F_doc%2F_search%3Fq%3D*%26sort%3Dage%3Adesc%26size%3D2%0A%0A%23%23%23%23%23%20%202%20%E4%BD%BF%E7%94%A8DSL%E6%96%B9%E5%BC%8F%E5%8D%B3requestbody%E8%BF%9B%E8%A1%8C%E6%A3%80%E7%B4%A2%0A%23%23%23%23%23%23%202.1.%20%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%EF%BC%8C%E6%8C%89%E6%8C%87%E5%AE%9A%E5%AD%97%E6%AE%B5%E6%8E%92%E5%BA%8F%E5%B9%B6%E8%BF%94%E5%9B%9E%E6%8C%87%E5%AE%9A%E7%BB%93%E6%9E%9C%E6%95%B0%0A%0A%60%60%60%0AGET%20ems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22match_all%22%3A%7B%7D%0A%20%20%7D%2C%0A%20%20%22sort%22%3A%5B%7B%0A%20%20%20%20%22age%22%3A%7B%0A%20%20%20%20%20%20%22order%22%3A%22desc%22%0A%20%20%20%20%7D%0A%20%20%7D%5D%2C%0A%20%20%22size%22%3A2%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.2.%20%E6%9F%A5%E8%AF%A2%E7%BB%93%E6%9E%9C%E4%B8%AD%E8%BF%94%E5%9B%9E%E6%8C%87%E5%AE%9A%E5%AD%97%E6%AE%B5(_source)%0A%0A%60%60%60%0AGET%20ems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22match_all%22%3A%7B%7D%0A%20%20%7D%2C%0A%20%20%22_source%22%3A%5B%22name%22%2C%20%22content%22%5D%2C%0A%20%20%22sort%22%3A%5B%7B%0A%20%20%20%20%22age%22%3A%7B%0A%20%20%20%20%20%20%22order%22%3A%22desc%22%0A%20%20%20%20%7D%0A%20%20%7D%5D%2C%0A%20%20%22size%22%3A2%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.3.%20%E7%B2%BE%E5%87%86%E6%9F%A5%E8%AF%A2(term)%0A%3E%20term%E6%98%AF%E4%BB%A3%E8%A1%A8%E5%AE%8C%E5%85%A8%E5%8C%B9%E9%85%8D%EF%BC%8C%E5%8D%B3%E4%B8%8D%E8%BF%9B%E8%A1%8C%E5%88%86%E8%AF%8D%E5%99%A8%E5%88%86%E6%9E%90%EF%BC%8C%E6%96%87%E6%A1%A3%E4%B8%AD%E5%BF%85%E9%A1%BB%E5%8C%85%E5%90%AB%E6%95%B4%E4%B8%AA%E6%90%9C%E7%B4%A2%E7%9A%84%E8%AF%8D%E6%B1%87%2C%E4%B8%8D%E4%BC%9A%E5%8F%82%E4%B8%8EES%E5%88%86%E8%AF%8D%E6%9F%A5%E8%AF%A2%0A%60%60%60%0AGET%20ems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22term%22%3A%7B%0A%20%20%20%20%20%20%22content%22%3A%7B%0A%20%20%20%20%20%20%20%20%22value%22%3A%22consists%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.4.%20terms%20%E6%9F%A5%E8%AF%A2%E6%98%AFterm%E7%9A%84%E6%89%A9%E5%B1%95%0A%3E%20%E5%8F%AF%E4%BB%A5%E6%94%AF%E6%8C%81%E5%A4%9A%E4%B8%AAvlaue%E5%8C%B9%E9%85%8D%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E4%B8%80%E4%B8%AA%E5%8C%B9%E9%85%8D%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BA%86%0A%60%60%60%0AGET%20ems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22terms%22%3A%7B%0A%20%20%20%20%20%20%22content%22%3A%5B%22consists%22%2C%22query%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.5.%20%E8%8C%83%E5%9B%B4%E6%9F%A5%E8%AF%A2(range)%0A%3E%20%E6%A3%80%E7%B4%A2%E5%B9%B4%E9%BE%84%E5%A4%A7%E4%BA%8E%E7%AD%8913%E4%B8%94%E5%B0%8F%E4%BA%8E%E7%AD%89%E4%BA%8E33%E7%9A%84%E7%9B%B8%E5%85%B3%E6%96%87%E6%A1%A3%0A%60%60%60%0APOST%20%2Fems%2F_doc%2F_search%20%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22range%22%3A%7B%0A%20%20%20%20%20%20%22age%22%3A%7B%0A%20%20%20%20%20%20%20%20%22gte%22%3A13%2C%0A%20%20%20%20%20%20%20%20%22lte%22%3A%2033%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22sort%22%3A%5B%7B%0A%20%20%20%20%22age%22%3A%7B%0A%20%20%20%20%20%20%22order%22%3A%22asc%22%0A%20%20%20%20%7D%0A%20%20%7D%5D%0A%7D%0A%60%60%60%0A%23%23%23%23%23%23%202.6.%20%E5%89%8D%E7%BC%80%E6%9F%A5%E8%AF%A2(prefix)%0A%3E%20%E6%A3%80%E7%B4%A2%E5%90%AB%E6%9C%89%E6%8C%87%E5%AE%9A%E5%89%8D%E7%BC%80%E7%9A%84%E5%85%B3%E9%94%AE%E5%AD%97%E7%9B%B8%E5%85%B3%E6%96%87%E6%A1%A3%0A%3E%20%E4%BD%BF%E7%94%A8%E5%A4%A7%E5%86%99%E5%AD%97%E6%AF%8D%E4%B8%8D%E4%BC%9A%E6%A3%80%E7%B4%A2%E5%88%B0%E6%96%87%E6%A1%A3%EF%BC%8C%E5%9B%A0%E4%B8%BAES%E5%9C%A8%E5%AF%B9%E6%AF%8F%E4%B8%80%E4%B8%AA%E8%AF%8D%E5%BB%BA%E7%AB%8B%E7%B4%A2%E5%BC%95%E6%97%B6%E4%BC%9A%E5%B0%86%E8%AF%8D%E7%BB%9F%E4%B8%80%E8%BD%AC%E6%88%90%E5%B0%8F%E5%86%99%0A%0A%60%60%60%0APOST%20%2Fems%2F_doc%2F_search%20%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22prefix%22%3A%7B%0A%20%20%20%20%20%20%22content%22%3A%7B%0A%20%20%20%20%20%20%20%20%22value%22%3A%22or%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22sort%22%3A%5B%7B%0A%20%20%20%20%22age%22%3A%7B%0A%20%20%20%20%20%20%22order%22%3A%22asc%22%0A%20%20%20%20%7D%0A%20%20%7D%5D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.7.%20%E9%80%9A%E9%85%8D%E7%AC%A6%E6%9F%A5%E8%AF%A2(wildcard)%0A%3E%20%3F%20%E8%A1%A8%E6%9C%AA%E4%BB%BB%E6%84%8F%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%20%20%0A%3E%20%5C*%20%E8%A1%A8%E7%A4%BA%E9%9B%B6%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E5%AD%97%E7%AC%A6%0A%0A%0A%60%60%60%0APOST%20%2Fems%2F_doc%2F_search%20%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22wildcard%22%3A%7B%0A%20%20%20%20%20%20%22content%22%3A%7B%0A%20%20%20%20%20%20%20%20%22value%22%3A%22*ill*%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22_source%22%3A%5B%22name%22%2C%20%22content%22%5D%2C%0A%20%20%22sort%22%3A%5B%7B%0A%20%20%20%20%22age%22%3A%7B%0A%20%20%20%20%20%20%22order%22%3A%22asc%22%0A%20%20%20%20%7D%0A%20%20%7D%5D%0A%7D%0A%60%60%60%0A%23%23%23%23%23%23%202.8.%20%E5%A4%9Aid%E6%9F%A5%E8%AF%A2(ids)%0A%3E%20%E5%80%BC%E4%B8%BA%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%EF%BC%8C%E7%94%A8%E6%9D%A5%E8%8E%B7%E5%BE%97%E4%B8%80%E7%BB%84id%E5%AF%B9%E5%BA%94%E7%9A%84%E5%A4%9A%E4%B8%AA%E6%96%87%E6%A1%A3%0A%60%60%60%0APOST%20%2Fems%2F_doc%2F_search%20%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22ids%22%3A%7B%0A%20%20%20%20%20%20%22values%22%3A%5B%22sPWeBHsBjA6v-uGtRIg5%22%2C%20%22sfWeBHsBjA6v-uGtRIg5%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22_source%22%3A%5B%22name%22%2C%20%22content%22%5D%2C%0A%20%20%22sort%22%3A%5B%7B%0A%20%20%20%20%22age%22%3A%7B%0A%20%20%20%20%20%20%22order%22%3A%22asc%22%0A%20%20%20%20%7D%0A%20%20%7D%5D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.9.%20%E6%A8%A1%E7%B3%8A%E6%9F%A5%E8%AF%A2(fuzzy)%0A%3E%20%E7%94%A8%E6%9D%A5%E6%A8%A1%E7%B3%8A%E6%9F%A5%E8%AF%A2%E5%90%AB%E6%9C%89%E6%8C%87%E5%AE%9A%E5%85%B3%E9%94%AE%E5%AD%97%E7%9A%84%E6%96%87%E6%A1%A3%20%20%20%20%20%20%20%0A%3E%20%E6%B3%A8%E6%84%8F%EF%BC%9A%E6%9C%80%E5%A4%A7%E7%BC%96%E8%BE%91%E8%B7%9D%E7%A6%BB%E4%B8%BA0%201%202%20%20%0A%3E%20%E5%A6%82%E6%9E%9C%E5%85%B3%E9%94%AE%E8%AF%8D%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%BA2%EF%BC%8C%E5%88%99%E4%B8%8D%E5%85%81%E8%AE%B8%E6%9C%89%E9%94%99%E8%AF%AF%EF%BC%8C%E5%BF%85%E9%A1%BB%E5%AE%8C%E5%85%A8%E9%85%8D%E7%BD%AE%20%20%0A%3E%20%E5%A6%82%E6%9E%9C%E5%85%B3%E9%94%AE%E8%AF%8D%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%BA3%E5%88%B05%EF%BC%8C%E5%88%99%E5%85%81%E8%AE%B8%E6%9C%89%E4%B8%80%E4%B8%AA%E9%94%99%E8%AF%AF%20%20%0A%3E%20%E5%A6%82%E6%9E%9C%E5%85%B3%E9%94%AE%E8%AF%8D%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%BA%E5%A4%A7%E4%BA%8E5%EF%BC%8C%E5%88%99%E6%9C%80%E5%A4%9A%E5%85%81%E8%AE%B8%E6%9C%89%E4%B8%A4%E4%B8%AA%E9%94%99%E8%AF%AF%20%20%0A%0A--%20%E5%8F%AF%E4%BB%A5%E6%9F%A5%E8%AF%A2%E5%88%B0name%20%E4%B8%BA%60Ethan%60%E7%9A%84%E6%96%87%E6%A1%A3%0A%0A%60%60%60%0APOST%20%2Fems%2F_doc%2F_search%20%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22fuzzy%22%3A%7B%0A%20%20%20%20%20%20%22name%22%3A%22Ethxxn%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A--%20%E6%9F%A5%E8%AF%A2%E4%B8%8D%E5%88%B0name%20%E4%B8%BA%60Ethan%60%E7%9A%84%E6%96%87%E6%A1%A3%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%B8%8D%E9%85%8D%E7%BD%AE%E5%B0%BE%0A%60%60%60%0APOST%20%2Fems%2F_doc%2F_search%20%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22fuzzy%22%3A%7B%0A%20%20%20%20%20%20%22name%22%3A%22Ethxx%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%23%23%23%23%23%23%202.8.%20%E5%B8%83%E5%B0%94%E6%9F%A5%E8%AF%A2(bool)%0A%3E%20%E7%94%A8%E4%BA%8E%E7%BB%84%E5%90%88%E5%A4%9A%E6%9D%A1%E4%BB%B6%E5%AE%9E%E7%8E%B0%E5%A4%8D%E6%9D%82%E6%9F%A5%E8%AF%A2%20%20%0A%3E%20must%20%E7%9B%B8%E5%BD%93%E4%BA%8E%20%26%26%20%20%0A%3E%20should%20%E7%9B%B8%E5%BD%93%E4%BA%8E%20%7C%7C%20%20%0A%3E%20must_not%20%E7%9B%B8%E5%BD%93%E4%BA%8E!%20%20%0A%0A%3E%E6%9F%A5%E8%AF%A2elasticsearch%E5%85%B3%E9%94%AE%E5%AD%97%E5%90%8C%E6%97%B6id%E4%B8%8D%E6%98%AF%22sfWeBHsBjA6v-uGtRIg5%22%2C%20%22rvWeBHsBjA6v-uGtRIg5%22%E7%9A%84%E6%96%87%E6%A1%A3%0A%0A%60%60%60%0APOST%20%2Fems%2F_doc%2F_search%20%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22bool%22%3A%7B%0A%20%20%20%20%20%20%22must%22%3A%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22term%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22content%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22value%22%3A%22elasticsearch%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%5D%2C%0A%20%20%20%20%20%20%22must_not%22%3A%5B%7B%0A%20%20%20%20%20%20%20%20%22ids%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%22values%22%3A%5B%22sfWeBHsBjA6v-uGtRIg5%22%2C%20%22rvWeBHsBjA6v-uGtRIg5%22%5D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%5D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%23%23%23%23%23%23%202.9.%20%E5%A4%9A%E5%AD%97%E6%AE%B5%E6%9F%A5%E8%AF%A2(multi_match)%0A%3E%20%E5%9C%A8%E6%9F%A5%E8%AF%A2%E8%BF%87%E7%A8%8B%E4%B8%AD%E4%BC%9A%E5%85%88%E5%B0%86%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%E6%A0%B9%E6%8D%AE%E5%BD%93%E5%89%8D%E5%88%86%E8%AF%8D%E5%99%A8%E5%88%86%E8%AF%8D%E5%90%8E%E5%86%8D%E8%BF%9B%E8%A1%8C%E6%9F%A5%E8%AF%A2%20%20%0A%3E%20ES%E4%BC%9A%E8%B7%9F%E6%8D%AEmapping%20type%E4%B8%AD%E7%9A%84%E7%B1%BB%E5%9E%8B%E6%9D%A5%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E5%88%86%E8%AF%8D%E5%A4%84%E7%90%86%EF%BC%8C%E5%8F%AA%E6%9C%89text%E7%B1%BB%E5%9E%8B%E4%BC%9A%E5%88%86%E8%AF%8D%E5%A4%84%E7%90%86%EF%BC%8C%E5%85%B6%E5%AE%83%E7%B1%BB%E5%9E%8B%E5%9D%87%E4%B8%8D%E5%88%86%E8%AF%8D%E3%80%82%20%20%0A%3E%20%E4%B8%8D%E9%9C%80%E8%A6%81%E5%88%86%E8%AF%8D%E7%9A%84%E5%AD%97%E6%AE%B5%E4%BC%9A%E5%B0%86%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%E8%BF%9B%E8%A1%8C%E5%85%A8%E5%8C%B9%E9%85%8D%20%20%0A%3E%20%E9%9C%80%E8%A6%81%E5%88%86%E8%AF%8D%E7%9A%84%E5%AD%97%E6%AE%B5%E6%98%AF%E5%B0%86%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%E5%88%86%E8%AF%8D%E5%90%8E%E5%86%8D%E9%80%90%E4%B8%AA%E5%8C%B9%E9%85%8D%20%20%0A%0A%60%60%60%0AGET%20%2Fems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22multi_match%22%3A%7B%0A%20%20%20%20%20%20%22query%22%3A%22query%20request%22%2C%0A%20%20%20%20%20%20%22fields%22%3A%5B%22name%22%2C%22content%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%23%23%23%23%23%23%202.10.%20%E5%A4%9A%E5%AD%97%E6%AE%B5%E5%88%86%E8%AF%8D%E6%9F%A5%E8%AF%A2(query_string)%0A%3E%20%E5%9C%A8%E6%9F%A5%E8%AF%A2%E8%BF%87%E7%A8%8B%E4%B8%AD%E4%BC%9A%E5%85%88%E5%B0%86%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%E6%A0%B9%E6%8D%AE%E5%BD%93%E5%89%8D%E5%88%86%E8%AF%8D%E5%99%A8%E5%88%86%E8%AF%8D%E5%90%8E%E5%86%8D%E8%BF%9B%E8%A1%8C%E6%9F%A5%E8%AF%A2%0A%3E%20%E4%B8%8Emulti_match%E7%9B%B8%E6%AF%94%EF%BC%8C%E6%9C%80%E5%A4%A7%E7%9A%84%E5%A5%BD%E5%A4%84%E5%B0%B1%E6%98%AF%E5%9C%A8%E6%9F%A5%E8%AF%A2%E4%B8%AD%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E5%88%86%E8%AF%8D%E5%99%A8%0A%0A%60%60%60%0AGET%20%2Fems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%20%7B%0A%20%20%20%20%22query_string%22%3A%20%7B%0A%20%20%20%20%20%20%22query%22%3A%20%22query%20request%22%2C%0A%20%20%20%20%20%20%22fields%22%3A%20%5B%22name%22%2C%22content%22%5D%2C%0A%20%20%20%20%20%20%22analyzer%22%3A%22standard%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0AGET%20_analyze%0A%7B%0A%20%20%22analyzer%22%3A%20%22standard%22%2C%20%20--%20simple%0A%20%20%22text%22%3A%20%5B%22query%20request%22%5D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.11.%20%E9%AB%98%E4%BA%AE%E6%98%BE%E7%A4%BA%0A%3E%20%E5%8E%9F%E7%90%86%3A%20%E5%B0%86%E5%8E%9F%E5%A7%8B%E7%9A%84%E6%A3%80%E7%B4%A2%E7%BB%93%E6%9E%9C%E4%B8%8E%E6%A3%80%E7%B4%A2%E5%85%B3%E9%94%AE%E8%AF%8D%E7%9A%84%E5%88%86%E8%AF%8D%E4%BD%9C%E5%8C%B9%E9%85%8D%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%83%BD%E5%AF%B9%E5%BA%94%E4%B8%8A%E5%88%99%E5%AF%B9%E5%9C%A8%E8%AF%A5%E8%AF%8D%E7%9A%84%E5%89%8D%E5%90%8E%E9%BB%98%E8%AE%A4%E5%8A%A0%E4%B8%8A%5C%3Cem%3E%0A%0A%3E%20%E5%A4%9A%E5%AD%97%E6%AE%B5%E6%9F%A5%E8%AF%A2%E5%B9%B6%E5%AF%B9content%E5%AD%97%E6%AE%B5%E4%B8%AD%E7%9A%84%E6%9F%A5%E8%AF%A2%E5%88%86%E8%AF%8D%E9%AB%98%E4%BA%AE%E6%98%BE%E7%A4%BA%0A%60%60%60%0AGET%20%2Fems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22multi_match%22%3A%7B%0A%20%20%20%20%20%20%22query%22%3A%22query%20request%22%2C%0A%20%20%20%20%20%20%22fields%22%3A%5B%22name%22%2C%22content%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22highlight%22%3A%7B%0A%20%20%20%20%22fields%22%3A%7B%22content%22%3A%7B%7D%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E8%87%AA%E5%AE%9A%E4%B9%89%E9%AB%98%E4%BA%AE%E6%98%BE%E7%A4%BA%E6%A0%87%E7%AD%BE%0A%0A%60%60%60%0AGET%20%2Fems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22multi_match%22%3A%7B%0A%20%20%20%20%20%20%22query%22%3A%22query%20request%22%2C%0A%20%20%20%20%20%20%22fields%22%3A%5B%22name%22%2C%22content%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22highlight%22%3A%7B%0A%20%20%20%20%22fields%22%3A%7B%22content%22%3A%7B%7D%7D%2C%0A%20%20%20%20%22pre_tags%22%3A%22%3Cspan%20style%3D'color%3Ared'%3E%22%2C%0A%20%20%20%20%22post_tags%22%3A%22%3Cspan%3E%22%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E5%AF%B9%E6%89%80%E6%9C%89%E6%9F%A5%E8%AF%A2%E5%AD%97%E6%AE%B5%E9%AB%98%E4%BA%AE%E6%98%BE%E7%A4%BA%E6%A0%87%E7%AD%BE%20%20%0A%3E%20require_field_match%3Afalse%0A%60%60%60%0AGET%20%2Fems%2F_doc%2F_search%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22multi_match%22%3A%7B%0A%20%20%20%20%20%20%22query%22%3A%22query%22%2C%0A%20%20%20%20%20%20%22fields%22%3A%5B%22content%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22highlight%22%3A%7B%0A%20%20%20%20%22fields%22%3A%7B%22*%22%3A%7B%7D%7D%2C%0A%20%20%20%20%22pre_tags%22%3A%22%3Cspan%20style%3D'color%3Ared'%3E%22%2C%0A%20%20%20%20%22post_tags%22%3A%22%3Cspan%3E%22%2C%0A%20%20%20%20%22require_field_match%22%3Afalse%0A%20%20%7D%0A%7D%0A%0A%7B%0A%20%20%20%20%22_index%22%20%3A%20%22ems%22%2C%0A%20%20%20%20%22_type%22%20%3A%20%22_doc%22%2C%0A%20%20%20%20%22_id%22%20%3A%20%22svXPBXsBjA6v-uGtDIi2%22%2C%0A%20%20%20%20%22_score%22%20%3A%200.89701396%2C%0A%20%20%20%20%22_source%22%20%3A%20%7B%0A%20%20%20%20%20%20%22name%22%20%3A%20%22query%22%2C%0A%20%20%20%20%20%20%22age%22%20%3A%2039%2C%0A%20%20%20%20%20%20%22bir%22%20%3A%20%222008-12-21%22%2C%0A%20%20%20%20%20%20%22content%22%20%3A%20%22it's%20operation%20for%20query%20the%20result%20your%20wannt%22%2C%0A%20%20%20%20%20%20%22address%22%20%3A%20%22Australia%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22highlight%22%20%3A%20%7B%0A%20%20%20%20%20%20%22name%22%20%3A%20%5B%0A%20%20%20%20%20%20%20%20%22%3Cspan%20style%3D'color%3Ared'%3Equery%3Cspan%3E%22%0A%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%22content%22%20%3A%20%5B%0A%20%20%20%20%20%20%20%20%22it's%20operation%20for%20%3Cspan%20style%3D'color%3Ared'%3Equery%3Cspan%3E%20the%20result%20your%20wannt%22%0A%20%20%20%20%20%20%5D%0A%7D%0A%60%60%60%0A%23%23%23%23%20%E7%B4%A2%E5%BC%95%E5%BA%93%E5%8E%9F%E7%90%86%0A%0A!%5B11635bc1dd2e7afa38766b0e48a10449.png%5D(en-resource%3A%2F%2Fdatabase%2F584%3A1)%0A%0A%3E%20%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%20%20%0A1.%E9%80%9A%E8%BF%87%E6%89%AB%E6%8F%8F%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%8C%89%E7%B4%A2%E5%BC%95%E4%B8%AD%E7%9A%84mapping%E5%AE%9A%E4%B9%89%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E5%88%86%E8%AF%8D%20%20%20%0A2.%E5%AF%B9%E6%AF%8F%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%E4%B8%AD%E7%9A%84%E5%88%86%E8%AF%8D%E7%BB%93%E6%9E%9C%E5%9C%A8%E7%B4%A2%E5%BC%95%E5%8C%BA%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%EF%BC%8C%E7%B4%A2%E5%BC%95%E4%B8%AD%E5%8C%85%E5%90%AB%E8%AF%A5%E8%AF%8D%E5%9C%A8%E6%96%87%E7%AB%A0%E4%B8%AD%E5%87%BA%E7%8E%B0%E7%9A%84%E4%BD%8D%E7%BD%AE%E5%92%8C%E6%AC%A1%E6%95%B0%20%20%0A3.%E5%85%83%E6%95%B0%E6%8D%AE%E5%8C%BA%E5%AD%98%E5%82%A8%E4%BA%86%E4%BB%A5_id%E6%89%93%E5%A4%B4%E6%96%87%E6%A1%A3%E7%9A%84%E5%8E%9F%E5%A7%8B%E6%95%B0%E6%8D%AE%20%20%0A%0A%3E%20%E6%A3%80%E7%B4%A2%E7%B4%A2%E5%BC%95%20%20%0A1.%E6%A0%B9%E6%8D%AE%E5%85%B3%E9%94%AE%E8%AF%8D%E5%AE%9A%E4%BD%8D%E7%B4%A2%E5%BC%95%20%20%0A2.%E6%A0%B9%E6%8D%AE%E7%B4%A2%E5%BC%95%E5%AE%9A%E4%BD%8D%E6%96%87%E6%A1%A3%0A%0A%23%23%23%23%20%E5%88%86%E8%AF%8D%E5%99%A8%0A%23%23%23%23%23%201%20%E5%AE%9A%E4%B9%89%EF%BC%9A%0A%3E%20%E5%B0%B1%E6%98%AF%E5%B0%86%E4%B8%80%E4%B8%AA%E6%96%87%E6%9C%AC%E9%87%8C%E9%9D%A2%E7%9A%84%E5%85%B3%E9%94%AE%E8%AF%8D%E6%8B%86%E5%88%86%E5%87%BA%E6%9D%A5%20%20%0A%E4%BE%8B%E5%A6%82%EF%BC%9A%E6%88%91%E6%98%AF%E4%B8%AD%E5%9B%BD%E4%BA%BA%20%20%0A%E6%8B%86%E5%88%86%E5%87%BA%3A%20%E4%B8%AD%E5%9B%BD%7C%E4%B8%AD%E5%9B%BD%E4%BA%BA%20%20%0A%E5%8E%BB%E6%8E%89%E5%81%9C%E7%94%A8%E8%AF%8D%E5%92%8C%E8%AF%AD%E6%B0%94%E8%AF%8D%20%20%0A%0A%23%23%23%23%23%202%20ES%E6%8F%90%E4%BE%9B%E7%9A%84%E5%88%86%E8%AF%8D%E5%99%A8%EF%BC%9A%0A1.%20%E9%BB%98%E8%AE%A4%E6%A0%87%E5%87%86%E5%88%86%E8%AF%8D%E5%99%A8%EF%BC%9Astandard%0A%3E%20%E5%AF%B9%E8%8B%B1%E6%96%87%E8%BF%9B%E8%A1%8C%E5%8D%95%E8%AF%8D%E5%88%86%E8%AF%8D%EF%BC%8C%E5%AF%B9%E4%B8%AD%E6%96%87%E8%BF%9B%E8%A1%8C%E5%8D%95%E5%AD%97%E5%88%86%E8%AF%8D%E3%80%82%0A%0A%60%60%60%0AGET%20_analyze%0A%7B%0A%20%20%22analyzer%22%3A%20%22standard%22%2C%0A%20%20%22text%22%3A%22redis%20%E9%9D%9E%E5%B8%B8%E5%A5%BD%E7%94%A8%20111%22%0A%7D%0A%0A%7B%0A%20%20%22tokens%22%20%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22token%22%20%3A%20%22redis%22%2C%0A%20%20%20%20%20%20%22start_offset%22%20%3A%200%2C%0A%20%20%20%20%20%20%22end_offset%22%20%3A%205%2C%0A%20%20%20%20%20%20%22type%22%20%3A%20%22%3CALPHANUM%3E%22%2C%0A%20%20%20%20%20%20%22position%22%20%3A%200%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22token%22%20%3A%20%22%E9%9D%9E%22%2C%0A%20%20%20%20%20%20%22start_offset%22%20%3A%206%2C%0A%20%20%20%20%20%20%22end_offset%22%20%3A%207%2C%0A%20%20%20%20%20%20%22type%22%20%3A%20%22%3CIDEOGRAPHIC%3E%22%2C%0A%20%20%20%20%20%20%22position%22%20%3A%201%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22token%22%20%3A%20%22%E5%B8%B8%22%2C%0A%20%20%20%20%20%20%22start_offset%22%20%3A%207%2C%0A%20%20%20%20%20%20%22end_offset%22%20%3A%208%2C%0A%20%20%20%20%20%20%22type%22%20%3A%20%22%3CIDEOGRAPHIC%3E%22%2C%0A%20%20%20%20%20%20%22position%22%20%3A%202%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22token%22%20%3A%20%22%E5%A5%BD%22%2C%0A%20%20%20%20%20%20%22start_offset%22%20%3A%208%2C%0A%20%20%20%20%20%20%22end_offset%22%20%3A%209%2C%0A%20%20%20%20%20%20%22type%22%20%3A%20%22%3CIDEOGRAPHIC%3E%22%2C%0A%20%20%20%20%20%20%22position%22%20%3A%203%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22token%22%20%3A%20%22%E7%94%A8%22%2C%0A%20%20%20%20%20%20%22start_offset%22%20%3A%209%2C%0A%20%20%20%20%20%20%22end_offset%22%20%3A%2010%2C%0A%20%20%20%20%20%20%22type%22%20%3A%20%22%3CIDEOGRAPHIC%3E%22%2C%0A%20%20%20%20%20%20%22position%22%20%3A%204%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22token%22%20%3A%20%22111%22%2C%0A%20%20%20%20%20%20%22start_offset%22%20%3A%2011%2C%0A%20%20%20%20%20%20%22end_offset%22%20%3A%2014%2C%0A%20%20%20%20%20%20%22type%22%20%3A%20%22%3CNUM%3E%22%2C%0A%20%20%20%20%20%20%22position%22%20%3A%205%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D%0A%60%60%60%0A%0A%0A2.%20%E7%AE%80%E5%8D%95%E5%88%86%E8%AF%8D%E5%99%A8simple%0A%3E%20%E8%8B%B1%E6%96%87%E5%8D%95%E8%AF%8D%E5%88%86%E8%AF%8D%E5%8E%BB%E6%8E%89%E6%95%B0%E5%AD%97%EF%BC%8C%E4%B8%AD%E6%96%87%E4%B8%8D%E5%88%86%E8%AF%8D%0A%0A%0A%0A%60%60%60%0AGET%20_analyze%0A%7B%0A%20%20%22analyzer%22%3A%20%22simple%22%2C%0A%20%20%22text%22%3A%22redis%20%E9%9D%9E%E5%B8%B8%E5%A5%BD%E7%94%A8%20111%22%0A%7D%0A%0A%7B%0A%20%20%22tokens%22%20%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22token%22%20%3A%20%22redis%22%2C%0A%20%20%20%20%20%20%22start_offset%22%20%3A%200%2C%0A%20%20%20%20%20%20%22end_offset%22%20%3A%205%2C%0A%20%20%20%20%20%20%22type%22%20%3A%20%22word%22%2C%0A%20%20%20%20%20%20%22position%22%20%3A%200%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22token%22%20%3A%20%22%E9%9D%9E%E5%B8%B8%E5%A5%BD%E7%94%A8%22%2C%0A%20%20%20%20%20%20%22start_offset%22%20%3A%206%2C%0A%20%20%20%20%20%20%22end_offset%22%20%3A%2010%2C%0A%20%20%20%20%20%20%22type%22%20%3A%20%22word%22%2C%0A%20%20%20%20%20%20%22position%22%20%3A%201%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D%0A%60%60%60%0A%0A%0A%23%23%23%23%23%203%20ik%E5%88%86%E8%AF%8D%E5%99%A8%0Ahttps%3A%2F%2Fgithub.com%2Fmedcl%2Felasticsearch-analysis-ik%0A%0A%3E%20%E8%A6%81%E6%B1%82%E4%BD%BF%E7%94%A8%E7%9A%84ik%E5%88%86%E8%AF%8D%E5%99%A8%E7%9A%84%E7%89%88%E6%9C%AC%E5%BF%85%E9%A1%BB%E4%B8%8EES%E7%89%88%E6%9C%AC%E4%B8%A5%E6%A0%BC%E4%B8%80%E8%87%B4%0A1.%20%E5%9C%A8%E7%BA%BF%E5%AE%89%E8%A3%85%0A%3E%20%E4%BC%9A%E6%8A%8Aplugin%E5%AE%89%E8%A3%85%E5%9C%A8elasticsearch-7.13.4%2Fplugins%E7%9B%AE%E5%BD%95%E4%B8%8B%20%20%0A%60%60%60%0Acd%20%2Fhome%2Fes%2Felasticsearch-7.13.4%2Fbin%0A.%2Fbin%2Felasticsearch-plugin%20install%20https%3A%2F%2Fgithub.com%2Fmedcl%2Felasticsearch-analysis-ik%2Freleases%2Fdownload%2Fv6.3.0%2Felasticsearch-analysis-ik-7.13.4.zip%0A%60%60%60%0A%0A2.%20%E6%9C%AC%E5%9C%B0%E5%AE%89%E8%A3%85%0A%3E%20%E4%B8%8B%E8%BD%BDzip%E5%8C%85%EF%BC%9A%20https%3A%2F%2Fgithub.com%2Fmedcl%2Felasticsearch-analysis-ik%2Freleases%0A%0A%60%60%60%0A%5Bes%40master%20~%5D%24%20unzip%20%20elasticsearch-analysis-ik-7.13.4.zip%20%20-d%20.%2Felasticsearch-ik%0A%5Bes%40master%20~%5D%24%20mv%20elasticsearch-ik%2F%20elasticsearch-7.13.4%2Fplugins%2F%0A%60%60%60%0A%0A%3E%20%E9%87%8D%E5%90%AFES%0A%60%60%60%0A%5Bes%40master%20bin%5D%24%20ps%20-ef%20%7C%20grep%20elastic%0A%5Bes%40master%20bin%5D%24%20kill%20-9%2010965%0A%5Bes%40master%20bin%5D%24%20.%2Felasticsearch%0A%60%60%60%0A%0A!%5B710d8b8a7602413d8cbe5422d4294b65.png%5D(en-resource%3A%2F%2Fdatabase%2F586%3A1)%0A%0A%0A3.%20ik_max_word%20%E5%92%8C%20ik_smart%20%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%3F%0A%3E%20ik_max_word%3A%20%E4%BC%9A%E5%B0%86%E6%96%87%E6%9C%AC%E5%81%9A%E6%9C%80%E7%BB%86%E7%B2%92%E5%BA%A6%E7%9A%84%E6%8B%86%E5%88%86%EF%BC%8C%E6%AF%94%E5%A6%82%E4%BC%9A%E5%B0%86%E2%80%9C%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E5%9B%BD%E6%AD%8C%E2%80%9D%E6%8B%86%E5%88%86%E4%B8%BA%E2%80%9C%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%2C%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%2C%E4%B8%AD%E5%8D%8E%2C%E5%8D%8E%E4%BA%BA%2C%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%2C%E4%BA%BA%E6%B0%91%2C%E4%BA%BA%2C%E6%B0%91%2C%E5%85%B1%E5%92%8C%E5%9B%BD%2C%E5%85%B1%E5%92%8C%2C%E5%92%8C%2C%E5%9B%BD%E5%9B%BD%2C%E5%9B%BD%E6%AD%8C%E2%80%9D%EF%BC%8C%E4%BC%9A%E7%A9%B7%E5%B0%BD%E5%90%84%E7%A7%8D%E5%8F%AF%E8%83%BD%E7%9A%84%E7%BB%84%E5%90%88%EF%BC%8C%E9%80%82%E5%90%88%20Term%20Query%EF%BC%9B%0A%0A%3E%20ik_smart%3A%20%E4%BC%9A%E5%81%9A%E6%9C%80%E7%B2%97%E7%B2%92%E5%BA%A6%E7%9A%84%E6%8B%86%E5%88%86%EF%BC%8C%E6%AF%94%E5%A6%82%E4%BC%9A%E5%B0%86%E2%80%9C%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E5%9B%BD%E6%AD%8C%E2%80%9D%E6%8B%86%E5%88%86%E4%B8%BA%E2%80%9C%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%2C%E5%9B%BD%E6%AD%8C%E2%80%9D%EF%BC%8C%E9%80%82%E5%90%88%20Phrase%20%E6%9F%A5%E8%AF%A2%E3%80%82%0A%0A4.%20%E4%BD%BF%E7%94%A8%0A%3E%20%22content%22%3A%7B%22type%22%3A%20%22text%22%2C%20%22analyzer%22%3A%20%22ik_max_word%22%7D%2C%0A%0A%60%60%60%0APUT%20%2Fems%2F%0A%7B%0A%20%20%22mappings%22%3A%20%7B%0A%20%20%20%20%22properties%22%3A%20%7B%0A%20%20%20%20%20%20%22name%22%3A%7B%22type%22%3A%20%22keyword%22%7D%2C%0A%20%20%20%20%20%20%22age%22%3A%7B%22type%22%3A%20%22integer%22%7D%2C%0A%20%20%20%20%20%20%22bir%22%3A%7B%22type%22%3A%20%22date%22%7D%2C%0A%20%20%20%20%20%20%22content%22%3A%7B%22type%22%3A%20%22text%22%2C%20%22analyzer%22%3A%20%22ik_max_word%22%7D%2C%0A%20%20%20%20%20%20%22address%22%3A%7B%22type%22%3A%20%22keyword%22%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0AGET%20%2Fems%2F_mapping%0A%0APOST%20%2Fems%2F_doc%2F_bulk%0A%7B%20%22index%22%20%3A%7B%7D%7D%0A%7B%20%22name%22%3A%22chris%22%2C%20%22age%22%3A23%2C%20%22bir%22%3A%222016-12-21%22%2C%20%22content%22%3A%22%E7%BE%8E%E5%9B%BD%E7%95%99%E7%BB%99%E4%BC%8A%E6%8B%89%E5%85%8B%E7%9A%84%E6%98%AF%E4%B8%AA%E7%83%82%E6%91%8A%E5%AD%90%E5%90%97.%22%2C%20%22address%22%3A%22China%22%7D%0A%7B%20%22index%22%20%3A%20%7B%7D%20%7D%0A%7B%20%22name%22%3A%22john%22%2C%20%22age%22%3A33%2C%20%22bir%22%3A%222018-09-12%22%2C%20%22content%22%3A%22%E5%85%AC%E5%AE%89%E9%83%A8%EF%BC%9A%E5%90%84%E5%9C%B0%E6%A0%A1%E8%BD%A6%E5%B0%86%E4%BA%AB%E6%9C%80%E9%AB%98%E8%B7%AF%E6%9D%83%22%2C%20%22address%22%3A%22US%22%7D%0A%7B%20%22index%22%20%3A%20%7B%7D%7D%0A%7B%20%22name%22%3A%22petter%22%2C%20%22age%22%3A13%2C%20%22bir%22%3A%222001-11-09%22%2C%20%22content%22%3A%22%E4%B8%AD%E9%9F%A9%E6%B8%94%E8%AD%A6%E5%86%B2%E7%AA%81%E8%B0%83%E6%9F%A5%EF%BC%9A%E9%9F%A9%E8%AD%A6%E5%B9%B3%E5%9D%87%E6%AF%8F%E5%A4%A9%E6%89%A31%E8%89%98%E4%B8%AD%E5%9B%BD%E6%B8%94%E8%88%B9%22%2C%20%22address%22%3A%22Franch%22%7D%0A%7B%20%22create%22%20%3A%20%7B%7D%20%7D%0A%7B%20%22name%22%3A%22Ethen%22%2C%20%20%22age%22%3A43%2C%20%22bir%22%3A%222019-09-01%22%2C%20%22content%22%3A%22%E4%B8%AD%E5%9B%BD%E9%A9%BB%E6%B4%9B%E6%9D%89%E7%9F%B6%E9%A2%86%E4%BA%8B%E9%A6%86%E9%81%AD%E4%BA%9A%E8%A3%94%E7%94%B7%E5%AD%90%E6%9E%AA%E5%87%BB%20%E5%AB%8C%E7%8A%AF%E5%B7%B2%E8%87%AA%E9%A6%96%22%2C%20%22address%22%3A%22China%22%7D%0A%0A%0APOST%20%2Fems%2F_doc%2F_search%20%0A%7B%0A%20%20%22query%22%3A%7B%0A%20%20%20%20%22term%22%3A%7B%0A%20%20%20%20%20%20%22content%22%3A%7B%0A%20%20%20%20%20%20%20%20%22value%22%3A%22%E4%B8%AD%E5%9B%BD%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%204%20ik%E6%89%A9%E5%B1%95%E8%AF%8D%E5%92%8C%E5%81%9C%E7%94%A8%E8%AF%8D%0A%0A%23%23%23%23%23%23%204.1.%20%E6%89%A9%E5%B1%95%E8%AF%8D%0A1.%20%E4%BF%AE%E6%94%B9IKAnalyzer.cfg.xml%0A%60%60%60%0A%5Bes%40master%20config%5D%24%20vi%20IKAnalyzer.cfg.xml%0A--%20%E4%BF%AE%E6%94%B9%E4%B8%BA%EF%BC%9A%0A%3Centry%20key%3D%22ext_dict%22%3Eext.dic%3C%2Fentry%3E%0A%60%60%60%0A2.%20%E5%88%9B%E5%BB%BAext.dict%E6%96%87%E4%BB%B6%0A%60%60%60%0A%5Bes%40master%20config%5D%24%20cp%20extra_main.dic%20ext.dict%0Avi%20ext.dict%0A%E7%A2%B0%E7%93%B7%0A%E6%9D%8E%E6%AF%9B%E6%AF%9B%0A%60%60%60%20%0A%0A3.%20%E9%87%8D%E5%90%AFes%0A%0A%23%23%23%23%23%23%204.2.%20%E5%81%9C%E7%94%A8%E8%AF%8D%0A%0A1.%20%E4%BF%AE%E6%94%B9IKAnalyzer.cfg.xml%0A%60%60%60%0A%5Bes%40master%20config%5D%24%20vi%20IKAnalyzer.cfg.xml%0A--%20%E4%BF%AE%E6%94%B9%E4%B8%BA%EF%BC%9A%0A%3Centry%20key%3D%22ext_stopwords%22%3Estopext.dic%3C%2Fentry%3E%0A%60%60%60%0A2.%20%E5%88%9B%E5%BB%BAext.dict%E6%96%87%E4%BB%B6%0A%60%60%60%0A%5Bes%40master%20config%5D%24%20cp%20ext.dic%20stopext.dict%0Avi%20ext.dict%0A%E9%81%87%E5%88%B0%0A%60%60%60%20%0A%0A3.%20%E9%87%8D%E5%90%AFes%0A%0A%23%23%23%23%23%23%204.3.%20%E5%90%AF%E7%94%A8%E8%BF%9C%E7%A8%8B%E6%89%A9%E5%B1%95%E8%AF%8D%E5%92%8C%E5%81%9C%E7%94%A8%E8%AF%8D%0A%0A%E6%B3%A8%E6%84%8F%EF%BC%9A%0A1.%20%E6%9B%B4%E6%96%B0%E8%BF%9C%E7%A8%8B%E8%AF%8D%E5%BA%93%E7%9A%84%E7%83%AD%E8%AF%8D%E5%90%8E%E4%B8%8D%E4%BC%9A%E5%AF%B9%E5%B7%B2%E7%94%9F%E6%88%90%E7%9A%84%E7%B4%A2%E5%BC%95%E7%9A%84%E6%96%87%E6%A1%A3%E6%95%B0%E6%8D%AE%E4%BA%A7%E7%94%9F%E5%BD%B1%E5%93%8D%EF%BC%8C%20%E5%8F%AA%E8%83%BD%E5%AF%B9%E5%90%8E%E7%BB%AD%E6%96%B0%E5%8A%A0%E5%85%A5%E7%9A%84%E6%96%87%E6%A1%A3%E6%95%B0%E6%8D%AE%E7%94%9F%E6%95%88%0A2.%20%E6%89%80%E4%BB%A5%E6%9B%B4%E6%96%B0%E8%BF%9C%E7%A8%8B%E8%AF%8D%E5%BA%93%E5%90%8E%E9%9C%80%E8%A6%81%E6%8A%8A%E5%8E%9F%E6%9D%A5%E7%9A%84%E6%96%87%E6%A1%A3%E6%95%B0%E6%8D%AE%E9%87%8D%E6%96%B0%E5%BD%95%E5%85%A5

SpringBoot 启动参数

创建时间:2022/8/10 21:34
更新时间:2022/8/10 21:49
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzI4NTM1NDgwNw==&mid=2247526292&idx=2&sn=d5243b94e72ef638e7ab579b2f72044f&chksm=ebef59ccdc98d0da6c867bfd5086e55b61d729be0a8f7c590dcd9ce48b45df8264905e93c334&mpshare=1&scene=24&srcid=0803fGRB7Z2FEwdonZh5Qys2&sharer_sharetime=1659490346617&sharer_shareid=8f247ffae0fc886917cba955f4d8c07b&key=0c39e6df4357455006710ee7a3a967f35758aa58e26dc437768d063f70f6390896575d76594b0a0bcbc0af2056d812977b86cb1999949b1a7511cc883525e2a1f3140a79745fcc87265ab1bd02417c0c0887f8c698dfd5257b7e6274e06676c33a436acf2809dc3e0a359495d405f52fea608fe1ed48994dd2dd32872ee4f296&ascene=14&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=63070517&lang=en&exportkey=AegEwpW1melco4SD5Dc6EtY%3D&acctmode=0&pass_ticket=WJvdvo5AEKTNS4bX6My1ikLg6XaZssjgbitYt6JfRFeBVFe3JPiKo7Q6M0EW0huA&wx_header=0&fontgear=3

1. 配置文件配置

1.1 application.yml

# springboot多环境配置
# springboot多环境配置
# 端口,项目上下文
server:
  port: 8080
  servlet:
    context-path: /springboot-params-demo

# 默认启动的是测试环境配置
spring:
  profiles:
    active: test

# 日志输出配置
logging:
  level:
    root: INFO
    org:
      springframework:
        security: WARN
        web: ERROR
  file:
    path: ./logs
    name: './logs/springboot-params-demo.log'
  pattern:
    file: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n'
    console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n'

1.2 application-test.yml

# 自定义的参数
myParam: 'on'

1.3 application-prod.yml

# 自定义的参数
myParam: 'close'

获取自定义参数

package com.demo.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Slf4j
public class MyParamRunner implements CommandLineRunner {
   
     

    /**
     * 自定义测试参数
     */
    @Value("${myParam}")
    String myParam;

    /**
     * 获取环境变量参数
     */
    @Autowired
    Environment environment;

    @Override
    public void run(String... args) throws Exception {
   
     
        log.info("本地设置的参数myParam为:{}", myParam);
        log.info(environment.toString());
        log.info(String.valueOf(Arrays.asList(environment.getActiveProfiles())));
    }
}

2. 启动jar包进行测试

2.1 直接启动

java -jar /usr/local/springboot_demos/springboot-port8001/springboot-jvm-params-1.0-SNAPSHOT.jar

2.2 修改启动配置

2.2.1 系统变量
java -jar -Dspring.profiles.active=prod /usr/local/springboot_demos/springboot-port8001/springboot-jvm-params-1.0-SNAPSHOT.jar

2.2.2 命令行参数
java -jar /usr/local/springboot_demos/springboot-port8001/springboot-jvm-params-1.0-SNAPSHOT.jar --spring.profiles.active=prod --myParam='test'

2.2.3 同时修改
java -jar -DmyParam='test1' /usr/local/springboot_demos/springboot-port8001/springboot-jvm-params-1.0-SNAPSHOT.jar --spring.profiles.active=prod --myParam='test2'

2.3 参数的优先级

配置文件变量 < JVM系统变量 < 命令行参数(注意:优先级由低到高,非常多的启动命令中传参也是这个道理)

3. springboot启动参数解释

/usr/local/jdk/jdk1.8.0_261/bin/java -jar -server \          ## 服务模式,linux默认是server模式,window默认是client参数 
-XX:+HeapDumpOnOutOfMemoryError \              ## 当OOM发生时自动生成Heap Dump文件
-XX:HeapDumpPath=/usr/local/springboot_demos/springboot-port8001/dump/heap/oom.hprof \ ## 指定发生OOM时生成Dump文件存储位置
-Djava.io.tmpdir=/usr/local/springboot_demos/springboot-port8001/tmp/ \     ## 指定操作系统缓存的临时目录
-Dserver.port=8001 \                 ## web服务使用端口
-Dcom.sun.management.jmxremote \              ## 是否支持远程JMX访问,默认true
-Dcom.sun.management.jmxremote.port=5103 \            ## 配置jmx远程connection的端口号,要确认这个端口没有被占用
-Dcom.sun.management.jmxremote.rmi.port=6103 \           ## JMX在远程连接时,会随机开启一个RMI端口作为连接的数据端口
-Dcom.sun.management.jmxremote.authenticate=false \          ## 是否需要开启用户认证,默认开启
-Dcom.sun.management.jmxremote.ssl=false \            ## 是否连接开启SSL加密,默认开启
-Dcom.sun.management.jmxremote.access.file=/usr/local/jdk/jdk1.8.0_261/jre/lib/management/jmxremote.access \ 对访问用户的权限授权的文件的路径,默认路径是${
   
     JRE_HOME}/lib/management/jmxremote.access
-Xmx256m \                    ## 设置堆最大空间为256m
-Xms256m \                    ## 设置堆最小空间为256m
-XX:+DisableExplicitGC \                ## 禁止手动的system.gc
-Xloggc:/usr/local/springboot_demos/springboot-port8001/logs/springboot-jvm-params_gc.%t.log \ gc日志存放的位置
-XX:+PrintHeapAtGC \                 ## HotSpot在GC前后都会将GC堆的概要状况输出到log中
-XX:+PrintTenuringDistribution \              ## 打印Survivor对象年龄分布
-XX:+PrintGCApplicationStoppedTime \             ## 预估垃圾收集"Stop the world"暂停所阻塞的时间
-XX:+PrintGCTaskTimeStamps \               ## 打印gc线程的时间戳
-XX:+PrintGCDetails \                 ## 打印gc详情
-XX:+PrintGCDateStamps \                ## 日志开头显示日期以及时间
-Dserver.connection-timeout=60000 \              ## HTTP请求超时时间
-Dserver.tomcat.accept-count=1000 \              ## 所有可能的请求处理线程正在使用时,传入连接请求的最大队列长度
-Dserver.tomcat.max-threads=300 \              ## 最大工作线程数
-Dserver.tomcat.min-spare-threads=65 \             ## 最小工作线程数
-Dserver.tomcat.accesslog.enabled=false \            ## 启用访问你日志
-Dserver.tomcat.accesslog.directory=/usr/local/springboot_demos/springboot-port8001/logs/ \ ## 日志文件路径
-Dserver.tomcat.accesslog.prefix=access_log \           ## 日志文件名前缀
-Dserver.tomcat.accesslog.pattern=combined \           ## 日志格式
-Dserver.tomcat.accesslog.suffix=.log \             ## 日志文件后缀
-Dserver.tomcat.accesslog.file-date-format=.yyyy-MM-dd          ## 放在日志文件名中的日期格式 
-Dserver.tomcat.accesslog.rotate=true \             ## 是否启用访问日志分割
-Dserver.tomcat.accesslog.rename-on-rotate=true \          ## 推迟在文件名中加入日期表示,直到日志分割时
-Dserver.tomcat.accesslog.request-attributes-enabled=true \        ## 为请求使用的IP地址、主机名、协议和端口设置请求属性
-Dserver.tomcat.accesslog.buffered=true \            ## 缓存日志定期刷新输出(建议设置为true,否则当有请求立即打印日志对服务的响应会有影响)
-XX:NewRatio=4 \                  ## 设置Yang和Old的比例,设置4则Old是Yang的4倍,即Yang占1/5
-XX:SurvivorRatio=8 \                 ## 设置Eden和Suivior的比例,Eden:S0:S1=8:1:1
-XX:MaxTenuringThreshold=15 \               ## 在新生代对象存活次数(经过Minor GC的次数)超过n后,就会晋升到老年代
-XX:TargetSurvivorRatio=90 \               ## 在新生代的对象不一定要满足存活年龄达到MaxTenuringThreshold才能去老年代,当Survivor空间中相同年龄所有对象大小总和大于[Desired survivor size]时,年龄大于或等于该年龄的对象直接进入老年代。[Desired survivor size]=单个survivor大小*TargetSurvivorRatio百分比
-XX:+UseCMSInitiatingOccupancyOnly \                                                    指在使用CMS收集器的情况下,老年代使用了指定阈值的内存时,触发FullGC
-XX:CMSInitiatingOccupancyFraction=70 \             ## 指在使用CMS收集器的情况下,老年代使用达到70%,出发CMS垃圾回收
-XX:ParallelGCThreads=8 \                ## parallel回收的时候可以设置年轻代的并行线程数,取决于cpu核数
-XX:ConcGCThreads=2 \                 ## 设置并行标记的线程数。将n设置为并行垃圾回收线程数(ParallelGCThreads)的 1/4 左右。
-XX:-UseGCOverheadLimit \                ## jvm gc行为中超过98%以上的时间去释放小于2%的堆空间时会报“GC overhead limit exceeded”错误,此参数避免此报错
-XX:+UseParNewGC \                  ## 开启此参数使用ParNew & serial old搜集器(不推荐)使用这个参数后会在新生代进行并行回收
-XX:+UseConcMarkSweepGC \                ## 开启此参数使用ParNew & CMS(serial old为替补)搜集器
-XX:CMSFullGCsBeforeCompaction=1 \              ## 设置在几次CMS垃圾收集后,触发一次内存整理
-XX:+CMSParallelRemarkEnabled \               ## 降低标记停顿
-XX:+CMSScavengeBeforeRemark \               ## 开启或关闭在 CMS-remark 阶段之前的清除(Young GC)尝试
-XX:+ParallelRefProcEnabled \               ## 并行处理Reference,加快处理速度,缩短耗时
-XX:+UseCMSCompactAtFullCollection \             ## 年老代使用CMS,默认是不会整理堆碎片的。设置此配置打开对年老代的压缩,即执行Full GC后对内存进行整理压缩,免得产生内存碎片,但有可能会影响性能。
-XX:CMSMaxAbortablePrecleanTime=6000 \               ## 指定CMS-concurrent-abortable-preclean阶段执行的时间,该阶段主要是执行一些预清理,减少应用暂停的时间
-XX:CompileThreshold=10 \                ## 超过10此进行JTI即时编译
-XX:MaxInlineSize=1024 \                ## 方法体的大小阈值。通过 -XX:CompileThreshold 来设置热点方法的阈值。但要强调一点,热点方法不一定会被 JVM 做内联优化,如果这个方法体太大了,JVM 将不执行内联操作
-Dsun.net.client.defaultConnectTimeout=60000 \           ## socket连接超时时间
-Dsun.net.client.defaultReadTimeout=60000 \            ## socket读取超时时间
-Dnetworkaddress.cache.ttl=300 \              ## JVM的DNS缓存有效期,单位秒
-Dsun.net.inetaddr.ttl=300 \               ## 缓存失败结果,如果在缓存时效内再次lookup时直接返回错误(减轻DNS服务压力)             
-Djsse.enableCBCProtection=false \              ## 关闭jvm中的java修复程序
-Djava.security.egd=file:/dev/./urandom \            ## 加快随机数产生过程
-Dfile.encoding=UTF-8 \                 ## 指定web应用编码
-Dlog.path=/usr/local/springboot_demos/springboot-port8001/logs/ \      ## 指定项目日志文件路径
-Dspring.profiles.active=prod \               ## 指定运行的环境配置
/usr/local/springboot_demos/springboot-port8001/springboot-jvm-params-1.0-SNAPSHOT.jar jvmparams
%0A%5Btoc%5D%0A%23%23%201.%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E9%85%8D%E7%BD%AE%0A%23%23%23%23%201.1%20%20application.yml%0A%60%60%60yml%0A%23%20springboot%E5%A4%9A%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%0A%23%20springboot%E5%A4%9A%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%0A%23%20%E7%AB%AF%E5%8F%A3%EF%BC%8C%E9%A1%B9%E7%9B%AE%E4%B8%8A%E4%B8%8B%E6%96%87%0Aserver%3A%0A%20%20port%3A%208080%0A%20%20servlet%3A%0A%20%20%20%20context-path%3A%20%2Fspringboot-params-demo%0A%0A%23%20%E9%BB%98%E8%AE%A4%E5%90%AF%E5%8A%A8%E7%9A%84%E6%98%AF%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%0Aspring%3A%0A%20%20profiles%3A%0A%20%20%20%20active%3A%20test%0A%0A%23%20%E6%97%A5%E5%BF%97%E8%BE%93%E5%87%BA%E9%85%8D%E7%BD%AE%0Alogging%3A%0A%20%20level%3A%0A%20%20%20%20root%3A%20INFO%0A%20%20%20%20org%3A%0A%20%20%20%20%20%20springframework%3A%0A%20%20%20%20%20%20%20%20security%3A%20WARN%0A%20%20%20%20%20%20%20%20web%3A%20ERROR%0A%20%20file%3A%0A%20%20%20%20path%3A%20.%2Flogs%0A%20%20%20%20name%3A%20'.%2Flogs%2Fspringboot-params-demo.log'%0A%20%20pattern%3A%0A%20%20%20%20file%3A%20'%25d%7Byyyy-MM-dd%20HH%3Amm%3Ass.SSS%7D%20%5B%25thread%5D%20%25-5level%20%25logger%7B50%7D%3A%25L%20-%20%25msg%25n'%0A%20%20%20%20console%3A%20'%25d%7Byyyy-MM-dd%20HH%3Amm%3Ass.SSS%7D%20%5B%25thread%5D%20%25-5level%20%25logger%7B50%7D%3A%25L%20-%20%25msg%25n'%0A%60%60%60%0A%0A%0A%23%23%23%23%201.2%20application-test.yml%0A%0A%60%60%60yml%0A%23%C2%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E5%8F%82%E6%95%B0%0AmyParam%3A%C2%A0'on'%0A%60%60%60%0A%0A%23%23%23%23%201.3%20application-prod.yml%0A%60%60%60yml%0A%23%C2%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E5%8F%82%E6%95%B0%0AmyParam%3A%C2%A0'close'%0A%60%60%60%0A%3E%20%E8%8E%B7%E5%8F%96%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%82%E6%95%B0%0A%60%60%60java%0Apackage%20com.demo.config%3B%0A%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.beans.factory.annotation.Autowired%3B%0Aimport%20org.springframework.beans.factory.annotation.Value%3B%0Aimport%20org.springframework.boot.CommandLineRunner%3B%0Aimport%20org.springframework.core.env.Environment%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0Aimport%20java.util.Arrays%3B%0A%0A%40Component%0A%40Slf4j%0Apublic%20class%20MyParamRunner%20implements%20CommandLineRunner%20%7B%0A%20%20%20%0A%20%20%20%20%20%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B5%8B%E8%AF%95%E5%8F%82%E6%95%B0%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Value(%22%24%7BmyParam%7D%22)%0A%20%20%20%20String%20myParam%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E8%8E%B7%E5%8F%96%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E5%8F%82%E6%95%B0%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Autowired%0A%20%20%20%20Environment%20environment%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20run(String...%20args)%20throws%20Exception%20%7B%0A%20%20%20%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20log.info(%22%E6%9C%AC%E5%9C%B0%E8%AE%BE%E7%BD%AE%E7%9A%84%E5%8F%82%E6%95%B0myParam%E4%B8%BA%EF%BC%9A%7B%7D%22%2C%20myParam)%3B%0A%20%20%20%20%20%20%20%20log.info(environment.toString())%3B%0A%20%20%20%20%20%20%20%20log.info(String.valueOf(Arrays.asList(environment.getActiveProfiles())))%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%23%23%202.%20%E5%90%AF%E5%8A%A8jar%E5%8C%85%E8%BF%9B%E8%A1%8C%E6%B5%8B%E8%AF%95%0A%0A%23%23%23%23%202.1%20%E7%9B%B4%E6%8E%A5%E5%90%AF%E5%8A%A8%0A%60%60%60%0Ajava%C2%A0-jar%C2%A0%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Fspringboot-jvm-params-1.0-SNAPSHOT.jar%0A%60%60%60%0A!%5B903d6004ef1c7085c51ec4b8eae3eced.png%5D(en-resource%3A%2F%2Fdatabase%2F1331%3A1)%0A%0A%0A%23%23%23%23%202.2%20%E4%BF%AE%E6%94%B9%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%0A%23%23%23%23%23%202.2.1%20%E7%B3%BB%E7%BB%9F%E5%8F%98%E9%87%8F%0A%60%60%60%0Ajava%C2%A0-jar%C2%A0-Dspring.profiles.active%3Dprod%C2%A0%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Fspringboot-jvm-params-1.0-SNAPSHOT.jar%0A%60%60%60%0A!%5Bade08bcf37d0beda62307518af57ccdf.png%5D(en-resource%3A%2F%2Fdatabase%2F1333%3A1)%0A%0A%0A%23%23%23%23%23%202.2.2%20%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%0A%60%60%60%0Ajava%C2%A0-jar%C2%A0%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Fspringboot-jvm-params-1.0-SNAPSHOT.jar%C2%A0--spring.profiles.active%3Dprod%C2%A0--myParam%3D'test'%0A%60%60%60%0A!%5Beca166b188b078144931bc699ec860b1.png%5D(en-resource%3A%2F%2Fdatabase%2F1335%3A1)%0A%0A%0A%23%23%23%23%23%202.2.3%20%E5%90%8C%E6%97%B6%E4%BF%AE%E6%94%B9%0A%60%60%60%0Ajava%C2%A0-jar%C2%A0-DmyParam%3D'test1'%C2%A0%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Fspringboot-jvm-params-1.0-SNAPSHOT.jar%C2%A0--spring.profiles.active%3Dprod%C2%A0--myParam%3D'test2'%0A%60%60%60%0A%0A!%5B6a5425371ee0f1818e990c9997d065c8.png%5D(en-resource%3A%2F%2Fdatabase%2F1337%3A1)%0A%0A%23%23%23%23%202.3%20%E5%8F%82%E6%95%B0%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%0A%3E%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%8F%98%E9%87%8F%20%3C%20JVM%E7%B3%BB%E7%BB%9F%E5%8F%98%E9%87%8F%20%3C%20%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%EF%BC%88%E6%B3%A8%E6%84%8F%EF%BC%9A%E4%BC%98%E5%85%88%E7%BA%A7%E7%94%B1%E4%BD%8E%E5%88%B0%E9%AB%98%EF%BC%8C%E9%9D%9E%E5%B8%B8%E5%A4%9A%E7%9A%84%E5%90%AF%E5%8A%A8%E5%91%BD%E4%BB%A4%E4%B8%AD%E4%BC%A0%E5%8F%82%E4%B9%9F%E6%98%AF%E8%BF%99%E4%B8%AA%E9%81%93%E7%90%86%EF%BC%89%0A%0A%23%23%203.%20springboot%E5%90%AF%E5%8A%A8%E5%8F%82%E6%95%B0%E8%A7%A3%E9%87%8A%0A%60%60%60%0A%2Fusr%2Flocal%2Fjdk%2Fjdk1.8.0_261%2Fbin%2Fjava%20-jar%20-server%20%5C%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%9C%8D%E5%8A%A1%E6%A8%A1%E5%BC%8F%EF%BC%8Clinux%E9%BB%98%E8%AE%A4%E6%98%AFserver%E6%A8%A1%E5%BC%8F%EF%BC%8Cwindow%E9%BB%98%E8%AE%A4%E6%98%AFclient%E5%8F%82%E6%95%B0%20%0A-XX%3A%2BHeapDumpOnOutOfMemoryError%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%BD%93OOM%E5%8F%91%E7%94%9F%E6%97%B6%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90Heap%20Dump%E6%96%87%E4%BB%B6%0A-XX%3AHeapDumpPath%3D%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Fdump%2Fheap%2Foom.hprof%20%5C%20%23%23%20%E6%8C%87%E5%AE%9A%E5%8F%91%E7%94%9FOOM%E6%97%B6%E7%94%9F%E6%88%90Dump%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8%E4%BD%8D%E7%BD%AE%0A-Djava.io.tmpdir%3D%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Ftmp%2F%20%5C%20%20%20%20%20%23%23%20%E6%8C%87%E5%AE%9A%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%BC%93%E5%AD%98%E7%9A%84%E4%B8%B4%E6%97%B6%E7%9B%AE%E5%BD%95%0A-Dserver.port%3D8001%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20web%E6%9C%8D%E5%8A%A1%E4%BD%BF%E7%94%A8%E7%AB%AF%E5%8F%A3%0A-Dcom.sun.management.jmxremote%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%98%AF%E5%90%A6%E6%94%AF%E6%8C%81%E8%BF%9C%E7%A8%8BJMX%E8%AE%BF%E9%97%AE%EF%BC%8C%E9%BB%98%E8%AE%A4true%0A-Dcom.sun.management.jmxremote.port%3D5103%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E9%85%8D%E7%BD%AEjmx%E8%BF%9C%E7%A8%8Bconnection%E7%9A%84%E7%AB%AF%E5%8F%A3%E5%8F%B7%EF%BC%8C%E8%A6%81%E7%A1%AE%E8%AE%A4%E8%BF%99%E4%B8%AA%E7%AB%AF%E5%8F%A3%E6%B2%A1%E6%9C%89%E8%A2%AB%E5%8D%A0%E7%94%A8%0A-Dcom.sun.management.jmxremote.rmi.port%3D6103%20%5C%20%20%20%20%20%20%20%20%20%20%20%23%23%20JMX%E5%9C%A8%E8%BF%9C%E7%A8%8B%E8%BF%9E%E6%8E%A5%E6%97%B6%EF%BC%8C%E4%BC%9A%E9%9A%8F%E6%9C%BA%E5%BC%80%E5%90%AF%E4%B8%80%E4%B8%AARMI%E7%AB%AF%E5%8F%A3%E4%BD%9C%E4%B8%BA%E8%BF%9E%E6%8E%A5%E7%9A%84%E6%95%B0%E6%8D%AE%E7%AB%AF%E5%8F%A3%0A-Dcom.sun.management.jmxremote.authenticate%3Dfalse%20%5C%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AF%E7%94%A8%E6%88%B7%E8%AE%A4%E8%AF%81%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%BC%80%E5%90%AF%0A-Dcom.sun.management.jmxremote.ssl%3Dfalse%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%98%AF%E5%90%A6%E8%BF%9E%E6%8E%A5%E5%BC%80%E5%90%AFSSL%E5%8A%A0%E5%AF%86%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%BC%80%E5%90%AF%0A-Dcom.sun.management.jmxremote.access.file%3D%2Fusr%2Flocal%2Fjdk%2Fjdk1.8.0_261%2Fjre%2Flib%2Fmanagement%2Fjmxremote.access%20%5C%20%E5%AF%B9%E8%AE%BF%E9%97%AE%E7%94%A8%E6%88%B7%E7%9A%84%E6%9D%83%E9%99%90%E6%8E%88%E6%9D%83%E7%9A%84%E6%96%87%E4%BB%B6%E7%9A%84%E8%B7%AF%E5%BE%84%EF%BC%8C%E9%BB%98%E8%AE%A4%E8%B7%AF%E5%BE%84%E6%98%AF%24%7B%0A%20%20%20%0A%20%20%20%20%20JRE_HOME%7D%2Flib%2Fmanagement%2Fjmxremote.access%0A-Xmx256m%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E8%AE%BE%E7%BD%AE%E5%A0%86%E6%9C%80%E5%A4%A7%E7%A9%BA%E9%97%B4%E4%B8%BA256m%0A-Xms256m%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E8%AE%BE%E7%BD%AE%E5%A0%86%E6%9C%80%E5%B0%8F%E7%A9%BA%E9%97%B4%E4%B8%BA256m%0A-XX%3A%2BDisableExplicitGC%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E7%A6%81%E6%AD%A2%E6%89%8B%E5%8A%A8%E7%9A%84system.gc%0A-Xloggc%3A%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Flogs%2Fspringboot-jvm-params_gc.%25t.log%20%5C%20gc%E6%97%A5%E5%BF%97%E5%AD%98%E6%94%BE%E7%9A%84%E4%BD%8D%E7%BD%AE%0A-XX%3A%2BPrintHeapAtGC%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20HotSpot%E5%9C%A8GC%E5%89%8D%E5%90%8E%E9%83%BD%E4%BC%9A%E5%B0%86GC%E5%A0%86%E7%9A%84%E6%A6%82%E8%A6%81%E7%8A%B6%E5%86%B5%E8%BE%93%E5%87%BA%E5%88%B0log%E4%B8%AD%0A-XX%3A%2BPrintTenuringDistribution%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%89%93%E5%8D%B0Survivor%E5%AF%B9%E8%B1%A1%E5%B9%B4%E9%BE%84%E5%88%86%E5%B8%83%0A-XX%3A%2BPrintGCApplicationStoppedTime%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E9%A2%84%E4%BC%B0%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%22Stop%20the%20world%22%E6%9A%82%E5%81%9C%E6%89%80%E9%98%BB%E5%A1%9E%E7%9A%84%E6%97%B6%E9%97%B4%0A-XX%3A%2BPrintGCTaskTimeStamps%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%89%93%E5%8D%B0gc%E7%BA%BF%E7%A8%8B%E7%9A%84%E6%97%B6%E9%97%B4%E6%88%B3%0A-XX%3A%2BPrintGCDetails%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%89%93%E5%8D%B0gc%E8%AF%A6%E6%83%85%0A-XX%3A%2BPrintGCDateStamps%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%97%A5%E5%BF%97%E5%BC%80%E5%A4%B4%E6%98%BE%E7%A4%BA%E6%97%A5%E6%9C%9F%E4%BB%A5%E5%8F%8A%E6%97%B6%E9%97%B4%0A-Dserver.connection-timeout%3D60000%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20HTTP%E8%AF%B7%E6%B1%82%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%0A-Dserver.tomcat.accept-count%3D1000%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%89%80%E6%9C%89%E5%8F%AF%E8%83%BD%E7%9A%84%E8%AF%B7%E6%B1%82%E5%A4%84%E7%90%86%E7%BA%BF%E7%A8%8B%E6%AD%A3%E5%9C%A8%E4%BD%BF%E7%94%A8%E6%97%B6%EF%BC%8C%E4%BC%A0%E5%85%A5%E8%BF%9E%E6%8E%A5%E8%AF%B7%E6%B1%82%E7%9A%84%E6%9C%80%E5%A4%A7%E9%98%9F%E5%88%97%E9%95%BF%E5%BA%A6%0A-Dserver.tomcat.max-threads%3D300%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%9C%80%E5%A4%A7%E5%B7%A5%E4%BD%9C%E7%BA%BF%E7%A8%8B%E6%95%B0%0A-Dserver.tomcat.min-spare-threads%3D65%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%9C%80%E5%B0%8F%E5%B7%A5%E4%BD%9C%E7%BA%BF%E7%A8%8B%E6%95%B0%0A-Dserver.tomcat.accesslog.enabled%3Dfalse%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%90%AF%E7%94%A8%E8%AE%BF%E9%97%AE%E4%BD%A0%E6%97%A5%E5%BF%97%0A-Dserver.tomcat.accesslog.directory%3D%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Flogs%2F%20%5C%20%23%23%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E8%B7%AF%E5%BE%84%0A-Dserver.tomcat.accesslog.prefix%3Daccess_log%20%5C%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E5%90%8D%E5%89%8D%E7%BC%80%0A-Dserver.tomcat.accesslog.pattern%3Dcombined%20%5C%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%97%A5%E5%BF%97%E6%A0%BC%E5%BC%8F%0A-Dserver.tomcat.accesslog.suffix%3D.log%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E5%90%8E%E7%BC%80%0A-Dserver.tomcat.accesslog.file-date-format%3D.yyyy-MM-dd%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%94%BE%E5%9C%A8%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E5%90%8D%E4%B8%AD%E7%9A%84%E6%97%A5%E6%9C%9F%E6%A0%BC%E5%BC%8F%20%0A-Dserver.tomcat.accesslog.rotate%3Dtrue%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%98%AF%E5%90%A6%E5%90%AF%E7%94%A8%E8%AE%BF%E9%97%AE%E6%97%A5%E5%BF%97%E5%88%86%E5%89%B2%0A-Dserver.tomcat.accesslog.rename-on-rotate%3Dtrue%20%5C%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%8E%A8%E8%BF%9F%E5%9C%A8%E6%96%87%E4%BB%B6%E5%90%8D%E4%B8%AD%E5%8A%A0%E5%85%A5%E6%97%A5%E6%9C%9F%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%9B%B4%E5%88%B0%E6%97%A5%E5%BF%97%E5%88%86%E5%89%B2%E6%97%B6%0A-Dserver.tomcat.accesslog.request-attributes-enabled%3Dtrue%20%5C%20%20%20%20%20%20%20%20%23%23%20%E4%B8%BA%E8%AF%B7%E6%B1%82%E4%BD%BF%E7%94%A8%E7%9A%84IP%E5%9C%B0%E5%9D%80%E3%80%81%E4%B8%BB%E6%9C%BA%E5%90%8D%E3%80%81%E5%8D%8F%E8%AE%AE%E5%92%8C%E7%AB%AF%E5%8F%A3%E8%AE%BE%E7%BD%AE%E8%AF%B7%E6%B1%82%E5%B1%9E%E6%80%A7%0A-Dserver.tomcat.accesslog.buffered%3Dtrue%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E7%BC%93%E5%AD%98%E6%97%A5%E5%BF%97%E5%AE%9A%E6%9C%9F%E5%88%B7%E6%96%B0%E8%BE%93%E5%87%BA%EF%BC%88%E5%BB%BA%E8%AE%AE%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%EF%BC%8C%E5%90%A6%E5%88%99%E5%BD%93%E6%9C%89%E8%AF%B7%E6%B1%82%E7%AB%8B%E5%8D%B3%E6%89%93%E5%8D%B0%E6%97%A5%E5%BF%97%E5%AF%B9%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%93%8D%E5%BA%94%E4%BC%9A%E6%9C%89%E5%BD%B1%E5%93%8D%EF%BC%89%0A-XX%3ANewRatio%3D4%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E8%AE%BE%E7%BD%AEYang%E5%92%8COld%E7%9A%84%E6%AF%94%E4%BE%8B%EF%BC%8C%E8%AE%BE%E7%BD%AE4%E5%88%99Old%E6%98%AFYang%E7%9A%844%E5%80%8D%EF%BC%8C%E5%8D%B3Yang%E5%8D%A01%2F5%0A-XX%3ASurvivorRatio%3D8%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E8%AE%BE%E7%BD%AEEden%E5%92%8CSuivior%E7%9A%84%E6%AF%94%E4%BE%8B%EF%BC%8CEden%3AS0%3AS1%3D8%3A1%3A1%0A-XX%3AMaxTenuringThreshold%3D15%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%9C%A8%E6%96%B0%E7%94%9F%E4%BB%A3%E5%AF%B9%E8%B1%A1%E5%AD%98%E6%B4%BB%E6%AC%A1%E6%95%B0(%E7%BB%8F%E8%BF%87Minor%20GC%E7%9A%84%E6%AC%A1%E6%95%B0)%E8%B6%85%E8%BF%87n%E5%90%8E%EF%BC%8C%E5%B0%B1%E4%BC%9A%E6%99%8B%E5%8D%87%E5%88%B0%E8%80%81%E5%B9%B4%E4%BB%A3%0A-XX%3ATargetSurvivorRatio%3D90%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%9C%A8%E6%96%B0%E7%94%9F%E4%BB%A3%E7%9A%84%E5%AF%B9%E8%B1%A1%E4%B8%8D%E4%B8%80%E5%AE%9A%E8%A6%81%E6%BB%A1%E8%B6%B3%E5%AD%98%E6%B4%BB%E5%B9%B4%E9%BE%84%E8%BE%BE%E5%88%B0MaxTenuringThreshold%E6%89%8D%E8%83%BD%E5%8E%BB%E8%80%81%E5%B9%B4%E4%BB%A3%EF%BC%8C%E5%BD%93Survivor%E7%A9%BA%E9%97%B4%E4%B8%AD%E7%9B%B8%E5%90%8C%E5%B9%B4%E9%BE%84%E6%89%80%E6%9C%89%E5%AF%B9%E8%B1%A1%E5%A4%A7%E5%B0%8F%E6%80%BB%E5%92%8C%E5%A4%A7%E4%BA%8E%5BDesired%20survivor%20size%5D%E6%97%B6%EF%BC%8C%E5%B9%B4%E9%BE%84%E5%A4%A7%E4%BA%8E%E6%88%96%E7%AD%89%E4%BA%8E%E8%AF%A5%E5%B9%B4%E9%BE%84%E7%9A%84%E5%AF%B9%E8%B1%A1%E7%9B%B4%E6%8E%A5%E8%BF%9B%E5%85%A5%E8%80%81%E5%B9%B4%E4%BB%A3%E3%80%82%5BDesired%20survivor%20size%5D%3D%E5%8D%95%E4%B8%AAsurvivor%E5%A4%A7%E5%B0%8F*TargetSurvivorRatio%E7%99%BE%E5%88%86%E6%AF%94%0A-XX%3A%2BUseCMSInitiatingOccupancyOnly%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%E6%8C%87%E5%9C%A8%E4%BD%BF%E7%94%A8CMS%E6%94%B6%E9%9B%86%E5%99%A8%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E8%80%81%E5%B9%B4%E4%BB%A3%E4%BD%BF%E7%94%A8%E4%BA%86%E6%8C%87%E5%AE%9A%E9%98%88%E5%80%BC%E7%9A%84%E5%86%85%E5%AD%98%E6%97%B6%EF%BC%8C%E8%A7%A6%E5%8F%91FullGC%0A-XX%3ACMSInitiatingOccupancyFraction%3D70%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%8C%87%E5%9C%A8%E4%BD%BF%E7%94%A8CMS%E6%94%B6%E9%9B%86%E5%99%A8%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E8%80%81%E5%B9%B4%E4%BB%A3%E4%BD%BF%E7%94%A8%E8%BE%BE%E5%88%B070%25%EF%BC%8C%E5%87%BA%E5%8F%91CMS%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%0A-XX%3AParallelGCThreads%3D8%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20parallel%E5%9B%9E%E6%94%B6%E7%9A%84%E6%97%B6%E5%80%99%E5%8F%AF%E4%BB%A5%E8%AE%BE%E7%BD%AE%E5%B9%B4%E8%BD%BB%E4%BB%A3%E7%9A%84%E5%B9%B6%E8%A1%8C%E7%BA%BF%E7%A8%8B%E6%95%B0%2C%E5%8F%96%E5%86%B3%E4%BA%8Ecpu%E6%A0%B8%E6%95%B0%0A-XX%3AConcGCThreads%3D2%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E8%AE%BE%E7%BD%AE%E5%B9%B6%E8%A1%8C%E6%A0%87%E8%AE%B0%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%95%B0%E3%80%82%E5%B0%86n%E8%AE%BE%E7%BD%AE%E4%B8%BA%E5%B9%B6%E8%A1%8C%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%BA%BF%E7%A8%8B%E6%95%B0(ParallelGCThreads)%E7%9A%84%201%2F4%20%E5%B7%A6%E5%8F%B3%E3%80%82%0A-XX%3A-UseGCOverheadLimit%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20jvm%20gc%E8%A1%8C%E4%B8%BA%E4%B8%AD%E8%B6%85%E8%BF%8798%25%E4%BB%A5%E4%B8%8A%E7%9A%84%E6%97%B6%E9%97%B4%E5%8E%BB%E9%87%8A%E6%94%BE%E5%B0%8F%E4%BA%8E2%25%E7%9A%84%E5%A0%86%E7%A9%BA%E9%97%B4%E6%97%B6%E4%BC%9A%E6%8A%A5%E2%80%9CGC%20overhead%20limit%20exceeded%E2%80%9D%E9%94%99%E8%AF%AF%EF%BC%8C%E6%AD%A4%E5%8F%82%E6%95%B0%E9%81%BF%E5%85%8D%E6%AD%A4%E6%8A%A5%E9%94%99%0A-XX%3A%2BUseParNewGC%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%BC%80%E5%90%AF%E6%AD%A4%E5%8F%82%E6%95%B0%E4%BD%BF%E7%94%A8ParNew%20%26%20serial%20old%E6%90%9C%E9%9B%86%E5%99%A8%EF%BC%88%E4%B8%8D%E6%8E%A8%E8%8D%90%EF%BC%89%E4%BD%BF%E7%94%A8%E8%BF%99%E4%B8%AA%E5%8F%82%E6%95%B0%E5%90%8E%E4%BC%9A%E5%9C%A8%E6%96%B0%E7%94%9F%E4%BB%A3%E8%BF%9B%E8%A1%8C%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%0A-XX%3A%2BUseConcMarkSweepGC%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%BC%80%E5%90%AF%E6%AD%A4%E5%8F%82%E6%95%B0%E4%BD%BF%E7%94%A8ParNew%20%26%20CMS%EF%BC%88serial%20old%E4%B8%BA%E6%9B%BF%E8%A1%A5%EF%BC%89%E6%90%9C%E9%9B%86%E5%99%A8%0A-XX%3ACMSFullGCsBeforeCompaction%3D1%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E8%AE%BE%E7%BD%AE%E5%9C%A8%E5%87%A0%E6%AC%A1CMS%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%90%8E%EF%BC%8C%E8%A7%A6%E5%8F%91%E4%B8%80%E6%AC%A1%E5%86%85%E5%AD%98%E6%95%B4%E7%90%86%0A-XX%3A%2BCMSParallelRemarkEnabled%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E9%99%8D%E4%BD%8E%E6%A0%87%E8%AE%B0%E5%81%9C%E9%A1%BF%0A-XX%3A%2BCMSScavengeBeforeRemark%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%BC%80%E5%90%AF%E6%88%96%E5%85%B3%E9%97%AD%E5%9C%A8%20CMS-remark%20%E9%98%B6%E6%AE%B5%E4%B9%8B%E5%89%8D%E7%9A%84%E6%B8%85%E9%99%A4%EF%BC%88Young%20GC%EF%BC%89%E5%B0%9D%E8%AF%95%0A-XX%3A%2BParallelRefProcEnabled%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%B9%B6%E8%A1%8C%E5%A4%84%E7%90%86Reference%EF%BC%8C%E5%8A%A0%E5%BF%AB%E5%A4%84%E7%90%86%E9%80%9F%E5%BA%A6%EF%BC%8C%E7%BC%A9%E7%9F%AD%E8%80%97%E6%97%B6%0A-XX%3A%2BUseCMSCompactAtFullCollection%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%B9%B4%E8%80%81%E4%BB%A3%E4%BD%BF%E7%94%A8CMS%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%98%AF%E4%B8%8D%E4%BC%9A%E6%95%B4%E7%90%86%E5%A0%86%E7%A2%8E%E7%89%87%E7%9A%84%E3%80%82%E8%AE%BE%E7%BD%AE%E6%AD%A4%E9%85%8D%E7%BD%AE%E6%89%93%E5%BC%80%E5%AF%B9%E5%B9%B4%E8%80%81%E4%BB%A3%E7%9A%84%E5%8E%8B%E7%BC%A9%EF%BC%8C%E5%8D%B3%E6%89%A7%E8%A1%8CFull%20GC%E5%90%8E%E5%AF%B9%E5%86%85%E5%AD%98%E8%BF%9B%E8%A1%8C%E6%95%B4%E7%90%86%E5%8E%8B%E7%BC%A9%EF%BC%8C%E5%85%8D%E5%BE%97%E4%BA%A7%E7%94%9F%E5%86%85%E5%AD%98%E7%A2%8E%E7%89%87%EF%BC%8C%E4%BD%86%E6%9C%89%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%BD%B1%E5%93%8D%E6%80%A7%E8%83%BD%E3%80%82%0A-XX%3ACMSMaxAbortablePrecleanTime%3D6000%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%8C%87%E5%AE%9ACMS-concurrent-abortable-preclean%E9%98%B6%E6%AE%B5%E6%89%A7%E8%A1%8C%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%8C%E8%AF%A5%E9%98%B6%E6%AE%B5%E4%B8%BB%E8%A6%81%E6%98%AF%E6%89%A7%E8%A1%8C%E4%B8%80%E4%BA%9B%E9%A2%84%E6%B8%85%E7%90%86%EF%BC%8C%E5%87%8F%E5%B0%91%E5%BA%94%E7%94%A8%E6%9A%82%E5%81%9C%E7%9A%84%E6%97%B6%E9%97%B4%0A-XX%3ACompileThreshold%3D10%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E8%B6%85%E8%BF%8710%E6%AD%A4%E8%BF%9B%E8%A1%8CJTI%E5%8D%B3%E6%97%B6%E7%BC%96%E8%AF%91%0A-XX%3AMaxInlineSize%3D1024%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%96%B9%E6%B3%95%E4%BD%93%E7%9A%84%E5%A4%A7%E5%B0%8F%E9%98%88%E5%80%BC%E3%80%82%E9%80%9A%E8%BF%87%20-XX%3ACompileThreshold%20%E6%9D%A5%E8%AE%BE%E7%BD%AE%E7%83%AD%E7%82%B9%E6%96%B9%E6%B3%95%E7%9A%84%E9%98%88%E5%80%BC%E3%80%82%E4%BD%86%E8%A6%81%E5%BC%BA%E8%B0%83%E4%B8%80%E7%82%B9%EF%BC%8C%E7%83%AD%E7%82%B9%E6%96%B9%E6%B3%95%E4%B8%8D%E4%B8%80%E5%AE%9A%E4%BC%9A%E8%A2%AB%20JVM%20%E5%81%9A%E5%86%85%E8%81%94%E4%BC%98%E5%8C%96%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E4%BD%93%E5%A4%AA%E5%A4%A7%E4%BA%86%EF%BC%8CJVM%20%E5%B0%86%E4%B8%8D%E6%89%A7%E8%A1%8C%E5%86%85%E8%81%94%E6%93%8D%E4%BD%9C%0A-Dsun.net.client.defaultConnectTimeout%3D60000%20%5C%20%20%20%20%20%20%20%20%20%20%20%23%23%20socket%E8%BF%9E%E6%8E%A5%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%0A-Dsun.net.client.defaultReadTimeout%3D60000%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20socket%E8%AF%BB%E5%8F%96%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%0A-Dnetworkaddress.cache.ttl%3D300%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20JVM%E7%9A%84DNS%E7%BC%93%E5%AD%98%E6%9C%89%E6%95%88%E6%9C%9F%EF%BC%8C%E5%8D%95%E4%BD%8D%E7%A7%92%0A-Dsun.net.inetaddr.ttl%3D300%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E7%BC%93%E5%AD%98%E5%A4%B1%E8%B4%A5%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%9C%A8%E7%BC%93%E5%AD%98%E6%97%B6%E6%95%88%E5%86%85%E5%86%8D%E6%AC%A1lookup%E6%97%B6%E7%9B%B4%E6%8E%A5%E8%BF%94%E5%9B%9E%E9%94%99%E8%AF%AF%EF%BC%88%E5%87%8F%E8%BD%BBDNS%E6%9C%8D%E5%8A%A1%E5%8E%8B%E5%8A%9B%EF%BC%89%20%20%20%20%20%20%20%20%20%20%20%20%20%0A-Djsse.enableCBCProtection%3Dfalse%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%85%B3%E9%97%ADjvm%E4%B8%AD%E7%9A%84java%E4%BF%AE%E5%A4%8D%E7%A8%8B%E5%BA%8F%0A-Djava.security.egd%3Dfile%3A%2Fdev%2F.%2Furandom%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E5%8A%A0%E5%BF%AB%E9%9A%8F%E6%9C%BA%E6%95%B0%E4%BA%A7%E7%94%9F%E8%BF%87%E7%A8%8B%0A-Dfile.encoding%3DUTF-8%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%8C%87%E5%AE%9Aweb%E5%BA%94%E7%94%A8%E7%BC%96%E7%A0%81%0A-Dlog.path%3D%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Flogs%2F%20%5C%20%20%20%20%20%20%23%23%20%E6%8C%87%E5%AE%9A%E9%A1%B9%E7%9B%AE%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E8%B7%AF%E5%BE%84%0A-Dspring.profiles.active%3Dprod%20%5C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20%E6%8C%87%E5%AE%9A%E8%BF%90%E8%A1%8C%E7%9A%84%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%0A%2Fusr%2Flocal%2Fspringboot_demos%2Fspringboot-port8001%2Fspringboot-jvm-params-1.0-SNAPSHOT.jar%20jvmparams%0A%60%60%60

json path

创建时间:2022/5/20 15:07
更新时间:2022/5/20 18:05
作者:Chris
来源:https://blog.csdn.net/lwg_1540652358/article/details/84111339

代码来源

https://gitcode.net/mirrors/json-path/jsonpath?utm_source=csdn_github_accelerator

在线验证

Online validation

语法:

操作说明
$查询的根节点对象,用于表示一个jsono数据,可以是数组或对象
@处理当前节点对象类似于java中的this
*通配符,必要时可用任何地方的名称或数字
..深层扫描。可以理解为递归搜索
.<name>表示一个子节点
['<name>' (, '<name>')]括号表示子项
[<number> (, <number>) ]表示一个或多个数组下标
[start:end]数组切片操作,区间为 [start,end) , 不包含end
[?(<expression>)]过滤表达式。 表达式必须求值为一个布尔值

过滤器运算符

过滤器是用于筛选数组的逻辑表达式。一个典型的过滤器将是[?(@.age > 18)],其中@表示正在处理的当前项目。
可以使用逻辑运算符&&和||创建更复杂的过滤器。
字符串文字必须用单引号或双引号括起来 ([?(@.color == 'blue')] 或者 [?(@.color == "blue")])

操作符描述
==left等于right(注意1不等于'1')
!=不等于
<小于
<=小于等于
>大于
>=大于等于
=~匹配正则表达式[?(@.name =~ /foo.*?/i)]
in左边存在于右边 [?(@.size in ['S', 'M'])]
nin左边不存在于右边
size(数组或字符串)长度
empty(数组或字符串)为空
{
	"store": {
		"book": [{
				"category": "reference",
				"author": "Nigel Rees",
				"title": "Sayings of the Century",
				"price": 8.95
			}, {
				"category": "fiction",
				"author": "Evelyn Waugh",
				"title": "Sword of Honour",
				"price": 12.99
			}, {
				"category": "fiction",
				"author": "Herman Melville",
				"title": "Moby Dick",
				"isbn": "0-553-21311-3",
				"price": 8.99
			}, {
				"category": "fiction",
				"author": "J. R. R. Tolkien",
				"title": "The Lord of the Rings",
				"isbn": "0-395-19395-8",
				"price": 22.99
			}
		],
		"bicycle": {
			"color": "red",
			"price": 19.95
		}
	}
}
操作说明
$.store.book[*].authorThe authors of all books
$..authorAll authors
$.store.*All things, both books and bicycles
$.store..priceThe price of everything
$..book[2]The third book
$..book[-2]The second to last book
$..book[0,1] or $..book[:2]The first two books
$..book[:2]All books from index 0 (inclusive) until index 2 (exclusive)
$..book[1:2]All books from index 1 (inclusive) until index 2 (exclusive)
$..book[(@.length-2)] or $..book[-2:]Last two books
$..book[2:]Book number two from tail
$..book[?(@.isbn)]All books with an ISBN number
$.store.book[?(@.price < 10)]All books in store cheaper than 10
$..book[?(@.price <= $['expensive'])]All books in store that are not "expensive"
$..book[?(@.author =~ /.*REES/i)]All books matching regex (ignore case)
$..*Give me every thing
$..book.length()The number of books
%23%23%23%23%20%E4%BB%A3%E7%A0%81%E6%9D%A5%E6%BA%90%0A%3E%20https%3A%2F%2Fgitcode.net%2Fmirrors%2Fjson-path%2Fjsonpath%3Futm_source%3Dcsdn_github_accelerator%0A%3E%20%0A%0A%23%23%23%23%20%E5%9C%A8%E7%BA%BF%E9%AA%8C%E8%AF%81%0A%5BOnline%20validation%5D(http%3A%2F%2Fjsonpath.com%2F)%0A%0A%23%23%23%23%20%E8%AF%AD%E6%B3%95%EF%BC%9A%0A%0A%7C%20%E6%93%8D%E4%BD%9C%20%7C%E8%AF%B4%E6%98%8E%0A%7C%20---%20%7C%20---%20%7C%0A%7C%20%24%20%7C%20%E6%9F%A5%E8%AF%A2%E7%9A%84%E6%A0%B9%E8%8A%82%E7%82%B9%E5%AF%B9%E8%B1%A1%EF%BC%8C%E7%94%A8%E4%BA%8E%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AAjsono%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%98%AF%E6%95%B0%E7%BB%84%E6%88%96%E5%AF%B9%E8%B1%A1%20%7C%0A%7C%20%40%09%20%7C%20%E5%A4%84%E7%90%86%E5%BD%93%E5%89%8D%E8%8A%82%E7%82%B9%E5%AF%B9%E8%B1%A1%E7%B1%BB%E4%BC%BC%E4%BA%8Ejava%E4%B8%AD%E7%9A%84this%20%7C%0A%7C%20*%20%7C%20%E9%80%9A%E9%85%8D%E7%AC%A6%EF%BC%8C%E5%BF%85%E8%A6%81%E6%97%B6%E5%8F%AF%E7%94%A8%E4%BB%BB%E4%BD%95%E5%9C%B0%E6%96%B9%E7%9A%84%E5%90%8D%E7%A7%B0%E6%88%96%E6%95%B0%E5%AD%97%20%7C%0A%7C%20..%20%7C%20%E6%B7%B1%E5%B1%82%E6%89%AB%E6%8F%8F%E3%80%82%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BA%E9%80%92%E5%BD%92%E6%90%9C%E7%B4%A2%20%7C%0A%7C%20.%3Cname%3E%20%7C%20%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E5%AD%90%E8%8A%82%E7%82%B9%20%7C%0A%7C%20%5B'%3Cname%3E'%20(%2C%20'%3Cname%3E')%5D%20%7C%20%E6%8B%AC%E5%8F%B7%E8%A1%A8%E7%A4%BA%E5%AD%90%E9%A1%B9%20%7C%0A%7C%20%5B%3Cnumber%3E%20(%2C%20%3Cnumber%3E)%20%5D%20%7C%20%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E6%95%B0%E7%BB%84%E4%B8%8B%E6%A0%87%20%20%7C%0A%7C%20%5Bstart%3Aend%5D%20%7C%20%E6%95%B0%E7%BB%84%E5%88%87%E7%89%87%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%8C%BA%E9%97%B4%E4%B8%BA%20%60%5Bstart%2Cend)%60%20%2C%20%E4%B8%8D%E5%8C%85%E5%90%ABend%20%7C%0A%7C%20%5B%3F(%3Cexpression%3E)%5D%20%7C%20%E8%BF%87%E6%BB%A4%E8%A1%A8%E8%BE%BE%E5%BC%8F%E3%80%82%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BF%85%E9%A1%BB%E6%B1%82%E5%80%BC%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%B8%83%E5%B0%94%E5%80%BC%20%7C%0A%0A%23%23%23%23%20%E8%BF%87%E6%BB%A4%E5%99%A8%E8%BF%90%E7%AE%97%E7%AC%A6%0A%3E%20%E8%BF%87%E6%BB%A4%E5%99%A8%E6%98%AF%E7%94%A8%E4%BA%8E%E7%AD%9B%E9%80%89%E6%95%B0%E7%BB%84%E7%9A%84%E9%80%BB%E8%BE%91%E8%A1%A8%E8%BE%BE%E5%BC%8F%E3%80%82%E4%B8%80%E4%B8%AA%E5%85%B8%E5%9E%8B%E7%9A%84%E8%BF%87%E6%BB%A4%E5%99%A8%E5%B0%86%E6%98%AF%5B%3F(%40.age%20%3E%2018)%5D%EF%BC%8C%E5%85%B6%E4%B8%AD%40%E8%A1%A8%E7%A4%BA%E6%AD%A3%E5%9C%A8%E5%A4%84%E7%90%86%E7%9A%84%E5%BD%93%E5%89%8D%E9%A1%B9%E7%9B%AE%E3%80%82%20%0A%3E%20%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97%E7%AC%A6%26%26%E5%92%8C%7C%7C%E5%88%9B%E5%BB%BA%E6%9B%B4%E5%A4%8D%E6%9D%82%E7%9A%84%E8%BF%87%E6%BB%A4%E5%99%A8%E3%80%82%20%0A%3E%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%96%87%E5%AD%97%E5%BF%85%E9%A1%BB%E7%94%A8%E5%8D%95%E5%BC%95%E5%8F%B7%E6%88%96%E5%8F%8C%E5%BC%95%E5%8F%B7%E6%8B%AC%E8%B5%B7%E6%9D%A5%20%60(%5B%3F(%40.color%20%3D%3D%20'blue')%5D%20%E6%88%96%E8%80%85%20%5B%3F(%40.color%20%3D%3D%20%22blue%22)%5D)%60%0A%0A%7C%E6%93%8D%E4%BD%9C%E7%AC%A6%20%7C%20%E6%8F%8F%E8%BF%B0%0A%7C%20---%20%7C%20---%20%7C%0A%3D%3D%20%7C%20left%E7%AD%89%E4%BA%8Eright%EF%BC%88%E6%B3%A8%E6%84%8F1%E4%B8%8D%E7%AD%89%E4%BA%8E'1'%EF%BC%89%7C%0A%7C%20!%3D%20%7C%20%E4%B8%8D%E7%AD%89%E4%BA%8E%20%7C%0A%7C%20%3C%20%7C%20%E5%B0%8F%E4%BA%8E%20%20%7C%0A%7C%20%3C%3D%20%7C%20%E5%B0%8F%E4%BA%8E%E7%AD%89%E4%BA%8E%20%7C%0A%7C%20%3E%20%7C%20%E5%A4%A7%E4%BA%8E%20%7C%0A%7C%20%3E%3D%20%7C%20%E5%A4%A7%E4%BA%8E%E7%AD%89%E4%BA%8E%20%7C%0A%7C%20%3D~%20%7C%20%E5%8C%B9%E9%85%8D%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%5B%3F(%40.name%20%3D~%20%2Ffoo.*%3F%2Fi)%5D%20%20%7C%0A%7C%20in%20%7C%20%E5%B7%A6%E8%BE%B9%E5%AD%98%E5%9C%A8%E4%BA%8E%E5%8F%B3%E8%BE%B9%20%5B%3F(%40.size%20in%20%5B'S'%2C%20'M'%5D)%5D%20%20%7C%0A%7C%20nin%20%7C%20%E5%B7%A6%E8%BE%B9%E4%B8%8D%E5%AD%98%E5%9C%A8%E4%BA%8E%E5%8F%B3%E8%BE%B9%20%20%7C%0A%7C%20size%20%7C%20%EF%BC%88%E6%95%B0%E7%BB%84%E6%88%96%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%89%E9%95%BF%E5%BA%A6%20%20%7C%0A%7C%20empty%20%7C%20%EF%BC%88%E6%95%B0%E7%BB%84%E6%88%96%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%89%E4%B8%BA%E7%A9%BA%20%20%7C%0A%0A%60%60%60json%0A%7B%0A%09%22store%22%3A%20%7B%0A%09%09%22book%22%3A%20%5B%7B%0A%09%09%09%09%22category%22%3A%20%22reference%22%2C%0A%09%09%09%09%22author%22%3A%20%22Nigel%20Rees%22%2C%0A%09%09%09%09%22title%22%3A%20%22Sayings%20of%20the%20Century%22%2C%0A%09%09%09%09%22price%22%3A%208.95%0A%09%09%09%7D%2C%20%7B%0A%09%09%09%09%22category%22%3A%20%22fiction%22%2C%0A%09%09%09%09%22author%22%3A%20%22Evelyn%20Waugh%22%2C%0A%09%09%09%09%22title%22%3A%20%22Sword%20of%20Honour%22%2C%0A%09%09%09%09%22price%22%3A%2012.99%0A%09%09%09%7D%2C%20%7B%0A%09%09%09%09%22category%22%3A%20%22fiction%22%2C%0A%09%09%09%09%22author%22%3A%20%22Herman%20Melville%22%2C%0A%09%09%09%09%22title%22%3A%20%22Moby%20Dick%22%2C%0A%09%09%09%09%22isbn%22%3A%20%220-553-21311-3%22%2C%0A%09%09%09%09%22price%22%3A%208.99%0A%09%09%09%7D%2C%20%7B%0A%09%09%09%09%22category%22%3A%20%22fiction%22%2C%0A%09%09%09%09%22author%22%3A%20%22J.%20R.%20R.%20Tolkien%22%2C%0A%09%09%09%09%22title%22%3A%20%22The%20Lord%20of%20the%20Rings%22%2C%0A%09%09%09%09%22isbn%22%3A%20%220-395-19395-8%22%2C%0A%09%09%09%09%22price%22%3A%2022.99%0A%09%09%09%7D%0A%09%09%5D%2C%0A%09%09%22bicycle%22%3A%20%7B%0A%09%09%09%22color%22%3A%20%22red%22%2C%0A%09%09%09%22price%22%3A%2019.95%0A%09%09%7D%0A%09%7D%0A%7D%0A%60%60%60%0A%7C%20%E6%93%8D%E4%BD%9C%20%7C%E8%AF%B4%E6%98%8E%0A%7C%20---%20%7C%20---%20%7C%0A%7C%20%24.store.book%5B*%5D.author%20%7C%20The%20authors%20of%20all%20books%20%7C%20%0A%7C%20%24..author%20%7C%20All%20authors%20%7C%20%0A%7C%20%24.store.*%20%7C%20All%20things%2C%20both%20books%20and%20bicycles%20%7C%20%20%0A%7C%20%24.store..price%20%7C%20The%20price%20of%20everything%20%7C%20%0A%7C%20%24..book%5B2%5D%20%7C%20The%20third%20book%20%7C%20%0A%7C%20%24..book%5B-2%5D%20%7C%20The%20second%20to%20last%20book%20%7C%20%0A%7C%20%24..book%5B0%2C1%5D%20or%20%24..book%5B%3A2%5D%20%7C%20The%20first%20two%20books%20%7C%20%0A%7C%20%24..book%5B%3A2%5D%20%7C%20All%20books%20from%20index%200%20(inclusive)%20until%20index%202%20(exclusive)%20%7C%20%0A%7C%20%24..book%5B1%3A2%5D%20%7C%20All%20books%20from%20index%201%20(inclusive)%20until%20index%202%20(exclusive)%20%7C%20%0A%7C%20%24..book%5B(%40.length-2)%5D%20or%20%24..book%5B-2%3A%5D%20%7C%20Last%20two%20books%20%7C%20%0A%7C%20%24..book%5B2%3A%5D%20%7C%20Book%20number%20two%20from%20tail%20%7C%20%0A%7C%20%24..book%5B%3F(%40.isbn)%5D%20%7C%20All%20books%20with%20an%20ISBN%20number%20%7C%20%0A%7C%20%24.store.book%5B%3F(%40.price%20%3C%2010)%5D%20%7C%20All%20books%20in%20store%20cheaper%20than%2010%20%7C%20%0A%7C%20%24..book%5B%3F(%40.price%20%3C%3D%20%24%5B'expensive'%5D)%5D%20%7C%20All%20books%20in%20store%20that%20are%20not%20%22expensive%22%20%7C%20%0A%7C%20%24..book%5B%3F(%40.author%20%3D~%20%2F.*REES%2Fi)%5D%20%7C%20All%20books%20matching%20regex%20(ignore%20case)%20%7C%20%0A%7C%20%24..*%20%7C%20Give%20me%20every%20thing%20%0A%7C%20%24..book.length()%20%7C%20The%20number%20of%20books%20%7C%20%0A%0A

Condition

创建时间:2022/4/14 14:41
更新时间:2022/5/19 15:40
作者:Chris

org.springframework.context.annotation.Condition

org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor

org.springframework.context.annotation.Condition%0A%0Aorg.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor

kindle book

创建时间:2022/5/14 10:45
更新时间:2022/5/14 11:32
作者:Chris

http://so.baiduyun.me/
http://manybooks.net/
http://book.zi5.me/

https://libsolutions.net/booklist/419507/d51dd4

zh.singlelogin.app
zh.singlelogin.me
zh.zlib.life
zh.1lib.world
zh.libsolutions.domains


%60%60%60%0Ahttp%3A%2F%2Fso.baiduyun.me%2F%0Ahttp%3A%2F%2Fmanybooks.net%2F%0Ahttp%3A%2F%2Fbook.zi5.me%2F%0A%0Ahttps%3A%2F%2Flibsolutions.net%2Fbooklist%2F419507%2Fd51dd4%0A%0Azh.singlelogin.app%0Azh.singlelogin.me%0Azh.zlib.life%0Azh.1lib.world%0Azh.libsolutions.domains%0A%0A%60%60%60

idea tools

创建时间:2022/3/28 15:17
更新时间:2023/3/6 22:00
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzI5MTkxMDU2MQ==&mid=2247483895&idx=2&sn=9acfb895f94daaaf45a530f12e11bb0b&chksm=ec082739db7fae2f977773fd1eb8afac639243805b3785cb623dcd5a82f0476d9e6d4d0116f8&scene=27

idea 常用插件

1. arthas idea
2. Extra Icons
3. Free Mybatis plugin
4. Lombok
5. Maven Helper
6. Rainbow Brackets
7. Mybatis Log Plugin
8. AiXcoder Code Completer
9. CodeGlance 显示代码缩略图插件
%23%23%20idea%20%E5%B8%B8%E7%94%A8%E6%8F%92%E4%BB%B6%0A%0A%60%60%60%0A1.%20arthas%20idea%0A2.%20Extra%20Icons%0A3.%20Free%20Mybatis%20plugin%0A4.%20Lombok%0A5.%20Maven%20Helper%0A6.%20Rainbow%20Brackets%0A7.%20Mybatis%20Log%20Plugin%0A8.%20AiXcoder%20Code%20Completer%0A9.%20CodeGlance%20%E6%98%BE%E7%A4%BA%E4%BB%A3%E7%A0%81%E7%BC%A9%E7%95%A5%E5%9B%BE%E6%8F%92%E4%BB%B6%0A%60%60%60

java8新特性

创建时间:2020/11/2 10:05
更新时间:2022/5/6 19:31
作者:Chris
来源:http://loadhtml/

1. 新特性

1.1 Java8 2014.3发布

1.2 新特性

  1. 速度更快

    hashmap底层用红黑树算法实现,让查询等操作更快

  2. Lamble表达式

  3. Stream API

  4. 便于并行

    Stream API声明性的通过parallel() 和sequencial() 在并行流与顺序流之间进行切换

  5. 最大化的减少空指针

    可以通过Optional来配置一个默认的对象来帮我们减少空指针

2. lamble表达式

2.1 是什么

新的语法,是一个匿名函数,可以将代码像参数一样进行传递

@Test
public void test2() {
    Comparator<Integer> comparator = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return Integer.compare(o1, o2);
        }
    };

    int result1 = comparator.compare(12, 34);
    System.out.println(result1);

    //Lambda表达式
    Comparator<Integer> comparator2 = (o1, o2) -> Integer.compare(o1, o2);
    int result2 = comparator2.compare(12, 2);
    System.out.println(result2);

    //方法引用
    Comparator<Integer> comparator3 = Integer::compare;
    int result3 = comparator3.compare(12, 12);
    System.out.println(result3);
}

2.2 分为六种形式

Lambda表达式的本质就是作为函数式接口的实例
-> Lambda 操作符,
 左边为形参列表,其实就是是原来方法中的形参列表;
  1. 类型推断,参数的类型可以省略
  2. 无参无返回值,小括号不可以省略
  3. 如果只有一个参数,小括号可以省略
  4. 有两个及以上参数, 小括号不可以省略

 右边为Labmda体,其实就是重写的方法的方法体
  1. 多条执行语句,并且有返回值要有return和{}
  2. 只有一条语句, return与{}若有都可以省略
  1. 无参无返回值
  @Test
  public void test1() {
      Runnable r1 = new Runnable() {
          @Override
          public void run() {
              System.out.println("hellow runnable r1.");
          }
      };
      r1.run();
      // Lambda表达式做为左边接口的一个实例
      Runnable r2 = () -> System.out.println("hellow runnable r2.");
      r2.run();
  }
  1. 如果只有一个参数,小括号可以省略
    /**
    * 有一个参数无返回值
    */
    @Test
    public void test2() {
       Consumer<String> consumer = new Consumer<String>() {
           @Override
           public void accept(String s) {
               System.out.println(s);
           }
       };
       consumer.accept("谎言和誓言的区别是什么?");

       Consumer<String> consumer1 = (String s) -> System.out.println(s);
       consumer2.accept("一个是听的人当真了,一个是说的人当真了");


       //如果只有一个参数,小括号可以省略
       Consumer<String> consumer3 = s -> System.out.println(s);
       consumer3.accept("一个是听的人当真了,一个是说的人当真了");
    }
  1. 类型推断,参数的类型可以省略
    //类型推断,参数的类型可以省略
    Consumer<String> consumer2 = (s) -> System.out.println(s);
    consumer2.accept("一个是听的人当真了,一个是说的人当真了");
  1. 有两个及以上参数,小括号不可以省略

  2. 有多条执行语句,并且有返回值

    Comparator<Integer> comparator2 = (o1, o2) -> {
       System.out.println(o1);
       System.out.println(o2);
       return Integer.compare(o1, o2);
    };
    int result2 = comparator2.compare(12, 2);
    System.out.println(result2);
  1. Lambda体只有一条语句,return与{}若有都可以省略
    Comparator<Integer> comparator3 = (o1, o2) -> o1.compareTo(o2);
    int result3 = comparator3.compare(12, 12);
    System.out.println(result3);

2.3 函数式接口

如果一个接口中只有一个抽象方法,则此接口称为函数式接口

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}
  1. Java内置四大核心函数式接口
消费型 Consumer<T>      void accept(T t)
供给型 Supplier<T>      T get()
函数型 Function<T, R>   R apply(T t)
断定型 Predicate<T>     boolean test(T t)
public class LambdaTest2 {

   public void happTime(int money, Consumer<Integer> cost) {
       cost.accept(money);
   }

   @Test
   public void test1() {
       happTime(500, new Consumer<Integer>() {
           @Override
           public void accept(Integer cost) {
               System.out.println("the cost is :" + cost);
           }
       });

       //Lambda表达式
       happTime(400, money -> System.out.println("the cost is :" + money));
   }


   /**
    * 根据给定的规则过滤集合中的字符串,此规则由predicate的方法决定
    */
   public List<String> fileterStr(List<String> list, Predicate<String> pre) {
       List<String> afterFiltering = new ArrayList<>();
       for (String s : list) {
           if (pre.test(s)) {
               afterFiltering.add(s);
           }
       }
       return afterFiltering;
   }

   @Test
   public void test2() {
       List<String> list = Arrays.asList("Chris", "John", "Stephone", "Hedy");
       List<String> fileteredStr = fileterStr(list, new Predicate<String>() {
           @Override
           public boolean test(String s) {
               return s.contains("s");
           }
       });
       System.out.println(fileteredStr);

       //Lambda表达式
       List<String> fileteredStr2 = fileterStr(list, s -> s.contains("s"));
       System.out.println(fileteredStr2);

   }
}

4. StreamAPI

4.1 StreamAPI 是什么

StreamAPI把真正的函数式编程风格引入了JAVA,StreamAPI提供了极高的生产力,可以让我们的代码更加高效,干净和简洁

4.2 StreamAPI 能干什么

StreamAPI 提供了高效且易于使用的处理数据的方式
使用StreamAPI 可以对集合进行复杂的查找,过滤和映射操作,也可以使用StreamAPI 并行的来执行操作。

4.3 Collection和Stream的区别

Collection 是一种静态的内存数据结构
Stream 是有关数据的处理算法,是面向CPU的算法方式

4.4 Stream

  1. 不存储数据,
  2. 不会改变源对象,每次都会返回一个持有结果的新的Stream
  3. Steam操作是延迟执行的,会等到需要结果时再执行,即transform时不执行,action时才执行

4.4 Stream 怎么玩

4.4.1 Stream 操作分为三步
  1. 创建
  2. 中间操作 Transform
  3. 终止操作 Action
4.4.2 创建有四种方式
1. 通过集合创建Stream
public void createStreamByCollection() {
    List<Employee> employees = EmployeeData.getEmployees();
    //返回一个顺序流
    Stream<Employee> stream = employees.stream();

    //返回一个并行流
    Stream<Employee> parallelStream = employees.parallelStream();
}
2. 通过数组创建Stream
public void createStreamByArrays() {
    int[] intArr = new int[]{1, 2, 3, 4, 5, 6};
    IntStream stream = Arrays.stream(intArr);

    Employee chris = new Employee(1, "Chris", 23, 23000.43);
    Employee john = new Employee(2, "John", 14, 3000.43);
    Employee[] empArr = new Employee[]{chris, john};

    Stream<Employee> empStream = Arrays.stream(empArr);
}
3. 通过Stream的of()方法创建Steam
public void createStreamByStream() {
    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
}
4.  创建无限流
public void createStreamByStream2() {
    /*
     迭代
     创建并遍历前10个偶数
     */
    Stream.iterate(0, seed -> seed + 2).limit(10).forEach(System.out::println);

    /*
     生成
     创建并遍历前10个偶数
     */
    Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
4.4.3 中间操作
1. 筛选与分片

2. 映射

3. 排序

4.4.4 终止操作

终止操作可以从流中生成结果,其结果可以是任何非流的数据
流进行了终止操作后,不能两次使用

1. 匹配与查找

2. 归约

@Test
public void testReduce() {
    //计算1到10自然数之和
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    Integer sum = list.stream().reduce(0, Integer::sum);
    System.out.println(sum);
    //计算公司中所有员工的工资总和
    List<Employee> employees = EmployeeData.getEmployees();
    Stream<Double> doubleStream = employees.stream().map(Employee::getSalary);
    // Optional<Double> reduce= doubleStream.reduce((a, b) -> a + b);
    Optional<Double> reduce = doubleStream.reduce(Double::sum);
    Double totalSalary = reduce.orElse((double) 0);
    System.out.println(totalSalary);
}
3. 收集

    @Test
    public void testCollector() {
        List<Employee> employees = EmployeeData.getEmployees();
        List<Employee> list = employees.stream().filter(e -> e.getSalary() > 10000).collect(Collectors.toList());
        Set<Employee> set = employees.stream().filter(e -> e.getSalary() > 10000).collect(Collectors.toSet());
        List<Employee> list2 =
            employees.stream().filter(e -> e.getSalary() > 10000).collect(Collectors.toCollection(ArrayList::new));

        LinkedHashMap<Integer, List<Employee>> ageGrouping =
            employees.stream().collect(Collectors.groupingBy(Employee::getAge, LinkedHashMap::new, Collectors.toList()));

        Map<Integer, Employee> ageMaping = employees.stream().collect(Collectors.toMap(Employee::getAge, e -> e,
                                                                                       (oldKey, newKey) -> newKey));
    }

4.5 Optional

Optional<T> 是一个容器类,它可以保存类型T的值,代表这个值存在,或者仅仅保存为null, 表示这个值不存在。
原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且如以避免空指针异常。
如果值存在则 isPresent() 方法返回true,调用get() 方法会返回该对象。

4.5.1 创建对象的方法

Optional.of(T t) 创建一个Optional实例,t为非空对象
Optional.empty() 创建一个空的Optional实例
Optional.ofNullable(T t) t可以为空对象

4.5.2 判断Optional容器是否包含对象

boolean isPresent() 判断是否包含对象
void ifPresent(Consumer<? super T> consumer): 如果有值,就执行Consumer接口实现的代码,并且该值会作为参数传给它。

4.5.3 获取Optional容器的对象

T get() 如果调用对象包含值,返回该值,否则抛出异常
T orElse(T other) 如果有值则返回,否则返回指定的other对象
T orElseGet(Supplier<? extends T> other) 如果有值则返回,否则返回Supplier接口
实现的对象
T orElseThrow(Supplier<? extends X> exceptionSupplier) 如果有值则返回,否则返回Supplier接口实现的异常

注意

    User user = null;
    user = Optional.ofNullable(user).orElse(createUser());
    user = Optional.ofNullable(user).orElseGet(() -> createUser());

    public User createUser(){
        User user = new User();
        user.setName("zhangsan");
        return user;
    }

orElse(T other)和orElseGet(Supplier<? extends T> other)的区别:
当user不为null时,orElse函数依然会执行createUser方法,但会将原user值返回,
而orElseGet函数并不会执行createUser()方法,

4.5.4 map 和 flatMap

map(Function mapper) 和 flatMap(Function> mapper)
这两个函数,在函数体上没什么区别。
唯一区别的就是入参,
map函数所接受的入参类型为Function<? super T, ? extends U>,
而flapMap的入参类型为Function<? super T, Optional<U>>。

 public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
 }

public <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())  
        return empty();
    else {
        return Objects.requireNonNull(mapper.apply(value));
    }
}
public class User {
    private String name;
    public String getName() { return name; }
 }
 // 这时候取name的写法如下所示
String city = Optional.ofNullable(user).map(u-> u.getName()).get();

public class User {
    private String name;
    public Optional<String> getName() {
        return Optional.ofNullable(name);
    }
}
// 这时候取name的写法如下所示
String city = Optional.ofNullable(user).flatMap(u-> u.getName()).get();
4.5.5 isPresent() 和 ifPresent(Consumer consumer)

isPresent即判断value值是否为空,而ifPresent就是在value值不为空时执行consumer

4.5.6 filter(Predicate predicate)
public User getUser(User user) throws Exception{
    if(user!=null){
        String name = user.getName();
        if("zhangsan".equals(name)){
            return user;
        }
    }else{
        user = new User();
        user.setName("zhangsan");
        return user;
    }
}

// java8写法
public User getUser(User user) {
    return Optional.ofNullable(user)
                   .filter(u->"zhangsan".equals(u.getName()))
                   .orElseGet(()-> {
                        User user1 = new User();
                        user1.setName("zhangsan");
                        return user1;
                   });
}
public String getCity(User user)  throws Exception{
    if(user!=null){
        if(user.getAddress()!=null){
            Address address = user.getAddress();
            if(address.getCity()!=null){
                return address.getCity();
            }
        }
    }
    throw new Excpetion("取值错误");
}
// java8写法
public String getCity(User user) throws Exception{
    return Optional.ofNullable(user)
                   .map(u-> u.getAddress())
                   .map(a->a.getCity())
                   .orElseThrow(()->new Exception("取指错误"));
}

5 实例

5.1 Stream 实例

List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
System.out.println("求和:" + nums.stream()// 转成Stream
        .filter(team -> team != null)// 过滤
        .distinct()// 去重
        .mapToInt(num -> num * 2)// map操作
        .skip(2)// 跳过前2个元素
        .limit(4)// 限制取前4个元素
        .peek(System.out::println)// 流式处理对象函数
        .sum());//

5.2 Collectors.groupingBy

Map<String, List<Long>> actNameMap = activities.stream()
                    .filter(activity -> !Objects.equals(activity.getName(), ProcessActivityEnum.CountersignForEn.getActDisplay()))
                    .collect(Collectors.groupingBy(GimProcessActivity::getName, Collectors.mapping(GimProcessActivity::getId, Collectors.toList())));

5.3 Collectors.collectingAndThen

List<PlanCountryProviderConfigBean> uniqueCaEndc_Configs = configLists.stream()
                    .filter(configBean -> !isAllDel(configBean))
                    .collect(Collectors.collectingAndThen(
                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PlanCountryProviderConfigBean::getCaEndc))),
                            ArrayList::new));
 private <T> Predicate<T> distinctByProperties(String[] properties) {
        List<String[]> list = CollUtil.newLinkedList();
        return t -> {
            String[] t_values = buildValues(t, properties);
            if (CollUtil.isEmpty(list)) {
                list.add(t_values);
                return true;
            }
            int i = 0;
            for (; i < list.size(); i++) {
                String[] values = list.get(i);
                int j = 0;
                for (; j < values.length; j++) {
                    String t_value = t_values[j];
                    String value = values[j];
                    if (Objects.nonNull(t_value) && Objects.nonNull(value) && !t_value.equals(value)) {
                        break;
                    }
                }

                if (j == values.length) {
                    return false;
                }
            }

            if (i == list.size()) {
                list.add(t_values);
            }
            return true;
        };
    }


    private <T> String[] buildValues(T obj, String[] properties) {
        String[] values = new String[properties.length];
        Class<?> clz = obj.getClass();
        for (int i = 0; i < properties.length; i++) {
            Field field;
            String property = properties[i];
            try {
                field = clz.getDeclaredField(property);
                field.setAccessible(true);
                Object value = field.get(obj);
                values[i] = String.valueOf(value);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                log.error("error happened when get value of field:" + property + ", from:" + obj, e);
            }
        }
        return values;
    }
%5BTOC%5D%0A%23%23%23%201.%20%E6%96%B0%E7%89%B9%E6%80%A7%0A%0A%23%23%23%23%201.1%20Java8%202014.3%E5%8F%91%E5%B8%83%0A%0A%23%23%23%23%201.2%20%E6%96%B0%E7%89%B9%E6%80%A7%20%0A%0A1.%20%E9%80%9F%E5%BA%A6%E6%9B%B4%E5%BF%AB%0A%0A%20%20%20%3E%20hashmap%E5%BA%95%E5%B1%82%E7%94%A8%E7%BA%A2%E9%BB%91%E6%A0%91%E7%AE%97%E6%B3%95%E5%AE%9E%E7%8E%B0%EF%BC%8C%E8%AE%A9%E6%9F%A5%E8%AF%A2%E7%AD%89%E6%93%8D%E4%BD%9C%E6%9B%B4%E5%BF%AB%0A%0A2.%20Lamble%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%0A3.%20Stream%20API%0A%0A4.%20%E4%BE%BF%E4%BA%8E%E5%B9%B6%E8%A1%8C%0A%0A%20%20%20%3E%20Stream%20API%E5%A3%B0%E6%98%8E%E6%80%A7%E7%9A%84%E9%80%9A%E8%BF%87parallel()%20%E5%92%8Csequencial()%20%E5%9C%A8%E5%B9%B6%E8%A1%8C%E6%B5%81%E4%B8%8E%E9%A1%BA%E5%BA%8F%E6%B5%81%E4%B9%8B%E9%97%B4%E8%BF%9B%E8%A1%8C%E5%88%87%E6%8D%A2%0A%0A5.%20%E6%9C%80%E5%A4%A7%E5%8C%96%E7%9A%84%E5%87%8F%E5%B0%91%E7%A9%BA%E6%8C%87%E9%92%88%0A%0A%20%20%20%3E%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87Optional%E6%9D%A5%E9%85%8D%E7%BD%AE%E4%B8%80%E4%B8%AA%E9%BB%98%E8%AE%A4%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%9D%A5%E5%B8%AE%E6%88%91%E4%BB%AC%E5%87%8F%E5%B0%91%E7%A9%BA%E6%8C%87%E9%92%88%0A%0A%0A%0A%23%23%23%202.%20lamble%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%0A%23%23%23%23%202.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E6%96%B0%E7%9A%84%E8%AF%AD%E6%B3%95%EF%BC%8C%E6%98%AF%E4%B8%80%E4%B8%AA%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%B0%86%E4%BB%A3%E7%A0%81%E5%83%8F%E5%8F%82%E6%95%B0%E4%B8%80%E6%A0%B7%E8%BF%9B%E8%A1%8C%E4%BC%A0%E9%80%92%0A%3E%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20test2()%20%7B%0A%20%20%20%20Comparator%3CInteger%3E%20comparator%20%3D%20new%20Comparator%3CInteger%3E()%20%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20int%20compare(Integer%20o1%2C%20Integer%20o2)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20Integer.compare(o1%2C%20o2)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%3B%0A%0A%20%20%20%20int%20result1%20%3D%20comparator.compare(12%2C%2034)%3B%0A%20%20%20%20System.out.println(result1)%3B%0A%0A%20%20%20%20%2F%2FLambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%20%20%20%20Comparator%3CInteger%3E%20comparator2%20%3D%20(o1%2C%20o2)%20-%3E%20Integer.compare(o1%2C%20o2)%3B%0A%20%20%20%20int%20result2%20%3D%20comparator2.compare(12%2C%202)%3B%0A%20%20%20%20System.out.println(result2)%3B%0A%0A%20%20%20%20%2F%2F%E6%96%B9%E6%B3%95%E5%BC%95%E7%94%A8%0A%20%20%20%20Comparator%3CInteger%3E%20comparator3%20%3D%20Integer%3A%3Acompare%3B%0A%20%20%20%20int%20result3%20%3D%20comparator3.compare(12%2C%2012)%3B%0A%20%20%20%20System.out.println(result3)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202.2%20%E5%88%86%E4%B8%BA%E5%85%AD%E7%A7%8D%E5%BD%A2%E5%BC%8F%0A%0A%60%60%60%0ALambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E6%9C%AC%E8%B4%A8%E5%B0%B1%E6%98%AF%E4%BD%9C%E4%B8%BA%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%AE%9E%E4%BE%8B%0A-%3E%20Lambda%20%E6%93%8D%E4%BD%9C%E7%AC%A6%EF%BC%8C%0A%20%E5%B7%A6%E8%BE%B9%E4%B8%BA%E5%BD%A2%E5%8F%82%E5%88%97%E8%A1%A8%EF%BC%8C%E5%85%B6%E5%AE%9E%E5%B0%B1%E6%98%AF%E6%98%AF%E5%8E%9F%E6%9D%A5%E6%96%B9%E6%B3%95%E4%B8%AD%E7%9A%84%E5%BD%A2%E5%8F%82%E5%88%97%E8%A1%A8%3B%0A%20%201.%20%E7%B1%BB%E5%9E%8B%E6%8E%A8%E6%96%AD%EF%BC%8C%E5%8F%82%E6%95%B0%E7%9A%84%E7%B1%BB%E5%9E%8B%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%20%202.%20%E6%97%A0%E5%8F%82%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC%2C%E5%B0%8F%E6%8B%AC%E5%8F%B7%E4%B8%8D%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%20%203.%20%E5%A6%82%E6%9E%9C%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%B0%8F%E6%8B%AC%E5%8F%B7%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%20%204.%20%E6%9C%89%E4%B8%A4%E4%B8%AA%E5%8F%8A%E4%BB%A5%E4%B8%8A%E5%8F%82%E6%95%B0%2C%20%E5%B0%8F%E6%8B%AC%E5%8F%B7%E4%B8%8D%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%0A%20%E5%8F%B3%E8%BE%B9%E4%B8%BALabmda%E4%BD%93%EF%BC%8C%E5%85%B6%E5%AE%9E%E5%B0%B1%E6%98%AF%E9%87%8D%E5%86%99%E7%9A%84%E6%96%B9%E6%B3%95%E7%9A%84%E6%96%B9%E6%B3%95%E4%BD%93%0A%20%201.%20%E5%A4%9A%E6%9D%A1%E6%89%A7%E8%A1%8C%E8%AF%AD%E5%8F%A5%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%9C%89%E8%BF%94%E5%9B%9E%E5%80%BC%E8%A6%81%E6%9C%89return%E5%92%8C%7B%7D%0A%20%202.%20%E5%8F%AA%E6%9C%89%E4%B8%80%E6%9D%A1%E8%AF%AD%E5%8F%A5%2C%20return%E4%B8%8E%7B%7D%E8%8B%A5%E6%9C%89%E9%83%BD%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%60%60%60%0A%0A1.%20%E6%97%A0%E5%8F%82%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC%0A%20%0A%20%60%60%60java%0A%20%20%20%40Test%0A%20%20%20public%20void%20test1()%20%7B%0A%20%20%20%20%20%20%20Runnable%20r1%20%3D%20new%20Runnable()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22hellow%20runnable%20r1.%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20r1.run()%3B%0A%20%20%20%20%20%20%20%2F%2F%20Lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%81%9A%E4%B8%BA%E5%B7%A6%E8%BE%B9%E6%8E%A5%E5%8F%A3%E7%9A%84%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%0A%20%20%20%20%20%20%20Runnable%20r2%20%3D%20()%20-%3E%20System.out.println(%22hellow%20runnable%20r2.%22)%3B%0A%20%20%20%20%20%20%20r2.run()%3B%0A%20%20%20%7D%0A%60%60%60%0A%0A%20%20%20%0A%0A2.%20%E5%A6%82%E6%9E%9C%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%B0%8F%E6%8B%AC%E5%8F%B7%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%0A%60%60%60java%0A%20%20%20%20%2F**%0A%20%20%20%20*%20%E6%9C%89%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC%0A%20%20%20%20*%2F%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test2()%20%7B%0A%20%20%20%20%20%20%20Consumer%3CString%3E%20consumer%20%3D%20new%20Consumer%3CString%3E()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20public%20void%20accept(String%20s)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(s)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20consumer.accept(%22%E8%B0%8E%E8%A8%80%E5%92%8C%E8%AA%93%E8%A8%80%E7%9A%84%E5%8C%BA%E5%88%AB%E6%98%AF%E4%BB%80%E4%B9%88%3F%22)%3B%0A%0A%20%20%20%20%20%20%20Consumer%3CString%3E%20consumer1%20%3D%20(String%20s)%20-%3E%20System.out.println(s)%3B%0A%20%20%20%20%20%20%20consumer2.accept(%22%E4%B8%80%E4%B8%AA%E6%98%AF%E5%90%AC%E7%9A%84%E4%BA%BA%E5%BD%93%E7%9C%9F%E4%BA%86%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%98%AF%E8%AF%B4%E7%9A%84%E4%BA%BA%E5%BD%93%E7%9C%9F%E4%BA%86%22)%3B%0A%0A%0A%20%20%20%20%20%20%20%2F%2F%E5%A6%82%E6%9E%9C%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%B0%8F%E6%8B%AC%E5%8F%B7%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%20%20%20%20%20%20%20Consumer%3CString%3E%20consumer3%20%3D%20s%20-%3E%20System.out.println(s)%3B%0A%20%20%20%20%20%20%20consumer3.accept(%22%E4%B8%80%E4%B8%AA%E6%98%AF%E5%90%AC%E7%9A%84%E4%BA%BA%E5%BD%93%E7%9C%9F%E4%BA%86%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%98%AF%E8%AF%B4%E7%9A%84%E4%BA%BA%E5%BD%93%E7%9C%9F%E4%BA%86%22)%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A3.%20%E7%B1%BB%E5%9E%8B%E6%8E%A8%E6%96%AD%EF%BC%8C%E5%8F%82%E6%95%B0%E7%9A%84%E7%B1%BB%E5%9E%8B%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%0A%60%60%60java%0A%20%20%20%20%2F%2F%E7%B1%BB%E5%9E%8B%E6%8E%A8%E6%96%AD%EF%BC%8C%E5%8F%82%E6%95%B0%E7%9A%84%E7%B1%BB%E5%9E%8B%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%20%20%20%20Consumer%3CString%3E%20consumer2%20%3D%20(s)%20-%3E%20System.out.println(s)%3B%0A%20%20%20%20consumer2.accept(%22%E4%B8%80%E4%B8%AA%E6%98%AF%E5%90%AC%E7%9A%84%E4%BA%BA%E5%BD%93%E7%9C%9F%E4%BA%86%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%98%AF%E8%AF%B4%E7%9A%84%E4%BA%BA%E5%BD%93%E7%9C%9F%E4%BA%86%22)%3B%0A%60%60%60%0A%0A4.%20%E6%9C%89%E4%B8%A4%E4%B8%AA%E5%8F%8A%E4%BB%A5%E4%B8%8A%E5%8F%82%E6%95%B0%EF%BC%8C%E5%B0%8F%E6%8B%AC%E5%8F%B7%E4%B8%8D%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%0A5.%20%E6%9C%89%E5%A4%9A%E6%9D%A1%E6%89%A7%E8%A1%8C%E8%AF%AD%E5%8F%A5%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%9C%89%E8%BF%94%E5%9B%9E%E5%80%BC%0A%0A%60%60%60java%0A%20%20%20%20Comparator%3CInteger%3E%20comparator2%20%3D%20(o1%2C%20o2)%20-%3E%20%7B%0A%20%20%20%20%20%20%20System.out.println(o1)%3B%0A%20%20%20%20%20%20%20System.out.println(o2)%3B%0A%20%20%20%20%20%20%20return%20Integer.compare(o1%2C%20o2)%3B%0A%20%20%20%20%7D%3B%0A%20%20%20%20int%20result2%20%3D%20comparator2.compare(12%2C%202)%3B%0A%20%20%20%20System.out.println(result2)%3B%0A%60%60%60%0A%0A6.%20Lambda%E4%BD%93%E5%8F%AA%E6%9C%89%E4%B8%80%E6%9D%A1%E8%AF%AD%E5%8F%A5%EF%BC%8Creturn%E4%B8%8E%7B%7D%E8%8B%A5%E6%9C%89%E9%83%BD%E5%8F%AF%E4%BB%A5%E7%9C%81%E7%95%A5%0A%0A%60%60%60java%0A%20%20%20%20Comparator%3CInteger%3E%20comparator3%20%3D%20(o1%2C%20o2)%20-%3E%20o1.compareTo(o2)%3B%0A%20%20%20%20int%20result3%20%3D%20comparator3.compare(12%2C%2012)%3B%0A%20%20%20%20System.out.println(result3)%3B%0A%60%60%60%0A%23%23%23%23%202.3%20%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%E4%B8%AD%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E6%8A%BD%E8%B1%A1%E6%96%B9%E6%B3%95%EF%BC%8C%E5%88%99%E6%AD%A4%E6%8E%A5%E5%8F%A3%E7%A7%B0%E4%B8%BA%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3%0A%0A%60%60%60java%0A%40FunctionalInterface%0Apublic%20interface%20Runnable%20%7B%0A%20%20%20%20public%20abstract%20void%20run()%3B%0A%7D%0A%60%60%60%0A%0A1.%20Java%E5%86%85%E7%BD%AE%E5%9B%9B%E5%A4%A7%E6%A0%B8%E5%BF%83%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3%0A%0A%60%60%60%0A%E6%B6%88%E8%B4%B9%E5%9E%8B%20Consumer%3CT%3E%20%20%20%20%20%20void%20accept(T%20t)%0A%E4%BE%9B%E7%BB%99%E5%9E%8B%20Supplier%3CT%3E%20%20%20%20%20%20T%20get()%0A%E5%87%BD%E6%95%B0%E5%9E%8B%20Function%3CT%2C%20R%3E%20%20%20R%20apply(T%20t)%0A%E6%96%AD%E5%AE%9A%E5%9E%8B%20Predicate%3CT%3E%20%20%20%20%20boolean%20test(T%20t)%0A%60%60%60%0A%0A%60%60%60java%0Apublic%20class%20LambdaTest2%20%7B%0A%0A%20%20%20public%20void%20happTime(int%20money%2C%20Consumer%3CInteger%3E%20cost)%20%7B%0A%20%20%20%20%20%20%20cost.accept(money)%3B%0A%20%20%20%7D%0A%0A%20%20%20%40Test%0A%20%20%20public%20void%20test1()%20%7B%0A%20%20%20%20%20%20%20happTime(500%2C%20new%20Consumer%3CInteger%3E()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20public%20void%20accept(Integer%20cost)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22the%20cost%20is%20%3A%22%20%2B%20cost)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D)%3B%0A%0A%20%20%20%20%20%20%20%2F%2FLambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%20%20%20%20%20%20%20happTime(400%2C%20money%20-%3E%20System.out.println(%22the%20cost%20is%20%3A%22%20%2B%20money))%3B%0A%20%20%20%7D%0A%0A%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%A0%B9%E6%8D%AE%E7%BB%99%E5%AE%9A%E7%9A%84%E8%A7%84%E5%88%99%E8%BF%87%E6%BB%A4%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E6%AD%A4%E8%A7%84%E5%88%99%E7%94%B1predicate%E7%9A%84%E6%96%B9%E6%B3%95%E5%86%B3%E5%AE%9A%0A%20%20%20%20*%2F%0A%20%20%20public%20List%3CString%3E%20fileterStr(List%3CString%3E%20list%2C%20Predicate%3CString%3E%20pre)%20%7B%0A%20%20%20%20%20%20%20List%3CString%3E%20afterFiltering%20%3D%20new%20ArrayList%3C%3E()%3B%0A%20%20%20%20%20%20%20for%20(String%20s%20%3A%20list)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(pre.test(s))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20afterFiltering.add(s)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20return%20afterFiltering%3B%0A%20%20%20%7D%0A%0A%20%20%20%40Test%0A%20%20%20public%20void%20test2()%20%7B%0A%20%20%20%20%20%20%20List%3CString%3E%20list%20%3D%20Arrays.asList(%22Chris%22%2C%20%22John%22%2C%20%22Stephone%22%2C%20%22Hedy%22)%3B%0A%20%20%20%20%20%20%20List%3CString%3E%20fileteredStr%20%3D%20fileterStr(list%2C%20new%20Predicate%3CString%3E()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20public%20boolean%20test(String%20s)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20s.contains(%22s%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20System.out.println(fileteredStr)%3B%0A%0A%20%20%20%20%20%20%20%2F%2FLambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%20%20%20%20%20%20%20List%3CString%3E%20fileteredStr2%20%3D%20fileterStr(list%2C%20s%20-%3E%20s.contains(%22s%22))%3B%0A%20%20%20%20%20%20%20System.out.println(fileteredStr2)%3B%0A%0A%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%23%23%23%204.%20StreamAPI%0A%23%23%23%23%204.1%20StreamAPI%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20StreamAPI%E6%8A%8A%E7%9C%9F%E6%AD%A3%E7%9A%84%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B%E9%A3%8E%E6%A0%BC%E5%BC%95%E5%85%A5%E4%BA%86JAVA%EF%BC%8CStreamAPI%E6%8F%90%E4%BE%9B%E4%BA%86%E6%9E%81%E9%AB%98%E7%9A%84%E7%94%9F%E4%BA%A7%E5%8A%9B%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%AE%A9%E6%88%91%E4%BB%AC%E7%9A%84%E4%BB%A3%E7%A0%81%E6%9B%B4%E5%8A%A0%E9%AB%98%E6%95%88%EF%BC%8C%E5%B9%B2%E5%87%80%E5%92%8C%E7%AE%80%E6%B4%81%0A%0A%23%23%23%23%204.2%20StreamAPI%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%3E%20StreamAPI%20%E6%8F%90%E4%BE%9B%E4%BA%86%E9%AB%98%E6%95%88%E4%B8%94%E6%98%93%E4%BA%8E%E4%BD%BF%E7%94%A8%E7%9A%84%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE%E7%9A%84%E6%96%B9%E5%BC%8F%20%0A%E4%BD%BF%E7%94%A8StreamAPI%20%E5%8F%AF%E4%BB%A5%E5%AF%B9%E9%9B%86%E5%90%88%E8%BF%9B%E8%A1%8C%E5%A4%8D%E6%9D%82%E7%9A%84%E6%9F%A5%E6%89%BE%EF%BC%8C%E8%BF%87%E6%BB%A4%E5%92%8C%E6%98%A0%E5%B0%84%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8StreamAPI%20%E5%B9%B6%E8%A1%8C%E7%9A%84%E6%9D%A5%E6%89%A7%E8%A1%8C%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A%23%23%23%23%204.3%20Collection%E5%92%8CStream%E7%9A%84%E5%8C%BA%E5%88%AB%0A%3E%20Collection%20%E6%98%AF%E4%B8%80%E7%A7%8D%E9%9D%99%E6%80%81%E7%9A%84%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%0A%3E%20Stream%20%E6%98%AF%E6%9C%89%E5%85%B3%E6%95%B0%E6%8D%AE%E7%9A%84%E5%A4%84%E7%90%86%E7%AE%97%E6%B3%95%EF%BC%8C%E6%98%AF%E9%9D%A2%E5%90%91CPU%E7%9A%84%E7%AE%97%E6%B3%95%E6%96%B9%E5%BC%8F%0A%0A%0A%0A%23%23%23%23%204.4%20Stream%20%0A%3E%201.%20%E4%B8%8D%E5%AD%98%E5%82%A8%E6%95%B0%E6%8D%AE%EF%BC%8C%0A%3E%202.%20%E4%B8%8D%E4%BC%9A%E6%94%B9%E5%8F%98%E6%BA%90%E5%AF%B9%E8%B1%A1%EF%BC%8C%E6%AF%8F%E6%AC%A1%E9%83%BD%E4%BC%9A%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E6%8C%81%E6%9C%89%E7%BB%93%E6%9E%9C%E7%9A%84%E6%96%B0%E7%9A%84Stream%0A%3E%203.%20Steam%E6%93%8D%E4%BD%9C%E6%98%AF%E5%BB%B6%E8%BF%9F%E6%89%A7%E8%A1%8C%E7%9A%84%EF%BC%8C%E4%BC%9A%E7%AD%89%E5%88%B0%E9%9C%80%E8%A6%81%E7%BB%93%E6%9E%9C%E6%97%B6%E5%86%8D%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%8D%B3transform%E6%97%B6%E4%B8%8D%E6%89%A7%E8%A1%8C%EF%BC%8Caction%E6%97%B6%E6%89%8D%E6%89%A7%E8%A1%8C%0A%0A%23%23%23%23%204.4%20Stream%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%23%204.4.1%20%20Stream%20%E6%93%8D%E4%BD%9C%E5%88%86%E4%B8%BA%E4%B8%89%E6%AD%A5%0A%3E%201.%20%E5%88%9B%E5%BB%BA%0A%3E%202.%20%E4%B8%AD%E9%97%B4%E6%93%8D%E4%BD%9C%20Transform%0A%3E%203.%20%E7%BB%88%E6%AD%A2%E6%93%8D%E4%BD%9C%20Action%0A%0A%23%23%23%23%23%204.4.2%20%20%20%E5%88%9B%E5%BB%BA%E6%9C%89%E5%9B%9B%E7%A7%8D%E6%96%B9%E5%BC%8F%0A%23%23%23%23%23%23%201.%20%E9%80%9A%E8%BF%87%E9%9B%86%E5%90%88%E5%88%9B%E5%BB%BAStream%0A%0A%60%60%60java%0Apublic%20void%20createStreamByCollection()%20%7B%0A%20%20%20%20List%3CEmployee%3E%20employees%20%3D%20EmployeeData.getEmployees()%3B%0A%20%20%20%20%2F%2F%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E9%A1%BA%E5%BA%8F%E6%B5%81%0A%20%20%20%20Stream%3CEmployee%3E%20stream%20%3D%20employees.stream()%3B%0A%0A%20%20%20%20%2F%2F%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E5%B9%B6%E8%A1%8C%E6%B5%81%0A%20%20%20%20Stream%3CEmployee%3E%20parallelStream%20%3D%20employees.parallelStream()%3B%0A%7D%0A%60%60%60%0A%0A%0A%23%23%23%23%23%23%202.%20%E9%80%9A%E8%BF%87%E6%95%B0%E7%BB%84%E5%88%9B%E5%BB%BAStream%0A%60%60%60java%0Apublic%20void%20createStreamByArrays()%20%7B%0A%20%20%20%20int%5B%5D%20intArr%20%3D%20new%20int%5B%5D%7B1%2C%202%2C%203%2C%204%2C%205%2C%206%7D%3B%0A%20%20%20%20IntStream%20stream%20%3D%20Arrays.stream(intArr)%3B%0A%0A%20%20%20%20Employee%20chris%20%3D%20new%20Employee(1%2C%20%22Chris%22%2C%2023%2C%2023000.43)%3B%0A%20%20%20%20Employee%20john%20%3D%20new%20Employee(2%2C%20%22John%22%2C%2014%2C%203000.43)%3B%0A%20%20%20%20Employee%5B%5D%20empArr%20%3D%20new%20Employee%5B%5D%7Bchris%2C%20john%7D%3B%0A%0A%20%20%20%20Stream%3CEmployee%3E%20empStream%20%3D%20Arrays.stream(empArr)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%203.%C2%A0%E9%80%9A%E8%BF%87Stream%E7%9A%84of()%E6%96%B9%E6%B3%95%E5%88%9B%E5%BB%BASteam%0A%60%60%60java%0Apublic%20void%20createStreamByStream()%20%7B%0A%20%20%20%20Stream%3CInteger%3E%20stream%20%3D%20Stream.of(1%2C%202%2C%203%2C%204%2C%205%2C%206)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%204.%C2%A0%C2%A0%E5%88%9B%E5%BB%BA%E6%97%A0%E9%99%90%E6%B5%81%0A%60%60%60java%0Apublic%20void%20createStreamByStream2()%20%7B%0A%20%20%20%20%2F*%0A%20%20%20%20%20%E8%BF%AD%E4%BB%A3%0A%20%20%20%20%20%E5%88%9B%E5%BB%BA%E5%B9%B6%E9%81%8D%E5%8E%86%E5%89%8D10%E4%B8%AA%E5%81%B6%E6%95%B0%0A%20%20%20%20%20*%2F%0A%20%20%20%20Stream.iterate(0%2C%20seed%20-%3E%20seed%20%2B%202).limit(10).forEach(System.out%3A%3Aprintln)%3B%0A%0A%20%20%20%20%2F*%0A%20%20%20%20%20%E7%94%9F%E6%88%90%0A%20%20%20%20%20%E5%88%9B%E5%BB%BA%E5%B9%B6%E9%81%8D%E5%8E%86%E5%89%8D10%E4%B8%AA%E5%81%B6%E6%95%B0%0A%20%20%20%20%20*%2F%0A%20%20%20%20Stream.generate(Math%3A%3Arandom).limit(10).forEach(System.out%3A%3Aprintln)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%204.4.3%20%20%20%E4%B8%AD%E9%97%B4%E6%93%8D%E4%BD%9C%0A%0A%23%23%23%23%23%23%201.%20%E7%AD%9B%E9%80%89%E4%B8%8E%E5%88%86%E7%89%87%0A%0A%20%20%20!%5Be244b3ccc64a03c07ea536d8fe83ef71.png%5D(en-resource%3A%2F%2Fdatabase%2F860%3A1)%0A%20%20%20%20%0A%23%23%23%23%23%23%202.%20%E6%98%A0%E5%B0%84%0A%0A%20%20%20!%5Bc5dc51f28e359b572470ca6bacd63982.png%5D(en-resource%3A%2F%2Fdatabase%2F859%3A1)%0A%0A%23%23%23%23%23%23%203.%20%E6%8E%92%E5%BA%8F%0A%0A%20%20%20!%5B5c92132175c77e2afe997835f2385b43.png%5D(en-resource%3A%2F%2Fdatabase%2F862%3A1)%0A%0A%23%23%23%23%23%204.4.4%20%20%E7%BB%88%E6%AD%A2%E6%93%8D%E4%BD%9C%0A%0A%3E%20%E7%BB%88%E6%AD%A2%E6%93%8D%E4%BD%9C%E5%8F%AF%E4%BB%A5%E4%BB%8E%E6%B5%81%E4%B8%AD%E7%94%9F%E6%88%90%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%85%B6%E7%BB%93%E6%9E%9C%E5%8F%AF%E4%BB%A5%E6%98%AF%E4%BB%BB%E4%BD%95%E9%9D%9E%E6%B5%81%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20%E6%B5%81%E8%BF%9B%E8%A1%8C%E4%BA%86%E7%BB%88%E6%AD%A2%E6%93%8D%E4%BD%9C%E5%90%8E%EF%BC%8C%E4%B8%8D%E8%83%BD%E4%B8%A4%E6%AC%A1%E4%BD%BF%E7%94%A8%0A%0A%23%23%23%23%23%23%201.%20%E5%8C%B9%E9%85%8D%E4%B8%8E%E6%9F%A5%E6%89%BE%0A%20%20%0A%20%20%20!%5B95df28b66690c9b7e13795978074aa8a.png%5D(en-resource%3A%2F%2Fdatabase%2F1101%3A1)%0A%20%20%20%20%0A%20%23%23%23%23%23%23%202.%20%E5%BD%92%E7%BA%A6%0A%20%20%20!%5B08bbedf77dc29c564eb3848e13e74343.png%5D(en-resource%3A%2F%2Fdatabase%2F1105%3A1)%0A%20%20%20%20%0A%60%60%60java%0A%40Test%0Apublic%20void%20testReduce()%20%7B%0A%20%20%20%20%2F%2F%E8%AE%A1%E7%AE%971%E5%88%B010%E8%87%AA%E7%84%B6%E6%95%B0%E4%B9%8B%E5%92%8C%0A%20%20%20%20List%3CInteger%3E%20list%20%3D%20Arrays.asList(1%2C%202%2C%203%2C%204%2C%205%2C%206%2C%207%2C%208%2C%209%2C%2010)%3B%0A%20%20%20%20Integer%20sum%20%3D%20list.stream().reduce(0%2C%20Integer%3A%3Asum)%3B%0A%20%20%20%20System.out.println(sum)%3B%0A%20%20%20%20%2F%2F%E8%AE%A1%E7%AE%97%E5%85%AC%E5%8F%B8%E4%B8%AD%E6%89%80%E6%9C%89%E5%91%98%E5%B7%A5%E7%9A%84%E5%B7%A5%E8%B5%84%E6%80%BB%E5%92%8C%0A%20%20%20%20List%3CEmployee%3E%20employees%20%3D%20EmployeeData.getEmployees()%3B%0A%20%20%20%20Stream%3CDouble%3E%20doubleStream%20%3D%20employees.stream().map(Employee%3A%3AgetSalary)%3B%0A%20%20%20%20%2F%2F%20Optional%3CDouble%3E%20reduce%3D%20doubleStream.reduce((a%2C%20b)%20-%3E%20a%20%2B%20b)%3B%0A%20%20%20%20Optional%3CDouble%3E%20reduce%20%3D%20doubleStream.reduce(Double%3A%3Asum)%3B%0A%20%20%20%20Double%20totalSalary%20%3D%20reduce.orElse((double)%200)%3B%0A%20%20%20%20System.out.println(totalSalary)%3B%0A%7D%0A%60%60%60%0A%20%20%20%0A%20%23%23%23%23%23%23%203.%20%E6%94%B6%E9%9B%86%0A%20!%5Bbc7f7b440c95868f6dd29f3d3257729b.png%5D(en-resource%3A%2F%2Fdatabase%2F1107%3A1)%0A%20%20%20%20%0A%60%60%60java%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20testCollector()%20%7B%0A%20%20%20%20%20%20%20%20List%3CEmployee%3E%20employees%20%3D%20EmployeeData.getEmployees()%3B%0A%20%20%20%20%20%20%20%20List%3CEmployee%3E%20list%20%3D%20employees.stream().filter(e%20-%3E%20e.getSalary()%20%3E%2010000).collect(Collectors.toList())%3B%0A%20%20%20%20%20%20%20%20Set%3CEmployee%3E%20set%20%3D%20employees.stream().filter(e%20-%3E%20e.getSalary()%20%3E%2010000).collect(Collectors.toSet())%3B%0A%20%20%20%20%20%20%20%20List%3CEmployee%3E%20list2%20%3D%0A%20%20%20%20%20%20%20%20%20%20%20%20employees.stream().filter(e%20-%3E%20e.getSalary()%20%3E%2010000).collect(Collectors.toCollection(ArrayList%3A%3Anew))%3B%0A%0A%20%20%20%20%20%20%20%20LinkedHashMap%3CInteger%2C%20List%3CEmployee%3E%3E%20ageGrouping%20%3D%0A%20%20%20%20%20%20%20%20%20%20%20%20employees.stream().collect(Collectors.groupingBy(Employee%3A%3AgetAge%2C%20LinkedHashMap%3A%3Anew%2C%20Collectors.toList()))%3B%0A%0A%20%20%20%20%20%20%20%20Map%3CInteger%2C%20Employee%3E%20ageMaping%20%3D%20employees.stream().collect(Collectors.toMap(Employee%3A%3AgetAge%2C%20e%20-%3E%20e%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(oldKey%2C%20newKey)%20-%3E%20newKey))%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%20%20%20%20%20%20%20%20%0A%23%23%23%23%204.5%20Optional%0A%3E%20Optional%3CT%3E%20%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AE%B9%E5%99%A8%E7%B1%BB%EF%BC%8C%E5%AE%83%E5%8F%AF%E4%BB%A5%E4%BF%9D%E5%AD%98%E7%B1%BB%E5%9E%8BT%E7%9A%84%E5%80%BC%EF%BC%8C%E4%BB%A3%E8%A1%A8%E8%BF%99%E4%B8%AA%E5%80%BC%E5%AD%98%E5%9C%A8%EF%BC%8C%E6%88%96%E8%80%85%E4%BB%85%E4%BB%85%E4%BF%9D%E5%AD%98%E4%B8%BAnull%2C%20%E8%A1%A8%E7%A4%BA%E8%BF%99%E4%B8%AA%E5%80%BC%E4%B8%8D%E5%AD%98%E5%9C%A8%E3%80%82%0A%E5%8E%9F%E6%9D%A5%E7%94%A8null%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E5%80%BC%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E7%8E%B0%E5%9C%A8Optional%E5%8F%AF%E4%BB%A5%E6%9B%B4%E5%A5%BD%E7%9A%84%E8%A1%A8%E8%BE%BE%E8%BF%99%E4%B8%AA%E6%A6%82%E5%BF%B5%E3%80%82%E5%B9%B6%E4%B8%94%E5%A6%82%E4%BB%A5%E9%81%BF%E5%85%8D%E7%A9%BA%E6%8C%87%E9%92%88%E5%BC%82%E5%B8%B8%E3%80%82%0A%E5%A6%82%E6%9E%9C%E5%80%BC%E5%AD%98%E5%9C%A8%E5%88%99%20isPresent()%20%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9Etrue%EF%BC%8C%E8%B0%83%E7%94%A8get()%20%E6%96%B9%E6%B3%95%E4%BC%9A%E8%BF%94%E5%9B%9E%E8%AF%A5%E5%AF%B9%E8%B1%A1%E3%80%82%0A%0A%23%23%23%23%23%204.5.1%20%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%96%B9%E6%B3%95%0A%3E%20Optional.of(T%20t)%20%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAOptional%E5%AE%9E%E4%BE%8B%EF%BC%8Ct%E4%B8%BA%E9%9D%9E%E7%A9%BA%E5%AF%B9%E8%B1%A1%0A%3E%20Optional.empty()%20%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%A9%BA%E7%9A%84Optional%E5%AE%9E%E4%BE%8B%0A%3E%20Optional.ofNullable(T%20t)%20t%E5%8F%AF%E4%BB%A5%E4%B8%BA%E7%A9%BA%E5%AF%B9%E8%B1%A1%0A%0A!%5Beadfa4dcd6e0ded80175b8111f9c1946.png%5D(en-resource%3A%2F%2Fdatabase%2F1669%3A1)%0A%0A%23%23%23%23%23%204.5.2%20%E5%88%A4%E6%96%ADOptional%E5%AE%B9%E5%99%A8%E6%98%AF%E5%90%A6%E5%8C%85%E5%90%AB%E5%AF%B9%E8%B1%A1%0A%0A%3E%20boolean%20isPresent()%20%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E5%8C%85%E5%90%AB%E5%AF%B9%E8%B1%A1%0A%3E%20void%20ifPresent(Consumer%3C%3F%20super%20T%3E%20consumer)%3A%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%80%BC%EF%BC%8C%E5%B0%B1%E6%89%A7%E8%A1%8CConsumer%E6%8E%A5%E5%8F%A3%E5%AE%9E%E7%8E%B0%E7%9A%84%E4%BB%A3%E7%A0%81%EF%BC%8C%E5%B9%B6%E4%B8%94%E8%AF%A5%E5%80%BC%E4%BC%9A%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0%E4%BC%A0%E7%BB%99%E5%AE%83%E3%80%82%0A%0A%0A%23%23%23%23%23%204.5.3%20%E8%8E%B7%E5%8F%96Optional%E5%AE%B9%E5%99%A8%E7%9A%84%E5%AF%B9%E8%B1%A1%0A%0A%3E%20T%20get()%20%E5%A6%82%E6%9E%9C%E8%B0%83%E7%94%A8%E5%AF%B9%E8%B1%A1%E5%8C%85%E5%90%AB%E5%80%BC%EF%BC%8C%E8%BF%94%E5%9B%9E%E8%AF%A5%E5%80%BC%EF%BC%8C%E5%90%A6%E5%88%99%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%0A%3E%20T%20orElse(T%20other)%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%80%BC%E5%88%99%E8%BF%94%E5%9B%9E%EF%BC%8C%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9E%E6%8C%87%E5%AE%9A%E7%9A%84other%E5%AF%B9%E8%B1%A1%0A%3E%20T%20orElseGet(Supplier%3C%3F%20extends%20T%3E%20other)%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%80%BC%E5%88%99%E8%BF%94%E5%9B%9E%EF%BC%8C%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9ESupplier%E6%8E%A5%E5%8F%A3%0A%E5%AE%9E%E7%8E%B0%E7%9A%84%E5%AF%B9%E8%B1%A1%0A%3E%20T%20orElseThrow(Supplier%3C%3F%20extends%20X%3E%20exceptionSupplier)%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%80%BC%E5%88%99%E8%BF%94%E5%9B%9E%EF%BC%8C%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9ESupplier%E6%8E%A5%E5%8F%A3%E5%AE%9E%E7%8E%B0%E7%9A%84%E5%BC%82%E5%B8%B8%0A%0A%3E%20**%E6%B3%A8%E6%84%8F**%0A%60%60%60java%0A%20%20%20%20User%C2%A0user%C2%A0%3D%C2%A0null%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0user%C2%A0%3D%C2%A0Optional.ofNullable(user).orElse(createUser())%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0user%C2%A0%3D%C2%A0Optional.ofNullable(user).orElseGet(()%C2%A0-%3E%C2%A0createUser())%3B%0A%0A%20%20%20%20public%C2%A0User%C2%A0createUser()%7B%0A%20%20%20%20%20%20%20%20User%C2%A0user%C2%A0%3D%C2%A0new%C2%A0User()%3B%0A%20%20%20%20%20%20%20%20user.setName(%22zhangsan%22)%3B%0A%20%20%20%20%20%20%20%20return%C2%A0user%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%3E%20orElse(T%20other)%E5%92%8CorElseGet(Supplier%3C%3F%20extends%20T%3E%20other)%E7%9A%84%E5%8C%BA%E5%88%AB%EF%BC%9A%0A%3E%20%E5%BD%93user%E4%B8%8D%E4%B8%BAnull%E6%97%B6%EF%BC%8CorElse%E5%87%BD%E6%95%B0%E4%BE%9D%E7%84%B6%E4%BC%9A%E6%89%A7%E8%A1%8CcreateUser%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BD%86%E4%BC%9A%E5%B0%86%E5%8E%9Fuser%E5%80%BC%E8%BF%94%E5%9B%9E%EF%BC%8C%0A%3E%20%E8%80%8CorElseGet%E5%87%BD%E6%95%B0%E5%B9%B6%E4%B8%8D%E4%BC%9A%E6%89%A7%E8%A1%8CcreateUser()%E6%96%B9%E6%B3%95%EF%BC%8C%0A%0A%23%23%23%23%23%204.5.4%20map%20%E5%92%8C%20flatMap%0A%3E%20map(Function%20mapper)%20%E5%92%8C%20flatMap(Function%3E%20mapper)%0A%3E%20%E8%BF%99%E4%B8%A4%E4%B8%AA%E5%87%BD%E6%95%B0%EF%BC%8C%E5%9C%A8%E5%87%BD%E6%95%B0%E4%BD%93%E4%B8%8A%E6%B2%A1%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%E3%80%82%0A%3E%20%E5%94%AF%E4%B8%80%E5%8C%BA%E5%88%AB%E7%9A%84%E5%B0%B1%E6%98%AF%E5%85%A5%E5%8F%82%EF%BC%8C%0A%3E%20map%E5%87%BD%E6%95%B0%E6%89%80%E6%8E%A5%E5%8F%97%E7%9A%84%E5%85%A5%E5%8F%82%E7%B1%BB%E5%9E%8B%E4%B8%BAFunction%3C%3F%20super%20T%2C%20%3F%20extends%20U%3E%EF%BC%8C%0A%3E%20%E8%80%8CflapMap%E7%9A%84%E5%85%A5%E5%8F%82%E7%B1%BB%E5%9E%8B%E4%B8%BAFunction%3C%3F%20super%20T%2C%20Optional%3CU%3E%3E%E3%80%82%0A%0A%60%60%60java%0A%20public%20%3CU%3E%C2%A0Optional%3CU%3E%C2%A0map(Function%3C%3F%C2%A0super%C2%A0T%2C%C2%A0%3F%C2%A0extends%C2%A0U%3E%C2%A0mapper)%C2%A0%7B%0A%20%20%20%20Objects.requireNonNull(mapper)%3B%0A%20%20%20%20if%C2%A0(!isPresent())%0A%20%20%20%20%20%20%20%20return%C2%A0empty()%3B%0A%20%20%20%20else%C2%A0%7B%0A%20%20%20%20%20%20%20%20return%C2%A0Optional.ofNullable(mapper.apply(value))%3B%0A%20%20%20%20%7D%0A%20%7D%0A%0Apublic%20%3CU%3E%C2%A0Optional%3CU%3E%C2%A0flatMap(Function%3C%3F%C2%A0super%C2%A0T%2C%C2%A0Optional%3CU%3E%3E%C2%A0mapper)%C2%A0%7B%0A%20%20%20%20Objects.requireNonNull(mapper)%3B%0A%20%20%20%20if%C2%A0(!isPresent())%20%C2%A0%0A%20%20%20%20%20%20%20%20return%C2%A0empty()%3B%0A%20%20%20%20else%C2%A0%7B%0A%20%20%20%20%20%20%20%20return%C2%A0Objects.requireNonNull(mapper.apply(value))%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0Apublic%C2%A0class%C2%A0User%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0private%C2%A0String%C2%A0name%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0public%C2%A0String%C2%A0getName()%C2%A0%7B%20return%C2%A0name%3B%C2%A0%7D%0A%20%7D%0A%20%2F%2F%20%E8%BF%99%E6%97%B6%E5%80%99%E5%8F%96name%E7%9A%84%E5%86%99%E6%B3%95%E5%A6%82%E4%B8%8B%E6%89%80%E7%A4%BA%0AString%C2%A0city%C2%A0%3D%C2%A0Optional.ofNullable(user).map(u-%3E%C2%A0u.getName()).get()%3B%0A%0Apublic%C2%A0class%C2%A0User%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0private%C2%A0String%C2%A0name%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0public%C2%A0Optional%3CString%3E%C2%A0getName()%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0return%C2%A0Optional.ofNullable(name)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%7D%0A%2F%2F%20%E8%BF%99%E6%97%B6%E5%80%99%E5%8F%96name%E7%9A%84%E5%86%99%E6%B3%95%E5%A6%82%E4%B8%8B%E6%89%80%E7%A4%BA%0AString%C2%A0city%C2%A0%3D%C2%A0Optional.ofNullable(user).flatMap(u-%3E%C2%A0u.getName()).get()%3B%0A%60%60%60%0A%0A%23%23%23%23%23%204.5.5%20isPresent()%20%E5%92%8C%20ifPresent(Consumer%20consumer)%0A%3E%20isPresent%E5%8D%B3%E5%88%A4%E6%96%ADvalue%E5%80%BC%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%EF%BC%8C%E8%80%8CifPresent%E5%B0%B1%E6%98%AF%E5%9C%A8value%E5%80%BC%E4%B8%8D%E4%B8%BA%E7%A9%BA%E6%97%B6%E6%89%A7%E8%A1%8Cconsumer%0A%0A%0A%23%23%23%23%23%204.5.6%20filter(Predicate%20predicate)%0A%0A%60%60%60java%0Apublic%C2%A0User%C2%A0getUser(User%C2%A0user)%C2%A0throws%C2%A0Exception%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0if(user!%3Dnull)%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0String%C2%A0name%C2%A0%3D%C2%A0user.getName()%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0if(%22zhangsan%22.equals(name))%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0return%C2%A0user%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%C2%A0%C2%A0%C2%A0%C2%A0%7Delse%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0user%C2%A0%3D%C2%A0new%C2%A0User()%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0user.setName(%22zhangsan%22)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0return%C2%A0user%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%7D%0A%0A%2F%2F%20java8%E5%86%99%E6%B3%95%0Apublic%C2%A0User%C2%A0getUser(User%C2%A0user)%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0return%C2%A0Optional.ofNullable(user)%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0.filter(u-%3E%22zhangsan%22.equals(u.getName()))%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0.orElseGet(()-%3E%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0User%C2%A0user1%C2%A0%3D%C2%A0new%C2%A0User()%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0user1.setName(%22zhangsan%22)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0return%C2%A0user1%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%7D)%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0Apublic%C2%A0String%C2%A0getCity(User%C2%A0user)%C2%A0%C2%A0throws%C2%A0Exception%7B%0A%20%20%20%20if(user!%3Dnull)%7B%0A%20%20%20%20%20%20%20%20if(user.getAddress()!%3Dnull)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Address%C2%A0address%C2%A0%3D%C2%A0user.getAddress()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(address.getCity()!%3Dnull)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%C2%A0address.getCity()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20throw%C2%A0new%C2%A0Excpetion(%22%E5%8F%96%E5%80%BC%E9%94%99%E8%AF%AF%22)%3B%0A%7D%0A%2F%2F%20java8%E5%86%99%E6%B3%95%0Apublic%C2%A0String%C2%A0getCity(User%C2%A0user)%C2%A0throws%C2%A0Exception%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0return%C2%A0Optional.ofNullable(user)%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0.map(u-%3E%C2%A0u.getAddress())%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0.map(a-%3Ea.getCity())%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0.orElseThrow(()-%3Enew%C2%A0Exception(%22%E5%8F%96%E6%8C%87%E9%94%99%E8%AF%AF%22))%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%205%20%E5%AE%9E%E4%BE%8B%0A%23%23%23%23%205.1%20Stream%20%E5%AE%9E%E4%BE%8B%0A%60%60%60java%0AList%3CInteger%3E%20nums%20%3D%20Lists.newArrayList(1%2C%201%2C%20null%2C%202%2C%203%2C%204%2C%20null%2C%205%2C%206%2C%207%2C%208%2C%209%2C%2010)%3B%0ASystem.out.println(%22%E6%B1%82%E5%92%8C%EF%BC%9A%22%20%2B%20nums.stream()%2F%2F%20%E8%BD%AC%E6%88%90Stream%0A%20%20%20%20%20%20%20%20.filter(team%20-%3E%20team%20!%3D%20null)%2F%2F%20%E8%BF%87%E6%BB%A4%0A%20%20%20%20%20%20%20%20.distinct()%2F%2F%20%E5%8E%BB%E9%87%8D%0A%20%20%20%20%20%20%20%20.mapToInt(num%20-%3E%20num%20*%202)%2F%2F%20map%E6%93%8D%E4%BD%9C%0A%20%20%20%20%20%20%20%20.skip(2)%2F%2F%20%E8%B7%B3%E8%BF%87%E5%89%8D2%E4%B8%AA%E5%85%83%E7%B4%A0%0A%20%20%20%20%20%20%20%20.limit(4)%2F%2F%20%E9%99%90%E5%88%B6%E5%8F%96%E5%89%8D4%E4%B8%AA%E5%85%83%E7%B4%A0%0A%20%20%20%20%20%20%20%20.peek(System.out%3A%3Aprintln)%2F%2F%20%E6%B5%81%E5%BC%8F%E5%A4%84%E7%90%86%E5%AF%B9%E8%B1%A1%E5%87%BD%E6%95%B0%0A%20%20%20%20%20%20%20%20.sum())%3B%2F%2F%0A%60%60%60%0A%0A%23%23%23%23%205.2%20Collectors.groupingBy%0A%0A%60%60%60java%0AMap%3CString%2C%20List%3CLong%3E%3E%20actNameMap%20%3D%20activities.stream()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.filter(activity%20-%3E%20!Objects.equals(activity.getName()%2C%20ProcessActivityEnum.CountersignForEn.getActDisplay()))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.collect(Collectors.groupingBy(GimProcessActivity%3A%3AgetName%2C%20Collectors.mapping(GimProcessActivity%3A%3AgetId%2C%20Collectors.toList())))%3B%0A%60%60%60%0A%23%23%23%23%205.3%20Collectors.collectingAndThen%0A%60%60%60java%0AList%3CPlanCountryProviderConfigBean%3E%20uniqueCaEndc_Configs%20%3D%20configLists.stream()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.filter(configBean%20-%3E%20!isAllDel(configBean))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.collect(Collectors.collectingAndThen(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Collectors.toCollection(()%20-%3E%20new%20TreeSet%3C%3E(Comparator.comparing(PlanCountryProviderConfigBean%3A%3AgetCaEndc)))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ArrayList%3A%3Anew))%3B%0A%60%60%60%0A%0A%60%60%60java%0A%20private%20%3CT%3E%20Predicate%3CT%3E%20distinctByProperties(String%5B%5D%20properties)%20%7B%0A%20%20%20%20%20%20%20%20List%3CString%5B%5D%3E%20list%20%3D%20CollUtil.newLinkedList()%3B%0A%20%20%20%20%20%20%20%20return%20t%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20String%5B%5D%20t_values%20%3D%20buildValues(t%2C%20properties)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(CollUtil.isEmpty(list))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20list.add(t_values)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20i%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(%3B%20i%20%3C%20list.size()%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%5B%5D%20values%20%3D%20list.get(i)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20int%20j%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(%3B%20j%20%3C%20values.length%3B%20j%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20t_value%20%3D%20t_values%5Bj%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20value%20%3D%20values%5Bj%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(Objects.nonNull(t_value)%20%26%26%20Objects.nonNull(value)%20%26%26%20!t_value.equals(value))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(j%20%3D%3D%20values.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3D%3D%20list.size())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20list.add(t_values)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20private%20%3CT%3E%20String%5B%5D%20buildValues(T%20obj%2C%20String%5B%5D%20properties)%20%7B%0A%20%20%20%20%20%20%20%20String%5B%5D%20values%20%3D%20new%20String%5Bproperties.length%5D%3B%0A%20%20%20%20%20%20%20%20Class%3C%3F%3E%20clz%20%3D%20obj.getClass()%3B%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20properties.length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Field%20field%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20String%20property%20%3D%20properties%5Bi%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20field%20%3D%20clz.getDeclaredField(property)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20field.setAccessible(true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object%20value%20%3D%20field.get(obj)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20values%5Bi%5D%20%3D%20String.valueOf(value)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(NoSuchFieldException%20%7C%20IllegalAccessException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.error(%22error%20happened%20when%20get%20value%20of%20field%3A%22%20%2B%20property%20%2B%20%22%2C%20from%3A%22%20%2B%20obj%2C%20e)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20values%3B%0A%20%20%20%20%7D%0A%60%60%60

设计模式

创建时间:2022/5/2 12:10
更新时间:2023/3/19 21:07
作者:Chris

代码

https://github.com/mxg133/learnforJava_DesignPattern

1. 设计模式的目的

1.1 代码重用性

相同功能的代码不用重复编写

1.2 可读性

编程的规范性,便于其它人员阅读和理解

1.3 可扩展性

新增功能时非常的方便

1.4 可靠性

当新增或减少功能后,对原有的功能不会产生影响

所有以上特性都是为了让我们的代码呈现高内聚,低耦合

2. 设计模式七大原则

2.1 单一职责原则

即一个类只负责一个职责

若一个类负责不同的职责,当职责1的需求变化而改变类时,可能造成职责2的错误执行,所以需要将类拆分为类1和类2

降低类的复杂性和变更引起的风险,提高可读性和可扩展性
如果逻辑足够简单可以在方法级别实现单一职责原则

2.2 接口隔离原则

一个类对另一个类的依赖应该建立在最小的接口上
这个接口里面用不到的方法,应该把大的接口拆分成小的接口,然后依赖小的接口
类A通过接口1,2依赖类B
类C通过接口1,3依赖类C

public class Segregation1 {

	public static void main(String[] args) {

		A a = new A();
		a.depend1(new B()); // A类通过接口去依赖B类
		a.depend2(new B());
		a.depend3(new B());

		C c = new C();

		c.depend1(new D()); // C类通过接口去依赖(使用)D类
		c.depend4(new D());
		c.depend5(new D());
	}
}

// 接口1
interface Interface1 {
	void operation1();
}

// 接口2
interface Interface2 {
	void operation2();
	void operation3();
}

// 接口3
interface Interface3 {
	void operation4();
	void operation5();
}

class B implements Interface1, Interface2 {
	public void operation1() {
		System.out.println("B 实现了 operation1");
	}

	public void operation2() {
		System.out.println("B 实现了 operation2");
	}

	public void operation3() {
		System.out.println("B 实现了 operation3");
	}
}

class D implements Interface1, Interface3 {
	public void operation1() {
		System.out.println("D 实现了 operation1");
	}

	public void operation4() {
		System.out.println("D 实现了 operation4");
	}

	public void operation5() {
		System.out.println("D 实现了 operation5");
	}
}

// A类通过接口Interface1,Interface2 依赖(使用) B类,但是只会用到1,2,3方法
class A { 
	public void depend1(Interface1 i) {
		i.operation1();
	}
    
	public void depend2(Interface2 i) {
		i.operation2();
	}
    
	public void depend3(Interface2 i) {
		i.operation3();
	}
}

 // C类通过接口Interface1,Interface3 依赖(使用) D类,但是只会用到1,4,5方法
class C {
	public void depend1(Interface1 i) {
		i.operation1();
	}
	
	public void depend4(Interface3 i) {
		i.operation4();
	}

	public void depend5(Interface3 i) {
		i.operation5();
	}
}

2.3 依赖倒置原则

2.3.1 核心概念

  1. 核心思想就是依赖接口编程
  2. 高层模块不应该依赖低层模块,二者应该依赖于抽象
  3. 抽象不应该依赖于细节,细节应该依赖于抽象
  4. 细节是多变的,抽象是稳定的,所以抽象基础搭建的框架要比以细节为基础搭建的框架稳定的多。
  5. 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,具体的细节由实现类负责完成。
public class DependecyInversion {

	public static void main(String[] args) {
		Person person = new Person();
		person.receive(new Email());
	}
}

class Email {
	public String getInfo() {
		return "电子邮件信息: hello,world";
	}
}

/*
完成Person接收消息的功能
方式1分析
1. 简单,比较容易想到
2. 如果我们获取的对象是 weixin,短信等等,则新增类,同时Perons也要增加相应的接收方法
3. 解决思路:
   引入一个抽象的接口IReceiver, 表示接收者, 这样Person类与接口IReceiver发生依赖
   因为Email, WeiXin 等等属于接收的范围,他们各自实现IReceiver 接口就ok, 这样我们就符号依赖倒转原则
*/
class Person {
	public void receive(Email email ) {
		System.out.println(email.getInfo());
	}
}

改进后的方法

public class DependecyInversion {

	public static void main(String[] args) {
		//客户端无需改变
		Person person = new Person();
		person.receive(new Email());

		person.receive(new WeiXin());
	}

}

//定义接口
interface IReceiver {
	public String getInfo();
}

class Email implements IReceiver {
	public String getInfo() {
		return "电子邮件信息: hello,world";
	}
}

//增加微信
class WeiXin implements IReceiver {
	public String getInfo() {
		return "微信信息: hello,ok";
	}
}

//方式2
//同时也遵循了OCP,对使用方修改关闭,只需要增加消息提供方,即对提供方扩展开放
class Person {
	//这里我们是对接口的依赖
	public void receive(IReceiver receiver) {
		System.out.println(receiver.getInfo());
	}
}

2.3.2 依赖传递的三种方式

2.3.2.1 接口传递
// 方式1: 通过接口传递实现依赖
// 开关的接口
interface IOpenAndClose1 {
    void open1(ITV1 tv); //抽象方法,接收接口
}

interface ITV1 { //ITV接口
    void play1();
}

class ChangHong1 implements ITV1 {
    @Override
    public void play1() {
        // TODO Auto-generated method stub
        System.out.println("长虹电视机,打开");
    }       
}

// 实现接口
class OpenAndClose1 implements IOpenAndClose1 {
    public void open1(ITV1 tv) {
        tv.play1();
    }
}

public static void main(String[] args) {
        // TODO Auto-generated method stub
        ChangHong changHong = new ChangHong();
		OpenAndClose openAndClose = new OpenAndClose();
		openAndClose.open(changHong);
    }
2.3.2.2 构造方法传递
// 方式2: 通过构造方法依赖传递
interface IOpenAndClose2 {
    void open2(); //抽象方法
}

interface ITV2 { //ITV接口
    void play2();
}

class ChangHong2 implements ITV2 {
    @Override
    public void play2() {
        // TODO Auto-generated method stub
        System.out.println("长虹电视机,打开");
    }
}

class OpenAndClose2 implements IOpenAndClose2 {
    public ITV2 tv; //成员
    
    public OpenAndClose2(ITV2 tv) {
        //构造器
        this.tv = tv;
    }
    public void open2() {
        this.tv.play2();
    }
}

public static void main(String[] args) {
        // TODO Auto-generated method stub
        ChangHong2 changHong = new ChangHong2();
        //通过构造器进行依赖传递
		OpenAndClose2 openAndClose = new OpenAndClose2(changHong);
		openAndClose.open2();
}
2.3.2.3 setter方法传递
// 方式3 , 通过setter方法传递
interface IOpenAndClose {
    void open(); // 抽象方法

    void setTv(ITV tv);
}

interface ITV { // ITV接口
    void play();
}

class OpenAndClose implements IOpenAndClose {
    private ITV tv;

    public void setTv(ITV tv) {
        this.tv = tv;
    }

    public void open() {
        this.tv.play();
    }
}

class ChangHong implements ITV {
    @Override
    public void play() {
        // TODO Auto-generated method stub
        System.out.println("长虹电视机,打开");
    }
}

public static void main(String[] args) {
        // TODO Auto-generated method stub
        ChangHong changHong = new ChangHong();
        //通过setter方法进行依赖传递
        OpenAndClose openAndClose = new OpenAndClose();
        openAndClose.setTv(changHong);
        openAndClose.open();
    }

2.3.3 注意事项

  1. 低层模块尽量要有抽象类或接口, 或者两个都有,这样稳定性会更好
  2. 变量的声明类型尽量是抽象类或接口,这样我们变量的引用和实际对象间,就存在一个缓存层,利于扩展和优化。
  3. 继承时遵循里氏替换原则

2.4 里氏替换原则

2.4.1 继承存在的问题

  1. 继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
  2. 继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障
  3. 问题提出:在编程中,如何正确的使用继承? => 里氏替换原则

2.4.2 如何正确的使用继承

里氏替换原则是在告诉我们继承需要注意什么问题以及要遵守什么规则

  1. 所有引用父类的地方可以透明的使用其子类
  2. 在使用继承时,在子类中尽量不要重写父类的方法,特别是运行多态比较频繁的时候。
  3. 继承实际上是增加类之间的耦合性,通用的做法是:原来的父类和子类都继承一个更通用的基类, 在适当的情况下可以通过聚合,组合,依赖来解决问题。

public class Liskov {
    public static void main(String[] args) {
        A a = new A();
        System.out.println("11-3=" + a.func1(11, 3));
        System.out.println("1-8=" + a.func1(1, 8));

        System.out.println("-----------------------");
        B b = new B();
        System.out.println("11-3=" + b.func1(11, 3));//这里本意是求出11-3
        System.out.println("1-8=" + b.func1(1, 8));// 1-8
        System.out.println("11+3+9=" + b.func2(11, 3))
    }
}

// A类
class A {
    // 返回两个数的差
    public int func1(int num1, int num2) {
        return num1 - num2;
    }
}

/* 
 B类继承了A
 增加了一个新功能:完成两个数相加,然后和9求和
 */
class B extends A {
    //这里,重写了A类的方法, 可能是无意识
    public int func1(int a, int b) {
        return a + b;
    }

    public int func2(int a, int b) {
        return func1(a, b) + 9;
    }
}

改进后的代码

public class Liskov {
	public static void main(String[] args) {
		A a = new A();
		System.out.println("11-3=" + a.func1(11, 3));
		System.out.println("1-8=" + a.func1(1, 8));

		System.out.println("-----------------------");
		B b = new B();
		//因为B类不再继承A类,因此调用者,不会再func1是求减法
		//调用完成的功能就会很明确
		System.out.println("11+3=" + b.func1(11, 3));//这里本意是求出11+3
		System.out.println("1+8=" + b.func1(1, 8));// 1+8
		System.out.println("11+3+9=" + b.func2(11, 3));

		//使用组合仍然可以使用到A类相关方法
		System.out.println("11-3=" + b.func3(11, 3));// 这里本意是求出11-3
	}
}

//创建一个更加基础的基类
class Base {
	//把更加基础的方法和成员写到Base类
}

// A类
class A extends Base {
	// 返回两个数的差
	public int func1(int num1, int num2) {
		return num1 - num2;
	}
}

/* 
 B类继承了A
 增加了一个新功能:完成两个数相加,然后和9求和
 */
class B extends Base {
	//如果B需要使用A类的方法,使用组合关系
	private A a = new A();

	public int func1(int a, int b) {
		return a + b;
	}

	public int func2(int a, int b) {
		return func1(a, b) + 9;
	}

	//我们仍然想使用A的方法
	public int func3(int a, int b) {
		return this.a.func1(a, b);
	}
}

2.5 开闭原则

  1. 一个软件实体中类,模块和方法,应该对扩展开放【提供方】,对修改关闭【使用方】,用抽象构建框架,用实现扩展细节。
  2. 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
  3. 编程中遵循其实原则,以及使用设计模式的目的就是为了遵循开闭原则。

当新增画三角形,不仅要对提供方进行扩展,而且要对使用方的代码进行大量修改。

public class Ocp {

    public static void main(String[] args) {
        //使用看看存在的问题
        GraphicEditor graphicEditor = new GraphicEditor();
        graphicEditor.drawShape(new Rectangle());
        graphicEditor.drawShape(new Circle());
        
        //新增画三角形
        graphicEditor.drawShape(new Triangle());
    }

}

//这是一个用于绘图的类 [使用方]
class GraphicEditor {
    //接收Shape对象,然后根据type,来绘制不同的图形
    public void drawShape(Shape s) {
        if (s.m_type == 1)
            drawRectangle(s);
        else if (s.m_type == 2)
            drawCircle(s);
        else if (s.m_type == 3) //新增画三角形
            drawTriangle(s);
    }

    //绘制矩形
    public void drawRectangle(Shape r) {
        System.out.println(" 绘制矩形 ");
    }

    //绘制圆形
    public void drawCircle(Shape r) {
        System.out.println(" 绘制圆形 ");
    }

    //新增绘制三角形
    public void drawTriangle(Shape r) {
        System.out.println(" 绘制三角形 ");
    }
}

//Shape类,基类
class Shape {
    int m_type;
}

class Rectangle extends Shape {
    Rectangle() {
        super.m_type = 1;
    }
}

class Circle extends Shape {
    Circle() {
        super.m_type = 2;
    }
}

//新增画三角形
class Triangle extends Shape {
    Triangle() {
        super.m_type = 3;
    }
}

改进后的方法

public class Ocp {
    public static void main(String[] args) {
        GraphicEditor graphicEditor = new GraphicEditor();
        graphicEditor.drawShape(new Rectangle());
        graphicEditor.drawShape(new Circle());
        graphicEditor.drawShape(new Triangle());
        graphicEditor.drawShape(new OtherGraphic());
    }
}

//这是一个用于绘图的类 [使用方]
class GraphicEditor {
    //接收Shape对象,调用draw方法
    public void drawShape(Shape s) {
        s.draw();
    }
}

//Shape类,基类
abstract class Shape {
    public abstract void draw();//抽象方法
}

class Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println(" 绘制矩形 ");
    }
}

class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println(" 绘制圆形 ");
    }
}

//新增画三角形
class Triangle extends Shape {
    @Override
    public void draw() {
        System.out.println(" 绘制三角形 ");
    }
}

//新增一个图形
class OtherGraphic extends Shape {
    @Override
    public void draw() {
        System.out.println(" 绘制其它图形 ");
    }
}

2.6 迪米特法则

2.6.1 最少知道原则

  1. 一个对象应该对其他对象保持最少的了解

  2. 类与类关系越密切,耦合度越大

  3. 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于
    被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的 public 方法,不对外泄露任何信息

2.6.2 只与直接的朋友通信

迪米特法则还有个更简单的定义:只与直接的朋友通信

  1. 直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间
    是朋友关系。

  2. 耦合的方式很多,依赖,关联,组合,聚合等。其中,

  3. 我们称出现成员变量,方法参数,方法返回值 中的类为直接的朋友,

  4. 而出现在局部变量中的类是陌生朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。

//客户端
public class Demeter1 {
	public static void main(String[] args) {
		//创建了一个 SchoolManager 对象
		SchoolManager schoolManager = new SchoolManager();
		//输出学院的员工id和学校总部的员工信息
		schoolManager.printAllEmployee(new CollegeManager());
	}
}

//学校总部员工类
class Employee {
	private String id;

	public void setId(String id) {
		this.id = id;
	}

	public String getId() {
		return id;
	}
}

//学院的员工类
class CollegeEmployee {
	private String id;

	public void setId(String id) {
		this.id = id;
	}

	public String getId() {
		return id;
	}
}

//管理学院员工的管理类
class CollegeManager {
	//返回学院的所有员工
	public List<CollegeEmployee> getAllEmployee() {
		List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
		for (int i = 0; i < 10; i++) { //这里我们增加了10个员工到 list
			CollegeEmployee emp = new CollegeEmployee();
			emp.setId("学院员工id= " + i);
			list.add(emp);
		}
		return list;
	}
}

//学校管理类
//分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager
//CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则
class SchoolManager {
	//返回学校总部的员工
	public List<Employee> getAllEmployee() {
		List<Employee> list = new ArrayList<Employee>();

		for (int i = 0; i < 5; i++) { //这里我们增加了5个员工到 list
			Employee emp = new Employee();
			emp.setId("学校总部员工id= " + i);
			list.add(emp);
		}
		return list;
	}

	//该方法完成输出学校总部和学院员工信息(id)
	void printAllEmployee(CollegeManager sub) {

		//分析问题
		//1. 这里的 CollegeEmployee 不是 SchoolManager的直接朋友
		//2. CollegeEmployee 是以局部变量方式出现在 SchoolManager
		//3. 违反了 迪米特法则

		//获取到学院员工
		List<CollegeEmployee> list1 = sub.getAllEmployee();
		System.out.println("------------学院员工------------");
		for (CollegeEmployee e : list1) {
			System.out.println(e.getId());
		}
		//获取到学校总部员工
		List<Employee> list2 = this.getAllEmployee();
		System.out.println("------------学校总部员工------------");
		for (Employee e : list2) {
			System.out.println(e.getId());
		}
	}
}

改进后方法

//客户端
public class Demeter1 {
	public static void main(String[] args) {
		System.out.println("~~~使用迪米特法则的改进~~~");
		//创建了一个 SchoolManager 对象
		SchoolManager schoolManager = new SchoolManager();
		//输出学院的员工id 和 学校总部的员工信息
		schoolManager.printAllEmployee(new CollegeManager());
	}
}

//学校总部员工类
class Employee {
	private String id;

	public void setId(String id) {
		this.id = id;
	}

	public String getId() {
		return id;
	}
}

//学院的员工类
class CollegeEmployee {
	private String id;

	public void setId(String id) {
		this.id = id;
	}

	public String getId() {
		return id;
	}
}

//管理学院员工的管理类
class CollegeManager {
	//返回学院的所有员工
	public List<CollegeEmployee> getAllEmployee() {
		List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
		for (int i = 0; i < 10; i++) { //这里我们增加了10个员工到 list
			CollegeEmployee emp = new CollegeEmployee();
			emp.setId("学院员工id= " + i);
			list.add(emp);
		}
		return list;
	}

	//输出学院员工的信息
	public void printEmployee() {
		//获取到学院员工
		List<CollegeEmployee> list1 = getAllEmployee();
		System.out.println("------------学院员工------------");
		for (CollegeEmployee e : list1) {
			System.out.println(e.getId());
		}
	}
}

//学校管理类

//分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager
//CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则
class SchoolManager {
	//返回学校总部的员工
	public List<Employee> getAllEmployee() {
		List<Employee> list = new ArrayList<Employee>();

		for (int i = 0; i < 5; i++) { //这里我们增加了5个员工到 list
			Employee emp = new Employee();
			emp.setId("学校总部员工id= " + i);
			list.add(emp);
		}
		return list;
	}

	//该方法完成输出学校总部和学院员工信息(id)
	void printAllEmployee(CollegeManager sub) {

		//分析问题
		//1. 将输出学院的员工方法,封装到CollegeManager
		sub.printEmployee();

		//获取到学校总部员工
		List<Employee> list2 = this.getAllEmployee();
		System.out.println("------------学校总部员工------------");
		for (Employee e : list2) {
			System.out.println(e.getId());
		}
	}
}

2.6.3 注意事项和细节

  1. 迪米特法则的核心是降低类之间的耦合
  2. 但是注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系, 并不是
    要求完全没有依赖关系, 因为绝对不存在耦合关系类或对象是不存在的。

2.7 合成复用原则

原则是尽量使用合成/聚合的方式,而不是使用继承

3 类之间的关系

依赖、关联、泛化(继承)、实现、聚合与组合。

3.1 依赖(Dependency)

依赖(Dependency)关系是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。
在 UML 类图中,依赖关系使用带箭头的虚线来表示,箭头从使用类指向被依赖的类.

3.2 关联(Association)

关联(Association)关系是对象之间的一种引用关系,用于表示一类对象与另一类对象之间的联系,如老师和学生、师傅和徒弟、丈夫和妻子等。
关联可以是双向的,也可以是单向的

在 UML 类图中,双向的关联可以用带两个箭头或者没有箭头的实线来表示,单向的关联用带一个箭头的实线来表示,箭头从使用类指向被关联的类。也可以在关联线的两端标注角色名,代表两种不同的角色。

3.3 泛化(Generalization)

泛化(Generalization)关系是对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的关系,是一种继承关系,是 is-a 的关系。

在 UML 类图中,泛化关系用带空心三角箭头的实线来表示,箭头从子类指向父类。在代码实现时,使用面向对象的继承机制来实现泛化关系。例如,Student 类和 Teacher 类都是 Person 类的子类.

3.4 实现(Realization)

实现关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。

3.5 聚合(Aggregation)

聚合(Aggregation)关系是关联关系的一种,是强关联关系,是整体和部分之间的关系,是 has-a 的关系。

聚合关系也是通过成员对象来实现的,其中成员对象是整体对象的一部分,但是成员对象可以脱离整体对象而独立存在。例如,学校与老师的关系,学校包含老师,但如果学校停办了,老师依然存在。

在 UML 类图中,聚合关系可以用带空心菱形的实线来表示,菱形指向整体。

3.6 组合(Composition)

组合(Composition)关系也是关联关系的一种,也表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系,是 contains-a 关系。

在组合关系中,整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。例如,头和嘴的关系,没有了头,嘴也就不存在了。

在 UML 类图中,组合关系用带实心菱形的实线来表示,菱形指向整体。图 7 所示是头和嘴的关系图。

%5Btoc%5D%0A%0A%E4%BB%A3%E7%A0%81%0A%0Ahttps%3A%2F%2Fgithub.com%2Fmxg133%2FlearnforJava_DesignPattern%0A%0A%23%23%201.%20%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%9A%84%E7%9B%AE%E7%9A%84%09%0A%0A%23%23%23%201.1%20%E4%BB%A3%E7%A0%81%E9%87%8D%E7%94%A8%E6%80%A7%0A%0A%E7%9B%B8%E5%90%8C%E5%8A%9F%E8%83%BD%E7%9A%84%E4%BB%A3%E7%A0%81%E4%B8%8D%E7%94%A8%E9%87%8D%E5%A4%8D%E7%BC%96%E5%86%99%0A%0A%23%23%23%201.2%20%E5%8F%AF%E8%AF%BB%E6%80%A7%0A%0A%E7%BC%96%E7%A8%8B%E7%9A%84%E8%A7%84%E8%8C%83%E6%80%A7%EF%BC%8C%E4%BE%BF%E4%BA%8E%E5%85%B6%E5%AE%83%E4%BA%BA%E5%91%98%E9%98%85%E8%AF%BB%E5%92%8C%E7%90%86%E8%A7%A3%0A%0A%23%23%23%201.3%20%E5%8F%AF%E6%89%A9%E5%B1%95%E6%80%A7%0A%0A%E6%96%B0%E5%A2%9E%E5%8A%9F%E8%83%BD%E6%97%B6%E9%9D%9E%E5%B8%B8%E7%9A%84%E6%96%B9%E4%BE%BF%20%0A%0A%23%23%23%201.4%20%E5%8F%AF%E9%9D%A0%E6%80%A7%0A%0A%E5%BD%93%E6%96%B0%E5%A2%9E%E6%88%96%E5%87%8F%E5%B0%91%E5%8A%9F%E8%83%BD%E5%90%8E%EF%BC%8C%E5%AF%B9%E5%8E%9F%E6%9C%89%E7%9A%84%E5%8A%9F%E8%83%BD%E4%B8%8D%E4%BC%9A%E4%BA%A7%E7%94%9F%E5%BD%B1%E5%93%8D%0A%0A%3E%20%E6%89%80%E6%9C%89%E4%BB%A5%E4%B8%8A%E7%89%B9%E6%80%A7%E9%83%BD%E6%98%AF%E4%B8%BA%E4%BA%86%E8%AE%A9%E6%88%91%E4%BB%AC%E7%9A%84%E4%BB%A3%E7%A0%81%E5%91%88%E7%8E%B0%E9%AB%98%E5%86%85%E8%81%9A%EF%BC%8C%E4%BD%8E%E8%80%A6%E5%90%88%0A%0A%23%23%202.%20%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B8%83%E5%A4%A7%E5%8E%9F%E5%88%99%0A%0A%23%23%23%202.1%20%E5%8D%95%E4%B8%80%E8%81%8C%E8%B4%A3%E5%8E%9F%E5%88%99%0A%0A%3E%20%E5%8D%B3%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%8F%AA%E8%B4%9F%E8%B4%A3%E4%B8%80%E4%B8%AA%E8%81%8C%E8%B4%A3%0A%3E%0A%3E%20%E8%8B%A5%E4%B8%80%E4%B8%AA%E7%B1%BB%E8%B4%9F%E8%B4%A3%E4%B8%8D%E5%90%8C%E7%9A%84%E8%81%8C%E8%B4%A3%EF%BC%8C%E5%BD%93%E8%81%8C%E8%B4%A31%E7%9A%84%E9%9C%80%E6%B1%82%E5%8F%98%E5%8C%96%E8%80%8C%E6%94%B9%E5%8F%98%E7%B1%BB%E6%97%B6%EF%BC%8C%E5%8F%AF%E8%83%BD%E9%80%A0%E6%88%90%E8%81%8C%E8%B4%A32%E7%9A%84%E9%94%99%E8%AF%AF%E6%89%A7%E8%A1%8C%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E5%B0%86%E7%B1%BB%E6%8B%86%E5%88%86%E4%B8%BA%E7%B1%BB1%E5%92%8C%E7%B1%BB2%0A%0A%3E%20%E9%99%8D%E4%BD%8E%E7%B1%BB%E7%9A%84%E5%A4%8D%E6%9D%82%E6%80%A7%E5%92%8C%E5%8F%98%E6%9B%B4%E5%BC%95%E8%B5%B7%E7%9A%84%E9%A3%8E%E9%99%A9%EF%BC%8C%E6%8F%90%E9%AB%98%E5%8F%AF%E8%AF%BB%E6%80%A7%E5%92%8C%E5%8F%AF%E6%89%A9%E5%B1%95%E6%80%A7%0A%3E%20%E5%A6%82%E6%9E%9C%E9%80%BB%E8%BE%91%E8%B6%B3%E5%A4%9F%E7%AE%80%E5%8D%95%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%96%B9%E6%B3%95%E7%BA%A7%E5%88%AB%E5%AE%9E%E7%8E%B0%E5%8D%95%E4%B8%80%E8%81%8C%E8%B4%A3%E5%8E%9F%E5%88%99%0A%0A%23%23%23%202.2%20%E6%8E%A5%E5%8F%A3%E9%9A%94%E7%A6%BB%E5%8E%9F%E5%88%99%0A%0A%3E%20%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%AF%B9%E5%8F%A6%E4%B8%80%E4%B8%AA%E7%B1%BB%E7%9A%84%E4%BE%9D%E8%B5%96%E5%BA%94%E8%AF%A5%E5%BB%BA%E7%AB%8B%E5%9C%A8%60%E6%9C%80%E5%B0%8F%E7%9A%84%E6%8E%A5%E5%8F%A3%E4%B8%8A%60%0A%3E%20%E8%BF%99%E4%B8%AA%E6%8E%A5%E5%8F%A3%E9%87%8C%E9%9D%A2%E7%94%A8%E4%B8%8D%E5%88%B0%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%BA%94%E8%AF%A5%E6%8A%8A%E5%A4%A7%E7%9A%84%E6%8E%A5%E5%8F%A3%E6%8B%86%E5%88%86%E6%88%90%E5%B0%8F%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E7%84%B6%E5%90%8E%E4%BE%9D%E8%B5%96%E5%B0%8F%E7%9A%84%E6%8E%A5%E5%8F%A3%0A%3E%20%E7%B1%BBA%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%A31%EF%BC%8C2%E4%BE%9D%E8%B5%96%E7%B1%BBB%0A%3E%20%E7%B1%BBC%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%A31%EF%BC%8C3%E4%BE%9D%E8%B5%96%E7%B1%BBC%0A%0A!%5B4414894b22944389538c3d3178426bf1.png%5D(en-resource%3A%2F%2Fdatabase%2F1146%3A1)%0A%0A%60%60%60java%0Apublic%20class%20Segregation1%20%7B%0A%0A%09public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%0A%09%09A%20a%20%3D%20new%20A()%3B%0A%09%09a.depend1(new%20B())%3B%20%2F%2F%20A%E7%B1%BB%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%A3%E5%8E%BB%E4%BE%9D%E8%B5%96B%E7%B1%BB%0A%09%09a.depend2(new%20B())%3B%0A%09%09a.depend3(new%20B())%3B%0A%0A%09%09C%20c%20%3D%20new%20C()%3B%0A%0A%09%09c.depend1(new%20D())%3B%20%2F%2F%20C%E7%B1%BB%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%A3%E5%8E%BB%E4%BE%9D%E8%B5%96(%E4%BD%BF%E7%94%A8)D%E7%B1%BB%0A%09%09c.depend4(new%20D())%3B%0A%09%09c.depend5(new%20D())%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%20%E6%8E%A5%E5%8F%A31%0Ainterface%20Interface1%20%7B%0A%09void%20operation1()%3B%0A%7D%0A%0A%2F%2F%20%E6%8E%A5%E5%8F%A32%0Ainterface%20Interface2%20%7B%0A%09void%20operation2()%3B%0A%09void%20operation3()%3B%0A%7D%0A%0A%2F%2F%20%E6%8E%A5%E5%8F%A33%0Ainterface%20Interface3%20%7B%0A%09void%20operation4()%3B%0A%09void%20operation5()%3B%0A%7D%0A%0Aclass%20B%20implements%20Interface1%2C%20Interface2%20%7B%0A%09public%20void%20operation1()%20%7B%0A%09%09System.out.println(%22B%20%E5%AE%9E%E7%8E%B0%E4%BA%86%20operation1%22)%3B%0A%09%7D%0A%0A%09public%20void%20operation2()%20%7B%0A%09%09System.out.println(%22B%20%E5%AE%9E%E7%8E%B0%E4%BA%86%20operation2%22)%3B%0A%09%7D%0A%0A%09public%20void%20operation3()%20%7B%0A%09%09System.out.println(%22B%20%E5%AE%9E%E7%8E%B0%E4%BA%86%20operation3%22)%3B%0A%09%7D%0A%7D%0A%0Aclass%20D%20implements%20Interface1%2C%20Interface3%20%7B%0A%09public%20void%20operation1()%20%7B%0A%09%09System.out.println(%22D%20%E5%AE%9E%E7%8E%B0%E4%BA%86%20operation1%22)%3B%0A%09%7D%0A%0A%09public%20void%20operation4()%20%7B%0A%09%09System.out.println(%22D%20%E5%AE%9E%E7%8E%B0%E4%BA%86%20operation4%22)%3B%0A%09%7D%0A%0A%09public%20void%20operation5()%20%7B%0A%09%09System.out.println(%22D%20%E5%AE%9E%E7%8E%B0%E4%BA%86%20operation5%22)%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%20A%E7%B1%BB%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%A3Interface1%2CInterface2%20%E4%BE%9D%E8%B5%96(%E4%BD%BF%E7%94%A8)%20B%E7%B1%BB%EF%BC%8C%E4%BD%86%E6%98%AF%E5%8F%AA%E4%BC%9A%E7%94%A8%E5%88%B01%2C2%2C3%E6%96%B9%E6%B3%95%0Aclass%20A%20%7B%20%0A%09public%20void%20depend1(Interface1%20i)%20%7B%0A%09%09i.operation1()%3B%0A%09%7D%0A%20%20%20%20%0A%09public%20void%20depend2(Interface2%20i)%20%7B%0A%09%09i.operation2()%3B%0A%09%7D%0A%20%20%20%20%0A%09public%20void%20depend3(Interface2%20i)%20%7B%0A%09%09i.operation3()%3B%0A%09%7D%0A%7D%0A%0A%20%2F%2F%20C%E7%B1%BB%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%A3Interface1%2CInterface3%20%E4%BE%9D%E8%B5%96(%E4%BD%BF%E7%94%A8)%20D%E7%B1%BB%EF%BC%8C%E4%BD%86%E6%98%AF%E5%8F%AA%E4%BC%9A%E7%94%A8%E5%88%B01%2C4%2C5%E6%96%B9%E6%B3%95%0Aclass%20C%20%7B%0A%09public%20void%20depend1(Interface1%20i)%20%7B%0A%09%09i.operation1()%3B%0A%09%7D%0A%09%0A%09public%20void%20depend4(Interface3%20i)%20%7B%0A%09%09i.operation4()%3B%0A%09%7D%0A%0A%09public%20void%20depend5(Interface3%20i)%20%7B%0A%09%09i.operation5()%3B%0A%09%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%202.3%20%E4%BE%9D%E8%B5%96%E5%80%92%E7%BD%AE%E5%8E%9F%E5%88%99%0A%23%23%23%23%202.3.1%20%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%0A%0A%3E%201.%20%E6%A0%B8%E5%BF%83%E6%80%9D%E6%83%B3%E5%B0%B1%E6%98%AF%E4%BE%9D%E8%B5%96%E6%8E%A5%E5%8F%A3%E7%BC%96%E7%A8%8B%0A%3E%202.%20%E9%AB%98%E5%B1%82%E6%A8%A1%E5%9D%97%E4%B8%8D%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E4%BD%8E%E5%B1%82%E6%A8%A1%E5%9D%97%EF%BC%8C%E4%BA%8C%E8%80%85%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E4%BA%8E%E6%8A%BD%E8%B1%A1%0A%3E%203.%20%E6%8A%BD%E8%B1%A1%E4%B8%8D%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E4%BA%8E%E7%BB%86%E8%8A%82%EF%BC%8C%E7%BB%86%E8%8A%82%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E4%BA%8E%E6%8A%BD%E8%B1%A1%0A%3E%204.%20%E7%BB%86%E8%8A%82%E6%98%AF%E5%A4%9A%E5%8F%98%E7%9A%84%EF%BC%8C%E6%8A%BD%E8%B1%A1%E6%98%AF%E7%A8%B3%E5%AE%9A%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E6%8A%BD%E8%B1%A1%E5%9F%BA%E7%A1%80%E6%90%AD%E5%BB%BA%E7%9A%84%E6%A1%86%E6%9E%B6%E8%A6%81%E6%AF%94%E4%BB%A5%E7%BB%86%E8%8A%82%E4%B8%BA%E5%9F%BA%E7%A1%80%E6%90%AD%E5%BB%BA%E7%9A%84%E6%A1%86%E6%9E%B6%E7%A8%B3%E5%AE%9A%E7%9A%84%E5%A4%9A%E3%80%82%0A%3E%205.%20%E4%BD%BF%E7%94%A8%E6%8E%A5%E5%8F%A3%E6%88%96%E6%8A%BD%E8%B1%A1%E7%B1%BB%E7%9A%84%E7%9B%AE%E7%9A%84%E6%98%AF%E5%88%B6%E5%AE%9A%E5%A5%BD%E8%A7%84%E8%8C%83%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%B6%89%E5%8F%8A%E4%BB%BB%E4%BD%95%E5%85%B7%E4%BD%93%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%85%B7%E4%BD%93%E7%9A%84%E7%BB%86%E8%8A%82%E7%94%B1%E5%AE%9E%E7%8E%B0%E7%B1%BB%E8%B4%9F%E8%B4%A3%E5%AE%8C%E6%88%90%E3%80%82%0A%0A%60%60%60java%0Apublic%20class%20DependecyInversion%20%7B%0A%0A%09public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09%09Person%20person%20%3D%20new%20Person()%3B%0A%09%09person.receive(new%20Email())%3B%0A%09%7D%0A%7D%0A%0Aclass%20Email%20%7B%0A%09public%20String%20getInfo()%20%7B%0A%09%09return%20%22%E7%94%B5%E5%AD%90%E9%82%AE%E4%BB%B6%E4%BF%A1%E6%81%AF%3A%20hello%2Cworld%22%3B%0A%09%7D%0A%7D%0A%0A%2F*%0A%E5%AE%8C%E6%88%90Person%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%E7%9A%84%E5%8A%9F%E8%83%BD%0A%E6%96%B9%E5%BC%8F1%E5%88%86%E6%9E%90%0A1.%20%E7%AE%80%E5%8D%95%EF%BC%8C%E6%AF%94%E8%BE%83%E5%AE%B9%E6%98%93%E6%83%B3%E5%88%B0%0A2.%20%E5%A6%82%E6%9E%9C%E6%88%91%E4%BB%AC%E8%8E%B7%E5%8F%96%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%98%AF%20weixin%EF%BC%8C%E7%9F%AD%E4%BF%A1%E7%AD%89%E7%AD%89%EF%BC%8C%E5%88%99%E6%96%B0%E5%A2%9E%E7%B1%BB%EF%BC%8C%E5%90%8C%E6%97%B6Perons%E4%B9%9F%E8%A6%81%E5%A2%9E%E5%8A%A0%E7%9B%B8%E5%BA%94%E7%9A%84%E6%8E%A5%E6%94%B6%E6%96%B9%E6%B3%95%0A3.%20%E8%A7%A3%E5%86%B3%E6%80%9D%E8%B7%AF%EF%BC%9A%0A%20%20%20%E5%BC%95%E5%85%A5%E4%B8%80%E4%B8%AA%E6%8A%BD%E8%B1%A1%E7%9A%84%E6%8E%A5%E5%8F%A3IReceiver%2C%20%E8%A1%A8%E7%A4%BA%E6%8E%A5%E6%94%B6%E8%80%85%2C%20%E8%BF%99%E6%A0%B7Person%E7%B1%BB%E4%B8%8E%E6%8E%A5%E5%8F%A3IReceiver%E5%8F%91%E7%94%9F%E4%BE%9D%E8%B5%96%0A%20%20%20%E5%9B%A0%E4%B8%BAEmail%2C%20WeiXin%20%E7%AD%89%E7%AD%89%E5%B1%9E%E4%BA%8E%E6%8E%A5%E6%94%B6%E7%9A%84%E8%8C%83%E5%9B%B4%EF%BC%8C%E4%BB%96%E4%BB%AC%E5%90%84%E8%87%AA%E5%AE%9E%E7%8E%B0IReceiver%20%E6%8E%A5%E5%8F%A3%E5%B0%B1ok%2C%20%E8%BF%99%E6%A0%B7%E6%88%91%E4%BB%AC%E5%B0%B1%E7%AC%A6%E5%8F%B7%E4%BE%9D%E8%B5%96%E5%80%92%E8%BD%AC%E5%8E%9F%E5%88%99%0A*%2F%0Aclass%20Person%20%7B%0A%09public%20void%20receive(Email%20email%20)%20%7B%0A%09%09System.out.println(email.getInfo())%3B%0A%09%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%94%B9%E8%BF%9B%E5%90%8E%E7%9A%84%E6%96%B9%E6%B3%95%0A%0A%60%60%60java%0Apublic%20class%20DependecyInversion%20%7B%0A%0A%09public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09%09%2F%2F%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%97%A0%E9%9C%80%E6%94%B9%E5%8F%98%0A%09%09Person%20person%20%3D%20new%20Person()%3B%0A%09%09person.receive(new%20Email())%3B%0A%0A%09%09person.receive(new%20WeiXin())%3B%0A%09%7D%0A%0A%7D%0A%0A%2F%2F%E5%AE%9A%E4%B9%89%E6%8E%A5%E5%8F%A3%0Ainterface%20IReceiver%20%7B%0A%09public%20String%20getInfo()%3B%0A%7D%0A%0Aclass%20Email%20implements%20IReceiver%20%7B%0A%09public%20String%20getInfo()%20%7B%0A%09%09return%20%22%E7%94%B5%E5%AD%90%E9%82%AE%E4%BB%B6%E4%BF%A1%E6%81%AF%3A%20hello%2Cworld%22%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E5%A2%9E%E5%8A%A0%E5%BE%AE%E4%BF%A1%0Aclass%20WeiXin%20implements%20IReceiver%20%7B%0A%09public%20String%20getInfo()%20%7B%0A%09%09return%20%22%E5%BE%AE%E4%BF%A1%E4%BF%A1%E6%81%AF%3A%20hello%2Cok%22%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E6%96%B9%E5%BC%8F2%0A%2F%2F%E5%90%8C%E6%97%B6%E4%B9%9F%E9%81%B5%E5%BE%AA%E4%BA%86OCP%EF%BC%8C%E5%AF%B9%E4%BD%BF%E7%94%A8%E6%96%B9%E4%BF%AE%E6%94%B9%E5%85%B3%E9%97%AD%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E5%A2%9E%E5%8A%A0%E6%B6%88%E6%81%AF%E6%8F%90%E4%BE%9B%E6%96%B9%EF%BC%8C%E5%8D%B3%E5%AF%B9%E6%8F%90%E4%BE%9B%E6%96%B9%E6%89%A9%E5%B1%95%E5%BC%80%E6%94%BE%0Aclass%20Person%20%7B%0A%09%2F%2F%E8%BF%99%E9%87%8C%E6%88%91%E4%BB%AC%E6%98%AF%E5%AF%B9%E6%8E%A5%E5%8F%A3%E7%9A%84%E4%BE%9D%E8%B5%96%0A%09public%20void%20receive(IReceiver%20receiver)%20%7B%0A%09%09System.out.println(receiver.getInfo())%3B%0A%09%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202.3.2%20%E4%BE%9D%E8%B5%96%E4%BC%A0%E9%80%92%E7%9A%84%E4%B8%89%E7%A7%8D%E6%96%B9%E5%BC%8F%0A%0A%23%23%23%23%23%202.3.2.1%20%E6%8E%A5%E5%8F%A3%E4%BC%A0%E9%80%92%0A%0A%60%60%60java%0A%2F%2F%20%E6%96%B9%E5%BC%8F1%EF%BC%9A%20%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%A3%E4%BC%A0%E9%80%92%E5%AE%9E%E7%8E%B0%E4%BE%9D%E8%B5%96%0A%2F%2F%20%E5%BC%80%E5%85%B3%E7%9A%84%E6%8E%A5%E5%8F%A3%0Ainterface%20IOpenAndClose1%20%7B%0A%20%20%20%20void%20open1(ITV1%20tv)%3B%20%2F%2F%E6%8A%BD%E8%B1%A1%E6%96%B9%E6%B3%95%2C%E6%8E%A5%E6%94%B6%E6%8E%A5%E5%8F%A3%0A%7D%0A%0Ainterface%20ITV1%20%7B%20%2F%2FITV%E6%8E%A5%E5%8F%A3%0A%20%20%20%20void%20play1()%3B%0A%7D%0A%0Aclass%20ChangHong1%20implements%20ITV1%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20play1()%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20TODO%20Auto-generated%20method%20stub%0A%20%20%20%20%20%20%20%20System.out.println(%22%E9%95%BF%E8%99%B9%E7%94%B5%E8%A7%86%E6%9C%BA%EF%BC%8C%E6%89%93%E5%BC%80%22)%3B%0A%20%20%20%20%7D%20%20%20%20%20%20%20%0A%7D%0A%0A%2F%2F%20%E5%AE%9E%E7%8E%B0%E6%8E%A5%E5%8F%A3%0Aclass%20OpenAndClose1%20implements%20IOpenAndClose1%20%7B%0A%20%20%20%20public%20void%20open1(ITV1%20tv)%20%7B%0A%20%20%20%20%20%20%20%20tv.play1()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Apublic%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20TODO%20Auto-generated%20method%20stub%0A%20%20%20%20%20%20%20%20ChangHong%20changHong%20%3D%20new%20ChangHong()%3B%0A%09%09OpenAndClose%20openAndClose%20%3D%20new%20OpenAndClose()%3B%0A%09%09openAndClose.open(changHong)%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%23%23%23%23%23%202.3.2.2%20%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E4%BC%A0%E9%80%92%0A%0A%60%60%60java%0A%2F%2F%20%E6%96%B9%E5%BC%8F2%3A%20%E9%80%9A%E8%BF%87%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E4%BE%9D%E8%B5%96%E4%BC%A0%E9%80%92%0Ainterface%20IOpenAndClose2%20%7B%0A%20%20%20%20void%20open2()%3B%20%2F%2F%E6%8A%BD%E8%B1%A1%E6%96%B9%E6%B3%95%0A%7D%0A%0Ainterface%20ITV2%20%7B%20%2F%2FITV%E6%8E%A5%E5%8F%A3%0A%20%20%20%20void%20play2()%3B%0A%7D%0A%0Aclass%20ChangHong2%20implements%20ITV2%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20play2()%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20TODO%20Auto-generated%20method%20stub%0A%20%20%20%20%20%20%20%20System.out.println(%22%E9%95%BF%E8%99%B9%E7%94%B5%E8%A7%86%E6%9C%BA%EF%BC%8C%E6%89%93%E5%BC%80%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aclass%20OpenAndClose2%20implements%20IOpenAndClose2%20%7B%0A%20%20%20%20public%20ITV2%20tv%3B%20%2F%2F%E6%88%90%E5%91%98%0A%20%20%20%20%0A%20%20%20%20public%20OpenAndClose2(ITV2%20tv)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E6%9E%84%E9%80%A0%E5%99%A8%0A%20%20%20%20%20%20%20%20this.tv%20%3D%20tv%3B%0A%20%20%20%20%7D%0A%20%20%20%20public%20void%20open2()%20%7B%0A%20%20%20%20%20%20%20%20this.tv.play2()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Apublic%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20TODO%20Auto-generated%20method%20stub%0A%20%20%20%20%20%20%20%20ChangHong2%20changHong%20%3D%20new%20ChangHong2()%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E9%80%9A%E8%BF%87%E6%9E%84%E9%80%A0%E5%99%A8%E8%BF%9B%E8%A1%8C%E4%BE%9D%E8%B5%96%E4%BC%A0%E9%80%92%0A%09%09OpenAndClose2%20openAndClose%20%3D%20new%20OpenAndClose2(changHong)%3B%0A%09%09openAndClose.open2()%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%202.3.2.3%20setter%E6%96%B9%E6%B3%95%E4%BC%A0%E9%80%92%0A%0A%60%60%60java%0A%2F%2F%20%E6%96%B9%E5%BC%8F3%20%2C%20%E9%80%9A%E8%BF%87setter%E6%96%B9%E6%B3%95%E4%BC%A0%E9%80%92%0Ainterface%20IOpenAndClose%20%7B%0A%20%20%20%20void%20open()%3B%20%2F%2F%20%E6%8A%BD%E8%B1%A1%E6%96%B9%E6%B3%95%0A%0A%20%20%20%20void%20setTv(ITV%20tv)%3B%0A%7D%0A%0Ainterface%20ITV%20%7B%20%2F%2F%20ITV%E6%8E%A5%E5%8F%A3%0A%20%20%20%20void%20play()%3B%0A%7D%0A%0Aclass%20OpenAndClose%20implements%20IOpenAndClose%20%7B%0A%20%20%20%20private%20ITV%20tv%3B%0A%0A%20%20%20%20public%20void%20setTv(ITV%20tv)%20%7B%0A%20%20%20%20%20%20%20%20this.tv%20%3D%20tv%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20void%20open()%20%7B%0A%20%20%20%20%20%20%20%20this.tv.play()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aclass%20ChangHong%20implements%20ITV%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20play()%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20TODO%20Auto-generated%20method%20stub%0A%20%20%20%20%20%20%20%20System.out.println(%22%E9%95%BF%E8%99%B9%E7%94%B5%E8%A7%86%E6%9C%BA%EF%BC%8C%E6%89%93%E5%BC%80%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0Apublic%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20TODO%20Auto-generated%20method%20stub%0A%20%20%20%20%20%20%20%20ChangHong%20changHong%20%3D%20new%20ChangHong()%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E9%80%9A%E8%BF%87setter%E6%96%B9%E6%B3%95%E8%BF%9B%E8%A1%8C%E4%BE%9D%E8%B5%96%E4%BC%A0%E9%80%92%0A%20%20%20%20%20%20%20%20OpenAndClose%20openAndClose%20%3D%20new%20OpenAndClose()%3B%0A%20%20%20%20%20%20%20%20openAndClose.setTv(changHong)%3B%0A%20%20%20%20%20%20%20%20openAndClose.open()%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%23%23%23%23%202.3.3%20%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9%0A%0A%3E%201.%20%E4%BD%8E%E5%B1%82%E6%A8%A1%E5%9D%97%E5%B0%BD%E9%87%8F%E8%A6%81%E6%9C%89%E6%8A%BD%E8%B1%A1%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3%EF%BC%8C%20%E6%88%96%E8%80%85%E4%B8%A4%E4%B8%AA%E9%83%BD%E6%9C%89%EF%BC%8C%E8%BF%99%E6%A0%B7%E7%A8%B3%E5%AE%9A%E6%80%A7%E4%BC%9A%E6%9B%B4%E5%A5%BD%0A%3E%202.%20%E5%8F%98%E9%87%8F%E7%9A%84%E5%A3%B0%E6%98%8E%E7%B1%BB%E5%9E%8B%E5%B0%BD%E9%87%8F%E6%98%AF%E6%8A%BD%E8%B1%A1%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3%EF%BC%8C%E8%BF%99%E6%A0%B7%E6%88%91%E4%BB%AC%E5%8F%98%E9%87%8F%E7%9A%84%E5%BC%95%E7%94%A8%E5%92%8C%E5%AE%9E%E9%99%85%E5%AF%B9%E8%B1%A1%E9%97%B4%EF%BC%8C%E5%B0%B1%E5%AD%98%E5%9C%A8%E4%B8%80%E4%B8%AA%60%E7%BC%93%E5%AD%98%E5%B1%82%60%EF%BC%8C%E5%88%A9%E4%BA%8E%E6%89%A9%E5%B1%95%E5%92%8C%E4%BC%98%E5%8C%96%E3%80%82%0A%3E%203.%20%E7%BB%A7%E6%89%BF%E6%97%B6%E9%81%B5%E5%BE%AA%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%0A%0A%23%23%23%202.4%20%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%0A%0A%23%23%23%23%202.4.1%20%E7%BB%A7%E6%89%BF%E5%AD%98%E5%9C%A8%E7%9A%84%E9%97%AE%E9%A2%98%0A%0A%3E%201.%20%E7%BB%A7%E6%89%BF%E5%8C%85%E5%90%AB%E8%BF%99%E6%A0%B7%E4%B8%80%E5%B1%82%E5%90%AB%E4%B9%89%EF%BC%9A%E7%88%B6%E7%B1%BB%E4%B8%AD%E5%87%A1%E6%98%AF%E5%B7%B2%E7%BB%8F%E5%AE%9E%E7%8E%B0%E5%A5%BD%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%AE%9E%E9%99%85%E4%B8%8A%E6%98%AF%E5%9C%A8%E8%AE%BE%E5%AE%9A%60%E8%A7%84%E8%8C%83%E5%92%8C%E5%A5%91%E7%BA%A6%60%EF%BC%8C%E8%99%BD%E7%84%B6%E5%AE%83%E4%B8%8D%E5%BC%BA%E5%88%B6%E8%A6%81%E6%B1%82%E6%89%80%E6%9C%89%E7%9A%84%E5%AD%90%E7%B1%BB%E5%BF%85%E9%A1%BB%E9%81%B5%E5%BE%AA%E8%BF%99%E4%BA%9B%E5%A5%91%E7%BA%A6%EF%BC%8C%E4%BD%86%E6%98%AF%E5%A6%82%E6%9E%9C%E5%AD%90%E7%B1%BB%E5%AF%B9%E8%BF%99%E4%BA%9B%E5%B7%B2%E7%BB%8F%E5%AE%9E%E7%8E%B0%E7%9A%84%E6%96%B9%E6%B3%95%E4%BB%BB%E6%84%8F%E4%BF%AE%E6%94%B9%EF%BC%8C%E5%B0%B1%E4%BC%9A%E5%AF%B9%E6%95%B4%E4%B8%AA%E7%BB%A7%E6%89%BF%E4%BD%93%E7%B3%BB%E9%80%A0%E6%88%90%E7%A0%B4%E5%9D%8F%E3%80%82%0A%3E%202.%20%20%E7%BB%A7%E6%89%BF%E5%9C%A8%E7%BB%99%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E5%B8%A6%E6%9D%A5%E4%BE%BF%E5%88%A9%E7%9A%84%E5%90%8C%E6%97%B6%EF%BC%8C%E4%B9%9F%E5%B8%A6%E6%9D%A5%E4%BA%86%E5%BC%8A%E7%AB%AF%E3%80%82%E6%AF%94%E5%A6%82%E4%BD%BF%E7%94%A8%E7%BB%A7%E6%89%BF%E4%BC%9A%E7%BB%99%E7%A8%8B%E5%BA%8F%E5%B8%A6%E6%9D%A5%60%E4%BE%B5%E5%85%A5%E6%80%A7%60%EF%BC%8C%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E7%A7%BB%E6%A4%8D%E6%80%A7%E9%99%8D%E4%BD%8E%EF%BC%8C%E5%A2%9E%E5%8A%A0%E5%AF%B9%E8%B1%A1%E9%97%B4%E7%9A%84%E8%80%A6%E5%90%88%E6%80%A7%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E7%B1%BB%E8%A2%AB%E5%85%B6%E4%BB%96%E7%9A%84%E7%B1%BB%E6%89%80%E7%BB%A7%E6%89%BF%EF%BC%8C%E5%88%99%E5%BD%93%E8%BF%99%E4%B8%AA%E7%B1%BB%E9%9C%80%E8%A6%81%E4%BF%AE%E6%94%B9%E6%97%B6%EF%BC%8C%E5%BF%85%E9%A1%BB%E8%80%83%E8%99%91%E5%88%B0%E6%89%80%E6%9C%89%E7%9A%84%E5%AD%90%E7%B1%BB%EF%BC%8C%E5%B9%B6%E4%B8%94%E7%88%B6%E7%B1%BB%E4%BF%AE%E6%94%B9%E5%90%8E%EF%BC%8C%E6%89%80%E6%9C%89%E6%B6%89%E5%8F%8A%E5%88%B0%E5%AD%90%E7%B1%BB%E7%9A%84%E5%8A%9F%E8%83%BD%E9%83%BD%E6%9C%89%E5%8F%AF%E8%83%BD%E4%BA%A7%E7%94%9F%E6%95%85%E9%9A%9C%20%0A%3E%203.%20%E9%97%AE%E9%A2%98%E6%8F%90%E5%87%BA%EF%BC%9A%E5%9C%A8%E7%BC%96%E7%A8%8B%E4%B8%AD%EF%BC%8C%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E7%9A%84%E4%BD%BF%E7%94%A8%E7%BB%A7%E6%89%BF%3F%20%3D%3E%20%60%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%60%0A%0A%23%23%23%23%202.4.2%20%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E7%9A%84%E4%BD%BF%E7%94%A8%E7%BB%A7%E6%89%BF%0A%0A%3E%20%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%E6%98%AF%E5%9C%A8%E5%91%8A%E8%AF%89%E6%88%91%E4%BB%AC%E7%BB%A7%E6%89%BF%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E4%BB%80%E4%B9%88%E9%97%AE%E9%A2%98%E4%BB%A5%E5%8F%8A%E8%A6%81%E9%81%B5%E5%AE%88%E4%BB%80%E4%B9%88%E8%A7%84%E5%88%99%0A%3E%0A%3E%201.%20%E6%89%80%E6%9C%89%E5%BC%95%E7%94%A8%E7%88%B6%E7%B1%BB%E7%9A%84%E5%9C%B0%E6%96%B9%E5%8F%AF%E4%BB%A5%E9%80%8F%E6%98%8E%E7%9A%84%E4%BD%BF%E7%94%A8%E5%85%B6%E5%AD%90%E7%B1%BB%0A%3E%202.%20%E5%9C%A8%E4%BD%BF%E7%94%A8%E7%BB%A7%E6%89%BF%E6%97%B6%EF%BC%8C%E5%9C%A8%E5%AD%90%E7%B1%BB%E4%B8%AD%E5%B0%BD%E9%87%8F%E4%B8%8D%E8%A6%81%E9%87%8D%E5%86%99%E7%88%B6%E7%B1%BB%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E7%89%B9%E5%88%AB%E6%98%AF%E8%BF%90%E8%A1%8C%60%E5%A4%9A%E6%80%81%60%E6%AF%94%E8%BE%83%E9%A2%91%E7%B9%81%E7%9A%84%E6%97%B6%E5%80%99%E3%80%82%0A%3E%203.%20%E7%BB%A7%E6%89%BF%E5%AE%9E%E9%99%85%E4%B8%8A%E6%98%AF%E5%A2%9E%E5%8A%A0%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E8%80%A6%E5%90%88%E6%80%A7%EF%BC%8C%E9%80%9A%E7%94%A8%E7%9A%84%E5%81%9A%E6%B3%95%E6%98%AF%EF%BC%9A%E5%8E%9F%E6%9D%A5%E7%9A%84%E7%88%B6%E7%B1%BB%E5%92%8C%E5%AD%90%E7%B1%BB%E9%83%BD%E7%BB%A7%E6%89%BF%E4%B8%80%E4%B8%AA%E6%9B%B4%E9%80%9A%E7%94%A8%E7%9A%84%E5%9F%BA%E7%B1%BB%EF%BC%8C%20%E5%9C%A8%E9%80%82%E5%BD%93%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%60%E8%81%9A%E5%90%88%EF%BC%8C%E7%BB%84%E5%90%88%EF%BC%8C%E4%BE%9D%E8%B5%96%60%E6%9D%A5%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98%E3%80%82%0A%0A!%5B7814739bbea653de75e1323621fd01d9.png%5D(en-resource%3A%2F%2Fdatabase%2F1147%3A1)%0A%0A%60%60%60java%0Apublic%20class%20Liskov%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20A%20a%20%3D%20new%20A()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%2211-3%3D%22%20%2B%20a.func1(11%2C%203))%3B%0A%20%20%20%20%20%20%20%20System.out.println(%221-8%3D%22%20%2B%20a.func1(1%2C%208))%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(%22-----------------------%22)%3B%0A%20%20%20%20%20%20%20%20B%20b%20%3D%20new%20B()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%2211-3%3D%22%20%2B%20b.func1(11%2C%203))%3B%2F%2F%E8%BF%99%E9%87%8C%E6%9C%AC%E6%84%8F%E6%98%AF%E6%B1%82%E5%87%BA11-3%0A%20%20%20%20%20%20%20%20System.out.println(%221-8%3D%22%20%2B%20b.func1(1%2C%208))%3B%2F%2F%201-8%0A%20%20%20%20%20%20%20%20System.out.println(%2211%2B3%2B9%3D%22%20%2B%20b.func2(11%2C%203))%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2F%20A%E7%B1%BB%0Aclass%20A%20%7B%0A%20%20%20%20%2F%2F%20%E8%BF%94%E5%9B%9E%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%9A%84%E5%B7%AE%0A%20%20%20%20public%20int%20func1(int%20num1%2C%20int%20num2)%20%7B%0A%20%20%20%20%20%20%20%20return%20num1%20-%20num2%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F*%20%0A%20B%E7%B1%BB%E7%BB%A7%E6%89%BF%E4%BA%86A%0A%20%E5%A2%9E%E5%8A%A0%E4%BA%86%E4%B8%80%E4%B8%AA%E6%96%B0%E5%8A%9F%E8%83%BD%EF%BC%9A%E5%AE%8C%E6%88%90%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%9B%B8%E5%8A%A0%2C%E7%84%B6%E5%90%8E%E5%92%8C9%E6%B1%82%E5%92%8C%0A%20*%2F%0Aclass%20B%20extends%20A%20%7B%0A%20%20%20%20%2F%2F%E8%BF%99%E9%87%8C%EF%BC%8C%E9%87%8D%E5%86%99%E4%BA%86A%E7%B1%BB%E7%9A%84%E6%96%B9%E6%B3%95%2C%20%E5%8F%AF%E8%83%BD%E6%98%AF%E6%97%A0%E6%84%8F%E8%AF%86%0A%20%20%20%20public%20int%20func1(int%20a%2C%20int%20b)%20%7B%0A%20%20%20%20%20%20%20%20return%20a%20%2B%20b%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20int%20func2(int%20a%2C%20int%20b)%20%7B%0A%20%20%20%20%20%20%20%20return%20func1(a%2C%20b)%20%2B%209%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%94%B9%E8%BF%9B%E5%90%8E%E7%9A%84%E4%BB%A3%E7%A0%81%0A%0A%60%60%60java%0Apublic%20class%20Liskov%20%7B%0A%09public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09%09A%20a%20%3D%20new%20A()%3B%0A%09%09System.out.println(%2211-3%3D%22%20%2B%20a.func1(11%2C%203))%3B%0A%09%09System.out.println(%221-8%3D%22%20%2B%20a.func1(1%2C%208))%3B%0A%0A%09%09System.out.println(%22-----------------------%22)%3B%0A%09%09B%20b%20%3D%20new%20B()%3B%0A%09%09%2F%2F%E5%9B%A0%E4%B8%BAB%E7%B1%BB%E4%B8%8D%E5%86%8D%E7%BB%A7%E6%89%BFA%E7%B1%BB%EF%BC%8C%E5%9B%A0%E6%AD%A4%E8%B0%83%E7%94%A8%E8%80%85%EF%BC%8C%E4%B8%8D%E4%BC%9A%E5%86%8Dfunc1%E6%98%AF%E6%B1%82%E5%87%8F%E6%B3%95%0A%09%09%2F%2F%E8%B0%83%E7%94%A8%E5%AE%8C%E6%88%90%E7%9A%84%E5%8A%9F%E8%83%BD%E5%B0%B1%E4%BC%9A%E5%BE%88%E6%98%8E%E7%A1%AE%0A%09%09System.out.println(%2211%2B3%3D%22%20%2B%20b.func1(11%2C%203))%3B%2F%2F%E8%BF%99%E9%87%8C%E6%9C%AC%E6%84%8F%E6%98%AF%E6%B1%82%E5%87%BA11%2B3%0A%09%09System.out.println(%221%2B8%3D%22%20%2B%20b.func1(1%2C%208))%3B%2F%2F%201%2B8%0A%09%09System.out.println(%2211%2B3%2B9%3D%22%20%2B%20b.func2(11%2C%203))%3B%0A%0A%09%09%2F%2F%E4%BD%BF%E7%94%A8%E7%BB%84%E5%90%88%E4%BB%8D%E7%84%B6%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E5%88%B0A%E7%B1%BB%E7%9B%B8%E5%85%B3%E6%96%B9%E6%B3%95%0A%09%09System.out.println(%2211-3%3D%22%20%2B%20b.func3(11%2C%203))%3B%2F%2F%20%E8%BF%99%E9%87%8C%E6%9C%AC%E6%84%8F%E6%98%AF%E6%B1%82%E5%87%BA11-3%0A%09%7D%0A%7D%0A%0A%2F%2F%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%9B%B4%E5%8A%A0%E5%9F%BA%E7%A1%80%E7%9A%84%E5%9F%BA%E7%B1%BB%0Aclass%20Base%20%7B%0A%09%2F%2F%E6%8A%8A%E6%9B%B4%E5%8A%A0%E5%9F%BA%E7%A1%80%E7%9A%84%E6%96%B9%E6%B3%95%E5%92%8C%E6%88%90%E5%91%98%E5%86%99%E5%88%B0Base%E7%B1%BB%0A%7D%0A%0A%2F%2F%20A%E7%B1%BB%0Aclass%20A%20extends%20Base%20%7B%0A%09%2F%2F%20%E8%BF%94%E5%9B%9E%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%9A%84%E5%B7%AE%0A%09public%20int%20func1(int%20num1%2C%20int%20num2)%20%7B%0A%09%09return%20num1%20-%20num2%3B%0A%09%7D%0A%7D%0A%0A%2F*%20%0A%20B%E7%B1%BB%E7%BB%A7%E6%89%BF%E4%BA%86A%0A%20%E5%A2%9E%E5%8A%A0%E4%BA%86%E4%B8%80%E4%B8%AA%E6%96%B0%E5%8A%9F%E8%83%BD%EF%BC%9A%E5%AE%8C%E6%88%90%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%9B%B8%E5%8A%A0%2C%E7%84%B6%E5%90%8E%E5%92%8C9%E6%B1%82%E5%92%8C%0A%20*%2F%0Aclass%20B%20extends%20Base%20%7B%0A%09%2F%2F%E5%A6%82%E6%9E%9CB%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8A%E7%B1%BB%E7%9A%84%E6%96%B9%E6%B3%95%2C%E4%BD%BF%E7%94%A8%E7%BB%84%E5%90%88%E5%85%B3%E7%B3%BB%0A%09private%20A%20a%20%3D%20new%20A()%3B%0A%0A%09public%20int%20func1(int%20a%2C%20int%20b)%20%7B%0A%09%09return%20a%20%2B%20b%3B%0A%09%7D%0A%0A%09public%20int%20func2(int%20a%2C%20int%20b)%20%7B%0A%09%09return%20func1(a%2C%20b)%20%2B%209%3B%0A%09%7D%0A%0A%09%2F%2F%E6%88%91%E4%BB%AC%E4%BB%8D%E7%84%B6%E6%83%B3%E4%BD%BF%E7%94%A8A%E7%9A%84%E6%96%B9%E6%B3%95%0A%09public%20int%20func3(int%20a%2C%20int%20b)%20%7B%0A%09%09return%20this.a.func1(a%2C%20b)%3B%0A%09%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%202.5%20%E5%BC%80%E9%97%AD%E5%8E%9F%E5%88%99%0A%0A%3E%201.%20%E4%B8%80%E4%B8%AA%E8%BD%AF%E4%BB%B6%E5%AE%9E%E4%BD%93%E4%B8%AD%E7%B1%BB%EF%BC%8C%E6%A8%A1%E5%9D%97%E5%92%8C%E6%96%B9%E6%B3%95%EF%BC%8C%E5%BA%94%E8%AF%A5%E5%AF%B9%E6%89%A9%E5%B1%95%E5%BC%80%E6%94%BE%E3%80%90%E6%8F%90%E4%BE%9B%E6%96%B9%E3%80%91%EF%BC%8C%E5%AF%B9%E4%BF%AE%E6%94%B9%E5%85%B3%E9%97%AD%E3%80%90%E4%BD%BF%E7%94%A8%E6%96%B9%E3%80%91%EF%BC%8C%E7%94%A8%E6%8A%BD%E8%B1%A1%E6%9E%84%E5%BB%BA%E6%A1%86%E6%9E%B6%EF%BC%8C%E7%94%A8%E5%AE%9E%E7%8E%B0%E6%89%A9%E5%B1%95%E7%BB%86%E8%8A%82%E3%80%82%0A%3E%202.%20%E5%BD%93%E8%BD%AF%E4%BB%B6%E9%9C%80%E8%A6%81%E5%8F%98%E5%8C%96%E6%97%B6%EF%BC%8C%E5%B0%BD%E9%87%8F%E9%80%9A%E8%BF%87%E6%89%A9%E5%B1%95%E8%BD%AF%E4%BB%B6%E5%AE%9E%E4%BD%93%E7%9A%84%E8%A1%8C%E4%B8%BA%E6%9D%A5%E5%AE%9E%E7%8E%B0%E5%8F%98%E5%8C%96%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%98%AF%E9%80%9A%E8%BF%87%E4%BF%AE%E6%94%B9%E5%B7%B2%E6%9C%89%E7%9A%84%E4%BB%A3%E7%A0%81%E6%9D%A5%E5%AE%9E%E7%8E%B0%E5%8F%98%E5%8C%96%E3%80%82%0A%3E%203.%20%E7%BC%96%E7%A8%8B%E4%B8%AD%E9%81%B5%E5%BE%AA%E5%85%B6%E5%AE%9E%E5%8E%9F%E5%88%99%EF%BC%8C%E4%BB%A5%E5%8F%8A%E4%BD%BF%E7%94%A8%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%9A%84%E7%9B%AE%E7%9A%84%E5%B0%B1%E6%98%AF%E4%B8%BA%E4%BA%86%E9%81%B5%E5%BE%AA%E5%BC%80%E9%97%AD%E5%8E%9F%E5%88%99%E3%80%82%0A%0A%3E%20%E5%BD%93%E6%96%B0%E5%A2%9E%E7%94%BB%E4%B8%89%E8%A7%92%E5%BD%A2%EF%BC%8C%E4%B8%8D%E4%BB%85%E8%A6%81%E5%AF%B9%E6%8F%90%E4%BE%9B%E6%96%B9%E8%BF%9B%E8%A1%8C%E6%89%A9%E5%B1%95%EF%BC%8C%E8%80%8C%E4%B8%94%E8%A6%81%E5%AF%B9%E4%BD%BF%E7%94%A8%E6%96%B9%E7%9A%84%E4%BB%A3%E7%A0%81%E8%BF%9B%E8%A1%8C%E5%A4%A7%E9%87%8F%E4%BF%AE%E6%94%B9%E3%80%82%0A%0A!%5B3758d260b2461a1695f08701fc0d161c.png%5D(en-resource%3A%2F%2Fdatabase%2F1148%3A1)%0A%0A%60%60%60java%0Apublic%20class%20Ocp%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E4%BD%BF%E7%94%A8%E7%9C%8B%E7%9C%8B%E5%AD%98%E5%9C%A8%E7%9A%84%E9%97%AE%E9%A2%98%0A%20%20%20%20%20%20%20%20GraphicEditor%20graphicEditor%20%3D%20new%20GraphicEditor()%3B%0A%20%20%20%20%20%20%20%20graphicEditor.drawShape(new%20Rectangle())%3B%0A%20%20%20%20%20%20%20%20graphicEditor.drawShape(new%20Circle())%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%E6%96%B0%E5%A2%9E%E7%94%BB%E4%B8%89%E8%A7%92%E5%BD%A2%0A%20%20%20%20%20%20%20%20graphicEditor.drawShape(new%20Triangle())%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%0A%2F%2F%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E7%94%A8%E4%BA%8E%E7%BB%98%E5%9B%BE%E7%9A%84%E7%B1%BB%20%5B%E4%BD%BF%E7%94%A8%E6%96%B9%5D%0Aclass%20GraphicEditor%20%7B%0A%20%20%20%20%2F%2F%E6%8E%A5%E6%94%B6Shape%E5%AF%B9%E8%B1%A1%EF%BC%8C%E7%84%B6%E5%90%8E%E6%A0%B9%E6%8D%AEtype%EF%BC%8C%E6%9D%A5%E7%BB%98%E5%88%B6%E4%B8%8D%E5%90%8C%E7%9A%84%E5%9B%BE%E5%BD%A2%0A%20%20%20%20public%20void%20drawShape(Shape%20s)%20%7B%0A%20%20%20%20%20%20%20%20if%20(s.m_type%20%3D%3D%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20drawRectangle(s)%3B%0A%20%20%20%20%20%20%20%20else%20if%20(s.m_type%20%3D%3D%202)%0A%20%20%20%20%20%20%20%20%20%20%20%20drawCircle(s)%3B%0A%20%20%20%20%20%20%20%20else%20if%20(s.m_type%20%3D%3D%203)%20%2F%2F%E6%96%B0%E5%A2%9E%E7%94%BB%E4%B8%89%E8%A7%92%E5%BD%A2%0A%20%20%20%20%20%20%20%20%20%20%20%20drawTriangle(s)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%E7%BB%98%E5%88%B6%E7%9F%A9%E5%BD%A2%0A%20%20%20%20public%20void%20drawRectangle(Shape%20r)%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%20%E7%BB%98%E5%88%B6%E7%9F%A9%E5%BD%A2%20%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%E7%BB%98%E5%88%B6%E5%9C%86%E5%BD%A2%0A%20%20%20%20public%20void%20drawCircle(Shape%20r)%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%20%E7%BB%98%E5%88%B6%E5%9C%86%E5%BD%A2%20%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%E6%96%B0%E5%A2%9E%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2%0A%20%20%20%20public%20void%20drawTriangle(Shape%20r)%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%20%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2%20%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2FShape%E7%B1%BB%EF%BC%8C%E5%9F%BA%E7%B1%BB%0Aclass%20Shape%20%7B%0A%20%20%20%20int%20m_type%3B%0A%7D%0A%0Aclass%20Rectangle%20extends%20Shape%20%7B%0A%20%20%20%20Rectangle()%20%7B%0A%20%20%20%20%20%20%20%20super.m_type%20%3D%201%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aclass%20Circle%20extends%20Shape%20%7B%0A%20%20%20%20Circle()%20%7B%0A%20%20%20%20%20%20%20%20super.m_type%20%3D%202%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2F%E6%96%B0%E5%A2%9E%E7%94%BB%E4%B8%89%E8%A7%92%E5%BD%A2%0Aclass%20Triangle%20extends%20Shape%20%7B%0A%20%20%20%20Triangle()%20%7B%0A%20%20%20%20%20%20%20%20super.m_type%20%3D%203%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%94%B9%E8%BF%9B%E5%90%8E%E7%9A%84%E6%96%B9%E6%B3%95%0A%0A%60%60%60java%0Apublic%20class%20Ocp%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20GraphicEditor%20graphicEditor%20%3D%20new%20GraphicEditor()%3B%0A%20%20%20%20%20%20%20%20graphicEditor.drawShape(new%20Rectangle())%3B%0A%20%20%20%20%20%20%20%20graphicEditor.drawShape(new%20Circle())%3B%0A%20%20%20%20%20%20%20%20graphicEditor.drawShape(new%20Triangle())%3B%0A%20%20%20%20%20%20%20%20graphicEditor.drawShape(new%20OtherGraphic())%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2F%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E7%94%A8%E4%BA%8E%E7%BB%98%E5%9B%BE%E7%9A%84%E7%B1%BB%20%5B%E4%BD%BF%E7%94%A8%E6%96%B9%5D%0Aclass%20GraphicEditor%20%7B%0A%20%20%20%20%2F%2F%E6%8E%A5%E6%94%B6Shape%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%B0%83%E7%94%A8draw%E6%96%B9%E6%B3%95%0A%20%20%20%20public%20void%20drawShape(Shape%20s)%20%7B%0A%20%20%20%20%20%20%20%20s.draw()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2FShape%E7%B1%BB%EF%BC%8C%E5%9F%BA%E7%B1%BB%0Aabstract%20class%20Shape%20%7B%0A%20%20%20%20public%20abstract%20void%20draw()%3B%2F%2F%E6%8A%BD%E8%B1%A1%E6%96%B9%E6%B3%95%0A%7D%0A%0Aclass%20Rectangle%20extends%20Shape%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20draw()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%20%E7%BB%98%E5%88%B6%E7%9F%A9%E5%BD%A2%20%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aclass%20Circle%20extends%20Shape%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20draw()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%20%E7%BB%98%E5%88%B6%E5%9C%86%E5%BD%A2%20%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2F%E6%96%B0%E5%A2%9E%E7%94%BB%E4%B8%89%E8%A7%92%E5%BD%A2%0Aclass%20Triangle%20extends%20Shape%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20draw()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%20%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2%20%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2F%E6%96%B0%E5%A2%9E%E4%B8%80%E4%B8%AA%E5%9B%BE%E5%BD%A2%0Aclass%20OtherGraphic%20extends%20Shape%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20draw()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%20%E7%BB%98%E5%88%B6%E5%85%B6%E5%AE%83%E5%9B%BE%E5%BD%A2%20%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%202.6%20%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%0A%0A%23%23%23%23%202.6.1%20%E6%9C%80%E5%B0%91%E7%9F%A5%E9%81%93%E5%8E%9F%E5%88%99%0A%0A1.%20%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%BA%94%E8%AF%A5%E5%AF%B9%E5%85%B6%E4%BB%96%E5%AF%B9%E8%B1%A1%E4%BF%9D%E6%8C%81%E6%9C%80%E5%B0%91%E7%9A%84%E4%BA%86%E8%A7%A3%0A%0A2.%20%E7%B1%BB%E4%B8%8E%E7%B1%BB%E5%85%B3%E7%B3%BB%E8%B6%8A%E5%AF%86%E5%88%87%EF%BC%8C%E8%80%A6%E5%90%88%E5%BA%A6%E8%B6%8A%E5%A4%A7%0A%0A3.%20%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99(Demeter%20Principle)%E5%8F%88%E5%8F%AB%60%E6%9C%80%E5%B0%91%E7%9F%A5%E9%81%93%E5%8E%9F%E5%88%99%60%EF%BC%8C%E5%8D%B3%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%AF%B9%E8%87%AA%E5%B7%B1%E4%BE%9D%E8%B5%96%E7%9A%84%E7%B1%BB%E7%9F%A5%E9%81%93%E7%9A%84%E8%B6%8A%E5%B0%91%E8%B6%8A%E5%A5%BD%E3%80%82%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E5%AF%B9%E4%BA%8E%0A%20%20%20%E8%A2%AB%E4%BE%9D%E8%B5%96%E7%9A%84%E7%B1%BB%E4%B8%8D%E7%AE%A1%E5%A4%9A%E4%B9%88%E5%A4%8D%E6%9D%82%EF%BC%8C%E9%83%BD%E5%B0%BD%E9%87%8F%E5%B0%86%E9%80%BB%E8%BE%91%E5%B0%81%E8%A3%85%E5%9C%A8%E7%B1%BB%E7%9A%84%E5%86%85%E9%83%A8%E3%80%82%E5%AF%B9%E5%A4%96%E9%99%A4%E4%BA%86%E6%8F%90%E4%BE%9B%E7%9A%84%20public%20%E6%96%B9%E6%B3%95%EF%BC%8C%E4%B8%8D%E5%AF%B9%E5%A4%96%E6%B3%84%E9%9C%B2%E4%BB%BB%E4%BD%95%E4%BF%A1%E6%81%AF%0A%0A%23%23%23%23%202.6.2%20%20%E5%8F%AA%E4%B8%8E%E7%9B%B4%E6%8E%A5%E7%9A%84%E6%9C%8B%E5%8F%8B%E9%80%9A%E4%BF%A1%0A%0A%20%20%20%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%E8%BF%98%E6%9C%89%E4%B8%AA%E6%9B%B4%E7%AE%80%E5%8D%95%E7%9A%84%E5%AE%9A%E4%B9%89%EF%BC%9A%60%E5%8F%AA%E4%B8%8E%E7%9B%B4%E6%8E%A5%E7%9A%84%E6%9C%8B%E5%8F%8B%E9%80%9A%E4%BF%A1%60%0A%0A1.%20%E7%9B%B4%E6%8E%A5%E7%9A%84%E6%9C%8B%E5%8F%8B%EF%BC%9A%E6%AF%8F%E4%B8%AA%E5%AF%B9%E8%B1%A1%E9%83%BD%E4%BC%9A%E4%B8%8E%E5%85%B6%E4%BB%96%E5%AF%B9%E8%B1%A1%E6%9C%89%E8%80%A6%E5%90%88%E5%85%B3%E7%B3%BB%EF%BC%8C%E5%8F%AA%E8%A6%81%E4%B8%A4%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E6%9C%89%E8%80%A6%E5%90%88%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%88%91%E4%BB%AC%E5%B0%B1%E8%AF%B4%E8%BF%99%E4%B8%A4%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%0A%20%20%20%E6%98%AF%E6%9C%8B%E5%8F%8B%E5%85%B3%E7%B3%BB%E3%80%82%0A%0A2.%20%E8%80%A6%E5%90%88%E7%9A%84%E6%96%B9%E5%BC%8F%E5%BE%88%E5%A4%9A%EF%BC%8C%E4%BE%9D%E8%B5%96%EF%BC%8C%E5%85%B3%E8%81%94%EF%BC%8C%E7%BB%84%E5%90%88%EF%BC%8C%E8%81%9A%E5%90%88%E7%AD%89%E3%80%82%E5%85%B6%E4%B8%AD%EF%BC%8C%0A%0A3.%20%E6%88%91%E4%BB%AC%E7%A7%B0%E5%87%BA%E7%8E%B0%60%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%EF%BC%8C%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%EF%BC%8C%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%80%BC%60%20%E4%B8%AD%E7%9A%84%E7%B1%BB%E4%B8%BA%E7%9B%B4%E6%8E%A5%E7%9A%84%E6%9C%8B%E5%8F%8B%EF%BC%8C%0A%0A4.%20%E8%80%8C%E5%87%BA%E7%8E%B0%E5%9C%A8%60%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E4%B8%AD%E7%9A%84%E7%B1%BB%60%E6%98%AF%E9%99%8C%E7%94%9F%E6%9C%8B%E5%8F%8B%E3%80%82%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E9%99%8C%E7%94%9F%E7%9A%84%E7%B1%BB%E6%9C%80%E5%A5%BD%E4%B8%8D%E8%A6%81%E4%BB%A5%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E7%9A%84%E5%BD%A2%E5%BC%8F%E5%87%BA%E7%8E%B0%E5%9C%A8%E7%B1%BB%E7%9A%84%E5%86%85%E9%83%A8%E3%80%82%0A%0A%0A%0A%60%60%60java%0A%2F%2F%E5%AE%A2%E6%88%B7%E7%AB%AF%0Apublic%20class%20Demeter1%20%7B%0A%09public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09%09%2F%2F%E5%88%9B%E5%BB%BA%E4%BA%86%E4%B8%80%E4%B8%AA%20SchoolManager%20%E5%AF%B9%E8%B1%A1%0A%09%09SchoolManager%20schoolManager%20%3D%20new%20SchoolManager()%3B%0A%09%09%2F%2F%E8%BE%93%E5%87%BA%E5%AD%A6%E9%99%A2%E7%9A%84%E5%91%98%E5%B7%A5id%E5%92%8C%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E7%9A%84%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF%0A%09%09schoolManager.printAllEmployee(new%20CollegeManager())%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%91%98%E5%B7%A5%E7%B1%BB%0Aclass%20Employee%20%7B%0A%09private%20String%20id%3B%0A%0A%09public%20void%20setId(String%20id)%20%7B%0A%09%09this.id%20%3D%20id%3B%0A%09%7D%0A%0A%09public%20String%20getId()%20%7B%0A%09%09return%20id%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E5%AD%A6%E9%99%A2%E7%9A%84%E5%91%98%E5%B7%A5%E7%B1%BB%0Aclass%20CollegeEmployee%20%7B%0A%09private%20String%20id%3B%0A%0A%09public%20void%20setId(String%20id)%20%7B%0A%09%09this.id%20%3D%20id%3B%0A%09%7D%0A%0A%09public%20String%20getId()%20%7B%0A%09%09return%20id%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E7%AE%A1%E7%90%86%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5%E7%9A%84%E7%AE%A1%E7%90%86%E7%B1%BB%0Aclass%20CollegeManager%20%7B%0A%09%2F%2F%E8%BF%94%E5%9B%9E%E5%AD%A6%E9%99%A2%E7%9A%84%E6%89%80%E6%9C%89%E5%91%98%E5%B7%A5%0A%09public%20List%3CCollegeEmployee%3E%20getAllEmployee()%20%7B%0A%09%09List%3CCollegeEmployee%3E%20list%20%3D%20new%20ArrayList%3CCollegeEmployee%3E()%3B%0A%09%09for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%20%2F%2F%E8%BF%99%E9%87%8C%E6%88%91%E4%BB%AC%E5%A2%9E%E5%8A%A0%E4%BA%8610%E4%B8%AA%E5%91%98%E5%B7%A5%E5%88%B0%20list%0A%09%09%09CollegeEmployee%20emp%20%3D%20new%20CollegeEmployee()%3B%0A%09%09%09emp.setId(%22%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5id%3D%20%22%20%2B%20i)%3B%0A%09%09%09list.add(emp)%3B%0A%09%09%7D%0A%09%09return%20list%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E5%AD%A6%E6%A0%A1%E7%AE%A1%E7%90%86%E7%B1%BB%0A%2F%2F%E5%88%86%E6%9E%90%20SchoolManager%20%E7%B1%BB%E7%9A%84%E7%9B%B4%E6%8E%A5%E6%9C%8B%E5%8F%8B%E7%B1%BB%E6%9C%89%E5%93%AA%E4%BA%9B%20Employee%E3%80%81CollegeManager%0A%2F%2FCollegeEmployee%20%E4%B8%8D%E6%98%AF%20%E7%9B%B4%E6%8E%A5%E6%9C%8B%E5%8F%8B%20%E8%80%8C%E6%98%AF%E4%B8%80%E4%B8%AA%E9%99%8C%E7%94%9F%E7%B1%BB%EF%BC%8C%E8%BF%99%E6%A0%B7%E8%BF%9D%E8%83%8C%E4%BA%86%20%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%0Aclass%20SchoolManager%20%7B%0A%09%2F%2F%E8%BF%94%E5%9B%9E%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E7%9A%84%E5%91%98%E5%B7%A5%0A%09public%20List%3CEmployee%3E%20getAllEmployee()%20%7B%0A%09%09List%3CEmployee%3E%20list%20%3D%20new%20ArrayList%3CEmployee%3E()%3B%0A%0A%09%09for%20(int%20i%20%3D%200%3B%20i%20%3C%205%3B%20i%2B%2B)%20%7B%20%2F%2F%E8%BF%99%E9%87%8C%E6%88%91%E4%BB%AC%E5%A2%9E%E5%8A%A0%E4%BA%865%E4%B8%AA%E5%91%98%E5%B7%A5%E5%88%B0%20list%0A%09%09%09Employee%20emp%20%3D%20new%20Employee()%3B%0A%09%09%09emp.setId(%22%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%91%98%E5%B7%A5id%3D%20%22%20%2B%20i)%3B%0A%09%09%09list.add(emp)%3B%0A%09%09%7D%0A%09%09return%20list%3B%0A%09%7D%0A%0A%09%2F%2F%E8%AF%A5%E6%96%B9%E6%B3%95%E5%AE%8C%E6%88%90%E8%BE%93%E5%87%BA%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%92%8C%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF(id)%0A%09void%20printAllEmployee(CollegeManager%20sub)%20%7B%0A%0A%09%09%2F%2F%E5%88%86%E6%9E%90%E9%97%AE%E9%A2%98%0A%09%09%2F%2F1.%20%E8%BF%99%E9%87%8C%E7%9A%84%20CollegeEmployee%20%E4%B8%8D%E6%98%AF%20SchoolManager%E7%9A%84%E7%9B%B4%E6%8E%A5%E6%9C%8B%E5%8F%8B%0A%09%09%2F%2F2.%20CollegeEmployee%20%E6%98%AF%E4%BB%A5%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E6%96%B9%E5%BC%8F%E5%87%BA%E7%8E%B0%E5%9C%A8%20SchoolManager%0A%09%09%2F%2F3.%20%E8%BF%9D%E5%8F%8D%E4%BA%86%20%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%0A%0A%09%09%2F%2F%E8%8E%B7%E5%8F%96%E5%88%B0%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5%0A%09%09List%3CCollegeEmployee%3E%20list1%20%3D%20sub.getAllEmployee()%3B%0A%09%09System.out.println(%22------------%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5------------%22)%3B%0A%09%09for%20(CollegeEmployee%20e%20%3A%20list1)%20%7B%0A%09%09%09System.out.println(e.getId())%3B%0A%09%09%7D%0A%09%09%2F%2F%E8%8E%B7%E5%8F%96%E5%88%B0%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%91%98%E5%B7%A5%0A%09%09List%3CEmployee%3E%20list2%20%3D%20this.getAllEmployee()%3B%0A%09%09System.out.println(%22------------%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%91%98%E5%B7%A5------------%22)%3B%0A%09%09for%20(Employee%20e%20%3A%20list2)%20%7B%0A%09%09%09System.out.println(e.getId())%3B%0A%09%09%7D%0A%09%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%94%B9%E8%BF%9B%E5%90%8E%E6%96%B9%E6%B3%95%0A%0A%60%60%60java%0A%2F%2F%E5%AE%A2%E6%88%B7%E7%AB%AF%0Apublic%20class%20Demeter1%20%7B%0A%09public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09%09System.out.println(%22~~~%E4%BD%BF%E7%94%A8%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%E7%9A%84%E6%94%B9%E8%BF%9B~~~%22)%3B%0A%09%09%2F%2F%E5%88%9B%E5%BB%BA%E4%BA%86%E4%B8%80%E4%B8%AA%20SchoolManager%20%E5%AF%B9%E8%B1%A1%0A%09%09SchoolManager%20schoolManager%20%3D%20new%20SchoolManager()%3B%0A%09%09%2F%2F%E8%BE%93%E5%87%BA%E5%AD%A6%E9%99%A2%E7%9A%84%E5%91%98%E5%B7%A5id%20%E5%92%8C%20%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E7%9A%84%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF%0A%09%09schoolManager.printAllEmployee(new%20CollegeManager())%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%91%98%E5%B7%A5%E7%B1%BB%0Aclass%20Employee%20%7B%0A%09private%20String%20id%3B%0A%0A%09public%20void%20setId(String%20id)%20%7B%0A%09%09this.id%20%3D%20id%3B%0A%09%7D%0A%0A%09public%20String%20getId()%20%7B%0A%09%09return%20id%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E5%AD%A6%E9%99%A2%E7%9A%84%E5%91%98%E5%B7%A5%E7%B1%BB%0Aclass%20CollegeEmployee%20%7B%0A%09private%20String%20id%3B%0A%0A%09public%20void%20setId(String%20id)%20%7B%0A%09%09this.id%20%3D%20id%3B%0A%09%7D%0A%0A%09public%20String%20getId()%20%7B%0A%09%09return%20id%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E7%AE%A1%E7%90%86%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5%E7%9A%84%E7%AE%A1%E7%90%86%E7%B1%BB%0Aclass%20CollegeManager%20%7B%0A%09%2F%2F%E8%BF%94%E5%9B%9E%E5%AD%A6%E9%99%A2%E7%9A%84%E6%89%80%E6%9C%89%E5%91%98%E5%B7%A5%0A%09public%20List%3CCollegeEmployee%3E%20getAllEmployee()%20%7B%0A%09%09List%3CCollegeEmployee%3E%20list%20%3D%20new%20ArrayList%3CCollegeEmployee%3E()%3B%0A%09%09for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%20%2F%2F%E8%BF%99%E9%87%8C%E6%88%91%E4%BB%AC%E5%A2%9E%E5%8A%A0%E4%BA%8610%E4%B8%AA%E5%91%98%E5%B7%A5%E5%88%B0%20list%0A%09%09%09CollegeEmployee%20emp%20%3D%20new%20CollegeEmployee()%3B%0A%09%09%09emp.setId(%22%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5id%3D%20%22%20%2B%20i)%3B%0A%09%09%09list.add(emp)%3B%0A%09%09%7D%0A%09%09return%20list%3B%0A%09%7D%0A%0A%09%2F%2F%E8%BE%93%E5%87%BA%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5%E7%9A%84%E4%BF%A1%E6%81%AF%0A%09public%20void%20printEmployee()%20%7B%0A%09%09%2F%2F%E8%8E%B7%E5%8F%96%E5%88%B0%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5%0A%09%09List%3CCollegeEmployee%3E%20list1%20%3D%20getAllEmployee()%3B%0A%09%09System.out.println(%22------------%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5------------%22)%3B%0A%09%09for%20(CollegeEmployee%20e%20%3A%20list1)%20%7B%0A%09%09%09System.out.println(e.getId())%3B%0A%09%09%7D%0A%09%7D%0A%7D%0A%0A%2F%2F%E5%AD%A6%E6%A0%A1%E7%AE%A1%E7%90%86%E7%B1%BB%0A%0A%2F%2F%E5%88%86%E6%9E%90%20SchoolManager%20%E7%B1%BB%E7%9A%84%E7%9B%B4%E6%8E%A5%E6%9C%8B%E5%8F%8B%E7%B1%BB%E6%9C%89%E5%93%AA%E4%BA%9B%20Employee%E3%80%81CollegeManager%0A%2F%2FCollegeEmployee%20%E4%B8%8D%E6%98%AF%20%E7%9B%B4%E6%8E%A5%E6%9C%8B%E5%8F%8B%20%E8%80%8C%E6%98%AF%E4%B8%80%E4%B8%AA%E9%99%8C%E7%94%9F%E7%B1%BB%EF%BC%8C%E8%BF%99%E6%A0%B7%E8%BF%9D%E8%83%8C%E4%BA%86%20%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%0Aclass%20SchoolManager%20%7B%0A%09%2F%2F%E8%BF%94%E5%9B%9E%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E7%9A%84%E5%91%98%E5%B7%A5%0A%09public%20List%3CEmployee%3E%20getAllEmployee()%20%7B%0A%09%09List%3CEmployee%3E%20list%20%3D%20new%20ArrayList%3CEmployee%3E()%3B%0A%0A%09%09for%20(int%20i%20%3D%200%3B%20i%20%3C%205%3B%20i%2B%2B)%20%7B%20%2F%2F%E8%BF%99%E9%87%8C%E6%88%91%E4%BB%AC%E5%A2%9E%E5%8A%A0%E4%BA%865%E4%B8%AA%E5%91%98%E5%B7%A5%E5%88%B0%20list%0A%09%09%09Employee%20emp%20%3D%20new%20Employee()%3B%0A%09%09%09emp.setId(%22%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%91%98%E5%B7%A5id%3D%20%22%20%2B%20i)%3B%0A%09%09%09list.add(emp)%3B%0A%09%09%7D%0A%09%09return%20list%3B%0A%09%7D%0A%0A%09%2F%2F%E8%AF%A5%E6%96%B9%E6%B3%95%E5%AE%8C%E6%88%90%E8%BE%93%E5%87%BA%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%92%8C%E5%AD%A6%E9%99%A2%E5%91%98%E5%B7%A5%E4%BF%A1%E6%81%AF(id)%0A%09void%20printAllEmployee(CollegeManager%20sub)%20%7B%0A%0A%09%09%2F%2F%E5%88%86%E6%9E%90%E9%97%AE%E9%A2%98%0A%09%09%2F%2F1.%20%E5%B0%86%E8%BE%93%E5%87%BA%E5%AD%A6%E9%99%A2%E7%9A%84%E5%91%98%E5%B7%A5%E6%96%B9%E6%B3%95%EF%BC%8C%E5%B0%81%E8%A3%85%E5%88%B0CollegeManager%0A%09%09sub.printEmployee()%3B%0A%0A%09%09%2F%2F%E8%8E%B7%E5%8F%96%E5%88%B0%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%91%98%E5%B7%A5%0A%09%09List%3CEmployee%3E%20list2%20%3D%20this.getAllEmployee()%3B%0A%09%09System.out.println(%22------------%E5%AD%A6%E6%A0%A1%E6%80%BB%E9%83%A8%E5%91%98%E5%B7%A5------------%22)%3B%0A%09%09for%20(Employee%20e%20%3A%20list2)%20%7B%0A%09%09%09System.out.println(e.getId())%3B%0A%09%09%7D%0A%09%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%202.6.3%20%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9%E5%92%8C%E7%BB%86%E8%8A%82%0A%0A%3E%201.%20%20%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%E7%9A%84%E6%A0%B8%E5%BF%83%E6%98%AF%E9%99%8D%E4%BD%8E%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E8%80%A6%E5%90%88%0A%3E%202.%20%E4%BD%86%E6%98%AF%E6%B3%A8%E6%84%8F%EF%BC%9A%E7%94%B1%E4%BA%8E%E6%AF%8F%E4%B8%AA%E7%B1%BB%E9%83%BD%E5%87%8F%E5%B0%91%E4%BA%86%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E4%BE%9D%E8%B5%96%EF%BC%8C%E5%9B%A0%E6%AD%A4%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%E5%8F%AA%E6%98%AF%E8%A6%81%E6%B1%82%E9%99%8D%E4%BD%8E%E7%B1%BB%E9%97%B4(%E5%AF%B9%E8%B1%A1%E9%97%B4)%E8%80%A6%E5%90%88%E5%85%B3%E7%B3%BB%EF%BC%8C%20%E5%B9%B6%E4%B8%8D%E6%98%AF%0A%3E%20%20%20%20%E8%A6%81%E6%B1%82%E5%AE%8C%E5%85%A8%E6%B2%A1%E6%9C%89%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%2C%20%E5%9B%A0%E4%B8%BA%E7%BB%9D%E5%AF%B9%E4%B8%8D%E5%AD%98%E5%9C%A8%E8%80%A6%E5%90%88%E5%85%B3%E7%B3%BB%E7%B1%BB%E6%88%96%E5%AF%B9%E8%B1%A1%E6%98%AF%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%9A%84%E3%80%82%0A%0A%23%23%23%202.7%20%E5%90%88%E6%88%90%E5%A4%8D%E7%94%A8%E5%8E%9F%E5%88%99%0A%0A%3E%20%E5%8E%9F%E5%88%99%E6%98%AF%E5%B0%BD%E9%87%8F%E4%BD%BF%E7%94%A8%E5%90%88%E6%88%90%2F%E8%81%9A%E5%90%88%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%98%AF%E4%BD%BF%E7%94%A8%E7%BB%A7%E6%89%BF%0A%0A!%5B94a3484b050bb58fb1b44674bd1a91f5.png%5D(en-resource%3A%2F%2Fdatabase%2F1149%3A1)%0A%0A%0A%23%23%23%203%20%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%0A%0A%3E%20%E4%BE%9D%E8%B5%96%E3%80%81%E5%85%B3%E8%81%94%E3%80%81%E6%B3%9B%E5%8C%96%EF%BC%88%E7%BB%A7%E6%89%BF%EF%BC%89%E3%80%81%E5%AE%9E%E7%8E%B0%E3%80%81%E8%81%9A%E5%90%88%E4%B8%8E%E7%BB%84%E5%90%88%E3%80%82%0A%0A%23%23%23%23%203.1%20%E4%BE%9D%E8%B5%96%EF%BC%88Dependency%EF%BC%89%0A%3E%20%60%E4%BE%9D%E8%B5%96%EF%BC%88Dependency%EF%BC%89%60%E5%85%B3%E7%B3%BB%E6%98%AF%E4%B8%80%E7%A7%8D%60%E4%BD%BF%E7%94%A8%E5%85%B3%E7%B3%BB%60%EF%BC%8C%E5%AE%83%E6%98%AF%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E8%80%A6%E5%90%88%E5%BA%A6%E6%9C%80%E5%BC%B1%E7%9A%84%E4%B8%80%E7%A7%8D%E5%85%B3%E8%81%94%E6%96%B9%E5%BC%8F%EF%BC%8C%E6%98%AF%E4%B8%B4%E6%97%B6%E6%80%A7%E7%9A%84%E5%85%B3%E8%81%94%E3%80%82%0A%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E4%BD%BF%E7%94%A8%E5%B8%A6%E7%AE%AD%E5%A4%B4%E7%9A%84%E8%99%9A%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%AE%AD%E5%A4%B4%E4%BB%8E%E4%BD%BF%E7%94%A8%E7%B1%BB%E6%8C%87%E5%90%91%E8%A2%AB%E4%BE%9D%E8%B5%96%E7%9A%84%E7%B1%BB.%0A%0A!%5B4d10ac87b845539aeb5eba816a82951d.png%5D(en-resource%3A%2F%2Fdatabase%2F1154%3A1)%0A%0A%0A%23%23%23%23%203.2%20%E5%85%B3%E8%81%94%EF%BC%88Association%EF%BC%89%0A%3E%20%60%E5%85%B3%E8%81%94%EF%BC%88Association%EF%BC%89%60%E5%85%B3%E7%B3%BB%E6%98%AF%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E4%B8%80%E7%A7%8D%60%E5%BC%95%E7%94%A8%E5%85%B3%E7%B3%BB%60%EF%BC%8C%E7%94%A8%E4%BA%8E%E8%A1%A8%E7%A4%BA%E4%B8%80%E7%B1%BB%E5%AF%B9%E8%B1%A1%E4%B8%8E%E5%8F%A6%E4%B8%80%E7%B1%BB%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E8%81%94%E7%B3%BB%EF%BC%8C%E5%A6%82%E8%80%81%E5%B8%88%E5%92%8C%E5%AD%A6%E7%94%9F%E3%80%81%E5%B8%88%E5%82%85%E5%92%8C%E5%BE%92%E5%BC%9F%E3%80%81%E4%B8%88%E5%A4%AB%E5%92%8C%E5%A6%BB%E5%AD%90%E7%AD%89%E3%80%82%0A%3E%20%20%E5%85%B3%E8%81%94%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%8F%8C%E5%90%91%E7%9A%84%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%8D%95%E5%90%91%E7%9A%84%0A%0A%3E%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E5%8F%8C%E5%90%91%E7%9A%84%E5%85%B3%E8%81%94%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%B8%A6%E4%B8%A4%E4%B8%AA%E7%AE%AD%E5%A4%B4%E6%88%96%E8%80%85%E6%B2%A1%E6%9C%89%E7%AE%AD%E5%A4%B4%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E5%8D%95%E5%90%91%E7%9A%84%E5%85%B3%E8%81%94%E7%94%A8%E5%B8%A6%E4%B8%80%E4%B8%AA%E7%AE%AD%E5%A4%B4%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%AE%AD%E5%A4%B4%E4%BB%8E%E4%BD%BF%E7%94%A8%E7%B1%BB%E6%8C%87%E5%90%91%E8%A2%AB%E5%85%B3%E8%81%94%E7%9A%84%E7%B1%BB%E3%80%82%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%85%B3%E8%81%94%E7%BA%BF%E7%9A%84%E4%B8%A4%E7%AB%AF%E6%A0%87%E6%B3%A8%E8%A7%92%E8%89%B2%E5%90%8D%EF%BC%8C%E4%BB%A3%E8%A1%A8%E4%B8%A4%E7%A7%8D%E4%B8%8D%E5%90%8C%E7%9A%84%E8%A7%92%E8%89%B2%E3%80%82%0A%0A!%5B3280c2b2903c17ede1e9af43cb5306ea.png%5D(en-resource%3A%2F%2Fdatabase%2F1150%3A2)%0A%0A%23%23%23%23%203.3%20%E6%B3%9B%E5%8C%96%EF%BC%88Generalization%EF%BC%89%0A%3E%20%60%E6%B3%9B%E5%8C%96%EF%BC%88Generalization%EF%BC%89%60%E5%85%B3%E7%B3%BB%E6%98%AF%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E8%80%A6%E5%90%88%E5%BA%A6%E6%9C%80%E5%A4%A7%E7%9A%84%E4%B8%80%E7%A7%8D%E5%85%B3%E7%B3%BB%EF%BC%8C%E8%A1%A8%E7%A4%BA%E4%B8%80%E8%88%AC%E4%B8%8E%E7%89%B9%E6%AE%8A%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%E7%88%B6%E7%B1%BB%E4%B8%8E%E5%AD%90%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%E4%B8%80%E7%A7%8D%E7%BB%A7%E6%89%BF%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%20is-a%20%E7%9A%84%E5%85%B3%E7%B3%BB%E3%80%82%0A%0A%3E%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E6%B3%9B%E5%8C%96%E5%85%B3%E7%B3%BB%E7%94%A8%E5%B8%A6%E7%A9%BA%E5%BF%83%E4%B8%89%E8%A7%92%E7%AE%AD%E5%A4%B4%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%AE%AD%E5%A4%B4%E4%BB%8E%E5%AD%90%E7%B1%BB%E6%8C%87%E5%90%91%E7%88%B6%E7%B1%BB%E3%80%82%E5%9C%A8%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0%E6%97%B6%EF%BC%8C%E4%BD%BF%E7%94%A8%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%BB%A7%E6%89%BF%E6%9C%BA%E5%88%B6%E6%9D%A5%E5%AE%9E%E7%8E%B0%E6%B3%9B%E5%8C%96%E5%85%B3%E7%B3%BB%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%8CStudent%20%E7%B1%BB%E5%92%8C%20Teacher%20%E7%B1%BB%E9%83%BD%E6%98%AF%20Person%20%E7%B1%BB%E7%9A%84%E5%AD%90%E7%B1%BB.%0A%0A!%5B2182cebbf57e6e158153f587c4fb2501.png%5D(en-resource%3A%2F%2Fdatabase%2F1152%3A1)%0A%0A%23%23%23%23%203.4%20%E5%AE%9E%E7%8E%B0%EF%BC%88Realization%EF%BC%89%0A%3E%20%E5%AE%9E%E7%8E%B0%E5%85%B3%E7%B3%BB%E6%98%AF%E6%8E%A5%E5%8F%A3%E4%B8%8E%E5%AE%9E%E7%8E%B0%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%E3%80%82%E5%9C%A8%E8%BF%99%E7%A7%8D%E5%85%B3%E7%B3%BB%E4%B8%AD%EF%BC%8C%E7%B1%BB%E5%AE%9E%E7%8E%B0%E4%BA%86%E6%8E%A5%E5%8F%A3%EF%BC%8C%E7%B1%BB%E4%B8%AD%E7%9A%84%E6%93%8D%E4%BD%9C%E5%AE%9E%E7%8E%B0%E4%BA%86%E6%8E%A5%E5%8F%A3%E4%B8%AD%E6%89%80%E5%A3%B0%E6%98%8E%E7%9A%84%E6%89%80%E6%9C%89%E7%9A%84%E6%8A%BD%E8%B1%A1%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A!%5B1c1f1d52f6fc3250817e05628539c95d.png%5D(en-resource%3A%2F%2Fdatabase%2F1153%3A1)%0A%0A%23%23%23%23%203.5%20%E8%81%9A%E5%90%88%EF%BC%88Aggregation%EF%BC%89%0A%3E%20%60%E8%81%9A%E5%90%88%EF%BC%88Aggregation%EF%BC%89%60%E5%85%B3%E7%B3%BB%E6%98%AF%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%E7%9A%84%E4%B8%80%E7%A7%8D%EF%BC%8C%E6%98%AF%E5%BC%BA%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%E6%95%B4%E4%BD%93%E5%92%8C%E9%83%A8%E5%88%86%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%20has-a%20%E7%9A%84%E5%85%B3%E7%B3%BB%E3%80%82%0A%3E%20%0A%3E%20%E8%81%9A%E5%90%88%E5%85%B3%E7%B3%BB%E4%B9%9F%E6%98%AF%E9%80%9A%E8%BF%87%E6%88%90%E5%91%98%E5%AF%B9%E8%B1%A1%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8C%E5%85%B6%E4%B8%AD%E6%88%90%E5%91%98%E5%AF%B9%E8%B1%A1%E6%98%AF%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%EF%BC%8C%E4%BD%86%E6%98%AF%E6%88%90%E5%91%98%E5%AF%B9%E8%B1%A1%E5%8F%AF%E4%BB%A5%E8%84%B1%E7%A6%BB%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E8%80%8C%E7%8B%AC%E7%AB%8B%E5%AD%98%E5%9C%A8%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%8C%E5%AD%A6%E6%A0%A1%E4%B8%8E%E8%80%81%E5%B8%88%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E5%AD%A6%E6%A0%A1%E5%8C%85%E5%90%AB%E8%80%81%E5%B8%88%EF%BC%8C%E4%BD%86%E5%A6%82%E6%9E%9C%E5%AD%A6%E6%A0%A1%E5%81%9C%E5%8A%9E%E4%BA%86%EF%BC%8C%E8%80%81%E5%B8%88%E4%BE%9D%E7%84%B6%E5%AD%98%E5%9C%A8%E3%80%82%0A%3E%20%0A%3E%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E8%81%9A%E5%90%88%E5%85%B3%E7%B3%BB%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%B8%A6%E7%A9%BA%E5%BF%83%E8%8F%B1%E5%BD%A2%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E8%8F%B1%E5%BD%A2%E6%8C%87%E5%90%91%E6%95%B4%E4%BD%93%E3%80%82%0A%0A!%5B3280c2b2903c17ede1e9af43cb5306ea.png%5D(en-resource%3A%2F%2Fdatabase%2F1150%3A2)%0A%0A%23%23%23%23%203.6%20%E7%BB%84%E5%90%88%EF%BC%88Composition%EF%BC%89%0A%3E%20%60%E7%BB%84%E5%90%88%EF%BC%88Composition%EF%BC%89%60%E5%85%B3%E7%B3%BB%E4%B9%9F%E6%98%AF%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%E7%9A%84%E4%B8%80%E7%A7%8D%EF%BC%8C%E4%B9%9F%E8%A1%A8%E7%A4%BA%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E6%95%B4%E4%BD%93%E4%B8%8E%E9%83%A8%E5%88%86%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E4%BD%86%E5%AE%83%E6%98%AF%E4%B8%80%E7%A7%8D%E6%9B%B4%E5%BC%BA%E7%83%88%E7%9A%84%E8%81%9A%E5%90%88%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%20contains-a%20%E5%85%B3%E7%B3%BB%E3%80%82%0A%3E%20%0A%3E%20%E5%9C%A8%E7%BB%84%E5%90%88%E5%85%B3%E7%B3%BB%E4%B8%AD%EF%BC%8C%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E5%8F%AF%E4%BB%A5%E6%8E%A7%E5%88%B6%E9%83%A8%E5%88%86%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%EF%BC%8C%E4%B8%80%E6%97%A6%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%83%A8%E5%88%86%E5%AF%B9%E8%B1%A1%E4%B9%9F%E5%B0%86%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%83%A8%E5%88%86%E5%AF%B9%E8%B1%A1%E4%B8%8D%E8%83%BD%E8%84%B1%E7%A6%BB%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E8%80%8C%E5%AD%98%E5%9C%A8%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%8C%E5%A4%B4%E5%92%8C%E5%98%B4%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%B2%A1%E6%9C%89%E4%BA%86%E5%A4%B4%EF%BC%8C%E5%98%B4%E4%B9%9F%E5%B0%B1%E4%B8%8D%E5%AD%98%E5%9C%A8%E4%BA%86%E3%80%82%0A%3E%20%0A%3E%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E7%BB%84%E5%90%88%E5%85%B3%E7%B3%BB%E7%94%A8%E5%B8%A6%E5%AE%9E%E5%BF%83%E8%8F%B1%E5%BD%A2%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E8%8F%B1%E5%BD%A2%E6%8C%87%E5%90%91%E6%95%B4%E4%BD%93%E3%80%82%E5%9B%BE%207%20%E6%89%80%E7%A4%BA%E6%98%AF%E5%A4%B4%E5%92%8C%E5%98%B4%E7%9A%84%E5%85%B3%E7%B3%BB%E5%9B%BE%E3%80%82%0A%0A!%5Bf8cc1bd30ca382b4b237c490d6d92843.png%5D(en-resource%3A%2F%2Fdatabase%2F1151%3A1)

map

创建时间:2020/10/14 22:57
更新时间:2022/7/11 10:30
作者:Chris

Map

NameDescKeyValueSynchronized
HashMap根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度允许为null允许为null非同步
TreeMap能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器不允许为null允许为null非同步
Hashtable与HashMap类似不允许为null不允许为null支持线程同步
LinkedHashMap保存了记录的写入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先写入的允许为null允许为null非同步
WeakHashMap与HashMap类似允许为null允许为null非同步

WeakHashMap

  1. WeakHashMap 继承于AbstractMap,实现了Map接口。
    和HashMap一样,WeakHashMap 也是一个散列表,它存储的内容也是键值对(key-value)映射,而且键和值都可以是null。

  2. 不过WeakHashMap的键是“弱键”。
    在 WeakHashMap 中,当某个键不再正常使用时,会被从WeakHashMap中被自动移除。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。某个键被终止时,它对应的键值对也就从映射中有效地移除了。

  3. 这个“弱键”的原理呢?
    通过WeakReference和ReferenceQueue实现的。 WeakHashMap的key是“弱键”,即是WeakReference类型的;ReferenceQueue是一个队列,它会保存被GC回收的“弱键”。

  4. 和HashMap一样,WeakHashMap是不同步的。
    可以使用 Collections.synchronizedMap 方法来构造同步的 WeakHashMap

    线程安全问题

    WeakHashMap<String, String> weakHashMap=new WeakHashMap<String, String>(); 
    Map<String, String> intsmaze=Collections.synchronizedMap(weakHashMapintsmaze);
    

实现步骤是:

  1. 新建WeakHashMap,将“键值对”添加到WeakHashMap中。
    实际上,WeakHashMap是通过数组table保存Entry(键值对);每一个Entry实际上是一个单向链表,即Entry是键值对链表。
  2. 当某“弱键”不再被其它对象引用,并被GC回收时。在GC回收该“弱键”时,这个“弱键”也同时会被添加到ReferenceQueue(queue)队列中。
  3. 当下一次我们需要操作WeakHashMap时,会先同步table和queue。table中保存了全部的键值对,而queue中保存被GC回收的键值对;同步它们,就是删除table中被GC回收的键值对。
%23%23%23%23%20Map%0A%0A%7C%20Name%20%20%20%20%20%20%20%20%20%20%7C%20Desc%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Key%20%20%20%20%20%20%20%20%20%20%7C%20Value%20%20%20%20%20%20%20%20%7C%20Synchronized%20%7C%0A%7C%20-------------%20%7C%20------------------------------------------------------------%20%7C%20------------%20%7C%20------------%20%7C%20------------%20%7C%0A%7C%20HashMap%20%20%20%20%20%20%20%7C%20%E6%A0%B9%E6%8D%AE%E9%94%AE%E7%9A%84HashCode%E5%80%BC%E5%AD%98%E5%82%A8%E6%95%B0%E6%8D%AE%2C%E6%A0%B9%E6%8D%AE%E9%94%AE%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E8%8E%B7%E5%8F%96%E5%AE%83%E7%9A%84%E5%80%BC%EF%BC%8C%E5%85%B7%E6%9C%89%E5%BE%88%E5%BF%AB%E7%9A%84%E8%AE%BF%E9%97%AE%E9%80%9F%E5%BA%A6%20%7C%20%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%20%20%7C%20%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%20%20%7C%20%E9%9D%9E%E5%90%8C%E6%AD%A5%20%20%20%20%20%20%20%7C%0A%7C%20TreeMap%20%20%20%20%20%20%20%7C%20%E8%83%BD%E5%A4%9F%E6%8A%8A%E5%AE%83%E4%BF%9D%E5%AD%98%E7%9A%84%E8%AE%B0%E5%BD%95%E6%A0%B9%E6%8D%AE%E9%94%AE(key)%E6%8E%92%E5%BA%8F%2C%E9%BB%98%E8%AE%A4%E6%98%AF%E6%8C%89%E5%8D%87%E5%BA%8F%E6%8E%92%E5%BA%8F%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E6%8E%92%E5%BA%8F%E7%9A%84%E6%AF%94%E8%BE%83%E5%99%A8%20%7C%20%E4%B8%8D%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%7C%20%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%20%20%7C%20%E9%9D%9E%E5%90%8C%E6%AD%A5%20%20%20%20%20%20%20%7C%0A%7C%20Hashtable%20%20%20%20%20%7C%20%E4%B8%8EHashMap%E7%B1%BB%E4%BC%BC%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E4%B8%8D%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%7C%20%E4%B8%8D%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%7C%20%E6%94%AF%E6%8C%81%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%AD%A5%20%7C%0A%7C%20LinkedHashMap%20%7C%20%E4%BF%9D%E5%AD%98%E4%BA%86%E8%AE%B0%E5%BD%95%E7%9A%84%E5%86%99%E5%85%A5%E9%A1%BA%E5%BA%8F%EF%BC%8C%E5%9C%A8%E7%94%A8Iterator%E9%81%8D%E5%8E%86LinkedHashMap%E6%97%B6%EF%BC%8C%E5%85%88%E5%BE%97%E5%88%B0%E7%9A%84%E8%AE%B0%E5%BD%95%E8%82%AF%E5%AE%9A%E6%98%AF%E5%85%88%E5%86%99%E5%85%A5%E7%9A%84%20%7C%20%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%20%20%7C%20%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%20%20%7C%20%E9%9D%9E%E5%90%8C%E6%AD%A5%20%20%20%20%20%20%20%7C%0A%7C%20WeakHashMap%20%20%20%7C%20%E4%B8%8EHashMap%E7%B1%BB%E4%BC%BC%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%20%20%7C%20%E5%85%81%E8%AE%B8%E4%B8%BAnull%20%20%20%7C%20%E9%9D%9E%E5%90%8C%E6%AD%A5%20%20%20%20%20%20%20%7C%0A%0A%0A%0A%23%23%23%23%20WeakHashMap%0A1.%20WeakHashMap%20%E7%BB%A7%E6%89%BF%E4%BA%8EAbstractMap%EF%BC%8C%E5%AE%9E%E7%8E%B0%E4%BA%86Map%E6%8E%A5%E5%8F%A3%E3%80%82%0A%E5%92%8CHashMap%E4%B8%80%E6%A0%B7%EF%BC%8CWeakHashMap%20%E4%B9%9F%E6%98%AF%E4%B8%80%E4%B8%AA%E6%95%A3%E5%88%97%E8%A1%A8%EF%BC%8C%E5%AE%83%E5%AD%98%E5%82%A8%E7%9A%84%E5%86%85%E5%AE%B9%E4%B9%9F%E6%98%AF%E9%94%AE%E5%80%BC%E5%AF%B9(key-value)%E6%98%A0%E5%B0%84%EF%BC%8C%E8%80%8C%E4%B8%94%E9%94%AE%E5%92%8C%E5%80%BC%E9%83%BD%E5%8F%AF%E4%BB%A5%E6%98%AFnull%E3%80%82%0A%0A2.%20%E4%B8%8D%E8%BF%87WeakHashMap%E7%9A%84%E9%94%AE%E6%98%AF%E2%80%9C%E5%BC%B1%E9%94%AE%E2%80%9D%E3%80%82%0A%E5%9C%A8%20WeakHashMap%20%E4%B8%AD%EF%BC%8C%E5%BD%93%E6%9F%90%E4%B8%AA%E9%94%AE%E4%B8%8D%E5%86%8D%E6%AD%A3%E5%B8%B8%E4%BD%BF%E7%94%A8%E6%97%B6%EF%BC%8C%E4%BC%9A%E8%A2%AB%E4%BB%8EWeakHashMap%E4%B8%AD%E8%A2%AB%E8%87%AA%E5%8A%A8%E7%A7%BB%E9%99%A4%E3%80%82%E6%9B%B4%E7%B2%BE%E7%A1%AE%E5%9C%B0%E8%AF%B4%EF%BC%8C%E5%AF%B9%E4%BA%8E%E4%B8%80%E4%B8%AA%E7%BB%99%E5%AE%9A%E7%9A%84%E9%94%AE%EF%BC%8C%E5%85%B6%E6%98%A0%E5%B0%84%E7%9A%84%E5%AD%98%E5%9C%A8%E5%B9%B6%E4%B8%8D%E9%98%BB%E6%AD%A2%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E5%99%A8%E5%AF%B9%E8%AF%A5%E9%94%AE%E7%9A%84%E4%B8%A2%E5%BC%83%EF%BC%8C%E8%BF%99%E5%B0%B1%E4%BD%BF%E8%AF%A5%E9%94%AE%E6%88%90%E4%B8%BA%E5%8F%AF%E7%BB%88%E6%AD%A2%E7%9A%84%EF%BC%8C%E8%A2%AB%E7%BB%88%E6%AD%A2%EF%BC%8C%E7%84%B6%E5%90%8E%E8%A2%AB%E5%9B%9E%E6%94%B6%E3%80%82%E6%9F%90%E4%B8%AA%E9%94%AE%E8%A2%AB%E7%BB%88%E6%AD%A2%E6%97%B6%EF%BC%8C%E5%AE%83%E5%AF%B9%E5%BA%94%E7%9A%84%E9%94%AE%E5%80%BC%E5%AF%B9%E4%B9%9F%E5%B0%B1%E4%BB%8E%E6%98%A0%E5%B0%84%E4%B8%AD%E6%9C%89%E6%95%88%E5%9C%B0%E7%A7%BB%E9%99%A4%E4%BA%86%E3%80%82%0A%C2%A0%20%C2%A0%20%0A3.%20%20%E8%BF%99%E4%B8%AA%E2%80%9C%E5%BC%B1%E9%94%AE%E2%80%9D%E7%9A%84%E5%8E%9F%E7%90%86%E5%91%A2%EF%BC%9F%0A%20%E9%80%9A%E8%BF%87WeakReference%E5%92%8CReferenceQueue%E5%AE%9E%E7%8E%B0%E7%9A%84%E3%80%82%20WeakHashMap%E7%9A%84key%E6%98%AF%E2%80%9C%E5%BC%B1%E9%94%AE%E2%80%9D%EF%BC%8C%E5%8D%B3%E6%98%AFWeakReference%E7%B1%BB%E5%9E%8B%E7%9A%84%EF%BC%9BReferenceQueue%E6%98%AF%E4%B8%80%E4%B8%AA%E9%98%9F%E5%88%97%EF%BC%8C%E5%AE%83%E4%BC%9A%E4%BF%9D%E5%AD%98%E8%A2%ABGC%E5%9B%9E%E6%94%B6%E7%9A%84%E2%80%9C%E5%BC%B1%E9%94%AE%E2%80%9D%E3%80%82%0A4.%20%E5%92%8CHashMap%E4%B8%80%E6%A0%B7%EF%BC%8CWeakHashMap%E6%98%AF%E4%B8%8D%E5%90%8C%E6%AD%A5%E7%9A%84%E3%80%82%0A%20%20%20%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20Collections.synchronizedMap%20%E6%96%B9%E6%B3%95%E6%9D%A5%E6%9E%84%E9%80%A0%E5%90%8C%E6%AD%A5%E7%9A%84%20WeakHashMap%0A%20%20%20%0A%20%20%20%20%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98%0A%20%20%20%20%60%60%60%0A%20%20%20%20WeakHashMap%3CString%2C%20String%3E%20weakHashMap%3Dnew%20WeakHashMap%3CString%2C%20String%3E()%3B%20%0A%20%20%20%20Map%3CString%2C%20String%3E%20intsmaze%3DCollections.synchronizedMap(weakHashMapintsmaze)%3B%0A%20%20%20%20%60%60%60%0A%0A%E5%AE%9E%E7%8E%B0%E6%AD%A5%E9%AA%A4%E6%98%AF%EF%BC%9A%0A1.%20%20%E6%96%B0%E5%BB%BAWeakHashMap%EF%BC%8C%E5%B0%86%E2%80%9C%E9%94%AE%E5%80%BC%E5%AF%B9%E2%80%9D%E6%B7%BB%E5%8A%A0%E5%88%B0WeakHashMap%E4%B8%AD%E3%80%82%0A%20%20%20%20%20%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8CWeakHashMap%E6%98%AF%E9%80%9A%E8%BF%87%E6%95%B0%E7%BB%84table%E4%BF%9D%E5%AD%98Entry(%E9%94%AE%E5%80%BC%E5%AF%B9)%EF%BC%9B%E6%AF%8F%E4%B8%80%E4%B8%AAEntry%E5%AE%9E%E9%99%85%E4%B8%8A%E6%98%AF%E4%B8%80%E4%B8%AA%E5%8D%95%E5%90%91%E9%93%BE%E8%A1%A8%EF%BC%8C%E5%8D%B3Entry%E6%98%AF%E9%94%AE%E5%80%BC%E5%AF%B9%E9%93%BE%E8%A1%A8%E3%80%82%0A2.%20%20%E5%BD%93%E6%9F%90%E2%80%9C%E5%BC%B1%E9%94%AE%E2%80%9D%E4%B8%8D%E5%86%8D%E8%A2%AB%E5%85%B6%E5%AE%83%E5%AF%B9%E8%B1%A1%E5%BC%95%E7%94%A8%EF%BC%8C%E5%B9%B6%E8%A2%ABGC%E5%9B%9E%E6%94%B6%E6%97%B6%E3%80%82%E5%9C%A8GC%E5%9B%9E%E6%94%B6%E8%AF%A5%E2%80%9C%E5%BC%B1%E9%94%AE%E2%80%9D%E6%97%B6%EF%BC%8C%E8%BF%99%E4%B8%AA%E2%80%9C%E5%BC%B1%E9%94%AE%E2%80%9D%E4%B9%9F%E5%90%8C%E6%97%B6%E4%BC%9A%E8%A2%AB%E6%B7%BB%E5%8A%A0%E5%88%B0ReferenceQueue(queue)%E9%98%9F%E5%88%97%E4%B8%AD%E3%80%82%0A3.%20%E5%BD%93%E4%B8%8B%E4%B8%80%E6%AC%A1%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E6%93%8D%E4%BD%9CWeakHashMap%E6%97%B6%EF%BC%8C%E4%BC%9A%E5%85%88%E5%90%8C%E6%AD%A5table%E5%92%8Cqueue%E3%80%82table%E4%B8%AD%E4%BF%9D%E5%AD%98%E4%BA%86%E5%85%A8%E9%83%A8%E7%9A%84%E9%94%AE%E5%80%BC%E5%AF%B9%EF%BC%8C%E8%80%8Cqueue%E4%B8%AD%E4%BF%9D%E5%AD%98%E8%A2%ABGC%E5%9B%9E%E6%94%B6%E7%9A%84%E9%94%AE%E5%80%BC%E5%AF%B9%EF%BC%9B%E5%90%8C%E6%AD%A5%E5%AE%83%E4%BB%AC%EF%BC%8C%E5%B0%B1%E6%98%AF%E5%88%A0%E9%99%A4table%E4%B8%AD%E8%A2%ABGC%E5%9B%9E%E6%94%B6%E7%9A%84%E9%94%AE%E5%80%BC%E5%AF%B9%E3%80%82%0A%C2%A0%0A%0A%0A

Jrebel安装

创建时间:2022/7/8 10:09
更新时间:2022/7/8 10:11
作者:Chris

激活网站
http://www.cicoding.cn/other/jrebel-activation/

%0A!%5Ba0056bc09eee25646b1058e644ad1279.png%5D(en-resource%3A%2F%2Fdatabase%2F1834%3A1)%0A%0A%0A%3E%20%E6%BF%80%E6%B4%BB%E7%BD%91%E7%AB%99%0Ahttp%3A%2F%2Fwww.cicoding.cn%2Fother%2Fjrebel-activation%2F%0A%0A!%5Bd0be31ec478049766ee4d0cbdad5b78e.png%5D(en-resource%3A%2F%2Fdatabase%2F1836%3A1)%0A

CompletableFuture

创建时间:2021/12/23 22:17
更新时间:2022/7/7 11:15
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503491&idx=2&sn=12f5f4a67aad19a080d05df98d013ebc&chksm=fd63de3cca14572a21a560a3ae093f43e07a506f525ad33676592d58a9313ca50edc606b21ef&scene=21&key=601a5ac03618354f2dcc19fbb4c7beee76ba85fbab99b2d18e375d9cf2800a79923bc478e1152582651dd733dfc1a568cd41e6a1a8ff807be5423d4670f492bd707031bb639aebb0485ab7c4448e93b2f78ea360283e2206ee4a3a1f03de31251719ed92a9995927b7f4a3da12b2b24a5607c59207de174d00ddc4d7a88d6d09&ascene=0&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=63040026&lang=zh_CN&exportkey=ATLc0wnc6yYrpT96URwSIo0%3D&pass_ticket=o7%2F8p1PSOO%2BtRsKPjs3sz7l5tAR5yd9LgwTkgOPaP4222NMyyAvezKo6QoKIkYw2&wx_header=0&fontgear=2

1. CompletableFuture概述

1.1 Future缺点

Future虽然可以实现获取异步执行结果的需求,但是它没有提供通知的机制,我们无法得知Future什么时候完成。

  1. 要么使用阻塞,在 future.get() 的地方等待future返回的结果,这时又变成同步操作。
  2. 要么使用 isDone() 轮询地判断Future是否完成,这样会耗费CPU的资源。
1.2 CompletableFutre概述

CompletableFuture能够将回调放到与任务不同的线程中执行,也能将回调作为继续执行的同步函数,在与任务相同的线程中执行。它避免了传统回调最大的问题,那就是能够将控制流分离到不同的事件处理器中。

CompletableFuture弥补了Future模式的缺点。在异步的任务完成后,需要用其结果继续操作时,无需等待。可以直接通过thenAccept、thenApply、thenCompose等方式将前面异步处理的结果交给另外一个异步事件处理线程来处理。

2. 四种任务类型

Runnable
Consumer
Supplier
Function

runAsync 与 supplierAsync 是 CompletableFutre 的静态方法;
thenAccept、thenAsync、thenApply 是 CompletableFutre 的成员方法
因为初始的时候没有 CompletableFuture 对象,也没有参数可传,所以提交的只能是 Runnable 或者 Supplier,只能是静态方法;
通过静态方法生成 CompletableFuture 对象之后,便可以链式地提交其他任务了,这个时候就可以提交 Runnable、Consumer、Function且都是成员方法

3. CompletableFutre的静态方法

3.1 runAsync

CompletableFuture实现了Future接口,所以它也具有Future的特性:调用 get()方法会阻塞在那,直到结果返回。

@SneakyThrows
@Test
public void asyn1() {
    CompletableFuture<String> cf = new CompletableFuture<>();

    //complete方法完成该Future,否则在调用cf.get()阻塞主线程,等待返回结果
    cf.complete("hello future!");

    //调用者阻塞,等待返回结果
    String s = cf.get();
    System.out.println(s);
}
3.2 runAsync 无返回值

通过静态方法生成 CompletableFuture 对象之后,便可以链式地提交其他任务了

@SneakyThrows
@Test
public void runAsync() {
    CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
        try {
            System.out.println("task is running!");
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).thenRun(() -> System.out.println("call back method after getting result!"));

    //主线程阻塞,等待任务执行完成
    cf.get();
}
3.3 supplierAsync 有返回值
@SneakyThrows
@Test
public void supplyAsync() {
    CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "task has done!";
    }).thenApplyAsync(s -> s + ", call back method after getting result!");

    //主线程阻塞,等待任务执行完成
    String s = cf.get();
    System.out.println(s);
}

4. CompletableFutre的成员方法

4.1 thenRun、thenAccept、thenApply

thenRun 后面跟的是一个无参数、无返回值的方法,即 Runnable.
thenAccept 后面跟的是一个有参数、无返回值的方法,称为 Consumer.
thenApply 后面跟的是一个有参数、有返回值的方法,称为 Function.

 thenApplyAsync与thenApply的区别在于
 前者是将job2提交到线程池中异步执行,实际执行job2的线程可能是另外一个线程
 后者是由执行job1的线程立即执行job2,即两个job都是同一个线程执行的
4.2 exceptionally

指定某个任务执行异常时执行的回调方法,会将抛出异常作为参数传递到回调方法中
如果该任务正常执行会 exceptionally方法返回的CompletionStage的result就是该任务正常执行的结果

@SneakyThrows
@Test
public void testExceptionally() {
    CompletableFuture<Double> cf = CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread() + "job1 start, time->" + System.currentTimeMillis());
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //正常结果需要改为false
        if (true) {
            System.out.println("throw exception!");
            throw new RuntimeException("test exceptionally");
        }
        return 1.1;
    });

    CompletableFuture<Double> cf2 = cf.exceptionally((exception) -> {
        System.out.println(Thread.currentThread() + " start, time->" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("error stack trace->");
        exception.printStackTrace();
        System.out.println(Thread.currentThread() + " exit, time->" + System.currentTimeMillis());
        return 1.2;
    });
    System.out.println(cf2.get());
}

正常结果

Thread[ForkJoinPool.commonPool-worker-1,5,main]job1 start, time->1657161758634
1.1

异常结果

Thread[ForkJoinPool.commonPool-worker-1,5,main]job1 start, time->1657161554581
throw exception!
Thread[ForkJoinPool.commonPool-worker-1,5,main] start, time->1657161559581
error stack trace->
java.util.concurrent.CompletionException: java.lang.RuntimeException: test exceptionally
	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1592)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java)
	at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
	at java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.RuntimeException: test exceptionally
Thread[ForkJoinPool.commonPool-worker-1,5,main] exit, time->1657161561583
	at com.thread.future.async.CompletableFutureSourceCode.lambda$testExceptionally$7(CompletableFutureSourceCode.java:139)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1590)
	... 7 more
1.2
4.3 whenComplete

当某个任务执行完成后执行的回调方法,会将执行结果或者执行期间抛出的异常传递给回调方法,
如果是正常执行则异常为null,回调方法对应的CompletableFuture的result和该任务一致,如果该任务正常执行,
则get方法返回执行结果,如果是执行异常,则get方法抛出异常

@SneakyThrows
@Test
public void testWhenComplete() {
    CompletableFuture<Double> cf = CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread() + "job1 start, time->" + System.currentTimeMillis());
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //正常结果需要改为false
        if (true) {
            System.out.println("throw exception!");
            throw new RuntimeException("test exceptionally");
        }
        return 1.1;
    });

    CompletableFuture<Double> cf2 = cf.whenComplete((result, exception) -> {
        System.out.println(Thread.currentThread() + " start, time->" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("error stack trace->");
        if (Objects.nonNull(exception)) {
            exception.printStackTrace();
        }
        System.out.println(Thread.currentThread() + " exit, time->" + System.currentTimeMillis());
        System.out.println("result:" + result);
    });
    System.out.println(cf2.get());
}

正常结果

Thread[ForkJoinPool.commonPool-worker-1,5,main]job1 start, time->1657162560549
Thread[ForkJoinPool.commonPool-worker-1,5,main] start, time->1657162565550
error stack trace->
Thread[ForkJoinPool.commonPool-worker-1,5,main] exit, time->1657162567550
result:1.1
1.1

异常结果

Thread[ForkJoinPool.commonPool-worker-1,5,main]job1 start, time->1657162369911
throw exception!
Thread[ForkJoinPool.commonPool-worker-1,5,main] start, time->1657162374911
error stack trace->
java.util.concurrent.CompletionException: java.lang.RuntimeException: test exceptionally
	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1592)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java)
	at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
	at java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.RuntimeException: test exceptionally
	at com.thread.future.async.CompletableFutureSourceCode.lambda$testWhenComplete$9(CompletableFutureSourceCode.java:176)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1590)
	... 7 more
Thread[ForkJoinPool.commonPool-worker-1,5,main] exit, time->1657162376913
result:null
4.4 handle

跟whenComplete基本一致,区别在于handle的回调方法有返回值,
handle方法返回的CompletableFuture的result是回调方法的执行结果或者回调方法执行期间抛出的异常,与原始CompletableFuture的result无关了

@SneakyThrows
@Test
public void testHandle() {
    CompletableFuture<Double> cf = CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread() + "job1 start, time->" + System.currentTimeMillis());
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (true) {
            System.out.println("throw exception!");
            throw new RuntimeException("test exceptionally");
        }
        return 1.1;
    });

    CompletableFuture<String> handle = cf.handle((result, exception) -> {
        System.out.println(Thread.currentThread() + " start, time->" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("error stack trace->");
        if (Objects.nonNull(exception)) {
            exception.printStackTrace();
        }
        System.out.println(Thread.currentThread() + " exit, time->" + System.currentTimeMillis());
        if (Objects.isNull(exception)) {
            return "run success";
        } else {
            return "run error";
        }
    });
    System.out.println(handle.get());
}

正常结果

Thread[ForkJoinPool.commonPool-worker-1,5,main]job1 start, time->1657163319080
Thread[ForkJoinPool.commonPool-worker-1,5,main] start, time->1657163324081
error stack trace->
Thread[ForkJoinPool.commonPool-worker-1,5,main] exit, time->1657163326081
run success

异常结果

Thread[ForkJoinPool.commonPool-worker-1,5,main]job1 start, time->1657163045499
throw exception!
Thread[ForkJoinPool.commonPool-worker-1,5,main] start, time->1657163050500
error stack trace->
java.util.concurrent.CompletionException: java.lang.RuntimeException: test exceptionally
	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1592)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java)
	at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
	at java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
Thread[ForkJoinPool.commonPool-worker-1,5,main] exit, time->1657163052502
run success
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.RuntimeException: test exceptionally
	at com.thread.future.async.CompletableFutureSourceCode.lambda$testHandle$11(CompletableFutureSourceCode.java:215)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1590)
	... 7 more

5. 获取结果

同步获取结果

public T get()
public T get(long timeout, TimeUnit unit) 
public T getNow(T valueIfAbsent) //结果已经计算完则返回结果或者抛出异常,否则返回给定的valueIfAbsent值。
public T join() 

join()与get()区别在于join()返回计算的结果或者抛出一个unchecked异常(CompletionException),而get()返回一个具体的异常.

6. 主动结束

future.get()在等待执行结果时,程序会一直block,如果此时调用complete(T t)会立即执行。

complete(T t)                       完成异步操作,并返回future的结果
completeExceptionally(Throwable ex) 异步执行不正常的结束

future调用complete(T t)会立即执行。但是complete(T t)只能调用一次,后续的重复调用会失效。
如果future已经执行完毕能够返回结果,此时再调用complete(T t)则会无效。

@Slf4j
public class CompleableFutrueTest {

    @Test
    public void allOfTest() {
        List<CompletableFuture<String>> cfList = CollUtil.newArrayList();
        for (int i = 0; i < 10; i++) {
            CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
                String result = null;
                try {
                    String threadName = Thread.currentThread().getName();
                    System.out.println(threadName + " begin sleep");
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(threadName + " end sleep");
                    result = doSomething(threadName);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return result;
            });

            cfList.add(cf);
        }

        CompletableFuture<Void> allCF = CompletableFuture.allOf(cfList.toArray(new CompletableFuture[0]));

        try {
            allCF.get();

            CompletableFuture<List<String>> resultCF = allCF.thenApply(v -> cfList.stream().map(cf -> {
                try {
                    return cf.get();
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
                return null;
            }).collect(Collectors.toList()));

            List<String> result = resultCF.get();
            System.out.println(result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    public String doSomething(String jobNumber) {
        if (StrUtil.equals(jobNumber, "ForkJoinPool.commonPool-worker-2")) {
            throw new RuntimeException("ForkJoinPool.commonPool-worker-2 is exception");
        } else {
            for (int i = 0; i < 10; i++) {
                System.out.println(jobNumber + " is outputing:" + i);
            }
        }
        return jobNumber + " is done!";
    }
}
%5Btoc%5D%0A%23%23%23%23%201.%20CompletableFuture%E6%A6%82%E8%BF%B0%0A%23%23%23%23%23%201.1%20Future%E7%BC%BA%E7%82%B9%0A%3E%20Future%E8%99%BD%E7%84%B6%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%E8%8E%B7%E5%8F%96%E5%BC%82%E6%AD%A5%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%E7%9A%84%E9%9C%80%E6%B1%82%EF%BC%8C%E4%BD%86%E6%98%AF%E5%AE%83%E6%B2%A1%E6%9C%89%E6%8F%90%E4%BE%9B%E9%80%9A%E7%9F%A5%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E6%88%91%E4%BB%AC%E6%97%A0%E6%B3%95%E5%BE%97%E7%9F%A5Future%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E5%AE%8C%E6%88%90%E3%80%82%20%20%0A%0A%3E%201.%20%E8%A6%81%E4%B9%88%E4%BD%BF%E7%94%A8%E9%98%BB%E5%A1%9E%EF%BC%8C%E5%9C%A8%20%60future.get()%60%20%E7%9A%84%E5%9C%B0%E6%96%B9%E7%AD%89%E5%BE%85future%E8%BF%94%E5%9B%9E%E7%9A%84%E7%BB%93%E6%9E%9C%EF%BC%8C%E8%BF%99%E6%97%B6%E5%8F%88%E5%8F%98%E6%88%90%E5%90%8C%E6%AD%A5%E6%93%8D%E4%BD%9C%E3%80%82%20%20%20%0A%3E%202.%20%E8%A6%81%E4%B9%88%E4%BD%BF%E7%94%A8%20%60isDone()%60%20%E8%BD%AE%E8%AF%A2%E5%9C%B0%E5%88%A4%E6%96%ADFuture%E6%98%AF%E5%90%A6%E5%AE%8C%E6%88%90%EF%BC%8C%E8%BF%99%E6%A0%B7%E4%BC%9A%E8%80%97%E8%B4%B9CPU%E7%9A%84%E8%B5%84%E6%BA%90%E3%80%82%0A%0A%23%23%23%23%23%201.2%20CompletableFutre%E6%A6%82%E8%BF%B0%0A%3E%20CompletableFuture%E8%83%BD%E5%A4%9F%E5%B0%86%E5%9B%9E%E8%B0%83%E6%94%BE%E5%88%B0%E4%B8%8E%E4%BB%BB%E5%8A%A1%E4%B8%8D%E5%90%8C%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%B8%AD%E6%89%A7%E8%A1%8C%EF%BC%8C%E4%B9%9F%E8%83%BD%E5%B0%86%E5%9B%9E%E8%B0%83%E4%BD%9C%E4%B8%BA%E7%BB%A7%E7%BB%AD%E6%89%A7%E8%A1%8C%E7%9A%84%E5%90%8C%E6%AD%A5%E5%87%BD%E6%95%B0%EF%BC%8C%E5%9C%A8%E4%B8%8E%E4%BB%BB%E5%8A%A1%E7%9B%B8%E5%90%8C%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%B8%AD%E6%89%A7%E8%A1%8C%E3%80%82%E5%AE%83%E9%81%BF%E5%85%8D%E4%BA%86%E4%BC%A0%E7%BB%9F%E5%9B%9E%E8%B0%83%E6%9C%80%E5%A4%A7%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E9%82%A3%E5%B0%B1%E6%98%AF%E8%83%BD%E5%A4%9F%E5%B0%86%E6%8E%A7%E5%88%B6%E6%B5%81%E5%88%86%E7%A6%BB%E5%88%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%E5%99%A8%E4%B8%AD%E3%80%82%20%20%0A%0A%3E%20CompletableFuture%E5%BC%A5%E8%A1%A5%E4%BA%86Future%E6%A8%A1%E5%BC%8F%E7%9A%84%E7%BC%BA%E7%82%B9%E3%80%82%E5%9C%A8%E5%BC%82%E6%AD%A5%E7%9A%84%E4%BB%BB%E5%8A%A1%E5%AE%8C%E6%88%90%E5%90%8E%EF%BC%8C%E9%9C%80%E8%A6%81%E7%94%A8%E5%85%B6%E7%BB%93%E6%9E%9C%E7%BB%A7%E7%BB%AD%E6%93%8D%E4%BD%9C%E6%97%B6%EF%BC%8C%E6%97%A0%E9%9C%80%E7%AD%89%E5%BE%85%E3%80%82%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E9%80%9A%E8%BF%87thenAccept%E3%80%81thenApply%E3%80%81thenCompose%E7%AD%89%E6%96%B9%E5%BC%8F%E5%B0%86%E5%89%8D%E9%9D%A2%E5%BC%82%E6%AD%A5%E5%A4%84%E7%90%86%E7%9A%84%E7%BB%93%E6%9E%9C%E4%BA%A4%E7%BB%99%E5%8F%A6%E5%A4%96%E4%B8%80%E4%B8%AA%E5%BC%82%E6%AD%A5%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%E7%BA%BF%E7%A8%8B%E6%9D%A5%E5%A4%84%E7%90%86%E3%80%82%0A%0A%0A%23%23%23%23%202.%20%E5%9B%9B%E7%A7%8D%E4%BB%BB%E5%8A%A1%E7%B1%BB%E5%9E%8B%0A!%5Bc0b00587481513be05a8f651efd0e8e9.png%5D(en-resource%3A%2F%2Fdatabase%2F814%3A1)%0A%0A%3E%20Runnable%20%20%0A%3E%20Consumer%20%20%0A%3E%20Supplier%20%20%0A%3E%20Function%20%20%0A%0A%3E%20%60runAsync%20%E4%B8%8E%20supplierAsync%60%20%E6%98%AF%20CompletableFutre%20%E7%9A%84%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%EF%BC%9B%0A%E8%80%8C%20%60thenAccept%E3%80%81thenAsync%E3%80%81thenApply%60%20%E6%98%AF%20CompletableFutre%20%E7%9A%84%E6%88%90%E5%91%98%E6%96%B9%E6%B3%95%20%0A%E5%9B%A0%E4%B8%BA%E5%88%9D%E5%A7%8B%E7%9A%84%E6%97%B6%E5%80%99%E6%B2%A1%E6%9C%89%20CompletableFuture%20%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%B9%9F%E6%B2%A1%E6%9C%89%E5%8F%82%E6%95%B0%E5%8F%AF%E4%BC%A0%EF%BC%8C%E6%89%80%E4%BB%A5%E6%8F%90%E4%BA%A4%E7%9A%84%E5%8F%AA%E8%83%BD%E6%98%AF%20Runnable%20%E6%88%96%E8%80%85%20Supplier%EF%BC%8C%E5%8F%AA%E8%83%BD%E6%98%AF%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%EF%BC%9B%0A%E9%80%9A%E8%BF%87%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%E7%94%9F%E6%88%90%20CompletableFuture%20%E5%AF%B9%E8%B1%A1%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%BE%BF%E5%8F%AF%E4%BB%A5%E9%93%BE%E5%BC%8F%E5%9C%B0%E6%8F%90%E4%BA%A4%E5%85%B6%E4%BB%96%E4%BB%BB%E5%8A%A1%E4%BA%86%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%97%B6%E5%80%99%E5%B0%B1%E5%8F%AF%E4%BB%A5%E6%8F%90%E4%BA%A4%20Runnable%E3%80%81Consumer%E3%80%81Function%E4%B8%94%E9%83%BD%E6%98%AF%E6%88%90%E5%91%98%E6%96%B9%E6%B3%95%0A%0A%0A%0A%23%23%23%23%203.%20CompletableFutre%E7%9A%84%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%0A%23%23%23%23%23%203.1%20runAsync%0A%3E%20CompletableFuture%E5%AE%9E%E7%8E%B0%E4%BA%86Future%E6%8E%A5%E5%8F%A3%EF%BC%8C%E6%89%80%E4%BB%A5%E5%AE%83%E4%B9%9F%E5%85%B7%E6%9C%89Future%E7%9A%84%E7%89%B9%E6%80%A7%EF%BC%9A%E8%B0%83%E7%94%A8%20get()%E6%96%B9%E6%B3%95%E4%BC%9A%E9%98%BB%E5%A1%9E%E5%9C%A8%E9%82%A3%EF%BC%8C%E7%9B%B4%E5%88%B0%E7%BB%93%E6%9E%9C%E8%BF%94%E5%9B%9E%E3%80%82%0A%0A%60%60%60java%0A%40SneakyThrows%0A%40Test%0Apublic%20void%20asyn1()%20%7B%0A%20%20%20%20CompletableFuture%3CString%3E%20cf%20%3D%20new%20CompletableFuture%3C%3E()%3B%0A%0A%20%20%20%20%2F%2Fcomplete%E6%96%B9%E6%B3%95%E5%AE%8C%E6%88%90%E8%AF%A5Future%2C%E5%90%A6%E5%88%99%E5%9C%A8%E8%B0%83%E7%94%A8cf.get()%E9%98%BB%E5%A1%9E%E4%B8%BB%E7%BA%BF%E7%A8%8B%EF%BC%8C%E7%AD%89%E5%BE%85%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%0A%20%20%20%20cf.complete(%22hello%20future!%22)%3B%0A%0A%20%20%20%20%2F%2F%E8%B0%83%E7%94%A8%E8%80%85%E9%98%BB%E5%A1%9E%EF%BC%8C%E7%AD%89%E5%BE%85%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%0A%20%20%20%20String%20s%20%3D%20cf.get()%3B%0A%20%20%20%20System.out.println(s)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%203.2%20runAsync%20%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC%0A%3E%20%E9%80%9A%E8%BF%87%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%E7%94%9F%E6%88%90%20CompletableFuture%20%E5%AF%B9%E8%B1%A1%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%BE%BF%E5%8F%AF%E4%BB%A5%E9%93%BE%E5%BC%8F%E5%9C%B0%E6%8F%90%E4%BA%A4%E5%85%B6%E4%BB%96%E4%BB%BB%E5%8A%A1%E4%BA%86%0A%60%60%60java%0A%40SneakyThrows%0A%40Test%0Apublic%20void%20runAsync()%20%7B%0A%20%20%20%20CompletableFuture%3CVoid%3E%20cf%20%3D%20CompletableFuture.runAsync(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22task%20is%20running!%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(5)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D).thenRun(()%20-%3E%20System.out.println(%22call%20back%20method%20after%20getting%20result!%22))%3B%0A%0A%20%20%20%20%2F%2F%E4%B8%BB%E7%BA%BF%E7%A8%8B%E9%98%BB%E5%A1%9E%EF%BC%8C%E7%AD%89%E5%BE%85%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%88%90%0A%20%20%20%20cf.get()%3B%0A%7D%0A%60%60%60%0A%23%23%23%23%23%203.3%20supplierAsync%20%E6%9C%89%E8%BF%94%E5%9B%9E%E5%80%BC%0A%60%60%60java%0A%40SneakyThrows%0A%40Test%0Apublic%20void%20supplyAsync()%20%7B%0A%20%20%20%20CompletableFuture%3CString%3E%20cf%20%3D%20CompletableFuture.supplyAsync(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(5)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%22task%20has%20done!%22%3B%0A%20%20%20%20%7D).thenApplyAsync(s%20-%3E%20s%20%2B%20%22%2C%20call%20back%20method%20after%20getting%20result!%22)%3B%0A%0A%20%20%20%20%2F%2F%E4%B8%BB%E7%BA%BF%E7%A8%8B%E9%98%BB%E5%A1%9E%EF%BC%8C%E7%AD%89%E5%BE%85%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%88%90%0A%20%20%20%20String%20s%20%3D%20cf.get()%3B%0A%20%20%20%20System.out.println(s)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%204.%20CompletableFutre%E7%9A%84%E6%88%90%E5%91%98%E6%96%B9%E6%B3%95%0A%23%23%23%23%23%204.1%20thenRun%E3%80%81thenAccept%E3%80%81thenApply%0A%0A%3E%20%60thenRun%60%20%20%20%20%20%E5%90%8E%E9%9D%A2%E8%B7%9F%E7%9A%84%E6%98%AF%E4%B8%80%E4%B8%AA%E6%97%A0%E5%8F%82%E6%95%B0%E3%80%81%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8D%B3%20Runnable.%20%20%0A%3E%20%60thenAccept%60%20%E5%90%8E%E9%9D%A2%E8%B7%9F%E7%9A%84%E6%98%AF%E4%B8%80%E4%B8%AA%E6%9C%89%E5%8F%82%E6%95%B0%E3%80%81%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E7%A7%B0%E4%B8%BA%20Consumer.%20%20%0A%3E%20%60thenApply%60%20%20%E5%90%8E%E9%9D%A2%E8%B7%9F%E7%9A%84%E6%98%AF%E4%B8%80%E4%B8%AA%E6%9C%89%E5%8F%82%E6%95%B0%E3%80%81%E6%9C%89%E8%BF%94%E5%9B%9E%E5%80%BC%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E7%A7%B0%E4%B8%BA%20Function.%20%20%0A%0A%60%60%60%0A%20thenApplyAsync%E4%B8%8EthenApply%E7%9A%84%E5%8C%BA%E5%88%AB%E5%9C%A8%E4%BA%8E%0A%20%E5%89%8D%E8%80%85%E6%98%AF%E5%B0%86job2%E6%8F%90%E4%BA%A4%E5%88%B0%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B8%AD%E5%BC%82%E6%AD%A5%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%AE%9E%E9%99%85%E6%89%A7%E8%A1%8Cjob2%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%8F%AF%E8%83%BD%E6%98%AF%E5%8F%A6%E5%A4%96%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%0A%20%E5%90%8E%E8%80%85%E6%98%AF%E7%94%B1%E6%89%A7%E8%A1%8Cjob1%E7%9A%84%E7%BA%BF%E7%A8%8B%E7%AB%8B%E5%8D%B3%E6%89%A7%E8%A1%8Cjob2%EF%BC%8C%E5%8D%B3%E4%B8%A4%E4%B8%AAjob%E9%83%BD%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E7%9A%84%0A%60%60%60%0A%0A%23%23%23%23%23%204.2%20exceptionally%0A%3E%20%E6%8C%87%E5%AE%9A%E6%9F%90%E4%B8%AA%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C%E5%BC%82%E5%B8%B8%E6%97%B6%E6%89%A7%E8%A1%8C%E7%9A%84%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BC%9A%E5%B0%86%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0%E4%BC%A0%E9%80%92%E5%88%B0%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%E4%B8%AD%20%20%0A%E5%A6%82%E6%9E%9C%E8%AF%A5%E4%BB%BB%E5%8A%A1%E6%AD%A3%E5%B8%B8%E6%89%A7%E8%A1%8C%E4%BC%9A%20%60exceptionally%60%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E7%9A%84CompletionStage%E7%9A%84result%E5%B0%B1%E6%98%AF%E8%AF%A5%E4%BB%BB%E5%8A%A1%E6%AD%A3%E5%B8%B8%E6%89%A7%E8%A1%8C%E7%9A%84%E7%BB%93%E6%9E%9C%0A%60%60%60java%0A%40SneakyThrows%0A%40Test%0Apublic%20void%20testExceptionally()%20%7B%0A%20%20%20%20CompletableFuture%3CDouble%3E%20cf%20%3D%20CompletableFuture.supplyAsync(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22job1%20start%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(5)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%2F%2F%E6%AD%A3%E5%B8%B8%E7%BB%93%E6%9E%9C%E9%9C%80%E8%A6%81%E6%94%B9%E4%B8%BAfalse%0A%20%20%20%20%20%20%20%20if%20(true)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22throw%20exception!%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20RuntimeException(%22test%20exceptionally%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%201.1%3B%0A%20%20%20%20%7D)%3B%0A%0A%20%20%20%20CompletableFuture%3CDouble%3E%20cf2%20%3D%20cf.exceptionally((exception)%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22%20start%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(2000)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20System.out.println(%22error%20stack%20trace-%3E%22)%3B%0A%20%20%20%20%20%20%20%20exception.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22%20exit%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20return%201.2%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20System.out.println(cf2.get())%3B%0A%7D%0A%60%60%60%0A%3E%20%E6%AD%A3%E5%B8%B8%E7%BB%93%E6%9E%9C%0A%60%60%60%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5Djob1%20start%2C%20time-%3E1657161758634%0A1.1%0A%60%60%60%0A%3E%20%E5%BC%82%E5%B8%B8%E7%BB%93%E6%9E%9C%0A%60%60%60%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5Djob1%20start%2C%20time-%3E1657161554581%0Athrow%20exception!%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20start%2C%20time-%3E1657161559581%0Aerror%20stack%20trace-%3E%0Ajava.util.concurrent.CompletionException%3A%20java.lang.RuntimeException%3A%20test%20exceptionally%0A%09at%20java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java%3A273)%0A%09at%20java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java%3A280)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run%24%24%24capture(CompletableFuture.java%3A1592)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run(CompletableFuture.java)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.exec(CompletableFuture.java%3A1582)%0A%09at%20java.util.concurrent.ForkJoinTask.doExec%24%24%24capture(ForkJoinTask.java%3A289)%0A%09at%20java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)%0A%09at%20java.util.concurrent.ForkJoinPool%24WorkQueue.runTask(ForkJoinPool.java%3A1056)%0A%09at%20java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java%3A1692)%0A%09at%20java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java%3A157)%0ACaused%20by%3A%20java.lang.RuntimeException%3A%20test%20exceptionally%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20exit%2C%20time-%3E1657161561583%0A%09at%20com.thread.future.async.CompletableFutureSourceCode.lambda%24testExceptionally%247(CompletableFutureSourceCode.java%3A139)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run%24%24%24capture(CompletableFuture.java%3A1590)%0A%09...%207%20more%0A1.2%0A%60%60%60%0A%0A%23%23%23%23%23%204.3%20whenComplete%0A%3E%20%E5%BD%93%E6%9F%90%E4%B8%AA%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%88%90%E5%90%8E%E6%89%A7%E8%A1%8C%E7%9A%84%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BC%9A%E5%B0%86%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%E6%88%96%E8%80%85%E6%89%A7%E8%A1%8C%E6%9C%9F%E9%97%B4%E6%8A%9B%E5%87%BA%E7%9A%84%E5%BC%82%E5%B8%B8%E4%BC%A0%E9%80%92%E7%BB%99%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%EF%BC%8C%0A%E5%A6%82%E6%9E%9C%E6%98%AF%E6%AD%A3%E5%B8%B8%E6%89%A7%E8%A1%8C%E5%88%99%E5%BC%82%E5%B8%B8%E4%B8%BAnull%EF%BC%8C%60%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%E5%AF%B9%E5%BA%94%E7%9A%84CompletableFuture%E7%9A%84result%E5%92%8C%E8%AF%A5%E4%BB%BB%E5%8A%A1%E4%B8%80%E8%87%B4%60%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AF%A5%E4%BB%BB%E5%8A%A1%E6%AD%A3%E5%B8%B8%E6%89%A7%E8%A1%8C%EF%BC%8C%0A%E5%88%99get%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%98%AF%E6%89%A7%E8%A1%8C%E5%BC%82%E5%B8%B8%EF%BC%8C%E5%88%99get%E6%96%B9%E6%B3%95%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%0A%0A%60%60%60java%0A%40SneakyThrows%0A%40Test%0Apublic%20void%20testWhenComplete()%20%7B%0A%20%20%20%20CompletableFuture%3CDouble%3E%20cf%20%3D%20CompletableFuture.supplyAsync(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22job1%20start%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(5)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%2F%2F%E6%AD%A3%E5%B8%B8%E7%BB%93%E6%9E%9C%E9%9C%80%E8%A6%81%E6%94%B9%E4%B8%BAfalse%0A%20%20%20%20%20%20%20%20if%20(true)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22throw%20exception!%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20RuntimeException(%22test%20exceptionally%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%201.1%3B%0A%20%20%20%20%7D)%3B%0A%0A%20%20%20%20CompletableFuture%3CDouble%3E%20cf2%20%3D%20cf.whenComplete((result%2C%20exception)%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22%20start%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(2000)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20System.out.println(%22error%20stack%20trace-%3E%22)%3B%0A%20%20%20%20%20%20%20%20if%20(Objects.nonNull(exception))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20exception.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22%20exit%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22result%3A%22%20%2B%20result)%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20System.out.println(cf2.get())%3B%0A%7D%0A%60%60%60%0A%3E%20%E6%AD%A3%E5%B8%B8%E7%BB%93%E6%9E%9C%0A%60%60%60%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5Djob1%20start%2C%20time-%3E1657162560549%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20start%2C%20time-%3E1657162565550%0Aerror%20stack%20trace-%3E%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20exit%2C%20time-%3E1657162567550%0Aresult%3A1.1%0A1.1%0A%60%60%60%0A%3E%20%E5%BC%82%E5%B8%B8%E7%BB%93%E6%9E%9C%0A%60%60%60%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5Djob1%20start%2C%20time-%3E1657162369911%0Athrow%20exception!%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20start%2C%20time-%3E1657162374911%0Aerror%20stack%20trace-%3E%0Ajava.util.concurrent.CompletionException%3A%20java.lang.RuntimeException%3A%20test%20exceptionally%0A%09at%20java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java%3A273)%0A%09at%20java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java%3A280)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run%24%24%24capture(CompletableFuture.java%3A1592)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run(CompletableFuture.java)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.exec(CompletableFuture.java%3A1582)%0A%09at%20java.util.concurrent.ForkJoinTask.doExec%24%24%24capture(ForkJoinTask.java%3A289)%0A%09at%20java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)%0A%09at%20java.util.concurrent.ForkJoinPool%24WorkQueue.runTask(ForkJoinPool.java%3A1056)%0A%09at%20java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java%3A1692)%0A%09at%20java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java%3A157)%0ACaused%20by%3A%20java.lang.RuntimeException%3A%20test%20exceptionally%0A%09at%20com.thread.future.async.CompletableFutureSourceCode.lambda%24testWhenComplete%249(CompletableFutureSourceCode.java%3A176)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run%24%24%24capture(CompletableFuture.java%3A1590)%0A%09...%207%20more%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20exit%2C%20time-%3E1657162376913%0Aresult%3Anull%0A%60%60%60%0A%0A%23%23%23%23%23%204.4%20handle%0A%3E%20%E8%B7%9FwhenComplete%E5%9F%BA%E6%9C%AC%E4%B8%80%E8%87%B4%EF%BC%8C%E5%8C%BA%E5%88%AB%E5%9C%A8%E4%BA%8Ehandle%E7%9A%84%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%E6%9C%89%E8%BF%94%E5%9B%9E%E5%80%BC%EF%BC%8C%20%20%0A%E4%B8%94%60handle%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E7%9A%84CompletableFuture%E7%9A%84result%E6%98%AF%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%E7%9A%84%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%E6%88%96%E8%80%85%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E6%9C%9F%E9%97%B4%E6%8A%9B%E5%87%BA%E7%9A%84%E5%BC%82%E5%B8%B8%EF%BC%8C%E4%B8%8E%E5%8E%9F%E5%A7%8BCompletableFuture%E7%9A%84result%E6%97%A0%E5%85%B3%E4%BA%86%60%E3%80%82%0A%0A%60%60%60java%0A%40SneakyThrows%0A%40Test%0Apublic%20void%20testHandle()%20%7B%0A%20%20%20%20CompletableFuture%3CDouble%3E%20cf%20%3D%20CompletableFuture.supplyAsync(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22job1%20start%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(5)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(true)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22throw%20exception!%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20RuntimeException(%22test%20exceptionally%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%201.1%3B%0A%20%20%20%20%7D)%3B%0A%0A%20%20%20%20CompletableFuture%3CString%3E%20handle%20%3D%20cf.handle((result%2C%20exception)%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22%20start%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(2000)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20System.out.println(%22error%20stack%20trace-%3E%22)%3B%0A%20%20%20%20%20%20%20%20if%20(Objects.nonNull(exception))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20exception.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread()%20%2B%20%22%20exit%2C%20time-%3E%22%20%2B%20System.currentTimeMillis())%3B%0A%20%20%20%20%20%20%20%20if%20(Objects.isNull(exception))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%22run%20success%22%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%22run%20error%22%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D)%3B%0A%20%20%20%20System.out.println(handle.get())%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%AD%A3%E5%B8%B8%E7%BB%93%E6%9E%9C%0A%60%60%60%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5Djob1%20start%2C%20time-%3E1657163319080%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20start%2C%20time-%3E1657163324081%0Aerror%20stack%20trace-%3E%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20exit%2C%20time-%3E1657163326081%0Arun%20success%0A%60%60%60%0A%0A%3E%20%E5%BC%82%E5%B8%B8%E7%BB%93%E6%9E%9C%0A%60%60%60%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5Djob1%20start%2C%20time-%3E1657163045499%0Athrow%20exception!%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20start%2C%20time-%3E1657163050500%0Aerror%20stack%20trace-%3E%0Ajava.util.concurrent.CompletionException%3A%20java.lang.RuntimeException%3A%20test%20exceptionally%0A%09at%20java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java%3A273)%0A%09at%20java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java%3A280)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run%24%24%24capture(CompletableFuture.java%3A1592)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run(CompletableFuture.java)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.exec(CompletableFuture.java%3A1582)%0A%09at%20java.util.concurrent.ForkJoinTask.doExec%24%24%24capture(ForkJoinTask.java%3A289)%0A%09at%20java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)%0A%09at%20java.util.concurrent.ForkJoinPool%24WorkQueue.runTask(ForkJoinPool.java%3A1056)%0AThread%5BForkJoinPool.commonPool-worker-1%2C5%2Cmain%5D%20exit%2C%20time-%3E1657163052502%0Arun%20success%0A%09at%20java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java%3A1692)%0A%09at%20java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java%3A157)%0ACaused%20by%3A%20java.lang.RuntimeException%3A%20test%20exceptionally%0A%09at%20com.thread.future.async.CompletableFutureSourceCode.lambda%24testHandle%2411(CompletableFutureSourceCode.java%3A215)%0A%09at%20java.util.concurrent.CompletableFuture%24AsyncSupply.run%24%24%24capture(CompletableFuture.java%3A1590)%0A%09...%207%20more%0A%60%60%60%0A%0A%23%23%23%23%205.%20%E8%8E%B7%E5%8F%96%E7%BB%93%E6%9E%9C%0A%3E%20%E5%90%8C%E6%AD%A5%E8%8E%B7%E5%8F%96%E7%BB%93%E6%9E%9C%0A%60%60%60%0Apublic%20T%20get()%0Apublic%20T%20get(long%20timeout%2C%20TimeUnit%20unit)%20%0Apublic%20T%20getNow(T%20valueIfAbsent)%20%2F%2F%E7%BB%93%E6%9E%9C%E5%B7%B2%E7%BB%8F%E8%AE%A1%E7%AE%97%E5%AE%8C%E5%88%99%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E6%88%96%E8%80%85%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%EF%BC%8C%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9E%E7%BB%99%E5%AE%9A%E7%9A%84valueIfAbsent%E5%80%BC%E3%80%82%0Apublic%20T%20join()%20%0A%60%60%60%0A%3E%20join()%E4%B8%8Eget()%E5%8C%BA%E5%88%AB%E5%9C%A8%E4%BA%8Ejoin()%E8%BF%94%E5%9B%9E%E8%AE%A1%E7%AE%97%E7%9A%84%E7%BB%93%E6%9E%9C%E6%88%96%E8%80%85%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AAunchecked%E5%BC%82%E5%B8%B8(CompletionException)%EF%BC%8C%E8%80%8Cget()%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E5%85%B7%E4%BD%93%E7%9A%84%E5%BC%82%E5%B8%B8.%0A%0A%0A%23%23%23%23%206.%20%E4%B8%BB%E5%8A%A8%E7%BB%93%E6%9D%9F%0A%3E%20future.get()%E5%9C%A8%E7%AD%89%E5%BE%85%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%E6%97%B6%EF%BC%8C%E7%A8%8B%E5%BA%8F%E4%BC%9A%E4%B8%80%E7%9B%B4block%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%AD%A4%E6%97%B6%E8%B0%83%E7%94%A8complete(T%20t)%E4%BC%9A%E7%AB%8B%E5%8D%B3%E6%89%A7%E8%A1%8C%E3%80%82%0A%0A%60%60%60java%0Acomplete(T%20t)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%E5%AE%8C%E6%88%90%E5%BC%82%E6%AD%A5%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%B9%B6%E8%BF%94%E5%9B%9Efuture%E7%9A%84%E7%BB%93%E6%9E%9C%0AcompleteExceptionally(Throwable%20ex)%20%E5%BC%82%E6%AD%A5%E6%89%A7%E8%A1%8C%E4%B8%8D%E6%AD%A3%E5%B8%B8%E7%9A%84%E7%BB%93%E6%9D%9F%0A%60%60%60%0A%3E%20future%E8%B0%83%E7%94%A8complete(T%20t)%E4%BC%9A%E7%AB%8B%E5%8D%B3%E6%89%A7%E8%A1%8C%E3%80%82%E4%BD%86%E6%98%AFcomplete(T%20t)%E5%8F%AA%E8%83%BD%E8%B0%83%E7%94%A8%E4%B8%80%E6%AC%A1%EF%BC%8C%E5%90%8E%E7%BB%AD%E7%9A%84%E9%87%8D%E5%A4%8D%E8%B0%83%E7%94%A8%E4%BC%9A%E5%A4%B1%E6%95%88%E3%80%82%0A%3E%20%E5%A6%82%E6%9E%9Cfuture%E5%B7%B2%E7%BB%8F%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%E8%83%BD%E5%A4%9F%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%EF%BC%8C%E6%AD%A4%E6%97%B6%E5%86%8D%E8%B0%83%E7%94%A8complete(T%20t)%E5%88%99%E4%BC%9A%E6%97%A0%E6%95%88%E3%80%82%0A%0A%0A%0A%60%60%60java%0A%40Slf4j%0Apublic%20class%20CompleableFutrueTest%20%7B%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20allOfTest()%20%7B%0A%20%20%20%20%20%20%20%20List%3CCompletableFuture%3CString%3E%3E%20cfList%20%3D%20CollUtil.newArrayList()%3B%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20CompletableFuture%3CString%3E%20cf%20%3D%20CompletableFuture.supplyAsync(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20result%20%3D%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20threadName%20%3D%20Thread.currentThread().getName()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(threadName%20%2B%20%22%20begin%20sleep%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(3)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(threadName%20%2B%20%22%20end%20sleep%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20result%20%3D%20doSomething(threadName)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(Exception%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20result%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20cfList.add(cf)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20CompletableFuture%3CVoid%3E%20allCF%20%3D%20CompletableFuture.allOf(cfList.toArray(new%20CompletableFuture%5B0%5D))%3B%0A%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20allCF.get()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20CompletableFuture%3CList%3CString%3E%3E%20resultCF%20%3D%20allCF.thenApply(v%20-%3E%20cfList.stream().map(cf%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20cf.get()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20%7C%20ExecutionException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D).collect(Collectors.toList()))%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20List%3CString%3E%20result%20%3D%20resultCF.get()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(result)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20%7C%20ExecutionException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20String%20doSomething(String%20jobNumber)%20%7B%0A%20%20%20%20%20%20%20%20if%20(StrUtil.equals(jobNumber%2C%20%22ForkJoinPool.commonPool-worker-2%22))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20RuntimeException(%22ForkJoinPool.commonPool-worker-2%20is%20exception%22)%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(jobNumber%20%2B%20%22%20is%20outputing%3A%22%20%2B%20i)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20jobNumber%20%2B%20%22%20is%20done!%22%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60

StopWatch 统计代码耗时

创建时间:2022/6/30 16:47
更新时间:2022/6/30 17:03
作者:Chris

1. Spring StopWatch

Spring提供的计时器StopWatch对于秒、毫秒为单位方便计时的程序,
尤其是 单线程、顺序执行程序 的时间特性的统计输出支持比较好。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
</dependency>

@Test
public void test1() throws InterruptedException {
    StopWatch stopWatch = new StopWatch();

    // 任务一模拟休眠3秒钟
    stopWatch.start("TaskOneName");
    Thread.sleep(1000 * 3);
    System.out.println("当前任务名称:" + stopWatch.currentTaskName());
    stopWatch.stop();

    // 任务一模拟休眠10秒钟
    stopWatch.start("TaskTwoName");
    Thread.sleep(1000 * 10);
    System.out.println("当前任务名称:" + stopWatch.currentTaskName());
    stopWatch.stop();

    // 任务一模拟休眠10秒钟
    stopWatch.start("TaskThreeName");
    Thread.sleep(1000 * 10);
    System.out.println("当前任务名称:" + stopWatch.currentTaskName());
    stopWatch.stop();

    // 打印出耗时
    System.out.println(stopWatch.prettyPrint());
    System.out.println(stopWatch.shortSummary());
    // stop后它的值为null
    System.out.println(stopWatch.currentTaskName());

    // 最后一个任务的相关信息
    System.out.println(stopWatch.getLastTaskName());
    System.out.println(stopWatch.getLastTaskInfo());

    // 任务总的耗时  如果你想获取到每个任务详情(包括它的任务名、耗时等等)可使用
    System.out.println("所有任务总耗时:" + stopWatch.getTotalTimeMillis());
    System.out.println("任务总数:" + stopWatch.getTaskCount());
    System.out.println("所有任务详情:" + Arrays.toString(stopWatch.getTaskInfo()));

}

结果

当前任务名称:TaskOneName
当前任务名称:TaskTwoName
当前任务名称:TaskThreeName
StopWatch '': running time = 23002371100 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
3000873900  013%  TaskOneName
10000460000  043%  TaskTwoName
10001037200  043%  TaskThreeName

StopWatch '': running time = 23002371100 ns
null
TaskThreeName
org.springframework.util.StopWatch$TaskInfo@5e5d171f
所有任务总耗时:23002
任务总数:3
所有任务详情:[org.springframework.util.StopWatch$TaskInfo@24313fcc, org.springframework.util.StopWatch$TaskInfo@7d20d0b, org.springframework.util.StopWatch$TaskInfo@5e5d171f]

注意事项

1. StopWatch对象不是设计为线程安全的,并且不使用同步。
2.  一个StopWatch实例一次只能开启一个task,不能同时start多个task
3.  在该task还没stop之前不能start一个新的task,必须在该task stop之后才能开启新的task
4.  若要一次开启多个,需要new不同的StopWatch实例

2. Apache StopWatch

StopWath是 apache commons lang3 包下的一个任务执行时间监视器,与我们平时常用的秒表的行为比较类似

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>;
</dependency>

 @Test
 public void testApache() throws InterruptedException {
     //创建后立即start,常用
     StopWatch watch = StopWatch.createStarted();

     // StopWatch watch = new StopWatch();
     // watch.start();

     Thread.sleep(1000);
     System.out.println(watch.getTime());
     System.out.println("统计从开始到现在运行时间:" + watch.getTime() + "ms");

     Thread.sleep(1000);
     watch.split();
     System.out.println("从start到此刻为止的时间:" + watch.getTime());
     System.out.println("从开始到第一个切入点运行时间:" + watch.getSplitTime());
     Thread.sleep(1000);
     watch.split();
     System.out.println("从开始到第二个切入点运行时间:" + watch.getSplitTime());

     // 复位后, 重新计时
     watch.reset();
     watch.start();
     Thread.sleep(1000);
     System.out.println("重新开始后到当前运行时间是:" + watch.getTime());

     // 暂停 与 恢复
     watch.suspend();
     System.out.println("暂停2秒钟");
     Thread.sleep(2000);

     // 上面suspend,这里要想重新统计,需要恢复一下
     watch.resume();
     System.out.println("恢复后执行的时间是:" + watch.getTime());

     Thread.sleep(1000);
     watch.stop();

     System.out.println("花费的时间》》" + watch.getTime() + "ms");
     // 直接转成s
     System.out.println("花费的时间》》" + watch.getTime(TimeUnit.SECONDS) + "s");
 }

结果

1002
统计从开始到现在运行时间:1006ms
从start到此刻为止的时间:2017
从开始到第一个切入点运行时间:2017
从开始到第二个切入点运行时间:3017
重新开始后到当前运行时间是:1000
暂停2秒钟
恢复后执行的时间是:1000
花费的时间》》2001ms
花费的时间》》2s
%5Btoc%5D%0A%0A%23%23%201.%20Spring%20StopWatch%0A%3E%20Spring%E6%8F%90%E4%BE%9B%E7%9A%84%E8%AE%A1%E6%97%B6%E5%99%A8StopWatch%E5%AF%B9%E4%BA%8E%E7%A7%92%E3%80%81%E6%AF%AB%E7%A7%92%E4%B8%BA%E5%8D%95%E4%BD%8D%E6%96%B9%E4%BE%BF%E8%AE%A1%E6%97%B6%E7%9A%84%E7%A8%8B%E5%BA%8F%EF%BC%8C%0A%3E%20%E5%B0%A4%E5%85%B6%E6%98%AF%20%60%E5%8D%95%E7%BA%BF%E7%A8%8B%E3%80%81%E9%A1%BA%E5%BA%8F%E6%89%A7%E8%A1%8C%E7%A8%8B%E5%BA%8F%60%20%E7%9A%84%E6%97%B6%E9%97%B4%E7%89%B9%E6%80%A7%E7%9A%84%E7%BB%9F%E8%AE%A1%E8%BE%93%E5%87%BA%E6%94%AF%E6%8C%81%E6%AF%94%E8%BE%83%E5%A5%BD%E3%80%82%0A%0A%60%60%60xml%0A%3Cdependency%3E%0A%C2%A0%C2%A0%C2%A0%C2%A0%3CgroupId%3Eorg.springframework%3C%2FgroupId%3E%0A%C2%A0%C2%A0%C2%A0%C2%A0%3CartifactId%3Espring-core%3C%2FartifactId%3E%0A%C2%A0%C2%A0%C2%A0%C2%A0%3Cversion%3E%24%7Bspring.version%7D%3C%2Fversion%3E%0A%3C%2Fdependency%3E%0A%0A%60%60%60%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20test1()%20throws%20InterruptedException%20%7B%0A%20%20%20%20StopWatch%20stopWatch%20%3D%20new%20StopWatch()%3B%0A%0A%20%20%20%20%2F%2F%20%E4%BB%BB%E5%8A%A1%E4%B8%80%E6%A8%A1%E6%8B%9F%E4%BC%91%E7%9C%A03%E7%A7%92%E9%92%9F%0A%20%20%20%20stopWatch.start(%22TaskOneName%22)%3B%0A%20%20%20%20Thread.sleep(1000%20*%203)%3B%0A%20%20%20%20System.out.println(%22%E5%BD%93%E5%89%8D%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%9A%22%20%2B%20stopWatch.currentTaskName())%3B%0A%20%20%20%20stopWatch.stop()%3B%0A%0A%20%20%20%20%2F%2F%20%E4%BB%BB%E5%8A%A1%E4%B8%80%E6%A8%A1%E6%8B%9F%E4%BC%91%E7%9C%A010%E7%A7%92%E9%92%9F%0A%20%20%20%20stopWatch.start(%22TaskTwoName%22)%3B%0A%20%20%20%20Thread.sleep(1000%20*%2010)%3B%0A%20%20%20%20System.out.println(%22%E5%BD%93%E5%89%8D%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%9A%22%20%2B%20stopWatch.currentTaskName())%3B%0A%20%20%20%20stopWatch.stop()%3B%0A%0A%20%20%20%20%2F%2F%20%E4%BB%BB%E5%8A%A1%E4%B8%80%E6%A8%A1%E6%8B%9F%E4%BC%91%E7%9C%A010%E7%A7%92%E9%92%9F%0A%20%20%20%20stopWatch.start(%22TaskThreeName%22)%3B%0A%20%20%20%20Thread.sleep(1000%20*%2010)%3B%0A%20%20%20%20System.out.println(%22%E5%BD%93%E5%89%8D%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%9A%22%20%2B%20stopWatch.currentTaskName())%3B%0A%20%20%20%20stopWatch.stop()%3B%0A%0A%20%20%20%20%2F%2F%20%E6%89%93%E5%8D%B0%E5%87%BA%E8%80%97%E6%97%B6%0A%20%20%20%20System.out.println(stopWatch.prettyPrint())%3B%0A%20%20%20%20System.out.println(stopWatch.shortSummary())%3B%0A%20%20%20%20%2F%2F%20stop%E5%90%8E%E5%AE%83%E7%9A%84%E5%80%BC%E4%B8%BAnull%0A%20%20%20%20System.out.println(stopWatch.currentTaskName())%3B%0A%0A%20%20%20%20%2F%2F%20%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AA%E4%BB%BB%E5%8A%A1%E7%9A%84%E7%9B%B8%E5%85%B3%E4%BF%A1%E6%81%AF%0A%20%20%20%20System.out.println(stopWatch.getLastTaskName())%3B%0A%20%20%20%20System.out.println(stopWatch.getLastTaskInfo())%3B%0A%0A%20%20%20%20%2F%2F%20%E4%BB%BB%E5%8A%A1%E6%80%BB%E7%9A%84%E8%80%97%E6%97%B6%20%20%E5%A6%82%E6%9E%9C%E4%BD%A0%E6%83%B3%E8%8E%B7%E5%8F%96%E5%88%B0%E6%AF%8F%E4%B8%AA%E4%BB%BB%E5%8A%A1%E8%AF%A6%E6%83%85%EF%BC%88%E5%8C%85%E6%8B%AC%E5%AE%83%E7%9A%84%E4%BB%BB%E5%8A%A1%E5%90%8D%E3%80%81%E8%80%97%E6%97%B6%E7%AD%89%E7%AD%89%EF%BC%89%E5%8F%AF%E4%BD%BF%E7%94%A8%0A%20%20%20%20System.out.println(%22%E6%89%80%E6%9C%89%E4%BB%BB%E5%8A%A1%E6%80%BB%E8%80%97%E6%97%B6%EF%BC%9A%22%20%2B%20stopWatch.getTotalTimeMillis())%3B%0A%20%20%20%20System.out.println(%22%E4%BB%BB%E5%8A%A1%E6%80%BB%E6%95%B0%EF%BC%9A%22%20%2B%20stopWatch.getTaskCount())%3B%0A%20%20%20%20System.out.println(%22%E6%89%80%E6%9C%89%E4%BB%BB%E5%8A%A1%E8%AF%A6%E6%83%85%EF%BC%9A%22%20%2B%20Arrays.toString(stopWatch.getTaskInfo()))%3B%0A%0A%7D%0A%60%60%60%0A%0A%3E%20%E7%BB%93%E6%9E%9C%0A%0A%60%60%60%0A%E5%BD%93%E5%89%8D%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%9ATaskOneName%0A%E5%BD%93%E5%89%8D%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%9ATaskTwoName%0A%E5%BD%93%E5%89%8D%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%9ATaskThreeName%0AStopWatch%20''%3A%20running%20time%20%3D%2023002371100%20ns%0A---------------------------------------------%0Ans%20%20%20%20%20%20%20%20%20%25%20%20%20%20%20Task%20name%0A---------------------------------------------%0A3000873900%20%20013%25%20%20TaskOneName%0A10000460000%20%20043%25%20%20TaskTwoName%0A10001037200%20%20043%25%20%20TaskThreeName%0A%0AStopWatch%20''%3A%20running%20time%20%3D%2023002371100%20ns%0Anull%0ATaskThreeName%0Aorg.springframework.util.StopWatch%24TaskInfo%405e5d171f%0A%E6%89%80%E6%9C%89%E4%BB%BB%E5%8A%A1%E6%80%BB%E8%80%97%E6%97%B6%EF%BC%9A23002%0A%E4%BB%BB%E5%8A%A1%E6%80%BB%E6%95%B0%EF%BC%9A3%0A%E6%89%80%E6%9C%89%E4%BB%BB%E5%8A%A1%E8%AF%A6%E6%83%85%EF%BC%9A%5Borg.springframework.util.StopWatch%24TaskInfo%4024313fcc%2C%20org.springframework.util.StopWatch%24TaskInfo%407d20d0b%2C%20org.springframework.util.StopWatch%24TaskInfo%405e5d171f%5D%0A%60%60%60%0A%0A!%5B1984eb8b398ce073872c3a1dcd64ee67.png%5D(en-resource%3A%2F%2Fdatabase%2F1810%3A1)%0A%0A%3E%20%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9%0A%0A%60%60%60%0A1.%20StopWatch%E5%AF%B9%E8%B1%A1%E4%B8%8D%E6%98%AF%E8%AE%BE%E8%AE%A1%E4%B8%BA%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%B8%8D%E4%BD%BF%E7%94%A8%E5%90%8C%E6%AD%A5%E3%80%82%0A2.%20%20%E4%B8%80%E4%B8%AAStopWatch%E5%AE%9E%E4%BE%8B%E4%B8%80%E6%AC%A1%E5%8F%AA%E8%83%BD%E5%BC%80%E5%90%AF%E4%B8%80%E4%B8%AAtask%EF%BC%8C%E4%B8%8D%E8%83%BD%E5%90%8C%E6%97%B6start%E5%A4%9A%E4%B8%AAtask%0A3.%20%20%E5%9C%A8%E8%AF%A5task%E8%BF%98%E6%B2%A1stop%E4%B9%8B%E5%89%8D%E4%B8%8D%E8%83%BDstart%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84task%EF%BC%8C%E5%BF%85%E9%A1%BB%E5%9C%A8%E8%AF%A5task%20stop%E4%B9%8B%E5%90%8E%E6%89%8D%E8%83%BD%E5%BC%80%E5%90%AF%E6%96%B0%E7%9A%84task%0A4.%20%20%E8%8B%A5%E8%A6%81%E4%B8%80%E6%AC%A1%E5%BC%80%E5%90%AF%E5%A4%9A%E4%B8%AA%EF%BC%8C%E9%9C%80%E8%A6%81new%E4%B8%8D%E5%90%8C%E7%9A%84StopWatch%E5%AE%9E%E4%BE%8B%0A%60%60%60%0A%0A%23%23%202.%20Apache%20StopWatch%0A%3E%20StopWath%E6%98%AF%20apache%20commons%20lang3%20%E5%8C%85%E4%B8%8B%E7%9A%84%E4%B8%80%E4%B8%AA%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E7%9B%91%E8%A7%86%E5%99%A8%EF%BC%8C%E4%B8%8E%E6%88%91%E4%BB%AC%E5%B9%B3%E6%97%B6%E5%B8%B8%E7%94%A8%E7%9A%84%E7%A7%92%E8%A1%A8%E7%9A%84%E8%A1%8C%E4%B8%BA%E6%AF%94%E8%BE%83%E7%B1%BB%E4%BC%BC%0A%0A!%5B50192bf83826eb558d7c5ff530f0e323.png%5D(en-resource%3A%2F%2Fdatabase%2F1812%3A1)%0A%0A%0A%60%60%60xml%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Eorg.apache.commons%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Ecommons-lang3%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E3.12.0%3C%2Fversion%3E%3B%0A%3C%2Fdependency%3E%0A%60%60%60%0A%0A%60%60%60java%0A%0A%20%40Test%0A%20public%20void%20testApache()%20throws%20InterruptedException%20%7B%0A%20%20%20%20%20%2F%2F%E5%88%9B%E5%BB%BA%E5%90%8E%E7%AB%8B%E5%8D%B3start%EF%BC%8C%E5%B8%B8%E7%94%A8%0A%20%20%20%20%20StopWatch%20watch%20%3D%20StopWatch.createStarted()%3B%0A%0A%20%20%20%20%20%2F%2F%20StopWatch%20watch%20%3D%20new%20StopWatch()%3B%0A%20%20%20%20%20%2F%2F%20watch.start()%3B%0A%0A%20%20%20%20%20Thread.sleep(1000)%3B%0A%20%20%20%20%20System.out.println(watch.getTime())%3B%0A%20%20%20%20%20System.out.println(%22%E7%BB%9F%E8%AE%A1%E4%BB%8E%E5%BC%80%E5%A7%8B%E5%88%B0%E7%8E%B0%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%9A%22%20%2B%20watch.getTime()%20%2B%20%22ms%22)%3B%0A%0A%20%20%20%20%20Thread.sleep(1000)%3B%0A%20%20%20%20%20watch.split()%3B%0A%20%20%20%20%20System.out.println(%22%E4%BB%8Estart%E5%88%B0%E6%AD%A4%E5%88%BB%E4%B8%BA%E6%AD%A2%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%9A%22%20%2B%20watch.getTime())%3B%0A%20%20%20%20%20System.out.println(%22%E4%BB%8E%E5%BC%80%E5%A7%8B%E5%88%B0%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%88%87%E5%85%A5%E7%82%B9%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%9A%22%20%2B%20watch.getSplitTime())%3B%0A%20%20%20%20%20Thread.sleep(1000)%3B%0A%20%20%20%20%20watch.split()%3B%0A%20%20%20%20%20System.out.println(%22%E4%BB%8E%E5%BC%80%E5%A7%8B%E5%88%B0%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%88%87%E5%85%A5%E7%82%B9%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%9A%22%20%2B%20watch.getSplitTime())%3B%0A%0A%20%20%20%20%20%2F%2F%20%E5%A4%8D%E4%BD%8D%E5%90%8E%2C%20%E9%87%8D%E6%96%B0%E8%AE%A1%E6%97%B6%0A%20%20%20%20%20watch.reset()%3B%0A%20%20%20%20%20watch.start()%3B%0A%20%20%20%20%20Thread.sleep(1000)%3B%0A%20%20%20%20%20System.out.println(%22%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B%E5%90%8E%E5%88%B0%E5%BD%93%E5%89%8D%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%E6%98%AF%EF%BC%9A%22%20%2B%20watch.getTime())%3B%0A%0A%20%20%20%20%20%2F%2F%20%E6%9A%82%E5%81%9C%20%E4%B8%8E%20%E6%81%A2%E5%A4%8D%0A%20%20%20%20%20watch.suspend()%3B%0A%20%20%20%20%20System.out.println(%22%E6%9A%82%E5%81%9C2%E7%A7%92%E9%92%9F%22)%3B%0A%20%20%20%20%20Thread.sleep(2000)%3B%0A%0A%20%20%20%20%20%2F%2F%20%E4%B8%8A%E9%9D%A2suspend%EF%BC%8C%E8%BF%99%E9%87%8C%E8%A6%81%E6%83%B3%E9%87%8D%E6%96%B0%E7%BB%9F%E8%AE%A1%EF%BC%8C%E9%9C%80%E8%A6%81%E6%81%A2%E5%A4%8D%E4%B8%80%E4%B8%8B%0A%20%20%20%20%20watch.resume()%3B%0A%20%20%20%20%20System.out.println(%22%E6%81%A2%E5%A4%8D%E5%90%8E%E6%89%A7%E8%A1%8C%E7%9A%84%E6%97%B6%E9%97%B4%E6%98%AF%EF%BC%9A%22%20%2B%20watch.getTime())%3B%0A%0A%20%20%20%20%20Thread.sleep(1000)%3B%0A%20%20%20%20%20watch.stop()%3B%0A%0A%20%20%20%20%20System.out.println(%22%E8%8A%B1%E8%B4%B9%E7%9A%84%E6%97%B6%E9%97%B4%E3%80%8B%E3%80%8B%22%20%2B%20watch.getTime()%20%2B%20%22ms%22)%3B%0A%20%20%20%20%20%2F%2F%20%E7%9B%B4%E6%8E%A5%E8%BD%AC%E6%88%90s%0A%20%20%20%20%20System.out.println(%22%E8%8A%B1%E8%B4%B9%E7%9A%84%E6%97%B6%E9%97%B4%E3%80%8B%E3%80%8B%22%20%2B%20watch.getTime(TimeUnit.SECONDS)%20%2B%20%22s%22)%3B%0A%20%7D%0A%60%60%60%0A%0A%3E%20%E7%BB%93%E6%9E%9C%0A%0A%60%60%60%0A1002%0A%E7%BB%9F%E8%AE%A1%E4%BB%8E%E5%BC%80%E5%A7%8B%E5%88%B0%E7%8E%B0%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%9A1006ms%0A%E4%BB%8Estart%E5%88%B0%E6%AD%A4%E5%88%BB%E4%B8%BA%E6%AD%A2%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%9A2017%0A%E4%BB%8E%E5%BC%80%E5%A7%8B%E5%88%B0%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%88%87%E5%85%A5%E7%82%B9%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%9A2017%0A%E4%BB%8E%E5%BC%80%E5%A7%8B%E5%88%B0%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%88%87%E5%85%A5%E7%82%B9%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%9A3017%0A%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B%E5%90%8E%E5%88%B0%E5%BD%93%E5%89%8D%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%E6%98%AF%EF%BC%9A1000%0A%E6%9A%82%E5%81%9C2%E7%A7%92%E9%92%9F%0A%E6%81%A2%E5%A4%8D%E5%90%8E%E6%89%A7%E8%A1%8C%E7%9A%84%E6%97%B6%E9%97%B4%E6%98%AF%EF%BC%9A1000%0A%E8%8A%B1%E8%B4%B9%E7%9A%84%E6%97%B6%E9%97%B4%E3%80%8B%E3%80%8B2001ms%0A%E8%8A%B1%E8%B4%B9%E7%9A%84%E6%97%B6%E9%97%B4%E3%80%8B%E3%80%8B2s%0A%60%60%60

内部类

创建时间:2022/6/28 16:20
更新时间:2022/6/28 16:24
作者:Chris

使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

  • 1、内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
  • 2、在单个外部类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
  • 3、创建内部类对象的时刻并不依赖于外部类对象的创建。
  • 4、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
  • 5、内部类提供了更好的封装,除了该外部类,其他类都不能访问。

内部类是个编译时的概念,一旦编译成功后,它就与外部类属于两个完全不同的类(当然他们之间还是有联系的)。

对于一个名为 OuterClass 的外部类和一个名为 InnerClass 的内部类,在编译成功后,会出现这样两个class文件:OuterClass.class

OuterClass$InnerClass.class。

1. 成员内部类

在成员内部类中要注意两点,
第一:成员内部类中不能存在任何static的变量和方法;

第二:成员内部类是依附于外部类的,所以只有先创建了外部类才能够创建内部类。

    1. 在外部类内部创建内部类对象 Inner inner = new Inner();
    1. 在外部类外部创建内部类对象,Outter.Inner inner = new Outter().new Inner();

第三: 在内部类内部使用隐藏的外部类对象 隐藏的 this

@Getter
public class Outer {
    private String name = "outer";
    private String outer = "I'm outer";
    private Inner innerInstance;

    // 推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时
    public Inner getInnerInstance() {
        if (null == innerInstance) {
            innerInstance = new Inner();
        }
        return innerInstance;
    }

    @Getter
    class Inner {
        private String name = "inner";

        public Inner() {
            System.out.println("construct inner cls");
            System.out.println("outer:" + outer + ", " + name);

            //if you wanna visit outer'name
            System.out.println("outer:" + outer + ", " + Outer.this.name);
        }
    }


在外部类的外部创建内部类

public class TestInner {
    public static void main(String[] args) {
        Outer outer = new Outer();
        // the first way to create inner instance
        // Outer.Inner inner = outer.new Inner();

        // the second way to create inner instance
        Outer.Inner inner = outer.getInnerInstance();
        System.out.println(outer.getName());
        System.out.println(inner.getName());
    }
}

2. 静态内部类

定义在外部类的内部,使用static修饰,类比静态方法,静态内部类不需要产生外部类对象就能使用

  • 外部类内部:与成员内部类一样 Inner inner = new Inner();

  • 在外部类外部创建内部类对象 Outer2.Inner inner = new Outer2.Inner();

静态内部类不能访问外部类的成员域,但能访问静态域。

@Getter
public class Outer2 {
    private String name = "outer";
    private static String outer="I'm outer";

    @Getter
    static class Inner {
        private String name = "inner";

        public static void descInner() {
            System.out.println("outer:" + outer);
        }
    }
}

public class TestStaticInner {
    public static void main(String[] args) {
        Outer2.Inner inner  = new Outer2.Inner();
        System.out.println(inner.getName());
        Outer2.Inner.descInner();
    }
}

3. 方法内部类

定义在方法内部:类比局部变量

    1. 对外部完全隐藏,因此方法内部类不能有任何访问修饰符
    1. 方法内部类没有访问形参是,这个形参是可以在方法中随意修改的,一旦方法内部类中使用了形参,这个形参必须被声明为final。

4. 匿名内部类

  1. 必须继承一个抽象类或者实现一个接口

  2. 没有构造方法

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

@Test
public void test1() {
    Runnable r1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("hellow runnable r1.");
        }
    };
    r1.run();

    //Lambda表达式做为左边接口的一个实例
    Runnable r2 = () -> System.out.println("hellow runnable r2.");
    r2.run();
}
%5Btoc%5D%0A%0A%0A%0A%3E%20%E4%BD%BF%E7%94%A8%E5%86%85%E9%83%A8%E7%B1%BB%E6%9C%80%E5%90%B8%E5%BC%95%E4%BA%BA%E7%9A%84%E5%8E%9F%E5%9B%A0%E6%98%AF%EF%BC%9A%E6%AF%8F%E4%B8%AA%E5%86%85%E9%83%A8%E7%B1%BB%E9%83%BD%E8%83%BD%E7%8B%AC%E7%AB%8B%E5%9C%B0%E7%BB%A7%E6%89%BF%E4%B8%80%E4%B8%AA%EF%BC%88%E6%8E%A5%E5%8F%A3%E7%9A%84%EF%BC%89%E5%AE%9E%E7%8E%B0%EF%BC%8C%E6%89%80%E4%BB%A5%E6%97%A0%E8%AE%BA%E5%A4%96%E9%83%A8%E7%B1%BB%E6%98%AF%E5%90%A6%E5%B7%B2%E7%BB%8F%E7%BB%A7%E6%89%BF%E4%BA%86%E6%9F%90%E4%B8%AA%EF%BC%88%E6%8E%A5%E5%8F%A3%E7%9A%84%EF%BC%89%E5%AE%9E%E7%8E%B0%EF%BC%8C%E5%AF%B9%E4%BA%8E%E5%86%85%E9%83%A8%E7%B1%BB%E9%83%BD%E6%B2%A1%E6%9C%89%E5%BD%B1%E5%93%8D%E3%80%82%0A%3E%20-%201%E3%80%81%E5%86%85%E9%83%A8%E7%B1%BB%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%A4%9A%E4%B8%AA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E6%AF%8F%E4%B8%AA%E5%AE%9E%E4%BE%8B%E9%83%BD%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E7%8A%B6%E6%80%81%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%B8%8E%E5%85%B6%E4%BB%96%E5%A4%96%E5%9B%B4%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%BF%A1%E6%81%AF%E7%9B%B8%E4%BA%92%E7%8B%AC%E7%AB%8B%E3%80%82%0A%3E%20-%202%E3%80%81%E5%9C%A8%E5%8D%95%E4%B8%AA%E5%A4%96%E9%83%A8%E7%B1%BB%E4%B8%AD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%AE%A9%E5%A4%9A%E4%B8%AA%E5%86%85%E9%83%A8%E7%B1%BB%E4%BB%A5%E4%B8%8D%E5%90%8C%E7%9A%84%E6%96%B9%E5%BC%8F%E5%AE%9E%E7%8E%B0%E5%90%8C%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%EF%BC%8C%E6%88%96%E8%80%85%E7%BB%A7%E6%89%BF%E5%90%8C%E4%B8%80%E4%B8%AA%E7%B1%BB%E3%80%82%0A%3E%20-%203%E3%80%81%E5%88%9B%E5%BB%BA%E5%86%85%E9%83%A8%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%97%B6%E5%88%BB%E5%B9%B6%E4%B8%8D%E4%BE%9D%E8%B5%96%E4%BA%8E%E5%A4%96%E9%83%A8%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%88%9B%E5%BB%BA%E3%80%82%0A%3E%20-%204%E3%80%81%E5%86%85%E9%83%A8%E7%B1%BB%E5%B9%B6%E6%B2%A1%E6%9C%89%E4%BB%A4%E4%BA%BA%E8%BF%B7%E6%83%91%E7%9A%84%E2%80%9Cis-a%E2%80%9D%E5%85%B3%E7%B3%BB%EF%BC%8C%E4%BB%96%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E7%8B%AC%E7%AB%8B%E7%9A%84%E5%AE%9E%E4%BD%93%E3%80%82%0A%3E%20-%205%E3%80%81%E5%86%85%E9%83%A8%E7%B1%BB%E6%8F%90%E4%BE%9B%E4%BA%86%E6%9B%B4%E5%A5%BD%E7%9A%84%E5%B0%81%E8%A3%85%EF%BC%8C%E9%99%A4%E4%BA%86%E8%AF%A5%E5%A4%96%E9%83%A8%E7%B1%BB%EF%BC%8C%E5%85%B6%E4%BB%96%E7%B1%BB%E9%83%BD%E4%B8%8D%E8%83%BD%E8%AE%BF%E9%97%AE%E3%80%82%0A%0A%0A%0A%3E%20%E5%86%85%E9%83%A8%E7%B1%BB%E6%98%AF%E4%B8%AA%E7%BC%96%E8%AF%91%E6%97%B6%E7%9A%84%E6%A6%82%E5%BF%B5%EF%BC%8C%E4%B8%80%E6%97%A6%E7%BC%96%E8%AF%91%E6%88%90%E5%8A%9F%E5%90%8E%EF%BC%8C%E5%AE%83%E5%B0%B1%E4%B8%8E%E5%A4%96%E9%83%A8%E7%B1%BB%E5%B1%9E%E4%BA%8E%E4%B8%A4%E4%B8%AA%E5%AE%8C%E5%85%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E7%B1%BB%EF%BC%88%E5%BD%93%E7%84%B6%E4%BB%96%E4%BB%AC%E4%B9%8B%E9%97%B4%E8%BF%98%E6%98%AF%E6%9C%89%E8%81%94%E7%B3%BB%E7%9A%84%EF%BC%89%E3%80%82%0A%3E%0A%3E%20%E5%AF%B9%E4%BA%8E%E4%B8%80%E4%B8%AA%E5%90%8D%E4%B8%BA%20OuterClass%20%E7%9A%84%E5%A4%96%E9%83%A8%E7%B1%BB%E5%92%8C%E4%B8%80%E4%B8%AA%E5%90%8D%E4%B8%BA%20InnerClass%20%E7%9A%84%E5%86%85%E9%83%A8%E7%B1%BB%EF%BC%8C%E5%9C%A8%E7%BC%96%E8%AF%91%E6%88%90%E5%8A%9F%E5%90%8E%EF%BC%8C%E4%BC%9A%E5%87%BA%E7%8E%B0%E8%BF%99%E6%A0%B7%E4%B8%A4%E4%B8%AAclass%E6%96%87%E4%BB%B6%EF%BC%9AOuterClass.class%0A%3E%0A%3E%20OuterClass%24InnerClass.class%E3%80%82%0A%0A%23%23%201.%20%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%0A%0A%3E%20%20%E5%9C%A8%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%AD%E8%A6%81%E6%B3%A8%E6%84%8F%E4%B8%A4%E7%82%B9%EF%BC%8C%0A%3E%20%20%E7%AC%AC%E4%B8%80%EF%BC%9A%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%AD%E4%B8%8D%E8%83%BD%E5%AD%98%E5%9C%A8%E4%BB%BB%E4%BD%95%60static%60%E7%9A%84%E5%8F%98%E9%87%8F%E5%92%8C%E6%96%B9%E6%B3%95%EF%BC%9B%0A%3E%0A%3E%20%20%E7%AC%AC%E4%BA%8C%EF%BC%9A%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%E6%98%AF%E4%BE%9D%E9%99%84%E4%BA%8E%E5%A4%96%E9%83%A8%E7%B1%BB%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E5%8F%AA%E6%9C%89%E5%85%88%E5%88%9B%E5%BB%BA%E4%BA%86%E5%A4%96%E9%83%A8%E7%B1%BB%E6%89%8D%E8%83%BD%E5%A4%9F%E5%88%9B%E5%BB%BA%E5%86%85%E9%83%A8%E7%B1%BB%E3%80%82%0A%3E%0A%3E%20%20-%201.%20%E5%9C%A8%E5%A4%96%E9%83%A8%E7%B1%BB%E5%86%85%E9%83%A8%E5%88%9B%E5%BB%BA%E5%86%85%E9%83%A8%E7%B1%BB%E5%AF%B9%E8%B1%A1%20%60Inner%20inner%20%3D%20new%20Inner()%3B%60%0A%3E%0A%3E%20%20-%202.%20%E5%9C%A8%E5%A4%96%E9%83%A8%E7%B1%BB%E5%A4%96%E9%83%A8%E5%88%9B%E5%BB%BA%E5%86%85%E9%83%A8%E7%B1%BB%E5%AF%B9%E8%B1%A1%EF%BC%8C%60Outter.Inner%20inner%20%3D%20new%20Outter().new%20Inner()%3B%60%0A%3E%0A%3E%20%20%E7%AC%AC%E4%B8%89%3A%20%20%E5%9C%A8%E5%86%85%E9%83%A8%E7%B1%BB%E5%86%85%E9%83%A8%E4%BD%BF%E7%94%A8%E9%9A%90%E8%97%8F%E7%9A%84%E5%A4%96%E9%83%A8%E7%B1%BB%E5%AF%B9%E8%B1%A1%20%60%E9%9A%90%E8%97%8F%E7%9A%84%20this%60%0A%0A%60%60%60java%0A%40Getter%0Apublic%20class%20Outer%20%7B%0A%20%20%20%20private%20String%20name%20%3D%20%22outer%22%3B%0A%20%20%20%20private%20String%20outer%20%3D%20%22I'm%20outer%22%3B%0A%20%20%20%20private%20Inner%20innerInstance%3B%0A%0A%20%20%20%20%2F%2F%20%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8getxxx()%E6%9D%A5%E8%8E%B7%E5%8F%96%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%EF%BC%8C%E5%B0%A4%E5%85%B6%E6%98%AF%E8%AF%A5%E5%86%85%E9%83%A8%E7%B1%BB%E7%9A%84%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E6%97%A0%E5%8F%82%E6%95%B0%E6%97%B6%0A%20%20%20%20public%20Inner%20getInnerInstance()%20%7B%0A%20%20%20%20%20%20%20%20if%20(null%20%3D%3D%20innerInstance)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20innerInstance%20%3D%20new%20Inner()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20innerInstance%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Getter%0A%20%20%20%20class%20Inner%20%7B%0A%20%20%20%20%20%20%20%20private%20String%20name%20%3D%20%22inner%22%3B%0A%0A%20%20%20%20%20%20%20%20public%20Inner()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22construct%20inner%20cls%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22outer%3A%22%20%2B%20outer%20%2B%20%22%2C%20%22%20%2B%20name)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fif%20you%20wanna%20visit%20outer'name%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22outer%3A%22%20%2B%20outer%20%2B%20%22%2C%20%22%20%2B%20Outer.this.name)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%60%60%60%0A!%5B1ef2025c22013926fb9122150bb24caa.png%5D(en-resource%3A%2F%2Fdatabase%2F1798%3A1)%0A!%5B773718475be57bf44d689e2844b66dfd.png%5D(en-resource%3A%2F%2Fdatabase%2F1800%3A1)%0A%0A%0A%3E%20%20%E5%9C%A8%E5%A4%96%E9%83%A8%E7%B1%BB%E7%9A%84%E5%A4%96%E9%83%A8%E5%88%9B%E5%BB%BA%E5%86%85%E9%83%A8%E7%B1%BB%0A%0A%60%60%60java%0Apublic%20class%20TestInner%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20Outer%20outer%20%3D%20new%20Outer()%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20the%20first%20way%20to%20create%20inner%20instance%0A%20%20%20%20%20%20%20%20%2F%2F%20Outer.Inner%20inner%20%3D%20outer.new%20Inner()%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20the%20second%20way%20to%20create%20inner%20instance%0A%20%20%20%20%20%20%20%20Outer.Inner%20inner%20%3D%20outer.getInnerInstance()%3B%0A%20%20%20%20%20%20%20%20System.out.println(outer.getName())%3B%0A%20%20%20%20%20%20%20%20System.out.println(inner.getName())%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%202.%20%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB%0A%0A%3E%20%E5%AE%9A%E4%B9%89%E5%9C%A8%E5%A4%96%E9%83%A8%E7%B1%BB%E7%9A%84%E5%86%85%E9%83%A8%EF%BC%8C%E4%BD%BF%E7%94%A8static%E4%BF%AE%E9%A5%B0%EF%BC%8C%E7%B1%BB%E6%AF%94%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%EF%BC%8C%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%8D%E9%9C%80%E8%A6%81%E4%BA%A7%E7%94%9F%E5%A4%96%E9%83%A8%E7%B1%BB%E5%AF%B9%E8%B1%A1%E5%B0%B1%E8%83%BD%E4%BD%BF%E7%94%A8%0A%3E%0A%3E%20-%20%E5%A4%96%E9%83%A8%E7%B1%BB%E5%86%85%E9%83%A8%EF%BC%9A%E4%B8%8E%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%80%E6%A0%B7%20%60Inner%20inner%20%3D%20new%20Inner()%3B%60%0A%3E%0A%3E%20-%20%20%20%E5%9C%A8%E5%A4%96%E9%83%A8%E7%B1%BB%E5%A4%96%E9%83%A8%E5%88%9B%E5%BB%BA%E5%86%85%E9%83%A8%E7%B1%BB%E5%AF%B9%E8%B1%A1%20%60Outer2.Inner%20inner%20%20%3D%20new%20Outer2.Inner()%3B%60%0A%3E%0A%3E%20%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%8D%E8%83%BD%E8%AE%BF%E9%97%AE%E5%A4%96%E9%83%A8%E7%B1%BB%E7%9A%84%E6%88%90%E5%91%98%E5%9F%9F%EF%BC%8C%E4%BD%86%E8%83%BD%E8%AE%BF%E9%97%AE%E9%9D%99%E6%80%81%E5%9F%9F%E3%80%82%0A%0A%60%60%60java%0A%40Getter%0Apublic%20class%20Outer2%20%7B%0A%20%20%20%20private%20String%20name%20%3D%20%22outer%22%3B%0A%20%20%20%20private%20static%20String%20outer%3D%22I'm%20outer%22%3B%0A%0A%20%20%20%20%40Getter%0A%20%20%20%20static%20class%20Inner%20%7B%0A%20%20%20%20%20%20%20%20private%20String%20name%20%3D%20%22inner%22%3B%0A%0A%20%20%20%20%20%20%20%20public%20static%20void%20descInner()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22outer%3A%22%20%2B%20outer)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%0Apublic%20class%20TestStaticInner%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20Outer2.Inner%20inner%20%20%3D%20new%20Outer2.Inner()%3B%0A%20%20%20%20%20%20%20%20System.out.println(inner.getName())%3B%0A%20%20%20%20%20%20%20%20Outer2.Inner.descInner()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%203.%20%E6%96%B9%E6%B3%95%E5%86%85%E9%83%A8%E7%B1%BB%0A%0A%3E%20%E5%AE%9A%E4%B9%89%E5%9C%A8%E6%96%B9%E6%B3%95%E5%86%85%E9%83%A8%EF%BC%9A%E7%B1%BB%E6%AF%94%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%0A%3E%0A%3E%20-%201.%20%E5%AF%B9%E5%A4%96%E9%83%A8%E5%AE%8C%E5%85%A8%E9%9A%90%E8%97%8F%EF%BC%8C%E5%9B%A0%E6%AD%A4%E6%96%B9%E6%B3%95%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%8D%E8%83%BD%E6%9C%89%E4%BB%BB%E4%BD%95%E8%AE%BF%E9%97%AE%E4%BF%AE%E9%A5%B0%E7%AC%A6%0A%3E%0A%3E%20-%202.%20%E6%96%B9%E6%B3%95%E5%86%85%E9%83%A8%E7%B1%BB%E6%B2%A1%E6%9C%89%E8%AE%BF%E9%97%AE%E5%BD%A2%E5%8F%82%E6%98%AF%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%BD%A2%E5%8F%82%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%AD%E9%9A%8F%E6%84%8F%E4%BF%AE%E6%94%B9%E7%9A%84%EF%BC%8C%E4%B8%80%E6%97%A6%E6%96%B9%E6%B3%95%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%AD%E4%BD%BF%E7%94%A8%E4%BA%86%E5%BD%A2%E5%8F%82%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%BD%A2%E5%8F%82%E5%BF%85%E9%A1%BB%E8%A2%AB%E5%A3%B0%E6%98%8E%E4%B8%BAfinal%E3%80%82%0A%0A%23%23%204.%20%E5%8C%BF%E5%90%8D%E5%86%85%E9%83%A8%E7%B1%BB%0A%0A%3E%201.%20%E5%BF%85%E9%A1%BB%E7%BB%A7%E6%89%BF%E4%B8%80%E4%B8%AA%E6%8A%BD%E8%B1%A1%E7%B1%BB%E6%88%96%E8%80%85%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%0A%3E%0A%3E%202.%20%E6%B2%A1%E6%9C%89%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%0A%0A%60%60%60java%0A%40FunctionalInterface%0Apublic%20interface%20Runnable%20%7B%0A%20%20%20%20public%20abstract%20void%20run()%3B%0A%7D%0A%0A%40Test%0Apublic%20void%20test1()%20%7B%0A%20%20%20%20Runnable%20r1%20%3D%20new%20Runnable()%20%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22hellow%20runnable%20r1.%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%3B%0A%20%20%20%20r1.run()%3B%0A%0A%20%20%20%20%2F%2FLambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%81%9A%E4%B8%BA%E5%B7%A6%E8%BE%B9%E6%8E%A5%E5%8F%A3%E7%9A%84%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%0A%20%20%20%20Runnable%20r2%20%3D%20()%20-%3E%20System.out.println(%22hellow%20runnable%20r2.%22)%3B%0A%20%20%20%20r2.run()%3B%0A%7D%0A%60%60%60%0A%0A

tmp

创建时间:2021/12/29 18:24
更新时间:2022/6/13 10:09
作者:Chris
来源:https://odocs.myoas.com/sheets/gXqmeOVOV2FRPDqo/MODOC?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJvcHBvLW10cCIsInN1YiI6IjEzNjIyMzE0NTM5IiwiaXNzIjoiU1QtMTYzNTMyMDgtU0trWkJlS2ZhVDZLVkFsOW1sZWYtU0lBTSIsIm5hbWUiOiJTSUFNU1QiLCJ0eXBlIjoiU1QiLCJpYXQiOjE2NDA3NzMzMjd9.VDOYPsOBAtiHk7HfIlFYN6ESBF-5cNJ4iNE-DsN-TNA&tt_lang=en-US&new_client=1&ticket=APPURLWITHTICKETa2ec6b8be113b4a801514526c4ab58e7&client_id=100097&expire_time=1640776927331&msgShowStyle=31


@Configuration public class JsonConfigureAdapter implements WebMvcConfigurer


com.fasterxml.jackson.databind.ObjectMapper com.fasterxml.jackson.databind.ObjectMapper#convertValue(java.lang.Object, java.lang.Class<T>) ObjectMapper mapper = new ObjectMapper(); Map<String, Object> itemAttrMap = new HashMap<>(16); T item = mapper.convertValue(itemAttrMap, targetClass); com.fasterxml.jackson.databind.ObjectMapper#readValue(java.lang.String, java.lang.Class<T>) String result = response.body().string(); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); ALMBatchGsmRespBO almBatchGsmRespBO = objectMapper.readValue(result, ALMBatchGsmRespBO.class);



链接:https://pan.baidu.com/s/1fNkTZBKgC7FWeBuim5jBSg 
提取码:78o0 

AutoCloseable

创建时间:2021/3/24 11:19
更新时间:2022/6/9 19:05
作者:Chris

1. AutoCloseable

  1. AutoCloseable接口,表示一种不再使用时需要关闭的资源。这个接口下只有一个方法,close()。这个方法在try-with-resource语法下会被自动调用,支持抛出Exception,当然它也鼓励抛出更详细的异常。
  2. close()建议不要抛出线程中断的 InterruptedException。
  3. 对这个接口的实现,规范强烈建议close()是幂等的,也就是说多次调用close()方法和一次调用的结果是一样的。
@Test
public void TestTryWithResource() {   
    try (MyResource1 resource1 = new MyResource1(); 
    MyResource2 resource2 = new MyResource2()) {        
        resource1.readResource();       
        resource2.readResource();   
    } catch (Exception e) {       
        e.printStackTrace();    
    }
}
public class MyResource1 implements Closeable {
    @Override
    public void close() throws IOException {
        System.out.println("close resource1");
    }

    public void readResource() {
        System.out.println("read resource1");
    }
}
public class MyResource2 implements Closeable {
    @Override
    public void close() throws IOException {
        System.out.println("close resource2");
    }

    public void readResource() {
        System.out.println("read resource2");
    }
}

2. 关于带资源的try语句的3个关键点

%5Btoc%5D%0A%0A%23%23%23%23%201.%20AutoCloseable%0A%0A%3E%201.%20%20AutoCloseable%E6%8E%A5%E5%8F%A3%EF%BC%8C%E8%A1%A8%E7%A4%BA%E4%B8%80%E7%A7%8D%E4%B8%8D%E5%86%8D%E4%BD%BF%E7%94%A8%E6%97%B6%E9%9C%80%E8%A6%81%E5%85%B3%E9%97%AD%E7%9A%84%E8%B5%84%E6%BA%90%E3%80%82%E8%BF%99%E4%B8%AA%E6%8E%A5%E5%8F%A3%E4%B8%8B%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8Cclose()%E3%80%82%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E5%9C%A8try-with-resource%E8%AF%AD%E6%B3%95%E4%B8%8B%E4%BC%9A%E8%A2%AB%E8%87%AA%E5%8A%A8%E8%B0%83%E7%94%A8%EF%BC%8C%E6%94%AF%E6%8C%81%E6%8A%9B%E5%87%BAException%EF%BC%8C%E5%BD%93%E7%84%B6%E5%AE%83%E4%B9%9F%E9%BC%93%E5%8A%B1%E6%8A%9B%E5%87%BA%E6%9B%B4%E8%AF%A6%E7%BB%86%E7%9A%84%E5%BC%82%E5%B8%B8%E3%80%82%0A%3E%202.%20close()%E5%BB%BA%E8%AE%AE%E4%B8%8D%E8%A6%81%E6%8A%9B%E5%87%BA%E7%BA%BF%E7%A8%8B%E4%B8%AD%E6%96%AD%E7%9A%84%20InterruptedException%E3%80%82%0A%3E%203.%20%E5%AF%B9%E8%BF%99%E4%B8%AA%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%AE%9E%E7%8E%B0%EF%BC%8C%E8%A7%84%E8%8C%83%E5%BC%BA%E7%83%88%E5%BB%BA%E8%AE%AEclose()%E6%98%AF%E5%B9%82%E7%AD%89%E7%9A%84%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%E5%A4%9A%E6%AC%A1%E8%B0%83%E7%94%A8close()%E6%96%B9%E6%B3%95%E5%92%8C%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%E7%9A%84%E7%BB%93%E6%9E%9C%E6%98%AF%E4%B8%80%E6%A0%B7%E7%9A%84%E3%80%82%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20TestTryWithResource()%20%7B%C2%A0%C2%A0%C2%A0%0A%20%20%20%20try%20(MyResource1%20resource1%20%3D%20new%20MyResource1()%3B%20%0A%20%20%20%20MyResource2%20resource2%20%3D%20new%20MyResource2())%20%7B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%0A%20%20%20%20%20%20%20%20resource1.readResource()%3B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%0A%20%20%20%20%20%20%20%20resource2.readResource()%3B%C2%A0%C2%A0%C2%A0%0A%20%20%20%20%7D%20catch%20(Exception%20e)%20%7B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%C2%A0%C2%A0%C2%A0%20%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%60%60%60java%0Apublic%20class%20MyResource1%20implements%20Closeable%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20close()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22close%20resource1%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20void%20readResource()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22read%20resource1%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%60%60%60java%0Apublic%20class%20MyResource2%20implements%20Closeable%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20close()%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22close%20resource2%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20void%20readResource()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22read%20resource2%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202.%20%E5%85%B3%E4%BA%8E%E5%B8%A6%E8%B5%84%E6%BA%90%E7%9A%84try%E8%AF%AD%E5%8F%A5%E7%9A%843%E4%B8%AA%E5%85%B3%E9%94%AE%E7%82%B9%0A%20*%201.%20%E7%94%B1%E5%B8%A6%E8%B5%84%E6%BA%90%E7%9A%84try%E8%AF%AD%E5%8F%A5%E7%AE%A1%E7%90%86%E7%9A%84%E8%B5%84%E6%BA%90%E5%BF%85%E9%A1%BB%E6%98%AF%E5%AE%9E%E7%8E%B0%E4%BA%86AutoCloseable%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%E7%9A%84%E5%AF%B9%E8%B1%A1%E3%80%82%0A%20*%202.%20%E5%9C%A8try%E4%BB%A3%E7%A0%81%E4%B8%AD%E5%A3%B0%E6%98%8E%E7%9A%84%E8%B5%84%E6%BA%90%E8%A2%AB%E9%9A%90%E5%BC%8F%E5%A3%B0%E6%98%8E%E4%B8%BAfinal%E3%80%82%0A%20*%203.%20%E9%80%9A%E8%BF%87%E4%BD%BF%E7%94%A8%E5%88%86%E5%8F%B7%E5%88%86%E9%9A%94%E6%AF%8F%E4%B8%AA%E5%A3%B0%E6%98%8E%E5%8F%AF%E4%BB%A5%E7%AE%A1%E7%90%86%E5%A4%9A%E4%B8%AA%E8%B5%84%E6%BA%90%E3%80%82

design pattern

创建时间:2020/9/2 15:08
更新时间:2022/5/2 12:27
作者:Chris

1. 学习设计模式的意义

http://c.biancheng.net/view/1343.html

设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解

1.1 单例(Singleton)模式:

某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。

1.2 原型(Prototype)模式:

将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。

1.3 工厂方法(Factory Method)模式:

定义一个用于创建产品的接口,由子类决定生产什么产品。

1.4 抽象工厂(AbstractFactory)模式:

提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。

1.5 建造者(Builder)模式:

将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。

1.6 代理(Proxy)模式:

为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

1.7 适配器(Adapter)模式:

将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

1.8 桥接(Bridge)模式:

将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现, 从而降低了抽象和实现这两个可变维度的耦合度。

1.9 装饰(Decorator)模式:

动态的给对象增加一些职责,即增加其额外的功能。

1.10 外观(Facade)模式:

为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。

1.11 享元(Flyweight)模式:

运用共享技术来有效地支持大量细粒度对象的复用。

1.12 组合(Composite)模式:

将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。

1.13 模板方法(TemplateMethod)模式:

定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。

1.14 策略(Strategy)模式:

定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。

1.15 命令(Command)模式:

将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。

1.16 职责链(Chain of Responsibility)模式:

把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

1.17 状态(State)模式:

允许一个对象在其内部状态发生改变时改变其行为能力。

1.18 观察者(Observer)模式:

多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。

1.19 中介者(Mediator)模式:

定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。

1.20 迭代器(Iterator)模式:

提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

1.21 访问者(Visitor)模式:

在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。

1.22 备忘录(Memento)模式:

在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。

1.23 解释器(Interpreter)模式:

提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。

2. 类之间的关系

2.1 依赖(Dependency)

依赖(Dependency)关系是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。
在 UML 类图中,依赖关系使用带箭头的虚线来表示,箭头从使用类指向被依赖的类.

2.2 关联(Association)

关联(Association)关系是对象之间的一种引用关系,用于表示一类对象与另一类对象之间的联系,如老师和学生、师傅和徒弟、丈夫和妻子等。
关联可以是双向的,也可以是单向的

在 UML 类图中,双向的关联可以用带两个箭头或者没有箭头的实线来表示,单向的关联用带一个箭头的实线来表示,箭头从使用类指向被关联的类。也可以在关联线的两端标注角色名,代表两种不同的角色。

2.3 聚合(Aggregation)

聚合(Aggregation)关系是关联关系的一种,是强关联关系,是整体和部分之间的关系,是 has-a 的关系。

聚合关系也是通过成员对象来实现的,其中成员对象是整体对象的一部分,但是成员对象可以脱离整体对象而独立存在。例如,学校与老师的关系,学校包含老师,但如果学校停办了,老师依然存在。

在 UML 类图中,聚合关系可以用带空心菱形的实线来表示,菱形指向整体。

2.4 组合(Composition)

组合(Composition)关系也是关联关系的一种,也表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系,是 cxmtains-a 关系。

在组合关系中,整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。例如,头和嘴的关系,没有了头,嘴也就不存在了。
在 UML 类图中,组合关系用带实心菱形的实线来表示,菱形指向整体。图 7 所示是头和嘴的关系图。

2.5 泛化(Generalization)

泛化(Generalization)关系是对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的关系,是一种继承关系,是 is-a 的关系。

在 UML 类图中,泛化关系用带空心三角箭头的实线来表示,箭头从子类指向父类。在代码实现时,使用面向对象的继承机制来实现泛化关系。例如,Student 类和 Teacher 类都是 Person 类的子类.

2.6. 实现(Realization)

实现关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。

3.核心设计原则

3.1 开闭原则(Open Closed Principle,OCP)

定义

软件实体对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modification)

开闭原则的含义是:

当应用的需求改变时,在不修改软件实体的源代码前提下,可以扩展模块的功能,使其满足新的需求。

软件实体包括

  1. 项目中划分出的模块
  2. 类与接口
  3. 方法
3.2 里氏替换原则
  1. 里氏替换原则是实现开闭原则的重要方式之一
  2. 里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
  3. 如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。
  4. 如果程序违背了里氏替换原则,则继承类的对象在基类出现的地方会出现运行错误。这时其修正方法是:取消原来的继承关系,重新设计它们之间的关系。

例如,企鹅、鸵鸟和几维鸟从生物学的角度来划分,它们属于鸟类;但从类的继承关系来看,由于它们不能继承“鸟”会飞的功能,所以它们不能定义成“鸟”的子类

package principle;
public class LSPtest
{
    public static void main(String[] args)
    {
        Bird bird1=new Swallow();
        Bird bird2=new BrownKiwi();
        bird1.setSpeed(120);
        bird2.setSpeed(120);
        System.out.println("如果飞行300公里:");
        try
        {
            System.out.println("燕子将飞行"+bird1.getFlyTime(300)+"小时.");
            System.out.println("几维鸟将飞行"+bird2.getFlyTime(300)+"小时。");
        }
        catch(Exception err)
        {
            System.out.println("发生错误了!");
        }
    }
}
//鸟类
class Bird
{
    double flySpeed;
    public void setSpeed(double speed)
    {
        flySpeed=speed;
    }
    public double getFlyTime(double distance)
    {
        return(distance/flySpeed);
    }
}
//燕子类
class Swallow extends Bird{}
//几维鸟类
class BrownKiwi extends Bird
{
    public void setSpeed(double speed)
    {
           flySpeed=0;
    }
}
3.3 依赖倒置原则(Dependence Inversion Principle,DIP)

定义:
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
其核心思想是:要面向接口编程,不要面向实现编程。

目的:
依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。
由于在软件设计中,细节具有多变性,而抽象层则相对稳定,因此以抽象为基础搭建起来的架构要比以细节为基础搭建起来的架构要稳定得多。

实现原则:

1.每个类尽量提供接口或抽象类,或者两者都具备。
2.变量的声明类型尽量是接口或者是抽象类。
3.任何类都不应该从具体类派生。
4.使用继承时尽量遵循里氏替换原则

package principle;
public class DIPtest
{
    public static void main(String[] args)
    {
        Customer wang=new Customer();
        System.out.println("顾客购买以下商品:"); 
        wang.shopping(new ShaoguanShop()); 
        wang.shopping(new WuyuanShop());
    }
}
//商店
interface Shop
{
    public String sell(); //卖
}
//韶关网店
class ShaoguanShop implements Shop
{
    public String sell()
    {
        return "韶关土特产:香菇、木耳……"; 
    } 
}
//婺源网店
class WuyuanShop implements Shop
{
    public String sell()
    {
        return "婺源土特产:绿茶、酒糟鱼……"; 
    }
} 
//顾客
class Customer
{
    public void shopping(Shop shop)
    {
        //购物
        System.out.println(shop.sell()); 
    }
}
3.4 迪米特法则

定义是:
只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。

含义是:
如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。

目的是:
降低类之间的耦合度,提高模块的相对独立性。

从迪米特法则的定义和特点可知,它强调以下两点:

  1. 从依赖者的角度来说,只依赖应该依赖的对象。
  2. 从被依赖者的角度说,只暴露应该暴露的方法。

实现原则

  1. 在类的划分上,应该创建低耦合的类。类与类之间的耦合越低,就越有利于实现可复用的目标。
  2. 在类的结构设计上,尽量降低类成员的访问权限。
  3. 在类的设计上,优先考虑将一个类设置成不变类。
  4. 在对其他类的引用上,将引用其他对象的次数降到最低。
  5. 不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。
  6. 谨慎使用序列化(Serializable)功能
单例模式
定义:指一个类只有一个实例,且该类能自行创建这个类的实例。

单例模式有3个特点:

1.单例类只有一个实例对象;
2.该单例对象必须由单例类自行创建;
3.单例类对外提供一个访问该单例的全局访问点;

原型模式
定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象

原型模式有2个特点:

1.对象之间相同或相似,即只是个别的几个属性不同的时候。
2.对象的创建过程比较麻烦,但复制比较简单的时候。

工厂方法(Factory Method)模式
定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。

模式的结构

  1. 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
  2. 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  3. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  4. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

建造者(Builder)模式
定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,

该模式的主要优点如下:

  1. 各个具体的建造者相互独立,有利于系统的扩展。
  2. 客户端不必知道产品内部组成的细节,便于控制细节风险。

其缺点如下:

  1. 产品的组成部分必须相同,这限制了其使用范围。
  2. 如果产品的内部变化复杂,该模式会增加很多的建造者类。

模式的应用场景

建造者(Builder)模式创建的是复杂对象,其产品的各个部分经常面临着剧烈的变化,但将它们组合在一起的算法却相对稳定,所以它通常在以下场合使用。

  1. 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。
  2. 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。
装饰(Decorator)模式
定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式

装饰模式主要包含以下角色。

  1. 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  2. 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  3. 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  4. 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
备忘录(Memento
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态

备忘录模式的主要角色如下

  1. 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
  2. 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
  3. 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
%5Btoc%5D%0A%0A%23%23%23%23%201.%20%E5%AD%A6%E4%B9%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%9A%84%E6%84%8F%E4%B9%89%0A%0A%60http%3A%2F%2Fc.biancheng.net%2Fview%2F1343.html%60%0A%0A%3E%20%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%9A%84%E6%9C%AC%E8%B4%A8%E6%98%AF%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%E7%9A%84%E5%AE%9E%E9%99%85%E8%BF%90%E7%94%A8%EF%BC%8C%E6%98%AF%E5%AF%B9%E7%B1%BB%E7%9A%84%E5%B0%81%E8%A3%85%E6%80%A7%E3%80%81%E7%BB%A7%E6%89%BF%E6%80%A7%E5%92%8C%E5%A4%9A%E6%80%81%E6%80%A7%E4%BB%A5%E5%8F%8A%E7%B1%BB%E7%9A%84%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%E5%92%8C%E7%BB%84%E5%90%88%E5%85%B3%E7%B3%BB%E7%9A%84%E5%85%85%E5%88%86%E7%90%86%E8%A7%A3%0A%0A%23%23%23%23%23%201.1%20%E5%8D%95%E4%BE%8B%EF%BC%88Singleton%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%20%20%0A%3E%20%E6%9F%90%E4%B8%AA%E7%B1%BB%E5%8F%AA%E8%83%BD%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E8%AF%A5%E7%B1%BB%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E8%AE%BF%E9%97%AE%E7%82%B9%E4%BE%9B%E5%A4%96%E9%83%A8%E8%8E%B7%E5%8F%96%E8%AF%A5%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%85%B6%E6%8B%93%E5%B1%95%E6%98%AF%E6%9C%89%E9%99%90%E5%A4%9A%E4%BE%8B%E6%A8%A1%E5%BC%8F%E3%80%82%0A%0A%23%23%23%23%23%201.2%20%E5%8E%9F%E5%9E%8B%EF%BC%88Prototype%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%0A%3E%E5%B0%86%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%BD%9C%E4%B8%BA%E5%8E%9F%E5%9E%8B%EF%BC%8C%E9%80%9A%E8%BF%87%E5%AF%B9%E5%85%B6%E8%BF%9B%E8%A1%8C%E5%A4%8D%E5%88%B6%E8%80%8C%E5%85%8B%E9%9A%86%E5%87%BA%E5%A4%9A%E4%B8%AA%E5%92%8C%E5%8E%9F%E5%9E%8B%E7%B1%BB%E4%BC%BC%E7%9A%84%E6%96%B0%E5%AE%9E%E4%BE%8B%E3%80%82%0A%0A%23%23%23%23%23%201.3%20%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95%EF%BC%88Factory%20Method%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%20%20%0A%3E%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E7%94%A8%E4%BA%8E%E5%88%9B%E5%BB%BA%E4%BA%A7%E5%93%81%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E7%94%B1%E5%AD%90%E7%B1%BB%E5%86%B3%E5%AE%9A%E7%94%9F%E4%BA%A7%E4%BB%80%E4%B9%88%E4%BA%A7%E5%93%81%E3%80%82%0A%0A%23%23%23%23%23%201.4%20%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%EF%BC%88AbstractFactory%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%20%20%0A%3E%E6%8F%90%E4%BE%9B%E4%B8%80%E4%B8%AA%E5%88%9B%E5%BB%BA%E4%BA%A7%E5%93%81%E6%97%8F%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%85%B6%E6%AF%8F%E4%B8%AA%E5%AD%90%E7%B1%BB%E5%8F%AF%E4%BB%A5%E7%94%9F%E4%BA%A7%E4%B8%80%E7%B3%BB%E5%88%97%E7%9B%B8%E5%85%B3%E7%9A%84%E4%BA%A7%E5%93%81%E3%80%82%0A%0A%23%23%23%23%23%201.5%20%E5%BB%BA%E9%80%A0%E8%80%85%EF%BC%88Builder%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%20%20%0A%3E%E5%B0%86%E4%B8%80%E4%B8%AA%E5%A4%8D%E6%9D%82%E5%AF%B9%E8%B1%A1%E5%88%86%E8%A7%A3%E6%88%90%E5%A4%9A%E4%B8%AA%E7%9B%B8%E5%AF%B9%E7%AE%80%E5%8D%95%E7%9A%84%E9%83%A8%E5%88%86%EF%BC%8C%E7%84%B6%E5%90%8E%E6%A0%B9%E6%8D%AE%E4%B8%8D%E5%90%8C%E9%9C%80%E8%A6%81%E5%88%86%E5%88%AB%E5%88%9B%E5%BB%BA%E5%AE%83%E4%BB%AC%EF%BC%8C%E6%9C%80%E5%90%8E%E6%9E%84%E5%BB%BA%E6%88%90%E8%AF%A5%E5%A4%8D%E6%9D%82%E5%AF%B9%E8%B1%A1%E3%80%82%0A%0A%23%23%23%23%23%201.6%20%E4%BB%A3%E7%90%86%EF%BC%88Proxy%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%20%E4%B8%BA%E6%9F%90%E5%AF%B9%E8%B1%A1%E6%8F%90%E4%BE%9B%E4%B8%80%E7%A7%8D%E4%BB%A3%E7%90%86%E4%BB%A5%E6%8E%A7%E5%88%B6%E5%AF%B9%E8%AF%A5%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%AE%BF%E9%97%AE%E3%80%82%E5%8D%B3%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%80%9A%E8%BF%87%E4%BB%A3%E7%90%86%E9%97%B4%E6%8E%A5%E5%9C%B0%E8%AE%BF%E9%97%AE%E8%AF%A5%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BB%8E%E8%80%8C%E9%99%90%E5%88%B6%E3%80%81%E5%A2%9E%E5%BC%BA%E6%88%96%E4%BF%AE%E6%94%B9%E8%AF%A5%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%80%E4%BA%9B%E7%89%B9%E6%80%A7%E3%80%82%0A%0A%23%23%23%23%23%201.7%20%E9%80%82%E9%85%8D%E5%99%A8%EF%BC%88Adapter%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%20%E5%B0%86%E4%B8%80%E4%B8%AA%E7%B1%BB%E7%9A%84%E6%8E%A5%E5%8F%A3%E8%BD%AC%E6%8D%A2%E6%88%90%E5%AE%A2%E6%88%B7%E5%B8%8C%E6%9C%9B%E7%9A%84%E5%8F%A6%E5%A4%96%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%EF%BC%8C%E4%BD%BF%E5%BE%97%E5%8E%9F%E6%9C%AC%E7%94%B1%E4%BA%8E%E6%8E%A5%E5%8F%A3%E4%B8%8D%E5%85%BC%E5%AE%B9%E8%80%8C%E4%B8%8D%E8%83%BD%E4%B8%80%E8%B5%B7%E5%B7%A5%E4%BD%9C%E7%9A%84%E9%82%A3%E4%BA%9B%E7%B1%BB%E8%83%BD%E4%B8%80%E8%B5%B7%E5%B7%A5%E4%BD%9C%E3%80%82%0A%0A%23%23%23%23%23%201.8%20%E6%A1%A5%E6%8E%A5%EF%BC%88Bridge%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%B0%86%E6%8A%BD%E8%B1%A1%E4%B8%8E%E5%AE%9E%E7%8E%B0%E5%88%86%E7%A6%BB%EF%BC%8C%E4%BD%BF%E5%AE%83%E4%BB%AC%E5%8F%AF%E4%BB%A5%E7%8B%AC%E7%AB%8B%E5%8F%98%E5%8C%96%E3%80%82%E5%AE%83%E6%98%AF%E7%94%A8%E7%BB%84%E5%90%88%E5%85%B3%E7%B3%BB%E4%BB%A3%E6%9B%BF%E7%BB%A7%E6%89%BF%E5%85%B3%E7%B3%BB%E6%9D%A5%E5%AE%9E%E7%8E%B0%EF%BC%8C%20%20%20%E4%BB%8E%E8%80%8C%E9%99%8D%E4%BD%8E%E4%BA%86%E6%8A%BD%E8%B1%A1%E5%92%8C%E5%AE%9E%E7%8E%B0%E8%BF%99%E4%B8%A4%E4%B8%AA%E5%8F%AF%E5%8F%98%E7%BB%B4%E5%BA%A6%E7%9A%84%E8%80%A6%E5%90%88%E5%BA%A6%E3%80%82%0A%0A%23%23%23%23%23%201.9%20%E8%A3%85%E9%A5%B0%EF%BC%88Decorator%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%8A%A8%E6%80%81%E7%9A%84%E7%BB%99%E5%AF%B9%E8%B1%A1%E5%A2%9E%E5%8A%A0%E4%B8%80%E4%BA%9B%E8%81%8C%E8%B4%A3%EF%BC%8C%E5%8D%B3%E5%A2%9E%E5%8A%A0%E5%85%B6%E9%A2%9D%E5%A4%96%E7%9A%84%E5%8A%9F%E8%83%BD%E3%80%82%0A%0A%23%23%23%23%23%201.10%20%E5%A4%96%E8%A7%82%EF%BC%88Facade%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E4%B8%BA%E5%A4%9A%E4%B8%AA%E5%A4%8D%E6%9D%82%E7%9A%84%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%8F%90%E4%BE%9B%E4%B8%80%E4%B8%AA%E4%B8%80%E8%87%B4%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E4%BD%BF%E8%BF%99%E4%BA%9B%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%9B%B4%E5%8A%A0%E5%AE%B9%E6%98%93%E8%A2%AB%E8%AE%BF%E9%97%AE%E3%80%82%0A%0A%23%23%23%23%23%201.11%20%E4%BA%AB%E5%85%83%EF%BC%88Flyweight%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E8%BF%90%E7%94%A8%E5%85%B1%E4%BA%AB%E6%8A%80%E6%9C%AF%E6%9D%A5%E6%9C%89%E6%95%88%E5%9C%B0%E6%94%AF%E6%8C%81%E5%A4%A7%E9%87%8F%E7%BB%86%E7%B2%92%E5%BA%A6%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%A4%8D%E7%94%A8%E3%80%82%0A%0A%23%23%23%23%23%201.12%20%E7%BB%84%E5%90%88%EF%BC%88Composite%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%B0%86%E5%AF%B9%E8%B1%A1%E7%BB%84%E5%90%88%E6%88%90%E6%A0%91%E7%8A%B6%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84%EF%BC%8C%E4%BD%BF%E7%94%A8%E6%88%B7%E5%AF%B9%E5%8D%95%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%92%8C%E7%BB%84%E5%90%88%E5%AF%B9%E8%B1%A1%E5%85%B7%E6%9C%89%E4%B8%80%E8%87%B4%E7%9A%84%E8%AE%BF%E9%97%AE%E6%80%A7%E3%80%82%0A%0A%23%23%23%23%23%201.13%20%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95%EF%BC%88TemplateMethod%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E6%93%8D%E4%BD%9C%E4%B8%AD%E7%9A%84%E7%AE%97%E6%B3%95%E9%AA%A8%E6%9E%B6%EF%BC%8C%E8%80%8C%E5%B0%86%E7%AE%97%E6%B3%95%E7%9A%84%E4%B8%80%E4%BA%9B%E6%AD%A5%E9%AA%A4%E5%BB%B6%E8%BF%9F%E5%88%B0%E5%AD%90%E7%B1%BB%E4%B8%AD%EF%BC%8C%E4%BD%BF%E5%BE%97%E5%AD%90%E7%B1%BB%E5%8F%AF%E4%BB%A5%E4%B8%8D%E6%94%B9%E5%8F%98%E8%AF%A5%E7%AE%97%E6%B3%95%E7%BB%93%E6%9E%84%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E9%87%8D%E5%AE%9A%E4%B9%89%E8%AF%A5%E7%AE%97%E6%B3%95%E7%9A%84%E6%9F%90%E4%BA%9B%E7%89%B9%E5%AE%9A%E6%AD%A5%E9%AA%A4%E3%80%82%0A%0A%23%23%23%23%23%201.14%20%E7%AD%96%E7%95%A5%EF%BC%88Strategy%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%AE%9A%E4%B9%89%E4%BA%86%E4%B8%80%E7%B3%BB%E5%88%97%E7%AE%97%E6%B3%95%EF%BC%8C%E5%B9%B6%E5%B0%86%E6%AF%8F%E4%B8%AA%E7%AE%97%E6%B3%95%E5%B0%81%E8%A3%85%E8%B5%B7%E6%9D%A5%EF%BC%8C%E4%BD%BF%E5%AE%83%E4%BB%AC%E5%8F%AF%E4%BB%A5%E7%9B%B8%E4%BA%92%E6%9B%BF%E6%8D%A2%EF%BC%8C%E4%B8%94%E7%AE%97%E6%B3%95%E7%9A%84%E6%94%B9%E5%8F%98%E4%B8%8D%E4%BC%9A%E5%BD%B1%E5%93%8D%E4%BD%BF%E7%94%A8%E7%AE%97%E6%B3%95%E7%9A%84%E5%AE%A2%E6%88%B7%E3%80%82%0A%0A%23%23%23%23%23%201.15%20%E5%91%BD%E4%BB%A4%EF%BC%88Command%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%B0%86%E4%B8%80%E4%B8%AA%E8%AF%B7%E6%B1%82%E5%B0%81%E8%A3%85%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BD%BF%E5%8F%91%E5%87%BA%E8%AF%B7%E6%B1%82%E7%9A%84%E8%B4%A3%E4%BB%BB%E5%92%8C%E6%89%A7%E8%A1%8C%E8%AF%B7%E6%B1%82%E7%9A%84%E8%B4%A3%E4%BB%BB%E5%88%86%E5%89%B2%E5%BC%80%E3%80%82%0A%0A%23%23%23%23%23%201.16%20%E8%81%8C%E8%B4%A3%E9%93%BE%EF%BC%88Chain%20of%20Responsibility%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E6%8A%8A%E8%AF%B7%E6%B1%82%E4%BB%8E%E9%93%BE%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%BC%A0%E5%88%B0%E4%B8%8B%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%EF%BC%8C%E7%9B%B4%E5%88%B0%E8%AF%B7%E6%B1%82%E8%A2%AB%E5%93%8D%E5%BA%94%E4%B8%BA%E6%AD%A2%E3%80%82%E9%80%9A%E8%BF%87%E8%BF%99%E7%A7%8D%E6%96%B9%E5%BC%8F%E5%8E%BB%E9%99%A4%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E8%80%A6%E5%90%88%E3%80%82%0A%0A%23%23%23%23%23%201.17%20%E7%8A%B6%E6%80%81%EF%BC%88State%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%85%81%E8%AE%B8%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%9C%A8%E5%85%B6%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%E5%8F%91%E7%94%9F%E6%94%B9%E5%8F%98%E6%97%B6%E6%94%B9%E5%8F%98%E5%85%B6%E8%A1%8C%E4%B8%BA%E8%83%BD%E5%8A%9B%E3%80%82%0A%0A%23%23%23%23%23%201.18%20%E8%A7%82%E5%AF%9F%E8%80%85%EF%BC%88Observer%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%A4%9A%E4%B8%AA%E5%AF%B9%E8%B1%A1%E9%97%B4%E5%AD%98%E5%9C%A8%E4%B8%80%E5%AF%B9%E5%A4%9A%E5%85%B3%E7%B3%BB%EF%BC%8C%E5%BD%93%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%8F%91%E7%94%9F%E6%94%B9%E5%8F%98%E6%97%B6%EF%BC%8C%E6%8A%8A%E8%BF%99%E7%A7%8D%E6%94%B9%E5%8F%98%E9%80%9A%E7%9F%A5%E7%BB%99%E5%85%B6%E4%BB%96%E5%A4%9A%E4%B8%AA%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%BD%B1%E5%93%8D%E5%85%B6%E4%BB%96%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%A1%8C%E4%B8%BA%E3%80%82%0A%0A%23%23%23%23%23%201.19%20%E4%B8%AD%E4%BB%8B%E8%80%85%EF%BC%88Mediator%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E4%B8%AD%E4%BB%8B%E5%AF%B9%E8%B1%A1%E6%9D%A5%E7%AE%80%E5%8C%96%E5%8E%9F%E6%9C%89%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E4%BA%A4%E4%BA%92%E5%85%B3%E7%B3%BB%EF%BC%8C%E9%99%8D%E4%BD%8E%E7%B3%BB%E7%BB%9F%E4%B8%AD%E5%AF%B9%E8%B1%A1%E9%97%B4%E7%9A%84%E8%80%A6%E5%90%88%E5%BA%A6%EF%BC%8C%E4%BD%BF%E5%8E%9F%E6%9C%89%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E4%B8%8D%E5%BF%85%E7%9B%B8%E4%BA%92%E4%BA%86%E8%A7%A3%E3%80%82%0A%0A%23%23%23%23%23%201.20%20%E8%BF%AD%E4%BB%A3%E5%99%A8%EF%BC%88Iterator%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E6%8F%90%E4%BE%9B%E4%B8%80%E7%A7%8D%E6%96%B9%E6%B3%95%E6%9D%A5%E9%A1%BA%E5%BA%8F%E8%AE%BF%E9%97%AE%E8%81%9A%E5%90%88%E5%AF%B9%E8%B1%A1%E4%B8%AD%E7%9A%84%E4%B8%80%E7%B3%BB%E5%88%97%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%9A%B4%E9%9C%B2%E8%81%9A%E5%90%88%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%86%85%E9%83%A8%E8%A1%A8%E7%A4%BA%E3%80%82%0A%0A%23%23%23%23%23%201.21%20%E8%AE%BF%E9%97%AE%E8%80%85%EF%BC%88Visitor%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%9C%A8%E4%B8%8D%E6%94%B9%E5%8F%98%E9%9B%86%E5%90%88%E5%85%83%E7%B4%A0%E7%9A%84%E5%89%8D%E6%8F%90%E4%B8%8B%EF%BC%8C%E4%B8%BA%E4%B8%80%E4%B8%AA%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E6%AF%8F%E4%B8%AA%E5%85%83%E7%B4%A0%E6%8F%90%E4%BE%9B%E5%A4%9A%E7%A7%8D%E8%AE%BF%E9%97%AE%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%8D%B3%E6%AF%8F%E4%B8%AA%E5%85%83%E7%B4%A0%E6%9C%89%E5%A4%9A%E4%B8%AA%E8%AE%BF%E9%97%AE%E8%80%85%E5%AF%B9%E8%B1%A1%E8%AE%BF%E9%97%AE%E3%80%82%0A%0A%23%23%23%23%23%201.22%20%E5%A4%87%E5%BF%98%E5%BD%95%EF%BC%88Memento%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E5%9C%A8%E4%B8%8D%E7%A0%B4%E5%9D%8F%E5%B0%81%E8%A3%85%E6%80%A7%E7%9A%84%E5%89%8D%E6%8F%90%E4%B8%8B%EF%BC%8C%E8%8E%B7%E5%8F%96%E5%B9%B6%E4%BF%9D%E5%AD%98%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%EF%BC%8C%E4%BB%A5%E4%BE%BF%E4%BB%A5%E5%90%8E%E6%81%A2%E5%A4%8D%E5%AE%83%E3%80%82%0A%0A%23%23%23%23%23%201.23%20%E8%A7%A3%E9%87%8A%E5%99%A8%EF%BC%88Interpreter%EF%BC%89%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%20%3E%E6%8F%90%E4%BE%9B%E5%A6%82%E4%BD%95%E5%AE%9A%E4%B9%89%E8%AF%AD%E8%A8%80%E7%9A%84%E6%96%87%E6%B3%95%EF%BC%8C%E4%BB%A5%E5%8F%8A%E5%AF%B9%E8%AF%AD%E8%A8%80%E5%8F%A5%E5%AD%90%E7%9A%84%E8%A7%A3%E9%87%8A%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8D%B3%E8%A7%A3%E9%87%8A%E5%99%A8%E3%80%82%0A%0A%0A%23%23%23%23%202.%20%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%0A%0A%23%23%23%23%23%202.1%20%E4%BE%9D%E8%B5%96%EF%BC%88Dependency%EF%BC%89%0A%3E%20%60%E4%BE%9D%E8%B5%96%EF%BC%88Dependency%EF%BC%89%60%E5%85%B3%E7%B3%BB%E6%98%AF%E4%B8%80%E7%A7%8D%60%E4%BD%BF%E7%94%A8%E5%85%B3%E7%B3%BB%60%EF%BC%8C%E5%AE%83%E6%98%AF%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E8%80%A6%E5%90%88%E5%BA%A6%E6%9C%80%E5%BC%B1%E7%9A%84%E4%B8%80%E7%A7%8D%E5%85%B3%E8%81%94%E6%96%B9%E5%BC%8F%EF%BC%8C%E6%98%AF%E4%B8%B4%E6%97%B6%E6%80%A7%E7%9A%84%E5%85%B3%E8%81%94%E3%80%82%0A%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E4%BD%BF%E7%94%A8%E5%B8%A6%E7%AE%AD%E5%A4%B4%E7%9A%84%E8%99%9A%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%AE%AD%E5%A4%B4%E4%BB%8E%E4%BD%BF%E7%94%A8%E7%B1%BB%E6%8C%87%E5%90%91%E8%A2%AB%E4%BE%9D%E8%B5%96%E7%9A%84%E7%B1%BB.%0A%0A!%5B4d10ac87b845539aeb5eba816a82951d.png%5D(en-resource%3A%2F%2Fdatabase%2F563%3A1)%0A%0A%0A%23%23%23%23%23%20%202.2%20%E5%85%B3%E8%81%94%EF%BC%88Association%EF%BC%89%0A%3E%20%60%E5%85%B3%E8%81%94%EF%BC%88Association%EF%BC%89%60%E5%85%B3%E7%B3%BB%E6%98%AF%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E4%B8%80%E7%A7%8D%60%E5%BC%95%E7%94%A8%E5%85%B3%E7%B3%BB%60%EF%BC%8C%E7%94%A8%E4%BA%8E%E8%A1%A8%E7%A4%BA%E4%B8%80%E7%B1%BB%E5%AF%B9%E8%B1%A1%E4%B8%8E%E5%8F%A6%E4%B8%80%E7%B1%BB%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E8%81%94%E7%B3%BB%EF%BC%8C%E5%A6%82%E8%80%81%E5%B8%88%E5%92%8C%E5%AD%A6%E7%94%9F%E3%80%81%E5%B8%88%E5%82%85%E5%92%8C%E5%BE%92%E5%BC%9F%E3%80%81%E4%B8%88%E5%A4%AB%E5%92%8C%E5%A6%BB%E5%AD%90%E7%AD%89%E3%80%82%0A%3E%20%20%E5%85%B3%E8%81%94%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%8F%8C%E5%90%91%E7%9A%84%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%8D%95%E5%90%91%E7%9A%84%0A%0A%20%20%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E5%8F%8C%E5%90%91%E7%9A%84%E5%85%B3%E8%81%94%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%B8%A6%E4%B8%A4%E4%B8%AA%E7%AE%AD%E5%A4%B4%E6%88%96%E8%80%85%E6%B2%A1%E6%9C%89%E7%AE%AD%E5%A4%B4%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E5%8D%95%E5%90%91%E7%9A%84%E5%85%B3%E8%81%94%E7%94%A8%E5%B8%A6%E4%B8%80%E4%B8%AA%E7%AE%AD%E5%A4%B4%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%AE%AD%E5%A4%B4%E4%BB%8E%E4%BD%BF%E7%94%A8%E7%B1%BB%E6%8C%87%E5%90%91%E8%A2%AB%E5%85%B3%E8%81%94%E7%9A%84%E7%B1%BB%E3%80%82%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%85%B3%E8%81%94%E7%BA%BF%E7%9A%84%E4%B8%A4%E7%AB%AF%E6%A0%87%E6%B3%A8%E8%A7%92%E8%89%B2%E5%90%8D%EF%BC%8C%E4%BB%A3%E8%A1%A8%E4%B8%A4%E7%A7%8D%E4%B8%8D%E5%90%8C%E7%9A%84%E8%A7%92%E8%89%B2%E3%80%82%0A%0A!%5B5de20545ad910b47e07d9cba5f25090e.png%5D(en-resource%3A%2F%2Fdatabase%2F564%3A1)%0A%0A%0A%23%23%23%23%23%20%202.3%20%E8%81%9A%E5%90%88%EF%BC%88Aggregation%EF%BC%89%0A%3E%20%60%E8%81%9A%E5%90%88%EF%BC%88Aggregation%EF%BC%89%60%E5%85%B3%E7%B3%BB%E6%98%AF%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%E7%9A%84%E4%B8%80%E7%A7%8D%EF%BC%8C%E6%98%AF%E5%BC%BA%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%E6%95%B4%E4%BD%93%E5%92%8C%E9%83%A8%E5%88%86%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%20has-a%20%E7%9A%84%E5%85%B3%E7%B3%BB%E3%80%82%0A%20%0A%20%E8%81%9A%E5%90%88%E5%85%B3%E7%B3%BB%E4%B9%9F%E6%98%AF%E9%80%9A%E8%BF%87%E6%88%90%E5%91%98%E5%AF%B9%E8%B1%A1%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8C%E5%85%B6%E4%B8%AD%E6%88%90%E5%91%98%E5%AF%B9%E8%B1%A1%E6%98%AF%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%EF%BC%8C%E4%BD%86%E6%98%AF%E6%88%90%E5%91%98%E5%AF%B9%E8%B1%A1%E5%8F%AF%E4%BB%A5%E8%84%B1%E7%A6%BB%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E8%80%8C%E7%8B%AC%E7%AB%8B%E5%AD%98%E5%9C%A8%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%8C%E5%AD%A6%E6%A0%A1%E4%B8%8E%E8%80%81%E5%B8%88%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E5%AD%A6%E6%A0%A1%E5%8C%85%E5%90%AB%E8%80%81%E5%B8%88%EF%BC%8C%E4%BD%86%E5%A6%82%E6%9E%9C%E5%AD%A6%E6%A0%A1%E5%81%9C%E5%8A%9E%E4%BA%86%EF%BC%8C%E8%80%81%E5%B8%88%E4%BE%9D%E7%84%B6%E5%AD%98%E5%9C%A8%E3%80%82%0A%0A%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E8%81%9A%E5%90%88%E5%85%B3%E7%B3%BB%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%B8%A6%E7%A9%BA%E5%BF%83%E8%8F%B1%E5%BD%A2%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E8%8F%B1%E5%BD%A2%E6%8C%87%E5%90%91%E6%95%B4%E4%BD%93%E3%80%82%0A%0A!%5B3280c2b2903c17ede1e9af43cb5306ea.png%5D(en-resource%3A%2F%2Fdatabase%2F562%3A1)%0A%0A%0A%23%23%23%23%23%20%202.4%20%E7%BB%84%E5%90%88%EF%BC%88Composition%EF%BC%89%0A%3E%20%60%E7%BB%84%E5%90%88%EF%BC%88Composition%EF%BC%89%60%E5%85%B3%E7%B3%BB%E4%B9%9F%E6%98%AF%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%E7%9A%84%E4%B8%80%E7%A7%8D%EF%BC%8C%E4%B9%9F%E8%A1%A8%E7%A4%BA%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E6%95%B4%E4%BD%93%E4%B8%8E%E9%83%A8%E5%88%86%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E4%BD%86%E5%AE%83%E6%98%AF%E4%B8%80%E7%A7%8D%E6%9B%B4%E5%BC%BA%E7%83%88%E7%9A%84%E8%81%9A%E5%90%88%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%20cxmtains-a%20%E5%85%B3%E7%B3%BB%E3%80%82%0A%0A%E5%9C%A8%E7%BB%84%E5%90%88%E5%85%B3%E7%B3%BB%E4%B8%AD%EF%BC%8C%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E5%8F%AF%E4%BB%A5%E6%8E%A7%E5%88%B6%E9%83%A8%E5%88%86%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%EF%BC%8C%E4%B8%80%E6%97%A6%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%83%A8%E5%88%86%E5%AF%B9%E8%B1%A1%E4%B9%9F%E5%B0%86%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%83%A8%E5%88%86%E5%AF%B9%E8%B1%A1%E4%B8%8D%E8%83%BD%E8%84%B1%E7%A6%BB%E6%95%B4%E4%BD%93%E5%AF%B9%E8%B1%A1%E8%80%8C%E5%AD%98%E5%9C%A8%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%8C%E5%A4%B4%E5%92%8C%E5%98%B4%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%B2%A1%E6%9C%89%E4%BA%86%E5%A4%B4%EF%BC%8C%E5%98%B4%E4%B9%9F%E5%B0%B1%E4%B8%8D%E5%AD%98%E5%9C%A8%E4%BA%86%E3%80%82%0A%20%20%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E7%BB%84%E5%90%88%E5%85%B3%E7%B3%BB%E7%94%A8%E5%B8%A6%E5%AE%9E%E5%BF%83%E8%8F%B1%E5%BD%A2%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E8%8F%B1%E5%BD%A2%E6%8C%87%E5%90%91%E6%95%B4%E4%BD%93%E3%80%82%E5%9B%BE%207%20%E6%89%80%E7%A4%BA%E6%98%AF%E5%A4%B4%E5%92%8C%E5%98%B4%E7%9A%84%E5%85%B3%E7%B3%BB%E5%9B%BE%E3%80%82%0A%0A%0A!%5Bf8cc1bd30ca382b4b237c490d6d92843.png%5D(en-resource%3A%2F%2Fdatabase%2F565%3A1)%0A%0A%0A%23%23%23%23%23%20%202.5%20%E6%B3%9B%E5%8C%96%EF%BC%88Generalization%EF%BC%89%0A%3E%20%60%E6%B3%9B%E5%8C%96%EF%BC%88Generalization%EF%BC%89%60%E5%85%B3%E7%B3%BB%E6%98%AF%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E8%80%A6%E5%90%88%E5%BA%A6%E6%9C%80%E5%A4%A7%E7%9A%84%E4%B8%80%E7%A7%8D%E5%85%B3%E7%B3%BB%EF%BC%8C%E8%A1%A8%E7%A4%BA%E4%B8%80%E8%88%AC%E4%B8%8E%E7%89%B9%E6%AE%8A%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%E7%88%B6%E7%B1%BB%E4%B8%8E%E5%AD%90%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%E4%B8%80%E7%A7%8D%E7%BB%A7%E6%89%BF%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%98%AF%20is-a%20%E7%9A%84%E5%85%B3%E7%B3%BB%E3%80%82%0A%0A%20%20%20%E5%9C%A8%20UML%20%E7%B1%BB%E5%9B%BE%E4%B8%AD%EF%BC%8C%E6%B3%9B%E5%8C%96%E5%85%B3%E7%B3%BB%E7%94%A8%E5%B8%A6%E7%A9%BA%E5%BF%83%E4%B8%89%E8%A7%92%E7%AE%AD%E5%A4%B4%E7%9A%84%E5%AE%9E%E7%BA%BF%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%AE%AD%E5%A4%B4%E4%BB%8E%E5%AD%90%E7%B1%BB%E6%8C%87%E5%90%91%E7%88%B6%E7%B1%BB%E3%80%82%E5%9C%A8%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0%E6%97%B6%EF%BC%8C%E4%BD%BF%E7%94%A8%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%BB%A7%E6%89%BF%E6%9C%BA%E5%88%B6%E6%9D%A5%E5%AE%9E%E7%8E%B0%E6%B3%9B%E5%8C%96%E5%85%B3%E7%B3%BB%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%8CStudent%20%E7%B1%BB%E5%92%8C%20Teacher%20%E7%B1%BB%E9%83%BD%E6%98%AF%20Person%20%E7%B1%BB%E7%9A%84%E5%AD%90%E7%B1%BB.%0A%20%20%20%0A%0A!%5B2182cebbf57e6e158153f587c4fb2501.png%5D(en-resource%3A%2F%2Fdatabase%2F561%3A1)%0A%0A%0A%0A%0A%0A%23%23%23%23%23%20%202.6.%20%E5%AE%9E%E7%8E%B0%EF%BC%88Realization%EF%BC%89%0A%3E%20%E5%AE%9E%E7%8E%B0%E5%85%B3%E7%B3%BB%E6%98%AF%E6%8E%A5%E5%8F%A3%E4%B8%8E%E5%AE%9E%E7%8E%B0%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%E3%80%82%E5%9C%A8%E8%BF%99%E7%A7%8D%E5%85%B3%E7%B3%BB%E4%B8%AD%EF%BC%8C%E7%B1%BB%E5%AE%9E%E7%8E%B0%E4%BA%86%E6%8E%A5%E5%8F%A3%EF%BC%8C%E7%B1%BB%E4%B8%AD%E7%9A%84%E6%93%8D%E4%BD%9C%E5%AE%9E%E7%8E%B0%E4%BA%86%E6%8E%A5%E5%8F%A3%E4%B8%AD%E6%89%80%E5%A3%B0%E6%98%8E%E7%9A%84%E6%89%80%E6%9C%89%E7%9A%84%E6%8A%BD%E8%B1%A1%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A!%5B1c1f1d52f6fc3250817e05628539c95d.png%5D(en-resource%3A%2F%2Fdatabase%2F560%3A1)%0A%0A%0A%0A%23%23%23%23%203.%E6%A0%B8%E5%BF%83%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%0A%0A%23%23%23%23%23%203.1%20%E5%BC%80%E9%97%AD%E5%8E%9F%E5%88%99%EF%BC%88Open%20Closed%20Principle%EF%BC%8COCP%EF%BC%89%0A%0A%E5%AE%9A%E4%B9%89%0A%0A%3E%20%E8%BD%AF%E4%BB%B6%E5%AE%9E%E4%BD%93%E5%AF%B9%E6%89%A9%E5%B1%95%E5%BC%80%E6%94%BE%EF%BC%8C%E5%AF%B9%E4%BF%AE%E6%94%B9%E5%85%B3%E9%97%AD%EF%BC%88Software%20entities%20should%20be%20open%20for%20extension%EF%BC%8Cbut%20closed%20for%20modification%EF%BC%89%0A%0A%E5%BC%80%E9%97%AD%E5%8E%9F%E5%88%99%E7%9A%84%E5%90%AB%E4%B9%89%E6%98%AF%EF%BC%9A%0A%0A%3E%20%E5%BD%93%E5%BA%94%E7%94%A8%E7%9A%84%E9%9C%80%E6%B1%82%E6%94%B9%E5%8F%98%E6%97%B6%EF%BC%8C%E5%9C%A8%E4%B8%8D%E4%BF%AE%E6%94%B9%E8%BD%AF%E4%BB%B6%E5%AE%9E%E4%BD%93%E7%9A%84%E6%BA%90%E4%BB%A3%E7%A0%81%E5%89%8D%E6%8F%90%E4%B8%8B%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%89%A9%E5%B1%95%E6%A8%A1%E5%9D%97%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E4%BD%BF%E5%85%B6%E6%BB%A1%E8%B6%B3%E6%96%B0%E7%9A%84%E9%9C%80%E6%B1%82%E3%80%82%0A%0A%E8%BD%AF%E4%BB%B6%E5%AE%9E%E4%BD%93%E5%8C%85%E6%8B%AC%0A%3E%201.%20%E9%A1%B9%E7%9B%AE%E4%B8%AD%E5%88%92%E5%88%86%E5%87%BA%E7%9A%84%E6%A8%A1%E5%9D%97%0A%3E%202.%20%E7%B1%BB%E4%B8%8E%E6%8E%A5%E5%8F%A3%0A%3E%203.%20%E6%96%B9%E6%B3%95%0A%0A%0A%23%23%23%23%23%203.2%20%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%0A%0A%3E1.%20%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%E6%98%AF%E5%AE%9E%E7%8E%B0%E5%BC%80%E9%97%AD%E5%8E%9F%E5%88%99%E7%9A%84%E9%87%8D%E8%A6%81%E6%96%B9%E5%BC%8F%E4%B9%8B%E4%B8%80%0A%3E2.%20%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%E9%80%9A%E4%BF%97%E6%9D%A5%E8%AE%B2%E5%B0%B1%E6%98%AF%EF%BC%9A%E5%AD%90%E7%B1%BB%E5%8F%AF%E4%BB%A5%E6%89%A9%E5%B1%95%E7%88%B6%E7%B1%BB%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E4%BD%86%E4%B8%8D%E8%83%BD%E6%94%B9%E5%8F%98%E7%88%B6%E7%B1%BB%E5%8E%9F%E6%9C%89%E7%9A%84%E5%8A%9F%E8%83%BD%E3%80%82%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%9A%E5%AD%90%E7%B1%BB%E7%BB%A7%E6%89%BF%E7%88%B6%E7%B1%BB%E6%97%B6%EF%BC%8C%E9%99%A4%E6%B7%BB%E5%8A%A0%E6%96%B0%E7%9A%84%E6%96%B9%E6%B3%95%E5%AE%8C%E6%88%90%E6%96%B0%E5%A2%9E%E5%8A%9F%E8%83%BD%E5%A4%96%EF%BC%8C%E5%B0%BD%E9%87%8F%E4%B8%8D%E8%A6%81%E9%87%8D%E5%86%99%E7%88%B6%E7%B1%BB%E7%9A%84%E6%96%B9%E6%B3%95%E3%80%82%0A%3E3.%20%E5%A6%82%E6%9E%9C%E9%80%9A%E8%BF%87%E9%87%8D%E5%86%99%E7%88%B6%E7%B1%BB%E7%9A%84%E6%96%B9%E6%B3%95%E6%9D%A5%E5%AE%8C%E6%88%90%E6%96%B0%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%86%99%E8%B5%B7%E6%9D%A5%E8%99%BD%E7%84%B6%E7%AE%80%E5%8D%95%EF%BC%8C%E4%BD%86%E6%98%AF%E6%95%B4%E4%B8%AA%E7%BB%A7%E6%89%BF%E4%BD%93%E7%B3%BB%E7%9A%84%E5%8F%AF%E5%A4%8D%E7%94%A8%E6%80%A7%E4%BC%9A%E6%AF%94%E8%BE%83%E5%B7%AE%EF%BC%8C%E7%89%B9%E5%88%AB%E6%98%AF%E8%BF%90%E7%94%A8%E5%A4%9A%E6%80%81%E6%AF%94%E8%BE%83%E9%A2%91%E7%B9%81%E6%97%B6%EF%BC%8C%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E5%87%BA%E9%94%99%E7%9A%84%E6%A6%82%E7%8E%87%E4%BC%9A%E9%9D%9E%E5%B8%B8%E5%A4%A7%E3%80%82%0A%3E4.%20%E5%A6%82%E6%9E%9C%E7%A8%8B%E5%BA%8F%E8%BF%9D%E8%83%8C%E4%BA%86%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%EF%BC%8C%E5%88%99%E7%BB%A7%E6%89%BF%E7%B1%BB%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%9C%A8%E5%9F%BA%E7%B1%BB%E5%87%BA%E7%8E%B0%E7%9A%84%E5%9C%B0%E6%96%B9%E4%BC%9A%E5%87%BA%E7%8E%B0%E8%BF%90%E8%A1%8C%E9%94%99%E8%AF%AF%E3%80%82%E8%BF%99%E6%97%B6%E5%85%B6%E4%BF%AE%E6%AD%A3%E6%96%B9%E6%B3%95%E6%98%AF%EF%BC%9A%E5%8F%96%E6%B6%88%E5%8E%9F%E6%9D%A5%E7%9A%84%E7%BB%A7%E6%89%BF%E5%85%B3%E7%B3%BB%EF%BC%8C%E9%87%8D%E6%96%B0%E8%AE%BE%E8%AE%A1%E5%AE%83%E4%BB%AC%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%E3%80%82%0A%0A%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%8C%E4%BC%81%E9%B9%85%E3%80%81%E9%B8%B5%E9%B8%9F%E5%92%8C%E5%87%A0%E7%BB%B4%E9%B8%9F%E4%BB%8E%E7%94%9F%E7%89%A9%E5%AD%A6%E7%9A%84%E8%A7%92%E5%BA%A6%E6%9D%A5%E5%88%92%E5%88%86%EF%BC%8C%E5%AE%83%E4%BB%AC%E5%B1%9E%E4%BA%8E%E9%B8%9F%E7%B1%BB%EF%BC%9B%E4%BD%86%E4%BB%8E%E7%B1%BB%E7%9A%84%E7%BB%A7%E6%89%BF%E5%85%B3%E7%B3%BB%E6%9D%A5%E7%9C%8B%EF%BC%8C%E7%94%B1%E4%BA%8E%E5%AE%83%E4%BB%AC%E4%B8%8D%E8%83%BD%E7%BB%A7%E6%89%BF%E2%80%9C%E9%B8%9F%E2%80%9D%E4%BC%9A%E9%A3%9E%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E6%89%80%E4%BB%A5%E5%AE%83%E4%BB%AC%E4%B8%8D%E8%83%BD%E5%AE%9A%E4%B9%89%E6%88%90%E2%80%9C%E9%B8%9F%E2%80%9D%E7%9A%84%E5%AD%90%E7%B1%BB%0A%0A%60%60%60java%0Apackage%20principle%3B%0Apublic%20class%20LSPtest%0A%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20Bird%20bird1%3Dnew%20Swallow()%3B%0A%20%20%20%20%20%20%20%20Bird%20bird2%3Dnew%20BrownKiwi()%3B%0A%20%20%20%20%20%20%20%20bird1.setSpeed(120)%3B%0A%20%20%20%20%20%20%20%20bird2.setSpeed(120)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E5%A6%82%E6%9E%9C%E9%A3%9E%E8%A1%8C300%E5%85%AC%E9%87%8C%EF%BC%9A%22)%3B%0A%20%20%20%20%20%20%20%20try%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%87%95%E5%AD%90%E5%B0%86%E9%A3%9E%E8%A1%8C%22%2Bbird1.getFlyTime(300)%2B%22%E5%B0%8F%E6%97%B6.%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E5%87%A0%E7%BB%B4%E9%B8%9F%E5%B0%86%E9%A3%9E%E8%A1%8C%22%2Bbird2.getFlyTime(300)%2B%22%E5%B0%8F%E6%97%B6%E3%80%82%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20catch(Exception%20err)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E5%8F%91%E7%94%9F%E9%94%99%E8%AF%AF%E4%BA%86!%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%2F%2F%E9%B8%9F%E7%B1%BB%0Aclass%20Bird%0A%7B%0A%20%20%20%20double%20flySpeed%3B%0A%20%20%20%20public%20void%20setSpeed(double%20speed)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20flySpeed%3Dspeed%3B%0A%20%20%20%20%7D%0A%20%20%20%20public%20double%20getFlyTime(double%20distance)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20return(distance%2FflySpeed)%3B%0A%20%20%20%20%7D%0A%7D%0A%2F%2F%E7%87%95%E5%AD%90%E7%B1%BB%0Aclass%20Swallow%20extends%20Bird%7B%7D%0A%2F%2F%E5%87%A0%E7%BB%B4%E9%B8%9F%E7%B1%BB%0Aclass%20BrownKiwi%20extends%20Bird%0A%7B%0A%20%20%20%20public%20void%20setSpeed(double%20speed)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20flySpeed%3D0%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%203.3%20%E4%BE%9D%E8%B5%96%E5%80%92%E7%BD%AE%E5%8E%9F%E5%88%99%EF%BC%88Dependence%20Inversion%20Principle%EF%BC%8CDIP%EF%BC%89%0A%0A%3E%20%E5%AE%9A%E4%B9%89%EF%BC%9A%0A%3E%20%E9%AB%98%E5%B1%82%E6%A8%A1%E5%9D%97%E4%B8%8D%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E4%BD%8E%E5%B1%82%E6%A8%A1%E5%9D%97%EF%BC%8C%E4%B8%A4%E8%80%85%E9%83%BD%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E5%85%B6%E6%8A%BD%E8%B1%A1%EF%BC%9B%E6%8A%BD%E8%B1%A1%E4%B8%8D%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E7%BB%86%E8%8A%82%EF%BC%8C%E7%BB%86%E8%8A%82%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E6%8A%BD%E8%B1%A1%E3%80%82%0A%3E%20%E5%85%B6%E6%A0%B8%E5%BF%83%E6%80%9D%E6%83%B3%E6%98%AF%EF%BC%9A%E8%A6%81%E9%9D%A2%E5%90%91%E6%8E%A5%E5%8F%A3%E7%BC%96%E7%A8%8B%EF%BC%8C%E4%B8%8D%E8%A6%81%E9%9D%A2%E5%90%91%E5%AE%9E%E7%8E%B0%E7%BC%96%E7%A8%8B%E3%80%82%0A%0A%3E%20%E7%9B%AE%E7%9A%84%EF%BC%9A%0A%3E%20%E4%BE%9D%E8%B5%96%E5%80%92%E7%BD%AE%E5%8E%9F%E5%88%99%E6%98%AF%E5%AE%9E%E7%8E%B0%E5%BC%80%E9%97%AD%E5%8E%9F%E5%88%99%E7%9A%84%E9%87%8D%E8%A6%81%E9%80%94%E5%BE%84%E4%B9%8B%E4%B8%80%EF%BC%8C%E5%AE%83%E9%99%8D%E4%BD%8E%E4%BA%86%E5%AE%A2%E6%88%B7%E4%B8%8E%E5%AE%9E%E7%8E%B0%E6%A8%A1%E5%9D%97%E4%B9%8B%E9%97%B4%E7%9A%84%E8%80%A6%E5%90%88%E3%80%82%0A%3E%20%E7%94%B1%E4%BA%8E%E5%9C%A8%E8%BD%AF%E4%BB%B6%E8%AE%BE%E8%AE%A1%E4%B8%AD%EF%BC%8C%E7%BB%86%E8%8A%82%E5%85%B7%E6%9C%89%E5%A4%9A%E5%8F%98%E6%80%A7%EF%BC%8C%E8%80%8C%E6%8A%BD%E8%B1%A1%E5%B1%82%E5%88%99%E7%9B%B8%E5%AF%B9%E7%A8%B3%E5%AE%9A%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%BB%A5%E6%8A%BD%E8%B1%A1%E4%B8%BA%E5%9F%BA%E7%A1%80%E6%90%AD%E5%BB%BA%E8%B5%B7%E6%9D%A5%E7%9A%84%E6%9E%B6%E6%9E%84%E8%A6%81%E6%AF%94%E4%BB%A5%E7%BB%86%E8%8A%82%E4%B8%BA%E5%9F%BA%E7%A1%80%E6%90%AD%E5%BB%BA%E8%B5%B7%E6%9D%A5%E7%9A%84%E6%9E%B6%E6%9E%84%E8%A6%81%E7%A8%B3%E5%AE%9A%E5%BE%97%E5%A4%9A%E3%80%82%0A%0A%3E%20%E5%AE%9E%E7%8E%B0%E5%8E%9F%E5%88%99%EF%BC%9A%0A%3E%0A%3E%201.%E6%AF%8F%E4%B8%AA%E7%B1%BB%E5%B0%BD%E9%87%8F%E6%8F%90%E4%BE%9B%E6%8E%A5%E5%8F%A3%E6%88%96%E6%8A%BD%E8%B1%A1%E7%B1%BB%EF%BC%8C%E6%88%96%E8%80%85%E4%B8%A4%E8%80%85%E9%83%BD%E5%85%B7%E5%A4%87%E3%80%82%0A%3E%202.%E5%8F%98%E9%87%8F%E7%9A%84%E5%A3%B0%E6%98%8E%E7%B1%BB%E5%9E%8B%E5%B0%BD%E9%87%8F%E6%98%AF%E6%8E%A5%E5%8F%A3%E6%88%96%E8%80%85%E6%98%AF%E6%8A%BD%E8%B1%A1%E7%B1%BB%E3%80%82%0A%3E%203.%E4%BB%BB%E4%BD%95%E7%B1%BB%E9%83%BD%E4%B8%8D%E5%BA%94%E8%AF%A5%E4%BB%8E%E5%85%B7%E4%BD%93%E7%B1%BB%E6%B4%BE%E7%94%9F%E3%80%82%0A%3E%204.%E4%BD%BF%E7%94%A8%E7%BB%A7%E6%89%BF%E6%97%B6%E5%B0%BD%E9%87%8F%E9%81%B5%E5%BE%AA%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99%0A%0A%0A%0A%0A%0A%60%60%60java%0Apackage%20principle%3B%0Apublic%20class%20DIPtest%0A%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20Customer%20wang%3Dnew%20Customer()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E9%A1%BE%E5%AE%A2%E8%B4%AD%E4%B9%B0%E4%BB%A5%E4%B8%8B%E5%95%86%E5%93%81%EF%BC%9A%22)%3B%20%0A%20%20%20%20%20%20%20%20wang.shopping(new%20ShaoguanShop())%3B%20%0A%20%20%20%20%20%20%20%20wang.shopping(new%20WuyuanShop())%3B%0A%20%20%20%20%7D%0A%7D%0A%2F%2F%E5%95%86%E5%BA%97%0Ainterface%20Shop%0A%7B%0A%20%20%20%20public%20String%20sell()%3B%20%2F%2F%E5%8D%96%0A%7D%0A%2F%2F%E9%9F%B6%E5%85%B3%E7%BD%91%E5%BA%97%0Aclass%20ShaoguanShop%20implements%20Shop%0A%7B%0A%20%20%20%20public%20String%20sell()%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20return%20%22%E9%9F%B6%E5%85%B3%E5%9C%9F%E7%89%B9%E4%BA%A7%EF%BC%9A%E9%A6%99%E8%8F%87%E3%80%81%E6%9C%A8%E8%80%B3%E2%80%A6%E2%80%A6%22%3B%20%0A%20%20%20%20%7D%20%0A%7D%0A%2F%2F%E5%A9%BA%E6%BA%90%E7%BD%91%E5%BA%97%0Aclass%20WuyuanShop%20implements%20Shop%0A%7B%0A%20%20%20%20public%20String%20sell()%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20return%20%22%E5%A9%BA%E6%BA%90%E5%9C%9F%E7%89%B9%E4%BA%A7%EF%BC%9A%E7%BB%BF%E8%8C%B6%E3%80%81%E9%85%92%E7%B3%9F%E9%B1%BC%E2%80%A6%E2%80%A6%22%3B%20%0A%20%20%20%20%7D%0A%7D%20%0A%2F%2F%E9%A1%BE%E5%AE%A2%0Aclass%20Customer%0A%7B%0A%20%20%20%20public%20void%20shopping(Shop%20shop)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E8%B4%AD%E7%89%A9%0A%20%20%20%20%20%20%20%20System.out.println(shop.sell())%3B%20%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%23%23%23%23%23%20%203.4%20%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%0A%0A%3E%20%E5%AE%9A%E4%B9%89%E6%98%AF%EF%BC%9A%0A%3E%20%E5%8F%AA%E4%B8%8E%E4%BD%A0%E7%9A%84%E7%9B%B4%E6%8E%A5%E6%9C%8B%E5%8F%8B%E4%BA%A4%E8%B0%88%EF%BC%8C%E4%B8%8D%E8%B7%9F%E2%80%9C%E9%99%8C%E7%94%9F%E4%BA%BA%E2%80%9D%E8%AF%B4%E8%AF%9D%EF%BC%88Talk%20only%20to%20your%20immediate%20friends%20and%20not%20to%20strangers%EF%BC%89%E3%80%82%0A%0A%3E%20%E5%90%AB%E4%B9%89%E6%98%AF%EF%BC%9A%0A%3E%20%E5%A6%82%E6%9E%9C%E4%B8%A4%E4%B8%AA%E8%BD%AF%E4%BB%B6%E5%AE%9E%E4%BD%93%E6%97%A0%E9%A1%BB%E7%9B%B4%E6%8E%A5%E9%80%9A%E4%BF%A1%EF%BC%8C%E9%82%A3%E4%B9%88%E5%B0%B1%E4%B8%8D%E5%BA%94%E5%BD%93%E5%8F%91%E7%94%9F%E7%9B%B4%E6%8E%A5%E7%9A%84%E7%9B%B8%E4%BA%92%E8%B0%83%E7%94%A8%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E7%AC%AC%E4%B8%89%E6%96%B9%E8%BD%AC%E5%8F%91%E8%AF%A5%E8%B0%83%E7%94%A8%E3%80%82%0A%0A%3E%20%E7%9B%AE%E7%9A%84%E6%98%AF%3A%0A%3E%20%E9%99%8D%E4%BD%8E%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E8%80%A6%E5%90%88%E5%BA%A6%EF%BC%8C%E6%8F%90%E9%AB%98%E6%A8%A1%E5%9D%97%E7%9A%84%E7%9B%B8%E5%AF%B9%E7%8B%AC%E7%AB%8B%E6%80%A7%E3%80%82%0A%0A%0A%0A%E4%BB%8E%E8%BF%AA%E7%B1%B3%E7%89%B9%E6%B3%95%E5%88%99%E7%9A%84%E5%AE%9A%E4%B9%89%E5%92%8C%E7%89%B9%E7%82%B9%E5%8F%AF%E7%9F%A5%EF%BC%8C%E5%AE%83%E5%BC%BA%E8%B0%83%E4%BB%A5%E4%B8%8B%E4%B8%A4%E7%82%B9%EF%BC%9A%0A%3E%201.%20%E4%BB%8E%E4%BE%9D%E8%B5%96%E8%80%85%E7%9A%84%E8%A7%92%E5%BA%A6%E6%9D%A5%E8%AF%B4%EF%BC%8C%E5%8F%AA%E4%BE%9D%E8%B5%96%E5%BA%94%E8%AF%A5%E4%BE%9D%E8%B5%96%E7%9A%84%E5%AF%B9%E8%B1%A1%E3%80%82%0A%3E%202.%20%E4%BB%8E%E8%A2%AB%E4%BE%9D%E8%B5%96%E8%80%85%E7%9A%84%E8%A7%92%E5%BA%A6%E8%AF%B4%EF%BC%8C%E5%8F%AA%E6%9A%B4%E9%9C%B2%E5%BA%94%E8%AF%A5%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%96%B9%E6%B3%95%E3%80%82%0A%0A%E5%AE%9E%E7%8E%B0%E5%8E%9F%E5%88%99%0A%3E1.%20%E5%9C%A8%E7%B1%BB%E7%9A%84%E5%88%92%E5%88%86%E4%B8%8A%EF%BC%8C%E5%BA%94%E8%AF%A5%E5%88%9B%E5%BB%BA%E4%BD%8E%E8%80%A6%E5%90%88%E7%9A%84%E7%B1%BB%E3%80%82%E7%B1%BB%E4%B8%8E%E7%B1%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E8%80%A6%E5%90%88%E8%B6%8A%E4%BD%8E%EF%BC%8C%E5%B0%B1%E8%B6%8A%E6%9C%89%E5%88%A9%E4%BA%8E%E5%AE%9E%E7%8E%B0%E5%8F%AF%E5%A4%8D%E7%94%A8%E7%9A%84%E7%9B%AE%E6%A0%87%E3%80%82%0A%3E2.%20%E5%9C%A8%E7%B1%BB%E7%9A%84%E7%BB%93%E6%9E%84%E8%AE%BE%E8%AE%A1%E4%B8%8A%EF%BC%8C%E5%B0%BD%E9%87%8F%E9%99%8D%E4%BD%8E%E7%B1%BB%E6%88%90%E5%91%98%E7%9A%84%E8%AE%BF%E9%97%AE%E6%9D%83%E9%99%90%E3%80%82%0A%3E3.%20%E5%9C%A8%E7%B1%BB%E7%9A%84%E8%AE%BE%E8%AE%A1%E4%B8%8A%EF%BC%8C%E4%BC%98%E5%85%88%E8%80%83%E8%99%91%E5%B0%86%E4%B8%80%E4%B8%AA%E7%B1%BB%E8%AE%BE%E7%BD%AE%E6%88%90%E4%B8%8D%E5%8F%98%E7%B1%BB%E3%80%82%0A%3E4.%20%E5%9C%A8%E5%AF%B9%E5%85%B6%E4%BB%96%E7%B1%BB%E7%9A%84%E5%BC%95%E7%94%A8%E4%B8%8A%EF%BC%8C%E5%B0%86%E5%BC%95%E7%94%A8%E5%85%B6%E4%BB%96%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%AC%A1%E6%95%B0%E9%99%8D%E5%88%B0%E6%9C%80%E4%BD%8E%E3%80%82%0A%3E5.%20%E4%B8%8D%E6%9A%B4%E9%9C%B2%E7%B1%BB%E7%9A%84%E5%B1%9E%E6%80%A7%E6%88%90%E5%91%98%EF%BC%8C%E8%80%8C%E5%BA%94%E8%AF%A5%E6%8F%90%E4%BE%9B%E7%9B%B8%E5%BA%94%E7%9A%84%E8%AE%BF%E9%97%AE%E5%99%A8%EF%BC%88set%20%E5%92%8C%20get%20%E6%96%B9%E6%B3%95%EF%BC%89%E3%80%82%0A%3E6.%20%E8%B0%A8%E6%85%8E%E4%BD%BF%E7%94%A8%E5%BA%8F%E5%88%97%E5%8C%96%EF%BC%88Serializable%EF%BC%89%E5%8A%9F%E8%83%BD%0A%0A%23%23%23%23%23%20%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%0A%0A%60%60%60%0A%E5%AE%9A%E4%B9%89%EF%BC%9A%E6%8C%87%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E4%B8%94%E8%AF%A5%E7%B1%BB%E8%83%BD%E8%87%AA%E8%A1%8C%E5%88%9B%E5%BB%BA%E8%BF%99%E4%B8%AA%E7%B1%BB%E7%9A%84%E5%AE%9E%E4%BE%8B%E3%80%82%0A%60%60%60%0A%0A%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E6%9C%893%E4%B8%AA%E7%89%B9%E7%82%B9%EF%BC%9A%0A%3E%201.%E5%8D%95%E4%BE%8B%E7%B1%BB%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%E5%AF%B9%E8%B1%A1%EF%BC%9B%0A%3E%202.%E8%AF%A5%E5%8D%95%E4%BE%8B%E5%AF%B9%E8%B1%A1%E5%BF%85%E9%A1%BB%E7%94%B1%E5%8D%95%E4%BE%8B%E7%B1%BB%E8%87%AA%E8%A1%8C%E5%88%9B%E5%BB%BA%EF%BC%9B%0A%3E%203.%E5%8D%95%E4%BE%8B%E7%B1%BB%E5%AF%B9%E5%A4%96%E6%8F%90%E4%BE%9B%E4%B8%80%E4%B8%AA%E8%AE%BF%E9%97%AE%E8%AF%A5%E5%8D%95%E4%BE%8B%E7%9A%84%E5%85%A8%E5%B1%80%E8%AE%BF%E9%97%AE%E7%82%B9%EF%BC%9B%0A%0A%23%23%23%23%23%20%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F%0A%0A%60%60%60%0A%E5%AE%9A%E4%B9%89%3A%E7%94%A8%E4%B8%80%E4%B8%AA%E5%B7%B2%E7%BB%8F%E5%88%9B%E5%BB%BA%E7%9A%84%E5%AE%9E%E4%BE%8B%E4%BD%9C%E4%B8%BA%E5%8E%9F%E5%9E%8B%EF%BC%8C%E9%80%9A%E8%BF%87%E5%A4%8D%E5%88%B6%E8%AF%A5%E5%8E%9F%E5%9E%8B%E5%AF%B9%E8%B1%A1%E6%9D%A5%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%92%8C%E5%8E%9F%E5%9E%8B%E7%9B%B8%E5%90%8C%E6%88%96%E7%9B%B8%E4%BC%BC%E7%9A%84%E6%96%B0%E5%AF%B9%E8%B1%A1%0A%60%60%60%0A%0A%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F%E6%9C%892%E4%B8%AA%E7%89%B9%E7%82%B9%EF%BC%9A%0A%0A%3E%201.%E5%AF%B9%E8%B1%A1%E4%B9%8B%E9%97%B4%E7%9B%B8%E5%90%8C%E6%88%96%E7%9B%B8%E4%BC%BC%EF%BC%8C%E5%8D%B3%E5%8F%AA%E6%98%AF%E4%B8%AA%E5%88%AB%E7%9A%84%E5%87%A0%E4%B8%AA%E5%B1%9E%E6%80%A7%E4%B8%8D%E5%90%8C%E7%9A%84%E6%97%B6%E5%80%99%E3%80%82%0A%3E%202.%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%88%9B%E5%BB%BA%E8%BF%87%E7%A8%8B%E6%AF%94%E8%BE%83%E9%BA%BB%E7%83%A6%EF%BC%8C%E4%BD%86%E5%A4%8D%E5%88%B6%E6%AF%94%E8%BE%83%E7%AE%80%E5%8D%95%E7%9A%84%E6%97%B6%E5%80%99%E3%80%82%0A%0A%0A%0A%23%23%23%23%23%20%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95%EF%BC%88Factory%20Method%EF%BC%89%E6%A8%A1%E5%BC%8F%0A%0A%60%60%60%0A%E5%AE%9A%E4%B9%89%EF%BC%9A%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E5%88%9B%E5%BB%BA%E4%BA%A7%E5%93%81%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%B7%A5%E5%8E%82%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%B0%86%E4%BA%A7%E5%93%81%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AE%9E%E9%99%85%E5%88%9B%E5%BB%BA%E5%B7%A5%E4%BD%9C%E6%8E%A8%E8%BF%9F%E5%88%B0%E5%85%B7%E4%BD%93%E5%AD%90%E5%B7%A5%E5%8E%82%E7%B1%BB%E5%BD%93%E4%B8%AD%E3%80%82%E8%BF%99%E6%BB%A1%E8%B6%B3%E5%88%9B%E5%BB%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F%E4%B8%AD%E6%89%80%E8%A6%81%E6%B1%82%E7%9A%84%E2%80%9C%E5%88%9B%E5%BB%BA%E4%B8%8E%E4%BD%BF%E7%94%A8%E7%9B%B8%E5%88%86%E7%A6%BB%E2%80%9D%E7%9A%84%E7%89%B9%E7%82%B9%E3%80%82%0A%60%60%60%0A%E6%A8%A1%E5%BC%8F%E7%9A%84%E7%BB%93%E6%9E%84%0A%3E1.%20%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%EF%BC%88Abstract%20Factory%EF%BC%89%EF%BC%9A%E6%8F%90%E4%BE%9B%E4%BA%86%E5%88%9B%E5%BB%BA%E4%BA%A7%E5%93%81%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E8%B0%83%E7%94%A8%E8%80%85%E9%80%9A%E8%BF%87%E5%AE%83%E8%AE%BF%E9%97%AE%E5%85%B7%E4%BD%93%E5%B7%A5%E5%8E%82%E7%9A%84%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95%20newProduct()%20%E6%9D%A5%E5%88%9B%E5%BB%BA%E4%BA%A7%E5%93%81%E3%80%82%0A%3E2.%20%E5%85%B7%E4%BD%93%E5%B7%A5%E5%8E%82%EF%BC%88ConcreteFactory%EF%BC%89%EF%BC%9A%E4%B8%BB%E8%A6%81%E6%98%AF%E5%AE%9E%E7%8E%B0%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%E4%B8%AD%E7%9A%84%E6%8A%BD%E8%B1%A1%E6%96%B9%E6%B3%95%EF%BC%8C%E5%AE%8C%E6%88%90%E5%85%B7%E4%BD%93%E4%BA%A7%E5%93%81%E7%9A%84%E5%88%9B%E5%BB%BA%E3%80%82%0A%3E3.%20%E6%8A%BD%E8%B1%A1%E4%BA%A7%E5%93%81%EF%BC%88Product%EF%BC%89%EF%BC%9A%E5%AE%9A%E4%B9%89%E4%BA%86%E4%BA%A7%E5%93%81%E7%9A%84%E8%A7%84%E8%8C%83%EF%BC%8C%E6%8F%8F%E8%BF%B0%E4%BA%86%E4%BA%A7%E5%93%81%E7%9A%84%E4%B8%BB%E8%A6%81%E7%89%B9%E6%80%A7%E5%92%8C%E5%8A%9F%E8%83%BD%E3%80%82%0A%3E4.%20%E5%85%B7%E4%BD%93%E4%BA%A7%E5%93%81%EF%BC%88ConcreteProduct%EF%BC%89%EF%BC%9A%E5%AE%9E%E7%8E%B0%E4%BA%86%E6%8A%BD%E8%B1%A1%E4%BA%A7%E5%93%81%E8%A7%92%E8%89%B2%E6%89%80%E5%AE%9A%E4%B9%89%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E7%94%B1%E5%85%B7%E4%BD%93%E5%B7%A5%E5%8E%82%E6%9D%A5%E5%88%9B%E5%BB%BA%EF%BC%8C%E5%AE%83%E5%90%8C%E5%85%B7%E4%BD%93%E5%B7%A5%E5%8E%82%E4%B9%8B%E9%97%B4%E4%B8%80%E4%B8%80%E5%AF%B9%E5%BA%94%E3%80%82%0A%0A!%5B94455237b6224073f3ca50692406cc8c.png%5D(en-resource%3A%2F%2Fdatabase%2F566%3A1)%0A%0A%0A%E5%85%B6%E7%BC%BA%E7%82%B9%E6%98%AF%EF%BC%9A%E5%BD%93%E4%BA%A7%E5%93%81%E6%97%8F%E4%B8%AD%E9%9C%80%E8%A6%81%E5%A2%9E%E5%8A%A0%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E4%BA%A7%E5%93%81%E6%97%B6%EF%BC%8C%E6%89%80%E6%9C%89%E7%9A%84%E5%B7%A5%E5%8E%82%E7%B1%BB%E9%83%BD%E9%9C%80%E8%A6%81%E8%BF%9B%E8%A1%8C%E4%BF%AE%E6%94%B9%E3%80%82%0A%0A!%5Bcbbc026277a6611b1896c0c09178797c.png%5D(en-resource%3A%2F%2Fdatabase%2F567%3A1)%0A%0A%0A%23%23%23%23%23%20%E5%BB%BA%E9%80%A0%E8%80%85%EF%BC%88Builder%EF%BC%89%E6%A8%A1%E5%BC%8F%0A%0A%60%60%60%0A%E5%AE%9A%E4%B9%89%EF%BC%9A%E6%8C%87%E5%B0%86%E4%B8%80%E4%B8%AA%E5%A4%8D%E6%9D%82%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%9E%84%E9%80%A0%E4%B8%8E%E5%AE%83%E7%9A%84%E8%A1%A8%E7%A4%BA%E5%88%86%E7%A6%BB%EF%BC%8C%E4%BD%BF%E5%90%8C%E6%A0%B7%E7%9A%84%E6%9E%84%E5%BB%BA%E8%BF%87%E7%A8%8B%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E4%B8%8D%E5%90%8C%E7%9A%84%E8%A1%A8%E7%A4%BA%EF%BC%8C%0A%60%60%60%0A%E8%AF%A5%E6%A8%A1%E5%BC%8F%E7%9A%84%E4%B8%BB%E8%A6%81%E4%BC%98%E7%82%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%20%0A%3E1.%20%E5%90%84%E4%B8%AA%E5%85%B7%E4%BD%93%E7%9A%84%E5%BB%BA%E9%80%A0%E8%80%85%E7%9B%B8%E4%BA%92%E7%8B%AC%E7%AB%8B%EF%BC%8C%E6%9C%89%E5%88%A9%E4%BA%8E%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%89%A9%E5%B1%95%E3%80%82%0A%3E2.%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%B8%8D%E5%BF%85%E7%9F%A5%E9%81%93%E4%BA%A7%E5%93%81%E5%86%85%E9%83%A8%E7%BB%84%E6%88%90%E7%9A%84%E7%BB%86%E8%8A%82%EF%BC%8C%E4%BE%BF%E4%BA%8E%E6%8E%A7%E5%88%B6%E7%BB%86%E8%8A%82%E9%A3%8E%E9%99%A9%E3%80%82%0A%0A%E5%85%B6%E7%BC%BA%E7%82%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%3E1.%20%E4%BA%A7%E5%93%81%E7%9A%84%E7%BB%84%E6%88%90%E9%83%A8%E5%88%86%E5%BF%85%E9%A1%BB%E7%9B%B8%E5%90%8C%EF%BC%8C%E8%BF%99%E9%99%90%E5%88%B6%E4%BA%86%E5%85%B6%E4%BD%BF%E7%94%A8%E8%8C%83%E5%9B%B4%E3%80%82%0A%3E2.%20%E5%A6%82%E6%9E%9C%E4%BA%A7%E5%93%81%E7%9A%84%E5%86%85%E9%83%A8%E5%8F%98%E5%8C%96%E5%A4%8D%E6%9D%82%EF%BC%8C%E8%AF%A5%E6%A8%A1%E5%BC%8F%E4%BC%9A%E5%A2%9E%E5%8A%A0%E5%BE%88%E5%A4%9A%E7%9A%84%E5%BB%BA%E9%80%A0%E8%80%85%E7%B1%BB%E3%80%82%0A%0A%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%0A%3E%E5%BB%BA%E9%80%A0%E8%80%85%EF%BC%88Builder%EF%BC%89%E6%A8%A1%E5%BC%8F%E5%88%9B%E5%BB%BA%E7%9A%84%E6%98%AF%E5%A4%8D%E6%9D%82%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%85%B6%E4%BA%A7%E5%93%81%E7%9A%84%E5%90%84%E4%B8%AA%E9%83%A8%E5%88%86%E7%BB%8F%E5%B8%B8%E9%9D%A2%E4%B8%B4%E7%9D%80%E5%89%A7%E7%83%88%E7%9A%84%E5%8F%98%E5%8C%96%EF%BC%8C%E4%BD%86%E5%B0%86%E5%AE%83%E4%BB%AC%E7%BB%84%E5%90%88%E5%9C%A8%E4%B8%80%E8%B5%B7%E7%9A%84%E7%AE%97%E6%B3%95%E5%8D%B4%E7%9B%B8%E5%AF%B9%E7%A8%B3%E5%AE%9A%EF%BC%8C%E6%89%80%E4%BB%A5%E5%AE%83%E9%80%9A%E5%B8%B8%E5%9C%A8%E4%BB%A5%E4%B8%8B%E5%9C%BA%E5%90%88%E4%BD%BF%E7%94%A8%E3%80%82%0A%3E%0A%3E1.%20%E5%88%9B%E5%BB%BA%E7%9A%84%E5%AF%B9%E8%B1%A1%E8%BE%83%E5%A4%8D%E6%9D%82%EF%BC%8C%E7%94%B1%E5%A4%9A%E4%B8%AA%E9%83%A8%E4%BB%B6%E6%9E%84%E6%88%90%EF%BC%8C%E5%90%84%E9%83%A8%E4%BB%B6%E9%9D%A2%E4%B8%B4%E7%9D%80%E5%A4%8D%E6%9D%82%E7%9A%84%E5%8F%98%E5%8C%96%EF%BC%8C%E4%BD%86%E6%9E%84%E4%BB%B6%E9%97%B4%E7%9A%84%E5%BB%BA%E9%80%A0%E9%A1%BA%E5%BA%8F%E6%98%AF%E7%A8%B3%E5%AE%9A%E7%9A%84%E3%80%82%0A%3E2.%20%E5%88%9B%E5%BB%BA%E5%A4%8D%E6%9D%82%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%AE%97%E6%B3%95%E7%8B%AC%E7%AB%8B%E4%BA%8E%E8%AF%A5%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%BB%84%E6%88%90%E9%83%A8%E5%88%86%E4%BB%A5%E5%8F%8A%E5%AE%83%E4%BB%AC%E7%9A%84%E8%A3%85%E9%85%8D%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%8D%B3%E4%BA%A7%E5%93%81%E7%9A%84%E6%9E%84%E5%BB%BA%E8%BF%87%E7%A8%8B%E5%92%8C%E6%9C%80%E7%BB%88%E7%9A%84%E8%A1%A8%E7%A4%BA%E6%98%AF%E7%8B%AC%E7%AB%8B%E7%9A%84%E3%80%82%0A%0A%0A%23%23%23%23%23%20%E8%A3%85%E9%A5%B0%EF%BC%88Decorator%EF%BC%89%E6%A8%A1%E5%BC%8F%0A%0A%60%60%60%0A%E5%AE%9A%E4%B9%89%EF%BC%9A%E6%8C%87%E5%9C%A8%E4%B8%8D%E6%94%B9%E5%8F%98%E7%8E%B0%E6%9C%89%E5%AF%B9%E8%B1%A1%E7%BB%93%E6%9E%84%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E5%8A%A8%E6%80%81%E5%9C%B0%E7%BB%99%E8%AF%A5%E5%AF%B9%E8%B1%A1%E5%A2%9E%E5%8A%A0%E4%B8%80%E4%BA%9B%E8%81%8C%E8%B4%A3%EF%BC%88%E5%8D%B3%E5%A2%9E%E5%8A%A0%E5%85%B6%E9%A2%9D%E5%A4%96%E5%8A%9F%E8%83%BD%EF%BC%89%E7%9A%84%E6%A8%A1%E5%BC%8F%0A%60%60%60%0A%E8%A3%85%E9%A5%B0%E6%A8%A1%E5%BC%8F%E4%B8%BB%E8%A6%81%E5%8C%85%E5%90%AB%E4%BB%A5%E4%B8%8B%E8%A7%92%E8%89%B2%E3%80%82%0A%3E1.%20%E6%8A%BD%E8%B1%A1%E6%9E%84%E4%BB%B6%EF%BC%88Component%EF%BC%89%E8%A7%92%E8%89%B2%EF%BC%9A%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E6%8A%BD%E8%B1%A1%E6%8E%A5%E5%8F%A3%E4%BB%A5%E8%A7%84%E8%8C%83%E5%87%86%E5%A4%87%E6%8E%A5%E6%94%B6%E9%99%84%E5%8A%A0%E8%B4%A3%E4%BB%BB%E7%9A%84%E5%AF%B9%E8%B1%A1%E3%80%82%0A%3E2.%20%E5%85%B7%E4%BD%93%E6%9E%84%E4%BB%B6%EF%BC%88Concrete%20%20Component%EF%BC%89%E8%A7%92%E8%89%B2%EF%BC%9A%E5%AE%9E%E7%8E%B0%E6%8A%BD%E8%B1%A1%E6%9E%84%E4%BB%B6%EF%BC%8C%E9%80%9A%E8%BF%87%E8%A3%85%E9%A5%B0%E8%A7%92%E8%89%B2%E4%B8%BA%E5%85%B6%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%BA%9B%E8%81%8C%E8%B4%A3%E3%80%82%0A%3E3.%20%E6%8A%BD%E8%B1%A1%E8%A3%85%E9%A5%B0%EF%BC%88Decorator%EF%BC%89%E8%A7%92%E8%89%B2%EF%BC%9A%E7%BB%A7%E6%89%BF%E6%8A%BD%E8%B1%A1%E6%9E%84%E4%BB%B6%EF%BC%8C%E5%B9%B6%E5%8C%85%E5%90%AB%E5%85%B7%E4%BD%93%E6%9E%84%E4%BB%B6%E7%9A%84%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%85%B6%E5%AD%90%E7%B1%BB%E6%89%A9%E5%B1%95%E5%85%B7%E4%BD%93%E6%9E%84%E4%BB%B6%E7%9A%84%E5%8A%9F%E8%83%BD%E3%80%82%0A%3E4.%20%E5%85%B7%E4%BD%93%E8%A3%85%E9%A5%B0%EF%BC%88ConcreteDecorator%EF%BC%89%E8%A7%92%E8%89%B2%EF%BC%9A%E5%AE%9E%E7%8E%B0%E6%8A%BD%E8%B1%A1%E8%A3%85%E9%A5%B0%E7%9A%84%E7%9B%B8%E5%85%B3%E6%96%B9%E6%B3%95%EF%BC%8C%E5%B9%B6%E7%BB%99%E5%85%B7%E4%BD%93%E6%9E%84%E4%BB%B6%E5%AF%B9%E8%B1%A1%E6%B7%BB%E5%8A%A0%E9%99%84%E5%8A%A0%E7%9A%84%E8%B4%A3%E4%BB%BB%E3%80%82%0A%0A%0A%0A%23%23%23%23%23%20%E5%A4%87%E5%BF%98%E5%BD%95%EF%BC%88Memento%0A%60%60%60%0A%E5%9C%A8%E4%B8%8D%E7%A0%B4%E5%9D%8F%E5%B0%81%E8%A3%85%E6%80%A7%E7%9A%84%E5%89%8D%E6%8F%90%E4%B8%8B%EF%BC%8C%E6%8D%95%E8%8E%B7%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%EF%BC%8C%E5%B9%B6%E5%9C%A8%E8%AF%A5%E5%AF%B9%E8%B1%A1%E4%B9%8B%E5%A4%96%E4%BF%9D%E5%AD%98%E8%BF%99%E4%B8%AA%E7%8A%B6%E6%80%81%EF%BC%8C%E4%BB%A5%E4%BE%BF%E4%BB%A5%E5%90%8E%E5%BD%93%E9%9C%80%E8%A6%81%E6%97%B6%E8%83%BD%E5%B0%86%E8%AF%A5%E5%AF%B9%E8%B1%A1%E6%81%A2%E5%A4%8D%E5%88%B0%E5%8E%9F%E5%85%88%E4%BF%9D%E5%AD%98%E7%9A%84%E7%8A%B6%E6%80%81%0A%60%60%60%0A%0A%E5%A4%87%E5%BF%98%E5%BD%95%E6%A8%A1%E5%BC%8F%E7%9A%84%E4%B8%BB%E8%A6%81%E8%A7%92%E8%89%B2%E5%A6%82%E4%B8%8B%0A%0A%0A%3E1.%20%E5%8F%91%E8%B5%B7%E4%BA%BA%EF%BC%88Originator%EF%BC%89%E8%A7%92%E8%89%B2%EF%BC%9A%E8%AE%B0%E5%BD%95%E5%BD%93%E5%89%8D%E6%97%B6%E5%88%BB%E7%9A%84%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%E4%BF%A1%E6%81%AF%EF%BC%8C%E6%8F%90%E4%BE%9B%E5%88%9B%E5%BB%BA%E5%A4%87%E5%BF%98%E5%BD%95%E5%92%8C%E6%81%A2%E5%A4%8D%E5%A4%87%E5%BF%98%E5%BD%95%E6%95%B0%E6%8D%AE%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%AE%9E%E7%8E%B0%E5%85%B6%E4%BB%96%E4%B8%9A%E5%8A%A1%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%AE%83%E5%8F%AF%E4%BB%A5%E8%AE%BF%E9%97%AE%E5%A4%87%E5%BF%98%E5%BD%95%E9%87%8C%E7%9A%84%E6%89%80%E6%9C%89%E4%BF%A1%E6%81%AF%E3%80%82%0A%3E2.%20%E5%A4%87%E5%BF%98%E5%BD%95%EF%BC%88Memento%EF%BC%89%E8%A7%92%E8%89%B2%EF%BC%9A%E8%B4%9F%E8%B4%A3%E5%AD%98%E5%82%A8%E5%8F%91%E8%B5%B7%E4%BA%BA%E7%9A%84%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%EF%BC%8C%E5%9C%A8%E9%9C%80%E8%A6%81%E7%9A%84%E6%97%B6%E5%80%99%E6%8F%90%E4%BE%9B%E8%BF%99%E4%BA%9B%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%E7%BB%99%E5%8F%91%E8%B5%B7%E4%BA%BA%E3%80%82%0A%3E3.%20%E7%AE%A1%E7%90%86%E8%80%85%EF%BC%88Caretaker%EF%BC%89%E8%A7%92%E8%89%B2%EF%BC%9A%E5%AF%B9%E5%A4%87%E5%BF%98%E5%BD%95%E8%BF%9B%E8%A1%8C%E7%AE%A1%E7%90%86%EF%BC%8C%E6%8F%90%E4%BE%9B%E4%BF%9D%E5%AD%98%E4%B8%8E%E8%8E%B7%E5%8F%96%E5%A4%87%E5%BF%98%E5%BD%95%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E4%BD%86%E5%85%B6%E4%B8%8D%E8%83%BD%E5%AF%B9%E5%A4%87%E5%BF%98%E5%BD%95%E7%9A%84%E5%86%85%E5%AE%B9%E8%BF%9B%E8%A1%8C%E8%AE%BF%E9%97%AE%E4%B8%8E%E4%BF%AE%E6%94%B9%E3%80%82%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A

umlplant 安装

创建时间:2022/4/30 14:00
更新时间:2022/4/30 14:12
作者:Chris
来源:https://www.jb51.net/article/214989.htm

1 安装PlantUML

1.1 安装步骤为:

File -> Settings -> Plugins 搜索 PlantUML ,找到 PlantUML integration 并安装。

2 安装Graphviz

IDEA 安装 PlantUML 插件之后发现光有插件还不能渲染类图,还需要 Graphviz 的支持。

2.1 Graphviz安装

https://graphviz.org/download/

2.2 环境变量配置

打开电脑系统属性选择高级 -> 环境变量添加path变量,变量值为之前安装路径下的bin目录。

配置完成之后打开 cmd 输入:dot -version
如果版本号打印成功,说明环境配置完成

3 创建PlantUML File

成功之后重新启动 IDEA 即可创建 PlantUML File 了

点击之后可以发现可以创建很多 UML 图,
例如:时序图、用例图、类图、活动图、组件图、状态图、对象图。
各种图的具体说明 https://plantuml.com/

%5Btoc%5D%0A%0A%23%23%201%20%E5%AE%89%E8%A3%85PlantUML%0A%23%23%23%23%201.1%20%E5%AE%89%E8%A3%85%E6%AD%A5%E9%AA%A4%E4%B8%BA%EF%BC%9A%0A%60%60%60%0AFile%20-%3E%20Settings%20-%3E%20Plugins%20%E6%90%9C%E7%B4%A2%20PlantUML%20%EF%BC%8C%E6%89%BE%E5%88%B0%20PlantUML%20integration%20%E5%B9%B6%E5%AE%89%E8%A3%85%E3%80%82%0A%60%60%60%0A!%5Bf15178c55f72c486785b49103dcbcd52.png%5D(en-resource%3A%2F%2Fdatabase%2F1227%3A1)%0A%0A%23%23%202%20%E5%AE%89%E8%A3%85Graphviz%0A%3E%20IDEA%C2%A0%E5%AE%89%E8%A3%85%C2%A0PlantUML%C2%A0%E6%8F%92%E4%BB%B6%E4%B9%8B%E5%90%8E%E5%8F%91%E7%8E%B0%E5%85%89%E6%9C%89%E6%8F%92%E4%BB%B6%E8%BF%98%E4%B8%8D%E8%83%BD%E6%B8%B2%E6%9F%93%E7%B1%BB%E5%9B%BE%2C%E8%BF%98%E9%9C%80%E8%A6%81%C2%A0Graphviz%C2%A0%E7%9A%84%E6%94%AF%E6%8C%81%E3%80%82%0A%0A%23%23%23%23%23%202.1%20Graphviz%E5%AE%89%E8%A3%85%0Ahttps%3A%2F%2Fgraphviz.org%2Fdownload%2F%0A%0A!%5B874cd8200366972d3b343a65e1500650.png%5D(en-resource%3A%2F%2Fdatabase%2F1229%3A1)%0A%0A%23%23%23%23%23%202.2%20%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E9%85%8D%E7%BD%AE%0A%3E%20%E6%89%93%E5%BC%80%E7%94%B5%E8%84%91%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7%E9%80%89%E6%8B%A9%E9%AB%98%E7%BA%A7%20-%3E%20%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E6%B7%BB%E5%8A%A0path%E5%8F%98%E9%87%8F%EF%BC%8C%E5%8F%98%E9%87%8F%E5%80%BC%E4%B8%BA%E4%B9%8B%E5%89%8D%E5%AE%89%E8%A3%85%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%9A%84bin%E7%9B%AE%E5%BD%95%E3%80%82%0A%0A!%5B4805f9d174b3fa4d2ddc32e1b04e4b1e.png%5D(en-resource%3A%2F%2Fdatabase%2F1231%3A1)%0A%0A%3E%20%E9%85%8D%E7%BD%AE%E5%AE%8C%E6%88%90%E4%B9%8B%E5%90%8E%E6%89%93%E5%BC%80%C2%A0cmd%C2%A0%E8%BE%93%E5%85%A5%EF%BC%9Adot%20-version%0A%3E%20%E5%A6%82%E6%9E%9C%E7%89%88%E6%9C%AC%E5%8F%B7%E6%89%93%E5%8D%B0%E6%88%90%E5%8A%9F%EF%BC%8C%E8%AF%B4%E6%98%8E%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%AE%8C%E6%88%90%0A%0A!%5B17f2dca8f9a70e0caa1870d9e845264e.png%5D(en-resource%3A%2F%2Fdatabase%2F1233%3A1)%0A%0A%23%23%203%20%E5%88%9B%E5%BB%BAPlantUML%20File%0A%0A%3E%20%E6%88%90%E5%8A%9F%E4%B9%8B%E5%90%8E%E9%87%8D%E6%96%B0%E5%90%AF%E5%8A%A8%C2%A0IDEA%C2%A0%E5%8D%B3%E5%8F%AF%E5%88%9B%E5%BB%BA%C2%A0PlantUML%20File%C2%A0%E4%BA%86%0A%0A!%5B464b0a226953d296864c1e2df6ea0b63.png%5D(en-resource%3A%2F%2Fdatabase%2F1235%3A1)%0A%0A%3E%20%E7%82%B9%E5%87%BB%E4%B9%8B%E5%90%8E%E5%8F%AF%E4%BB%A5%E5%8F%91%E7%8E%B0%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E5%BE%88%E5%A4%9A%C2%A0UML%C2%A0%E5%9B%BE%EF%BC%8C%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%9A%E6%97%B6%E5%BA%8F%E5%9B%BE%E3%80%81%E7%94%A8%E4%BE%8B%E5%9B%BE%E3%80%81%E7%B1%BB%E5%9B%BE%E3%80%81%E6%B4%BB%E5%8A%A8%E5%9B%BE%E3%80%81%E7%BB%84%E4%BB%B6%E5%9B%BE%E3%80%81%E7%8A%B6%E6%80%81%E5%9B%BE%E3%80%81%E5%AF%B9%E8%B1%A1%E5%9B%BE%E3%80%82%0A%3E%20%E5%90%84%E7%A7%8D%E5%9B%BE%E7%9A%84%E5%85%B7%E4%BD%93%E8%AF%B4%E6%98%8E%20%60https%3A%2F%2Fplantuml.com%2F%60%0A%0A!%5B60f835a0e9d38baf668dd0d549c736d2.png%5D(en-resource%3A%2F%2Fdatabase%2F1237%3A1)%0A

RocketMQ

创建时间:2022/3/20 14:31
更新时间:2023/3/25 9:05
作者:Chris
来源:https://www.bilibili.com/video/BV1cf4y157sz?p=5

https://bright-boy.gitee.io/technical-notes
https://blog.csdn.net/qq_34930488/article/details/101293178

最佳实践

https://rocketmq.apache.org/zh/docs/4.x/bestPractice/01bestpractice

什么是MQ

MQ全称message queue(消息队列),是在消息传输的过程中保存消息的容器。
多用于分布式系统间进行通信
queue(队列):一种数据结构,特征为‘先进先出’

能干什么

  1. 应用解耦
  2. 异步提速
  3. 削峰填谷

应用解耦

当生产者生产完消息后,无需等待就可以进行下一步业务逻辑。
需要根据消息完成特定功能的业务组件只需要简单订阅消息即可完成对消息的消费。
即使后面有新增的业务组件,也只需要简单订阅消息就可以完成平滑的接入。

削峰填谷

对超量请求可以暂存其中,以便系统后续可以慢慢处理,从而避免请求丢失或系统被压垮
例如:使用MQ之后,限制消息消费的速度为1000条/s, 这样一来,高峰期产生的数据势必会积压在MQ中,这样高峰就被削掉,但因为消息的积压,高峰期过后一段时间内,消费消息的速度还在维持在1000/s直到消费后积压的消息为至,这就叫填谷。

MQ的劣势

系统可用性降低

引入的外部依赖越多,系统的稳定性就会越差,引入的MQ 宕机就会对业务造成影响
需要解决保证MQ的高可用问题

系统复杂度提高

MQ的加入增加了系统的复杂性,之前系统间是同步的远程调用,现在是通过MQ进行异步调用。
如何保证消息没有被重复消费
怎么处理消息丢失
如何保证消息传递的顺序性

一致性问题

A系统处理完业务通过MQ给 B,C,D三个系统发消息数据,如果B,C处理成功,但是D系统处理失败。
如何保证消息数据处理的一致性?

MQ产品介绍

ActiveMQ

ActiveMQ是使用Java语言开发一款MQ产品。早期很多公司与项目中都在使用。但现在的社区活跃度已经很低。现在的项目中已经很少使用了。

RabbitMQ

RabbitMQ是使用ErLang语言开发的一款MQ产品。其吞吐量较Kafka与RocketMQ要低,且由于其不是Java语言开发,所以公司内部对其实现定制化开发难度较大。

Kafka

Kafka是使用Scala/Java语言开发的一款MQ产品。其最大的特点就是高吞吐率,常用于大数据领域的实时计算、日志采集等场景。其没有遵循任何常见的MQ协议,而是使用自研协议。对于Spring Cloud Netfix,其仅支持RabbitMQ与Kafka。

RocketMQ

RocketMQ是使用Java语言开发的一款MQ产品。经过数年阿里双 11 的考验,性能与稳定性非常高。其没有遵循任何常见的MQ协议,而是使用自研协议。对于Spring Cloud Alibaba,其支持RabbitMQ、Kafka,但提倡使用RocketMQ。

Ali技术团队在Kafka开源后对其技术进行了深入的研究开发出一款新的MQ叫MetaMQ, 后来对MetaMQ进一步开发成为后面的RocketMQ。

对比

核心概念

生产者(Producer)

消息生产者,负责生产消息。
Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。

RocketMQ中的消息生产者都是以生产者组(Producer Group)的形式出现的。
生产者组是同一类生产者的集合,这类Producer发送相同Topic类型的消息。

一个生产者组可以同时发送多个主题的消息。
例如,业务系统产生的日志写入到MQ的过程,就是消息生产的过程
再如,电商平台中用户提交的秒杀请求写入到MQ的过程,就是消息生产的过程

消息消费者

消息消费者,负责消费消息。一个消息消费者会从Broker服务器中获取到消息,并对消息进行相关业务处理。

RocketMQ中的消息消费者都是以消费者组(Consumer Group)的形式出现的。
消费者组是同一类消费者的集合,这类Consumer消费的是同一个Topic类型的消息。不过,一个Topic类型的消息可以被多个消费者组同时消费

消费者组使得在消息消费方面,实现负载均衡(将一个Topic中的不同的Queue平均分配给同一个Consumer Group的不同的Consumer,注意,并不是将消息负载均衡)和容错(一个Consmer挂了,该Consumer Group中的其它Consumer可以接着消费原Consumer消费的Queue)的目标变得非常容易。

例如,QoS系统从MQ中读取日志,并对日志进行解析处理的过程就是消息消费的过程。

再如,电商平台的业务系统从MQ中读取到秒杀请求,并对请求进行处理的过程就是消息消费的过程。

消费者组中Consumer的数量应该小于等于订阅Topic的Queue数量。

如果超出Queue数量,则多出的Consumer将不能消费消息。

注意,

  • 1 消费者组只能消费一个Topic的消息,不能同时消费多个Topic消息
  • 2 一个消费者组中的消费者必须订阅完全相同的Topic

Name Server

功能介绍

NameServer是Broker与Topic路由的注册中心,支持Broker的动态注册与发现

RocketMQ的思想来自于Kafka,而Kafka是依赖zookeeper的,所以在RocketMQ早期版本中也依赖zookeeper。从MetaQ v3.0开始,RocketMQ去掉了zookeeper的依赖,使用b了自己的NameServer

主要功能有两个:

  • Broker管理:接受Broker集群的注册信息并且保存下来作为路由信息的基本数据;提供心跳检测机制,检查Broker是否还存活。
  • 路由信息管理:每个NameServer中都保存着Broker集群的整个路由信息和用于客户端查询的队列信息。Producer和Conumser通过NameServer可以获取整个Broker集群的路由信息,从而进行消息的投递和消费。
路由注册

NameServer通常也是以集群的方式部署,不过,NameServer是无状态的,即NameServer集群中的各个节点间是无差异的,各节点间相互不进行信息通讯

那各节点中的数据是如何进行数据同步的呢?

在Broker节点启动时,轮询NameServer列表,与每个NameServer节点建立长连接,发起注册请求。在NameServer内部维护着一个Broker列表,用来动态存储Broker的信息。

注意,这是与其它像zk、Eureka、Nacos等注册中心不同的地方。
这种NameServer的无状态方式,有什么优缺点:
优点:NameServer集群搭建简单,扩容简单。
缺点:对于Broker,必须明确指出所有NameServer地址。否则未指出的将不会去注册。也正因为如此,NameServer并不能随便扩容。因为,若Broker不重新配置,新增的NameServer对于Broker来说是不可见的,其不会向这个NameServer进行注册。

Broker节点为了证明自己是活着的,为了维护与NameServer间的长连接,会将最新的信息以心跳包的方式上报给NameServer,每 30 秒发送一次心跳。心跳包中包含 BrokerId、Broker地址(IP+Port)、Broker名称、Broker所属集群名称等等。NameServer在接收到心跳包后,会更新心跳时间戳,记录这个Broker的最新存活时间。

路由剔除

由于Broker关机、宕机或网络抖动等原因,NameServer没有收到Broker的心跳,NameServer可能会将其从Broker列表中剔除。

NameServer中有一个定时任务,每隔 10 秒就会扫描一次Broker表,查看每一个Broker的最新心跳时间戳距离当前时间是否超过 120 秒,如果超过,则会判定Broker失效,然后将其从Broker列表中剔除。

扩展:

对于RocketMQ日常运维工作,例如Broker升级,需要停掉Broker的工作。

OP需要怎么做?
OP需要将Broker的读写权限禁掉。一旦client(Consumer或Producer)向broker发送请求,都会收到broker的NO_PERMISSION响应,然后client会进行对其它Broker的重试。
当OP观察到这个Broker没有流量后,再关闭它,实现Broker从NameServer的移除。
OP:运维工程师
SRE:Site Reliability Engineer,现场可靠性工程师

路由发现

RocketMQ的路由发现采用的是Pull模型
在RocketMQ虽然有对于消费者有DefaultMQPullConsumerDefaultMQPushConsumer两个Api可供选择,但是底层其实都使用PullAPIWrapper这个类进行消息拉取,也就是说,RocketMQ使用的消费传递模型是Pull模型。

当Topic路由信息出现变化时,NameServer不会主动推送给客户端,而是客户端定时拉取主题最新的路由。
默认客户端每 30 秒会拉取一次最新的路由。

Push模型

Push模型:推送模型。其实时性较好,是一个发布-订阅模型,需要维护一个长连接。而长连接的维护是需要资源成本的。该模型适合于的场景:

  • 实时性要求较高

  • Client数量不多,Server数据变化较频繁

Pull模型

Pull模型:拉取模型。存在的问题是,实时性较差。

Long Polling模型

Long Polling模型:长轮询模型。其是对Push与Pull模型的整合,充分利用了这两种模型的优势,屏蔽了它们的劣势。

RocketMQ源码之长轮询实现

Broker

功能介绍

Broker充当着消息中转角色,负责存储消息、转发消息。Broker在RocketMQ系统中负责接收并存储从生产者发送来的消息,同时为消费者的拉取请求作准备。Broker同时也存储着消息相关的元数据,包括消费者组消费进度偏移offset、主题、队列等。

Kafka 0.8版本之后,offset是存放在Broker中的,之前版本是存放在Zookeeper中的。

集群部署

为了增强Broker性能与吞吐量,Broker一般都是以集群形式出现的。各集群节点中可能存放着相同Topic的不同Queue。不过,这里有个问题,如果某Broker节点宕机,如何保证数据不丢失呢?其解决方案是,将每个Broker集群节点进行横向扩展,即将Broker节点再建为一个HA集群,解决单点问题。

Broker节点集群是一个主从集群,即集群中具有Master与Slave两种角色。Master负责处理读写操作请求,Slave负责对Master中的数据进行备份。

当Master挂掉了,Slave则会自动切换为Master去工作。

所以这个Broker集群是主备集群。一个Master可以包含多个Slave,但一个Slave只能隶属于一个Master。

Master与Slave 的对应关系是通过指定相同的BrokerName、不同的BrokerId 来确定的。BrokerId为 0 表示Master,非 0 表示Slave。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。

读/写队列

是什么

从物理上来讲,读/写队列是同一个队列。所以,不存在读/写队列数据同步问题。读/写队列是逻辑上进行区分的概念。一般情况下,读/写队列数量是相同的。

例如,创建Topic时设置的写队列数量为 8 ,读队列数量为 4 ,此时系统会创建 8 个Queue,分别是0 1 2 3 4 5 6 7。Producer会将消息写入到这 8 个队列,但Consumer只会消费0 1 2 3这 4 个队列中的消息,4 5 6 7 中的消息是不会被消费到的。

再如,创建Topic时设置的写队列数量为 4 ,读队列数量为 8 ,此时系统会创建 8 个Queue,分别是0 1 2 3 4 5 6 7。Producer会将消息写入到0 1 2 3 这 4 个队列,但Consumer只会消费0 1 2 3 4 5 6 7这 8 个队列中的消息,但是4 5 6 7中是没有消息的。此时假设Consumer Group中包含两个Consumer,Consumer1消费0 1 2 3,而Consumer2消费4 5 6 7。但实际情况是,Consumer2是没有消息可消费的。

也就是说,当读/写队列数量设置不同时,总是有问题的。那么,为什么要这样设计呢?其这样设计的目的是为了,方便Topic的Queue的缩容。

例如,原来创建的Topic中包含 16 个Queue,如何能够使其Queue缩容为 8 个,还不会丢失消息?可以动态修改写队列数量为 8 ,读队列数量不变。此时新的消息只能写入到前 8 个队列,而消费都消费的却是16 个队列中的数据。当发现后 8 个Queue中的消息消费完毕后,就可以再将读队列数量动态设置为 8 。整个缩容过程,没有丢失任何消息。

权限

perm用于设置对当前创建Topic的操作权限:2 表示只写, 4 表示只读, 6 表示读写。

消息(Message)

消息是指,消息系统所传输信息的物理载体,生产和消费数据的最小单位,每条消息必须属于一个主题

Topics

概念介绍

topic表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是
RocketMQ进行消息订阅的基本单位。
一个生产者可以同时发送多种Topic的消息;
而一个消费者只对某种特定的Topic感兴趣,即只可以订阅和消费一种Topic的消息。
对应关系

topic:message 1:n   message:topic 1:1
producer:topic 1:n  consumer:topic 1:1

创建模式

手动创建Topic时,有两种模式:

  • 集群模式:该模式下创建的Topic在该集群中,所有Broker中的Queue数量是相同的。
  • Broker模式:该模式下创建的Topic在该集群中,每个Broker中的Queue数量可以不同。

自动创建Topic时,默认采用的是Broker模式,会为每个Broker默认创建 4 个Queue。

标签(Tag)

为消息设置的标签,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。标签能够有效地保持代码的清晰度和连贯性,并优化RocketMQ提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。

Topic是消息的一级分类,Tag是消息的二级分类。

Topic:货物
tag=上海
tag=江苏
tag=浙江
------- 消费者 -----
topic=货物 tag = 上海
topic=货物 tag = 上海|浙江
topic=货物 tag = *

队列(Queue)

存储消息的物理实体。
一个Topic中可以包含多个Queue,每个Queue中存放的就是该Topic的消息。
一个Topic的Queue也被称为一个Topic中消息的分区(Partition)。
一个Topic的Queue中的消息只能被一个消费者组中的一个消费者消费
一个Queue中的消息不允许被同一个消费者组中的多个消费者同时消费

分片(Sharding)

在学习参考其它相关资料时,还会看到一个概念:分片(Sharding)。分片不同于分区。在RocketMQ中,分片指的是存放相应Topic的Broker。每个分片中会创建出相应数量的分区,即Queue,每个Queue的大小都是相同的。

消息标识(MessageId/Key)

RocketMQ中每个消息拥有唯一的MessageId,且可以携带具有业务标识的Key,以方便对消息的查询。
不过需要注意的是,MessageId有两个:在生产者send()消息时会自动生成一个MessageId(msgId)
当消息到达Broker后,Broker也会自动生成一个MessageId(offsetMsgId)。
msgId、offsetMsgId与key都称为消息标识。

msgId:

  • 由producer端生成,其生成规则为:producerIp + 进程pid + MessageClientIDSetter类的ClassLoader的hashCode +当前时间 + AutomicInteger自增计数器

offsetMsgId:

  • 由broker端生成,其生成规则为:brokerIp + 物理分区的offset(Queue中的偏移量)

key:由用户指定的业务相关的唯一标识

工作原理

NamerServer 存放broker的IP地址信息
broker 部署着rocketmq的机器就是一个broker

  1. 生产者,消息者,broker启动之后都会把各自的IP信息注册到NamerServer里面,并与NameServer建立长连接,

    Producer启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取路由信息,即当前发送的Topic消息的Queue与Broker的地址(IP+Port)的映射关系。然后根据算法策略从队选择一个Queue,与队列所在的Broker建立长连接从而向Broker发消息。当然,在获取到路由信息后,Producer会首先将路由信息缓存到本地,再每 30 秒从NameServer更新一次路由信息。

    Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取其所订阅Topic的路由信息,然后根据算法策略从路由信息中获取到其所要消费的Queue,然后直接跟Broker建立长连接,开始消费其中的消息。Consumer在获取到路由信息后,同样也会每 30 秒从NameServer更新一次路由信息。不过不同于Producer的是,Consumer还会向Broker发送心跳,以确保Broker的存活状态。

    Broker启动后会与配置中的每一个NameServer保持长连接,并每30秒向NameServer发送心跳包。

  2. NamerServer除了记录IP信息外还负责通过心跳监听与各组件之间的连通性

  3. 当生产者生产消息时,先通过NamerServer找到可用的borker,然后把消息存入可用boker里面对应topic里面

  4. 消息者通过拉取模式或监听模式来获取boker里面对应topic里面的消息

消息者如何知道MQ里面有消息

集群搭建理论

数据复制与刷盘策略

复制策略

复制策略是Broker的Master与Slave间的数据同步方式

分为同步复制与异步复制:

  • 同步复制:消息写入master后,master会等待slave同步数据成功后才向producer返回成功ACK

  • 异步复制:消息写入master后,master立即向producer返回成功ACK,无需等待slave同步数据成功

异步复制策略会降低系统的写入延迟,RT变小,提高了系统的吞吐量

刷盘策略

刷盘策略指的是broker中消息的落盘方式,即消息发送到broker内存后消息持久化到磁盘的方式。

分为同步刷盘与异步刷盘.

  • 同步刷盘:当消息持久化到broker的磁盘后才算是消息写入成功。
  • 异步刷盘:当消息写入到broker的内存后即表示消息写入成功,无需等待消息持久化到磁盘。

1 . 异步刷盘策略会降低系统的写入延迟,RT变小,提高了系统的吞吐量
2 . 消息写入到Broker的内存,一般是写入到了PageCache
3 . 对于异步 刷盘策略,消息会写入到PageCache后立即返回成功ACK。但并不会立即做落盘操作,而是当PageCache到达一定量时会自动进行落盘。

Broker集群模式

单Master

只有一个broker(其本质上就不能称为集群)。

这种方式也只能是在测试时使用,生产环境下不能使用,因为存在单点问题。

多Master

broker集群仅由多个master构成,不存在Slave。同一Topic的各个Queue会平均分布在各个master节点上。

  • 优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢),性能最高;
  • 缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅(不可消费),消息实时性会受到影响。

以上优点的前提是,这些Master都配置了RAID10磁盘阵列。如果没有配置,一旦出现某Master宕机,则会发生大量消息丢失的情况。

多Master多Slave模式-异步复制

broker集群由多个master构成,每个master又配置了多个slave(在配置了RAID磁盘阵列的情况下,一个master一般配置一个slave即可)。

master与slave的关系是主备关系,即master负责处理消息的读写请求,而slave仅负责消息的备份与master宕机后的角色切换。

异步复制即前面所讲的复制策略中的异步复制策略,即消息写入master成功后,master立即向producer返回成功ACK,无需等待slave同步数据成功。

该模式的最大特点之一是,当master宕机后slave能够自动切换为master。不过由于slave从master的同步具有短暂的延迟(毫秒级),所以当master宕机后,这种异步复制方式可能会存在少量消息的丢失问题。

Slave从Master同步的延迟越短,其可能丢失的消息就越少

对于Master的RAID磁盘阵列,若使用的也是异步复制策略,同样也存在延迟问题,同样也可能会丢失消息。但RAID阵列的秘诀是(微秒级)的(因为是由硬盘支持的),所以其丢失的数据量会更少。

多Master多Slave模式-同步双写

该模式是多Master多Slave模式同步复制实现。所谓同步双写,指的是消息写入master成功后,master会等待slave同步数据成功后才向producer返回成功ACK,即master与slave都要写入成功后才会返回成功ACK,也即双写

该模式与异步复制模式相比,优点是消息的安全性更高,不存在消息丢失的情况。但单个消息的RT略高,从而导致性能要略低(大约低10%)。

该模式存在一个大的问题:对于目前的版本4.9.0,Master宕机后,Slave不会自动切换到Master。

部署配置:同步双写-异步刷盘

生产-消费模式

单生产者-多消费者模式

同一组多消费者

创建生产者

package com.chris.rocketmq;

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.io.UnsupportedEncodingException;

/**
 * @author Chris
 * @date 2022-03-24 6:35 PM
 */
public class Producer {

    public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException,
            InterruptedException, MQBrokerException {
        DefaultMQProducer producer = new DefaultMQProducer("rocketmq-producer-group-001");
        producer.setNamesrvAddr("master:9876");

        producer.start();
        System.out.println("producer has started!");

        for (int i = 0; i < 10; i++) {
            //Create a message instance, specifying topic, tag and message body.
            Message msg = new Message("topic-001" /* Topic */, "TagA" /* Tag */,
                    ("Hello Chris " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);
            //Call send message to deliver message to one of brokers.
            SendResult sendResult = producer.send(msg);
            System.out.printf("%s%n", sendResult);
        }
        //Shut down once the producer instance is not longer in use.
        producer.shutdown();

    }
}

创建消息者, 在消费组rocketmq-consumer-group-001 启动两个消费者实例

consumer.registerMessageListener

new MessageListenerConcurrently

package com.chris.rocketmq;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;

/**
 * @author Chris
 * @date 2022-03-24 6:40 PM
 */
public class Consumer {

    public static void main(String[] args) throws MQClientException {
        // Instantiate with specified consumer group name.
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("rocketmq-consumer-group-001");

        // Specify name server addresses.
        consumer.setNamesrvAddr("master:9876");

        // Subscribe one more more topics to consume.
        consumer.subscribe("topic-001", "*");
        // Register callback to execute on arrival of messages fetched from brokers.
        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
            for (MessageExt msg : msgs) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msg);
                String msg_str = new String(msg.getBody());
                System.out.println(msg_str);

            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });

        //Launch the consumer instance.
        consumer.start();

        System.out.printf("Consumer Started.%n");
    }
}

先启动conusmer1

再启动consumer2

最后启动生产者生产10条消息

conumser1消费结果

Consumer Started.
ConsumeMessageThread_1 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=198, queueOffset=25, sysFlag=0, bornTimestamp=1648123970750, bornHost=/192.168.101.1:61608, storeTimestamp=1648123374262, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036768, commitLogOffset=223080, bodyCRC=35715212, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=26, CONSUME_START_TIME=1648123971053, UNIQ_KEY=7F000001445418B4AAC27AC8A8BD0000, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 67, 104, 114, 105, 115, 32, 48], transaction}] 
Hello Chris 0
ConsumeMessageThread_2 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=198, queueOffset=26, sysFlag=0, bornTimestamp=1648123971007, bornHost=/192.168.101.1:61608, storeTimestamp=1648123374472, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036A80, commitLogOffset=223872, bodyCRC=88947861, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=27, CONSUME_START_TIME=1648123971083, UNIQ_KEY=7F000001445418B4AAC27AC8A9BE0004, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 67, 104, 114, 105, 115, 32, 52], transaction}] 
Hello Chris 4
ConsumeMessageThread_3 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=198, queueOffset=27, sysFlag=0, bornTimestamp=1648123971138, bornHost=/192.168.101.1:61608, storeTimestamp=1648123374560, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036D98, commitLogOffset=224664, bodyCRC=217804990, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=28, CONSUME_START_TIME=1648123971162, UNIQ_KEY=7F000001445418B4AAC27AC8AA420008, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 67, 104, 114, 105, 115, 32, 56], transaction}] 
Hello Chris 8

conumser2消费结果

ConsumeMessageThread_1 Receive New Messages: MessageExt [brokerName=master, queueId=1, storeSize=198, queueOffset=25, sysFlag=0, bornTimestamp=1648123970904, bornHost=/192.168.101.1:61608, storeTimestamp=1648123374326, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F00000000000368F4, commitLogOffset=223476, bodyCRC=1814993312, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=26, CONSUME_START_TIME=1648123971089, UNIQ_KEY=7F000001445418B4AAC27AC8A9580002, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 67, 104, 114, 105, 115, 32, 50], transaction}] 
Hello Chris 2
ConsumeMessageThread_2 Receive New Messages: MessageExt [brokerName=master, queueId=0, storeSize=198, queueOffset=25, sysFlag=0, bornTimestamp=1648123970885, bornHost=/192.168.101.1:61608, storeTimestamp=1648123374306, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F000000000003682E, commitLogOffset=223278, bodyCRC=1965541402, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=26, CONSUME_START_TIME=1648123971117, UNIQ_KEY=7F000001445418B4AAC27AC8A9450001, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 67, 104, 114, 105, 115, 32, 49], transaction}] 
Hello Chris 1
ConsumeMessageThread_3 Receive New Messages: MessageExt [brokerName=master, queueId=1, storeSize=198, queueOffset=26, sysFlag=0, bornTimestamp=1648123971100, bornHost=/192.168.101.1:61608, storeTimestamp=1648123374527, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036C0C, commitLogOffset=224268, bodyCRC=1799577017, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=27, CONSUME_START_TIME=1648123971140, UNIQ_KEY=7F000001445418B4AAC27AC8AA1C0006, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 67, 104, 114, 105, 115, 32, 54], transaction}] 
Hello Chris 6
ConsumeMessageThread_4 Receive New Messages: MessageExt [brokerName=master, queueId=0, storeSize=198, queueOffset=26, sysFlag=0, bornTimestamp=1648123971080, bornHost=/192.168.101.1:61608, storeTimestamp=1648123374507, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036B46, commitLogOffset=224070, bodyCRC=1917455363, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=27, CONSUME_START_TIME=1648123971148, UNIQ_KEY=7F000001445418B4AAC27AC8AA080005, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 67, 104, 114, 105, 115, 32, 53], transaction}] 
Hello Chris 5
ConsumeMessageThread_5 Receive New Messages: MessageExt [brokerName=master, queueId=0, storeSize=198, queueOffset=27, sysFlag=0, bornTimestamp=1648123971148, bornHost=/192.168.101.1:61608, storeTimestamp=1648123374575, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036E5E, commitLogOffset=224862, bodyCRC=2080129064, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=28, CONSUME_START_TIME=1648123971169, UNIQ_KEY=7F000001445418B4AAC27AC8AA4C0009, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 67, 104, 114, 105, 115, 32, 57], transaction}] 
Hello Chris 9
不同组多消费者

创建消息者

在消费组rocketmq-consumer-group-001 启动两个消费者实例 consumer1consumer2

然后再把消费组改为rocketmq-consumer-group-002 启动一个消费者实例 consuemer3

// Instantiate with specified consumer group name.
DefaultMQPushConsumer consumer1 = new DefaultMQPushConsumer("rocketmq-consumer-group-001");
DefaultMQPushConsumer consumer2 = new DefaultMQPushConsumer("rocketmq-consumer-group-001");
// Instantiate with specified consumer group name.
DefaultMQPushConsumer consumer3 = new DefaultMQPushConsumer("rocketmq-consumer-group-002");

启动生产者,并向topic-001中生产10条消息

consumer1消费结果:

Consumer Started.
ConsumeMessageThread_1 Receive New Messages: MessageExt [brokerName=master, queueId=0, storeSize=197, queueOffset=28, sysFlag=0, bornTimestamp=1648125413362, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813214, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F00000000000370AE, commitLogOffset=225454, bodyCRC=267036076, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=29, CONSUME_START_TIME=1648125413415, UNIQ_KEY=7F000001535C18B4AAC27ADEABF20002, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 50], transaction}] 
Hello John 2
ConsumeMessageThread_2 Receive New Messages: MessageExt [brokerName=master, queueId=1, storeSize=197, queueOffset=27, sysFlag=0, bornTimestamp=1648125413408, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813248, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000037173, commitLogOffset=225651, bodyCRC=2028836154, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=28, CONSUME_START_TIME=1648125413417, UNIQ_KEY=7F000001535C18B4AAC27ADEAC200003, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 51], transaction}] 
Hello John 3
ConsumeMessageThread_3 Receive New Messages: MessageExt [brokerName=master, queueId=0, storeSize=197, queueOffset=29, sysFlag=0, bornTimestamp=1648125413438, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813282, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F00000000000373C2, commitLogOffset=226242, bodyCRC=143090101, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=30, CONSUME_START_TIME=1648125413468, UNIQ_KEY=7F000001535C18B4AAC27ADEAC3E0006, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 54], transaction}] 
ConsumeMessageThread_4 Receive New Messages: MessageExt [brokerName=master, queueId=1, storeSize=197, queueOffset=28, sysFlag=0, bornTimestamp=1648125413447, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813294, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000037487, commitLogOffset=226439, bodyCRC=2139115811, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=29, CONSUME_START_TIME=1648125413468, UNIQ_KEY=7F000001535C18B4AAC27ADEAC470007, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 55], transaction}] 
Hello John 7
Hello John 6

consumer2消费结果:

Consumer Started.
ConsumeMessageThread_1 Receive New Messages: MessageExt [brokerName=master, queueId=2, storeSize=197, queueOffset=27, sysFlag=0, bornTimestamp=1648125413323, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813167, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036F24, commitLogOffset=225060, bodyCRC=1642382464, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=28, CONSUME_START_TIME=1648125413347, UNIQ_KEY=7F000001535C18B4AAC27ADEABCA0000, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 48], transaction}] 
Hello John 0
ConsumeMessageThread_2 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=197, queueOffset=28, sysFlag=0, bornTimestamp=1648125413333, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813186, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036FE9, commitLogOffset=225257, bodyCRC=384037910, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=29, CONSUME_START_TIME=1648125413378, UNIQ_KEY=7F000001535C18B4AAC27ADEABD50001, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 49], transaction}] 
Hello John 1
ConsumeMessageThread_3 Receive New Messages: MessageExt [brokerName=master, queueId=2, storeSize=197, queueOffset=28, sysFlag=0, bornTimestamp=1648125413413, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813256, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000037238, commitLogOffset=225848, bodyCRC=1720254617, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=29, CONSUME_START_TIME=1648125413440, UNIQ_KEY=7F000001535C18B4AAC27ADEAC250004, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 52], transaction}] 
Hello John 4
ConsumeMessageThread_4 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=197, queueOffset=29, sysFlag=0, bornTimestamp=1648125413431, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813272, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F00000000000372FD, commitLogOffset=226045, bodyCRC=294531087, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=30, CONSUME_START_TIME=1648125413447, UNIQ_KEY=7F000001535C18B4AAC27ADEAC370005, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 53], transaction}] 
Hello John 5
ConsumeMessageThread_5 Receive New Messages: MessageExt [brokerName=master, queueId=2, storeSize=197, queueOffset=29, sysFlag=0, bornTimestamp=1648125413459, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813305, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F000000000003754C, commitLogOffset=226636, bodyCRC=1866419378, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=30, CONSUME_START_TIME=1648125413477, UNIQ_KEY=7F000001535C18B4AAC27ADEAC530008, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 56], transaction}] 
Hello John 8
ConsumeMessageThread_6 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=197, queueOffset=30, sysFlag=0, bornTimestamp=1648125413470, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813310, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000037611, commitLogOffset=226833, bodyCRC=406354980, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=31, CONSUME_START_TIME=1648125413494, UNIQ_KEY=7F000001535C18B4AAC27ADEAC5E0009, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 57], transaction}] 
Hello John 9

consumer3消费结果:

Hello John 0
ConsumeMessageThread_13 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=197, queueOffset=28, sysFlag=0, bornTimestamp=1648125413333, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813186, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000036FE9, commitLogOffset=225257, bodyCRC=384037910, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=29, CONSUME_START_TIME=1648125413366, UNIQ_KEY=7F000001535C18B4AAC27ADEABD50001, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 49], transaction}] 
Hello John 1
ConsumeMessageThread_9 Receive New Messages: MessageExt [brokerName=master, queueId=0, storeSize=197, queueOffset=28, sysFlag=0, bornTimestamp=1648125413362, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813214, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F00000000000370AE, commitLogOffset=225454, bodyCRC=267036076, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=29, CONSUME_START_TIME=1648125413407, UNIQ_KEY=7F000001535C18B4AAC27ADEABF20002, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 50], transaction}] 
Hello John 2
ConsumeMessageThread_5 Receive New Messages: MessageExt [brokerName=master, queueId=1, storeSize=197, queueOffset=27, sysFlag=0, bornTimestamp=1648125413408, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813248, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000037173, commitLogOffset=225651, bodyCRC=2028836154, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=28, CONSUME_START_TIME=1648125413419, UNIQ_KEY=7F000001535C18B4AAC27ADEAC200003, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 51], transaction}] 
Hello John 3
ConsumeMessageThread_10 Receive New Messages: MessageExt [brokerName=master, queueId=2, storeSize=197, queueOffset=28, sysFlag=0, bornTimestamp=1648125413413, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813256, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000037238, commitLogOffset=225848, bodyCRC=1720254617, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=29, CONSUME_START_TIME=1648125413435, UNIQ_KEY=7F000001535C18B4AAC27ADEAC250004, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 52], transaction}] 
Hello John 4
ConsumeMessageThread_8 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=197, queueOffset=29, sysFlag=0, bornTimestamp=1648125413431, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813272, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F00000000000372FD, commitLogOffset=226045, bodyCRC=294531087, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=30, CONSUME_START_TIME=1648125413443, UNIQ_KEY=7F000001535C18B4AAC27ADEAC370005, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 53], transaction}] 
Hello John 5
ConsumeMessageThread_7 Receive New Messages: MessageExt [brokerName=master, queueId=0, storeSize=197, queueOffset=29, sysFlag=0, bornTimestamp=1648125413438, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813282, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F00000000000373C2, commitLogOffset=226242, bodyCRC=143090101, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=30, CONSUME_START_TIME=1648125413460, UNIQ_KEY=7F000001535C18B4AAC27ADEAC3E0006, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 54], transaction}] 
Hello John 6
ConsumeMessageThread_6 Receive New Messages: MessageExt [brokerName=master, queueId=1, storeSize=197, queueOffset=28, sysFlag=0, bornTimestamp=1648125413447, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813294, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000037487, commitLogOffset=226439, bodyCRC=2139115811, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=29, CONSUME_START_TIME=1648125413464, UNIQ_KEY=7F000001535C18B4AAC27ADEAC470007, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 55], transaction}] 
Hello John 7
ConsumeMessageThread_19 Receive New Messages: MessageExt [brokerName=master, queueId=2, storeSize=197, queueOffset=29, sysFlag=0, bornTimestamp=1648125413459, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813305, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F000000000003754C, commitLogOffset=226636, bodyCRC=1866419378, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=30, CONSUME_START_TIME=1648125413474, UNIQ_KEY=7F000001535C18B4AAC27ADEAC530008, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 56], transaction}] 
Hello John 8
ConsumeMessageThread_1 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=197, queueOffset=30, sysFlag=0, bornTimestamp=1648125413470, bornHost=/192.168.101.1:61991, storeTimestamp=1648124813310, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000037611, commitLogOffset=226833, bodyCRC=406354980, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-001', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=31, CONSUME_START_TIME=1648125413492, UNIQ_KEY=7F000001535C18B4AAC27ADEAC5E0009, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 74, 111, 104, 110, 32, 57], transaction}] 
Hello John 9

结论

可以看出consumer1和consumer2分摊topic-001中的消息, 即两个消费者所消费的消息总和为10条

而consumer3将topic-001中的消息全部消息掉

消费者模式

集群模式广播模式

默认集群模式

如果改为广播模式,即使是同一组的不同消费者也会消费到生产者生产的全部消息


consumer.setMessageModel(MessageModel.BROADCASTING);

/**
 * broadcast
 */
BROADCASTING("BROADCASTING"),
/**
 * clustering
 */
CLUSTERING("CLUSTERING");

同步消息

SendResult sendResult = producer.send(msg);

//发送同步消息
SendResult sendResult = producer.send(msg);

异步消息

producer.send(msg, new SendCallback()

package com.chris.rocketmq;

import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.io.UnsupportedEncodingException;
import java.util.concurrent.CountDownLatch;

/**
 * @author Chris
 * @date 2022-03-24 6:35 PM
 */
public class ProducerAsync {

    public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException,
            InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("rocketmq-producer-group-001");
        producer.setNamesrvAddr("master:9876");

        producer.start();
        producer.setRetryTimesWhenSendAsyncFailed(0);

        System.out.println("producer has started!");

        int messageCount = 10;
        CountDownLatch countDownLatch = new CountDownLatch(messageCount);

        for (int i = 0; i < messageCount; i++) {
            //Create a message instance, specifying topic, tag and message body.
            Message msg = new Message("topic-003" /* Topic */, "TagA" /* Tag */,
                    ("Hello Async " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);


            //Send Messages Asynchronously
            //Asynchronous transmission is generally used in response time sensitive business scenarios.
            producer.send(msg, new SendCallback() {
                @Override
                public void onSuccess(SendResult sendResult) {
                    countDownLatch.countDown();
                    System.out.printf("%s%n", sendResult);
                }

                @Override
                public void onException(Throwable e) {
                    countDownLatch.countDown();
                    System.out.println("exception:" + e.getMessage());
                }
            });
        }

        countDownLatch.await();
        producer.shutdown();
    }
}

单向消息

不需要有回执的消息,比如说日志类消息

producer.sendOneway(msg);

public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException,
            InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("rocketmq-producer-group-001");
        producer.setNamesrvAddr("master:9876");

        producer.start();
        producer.setRetryTimesWhenSendAsyncFailed(0);

        System.out.println("producer has started!");

        int messageCount = 10;

        for (int i = 0; i < messageCount; i++) {
            //Create a message instance, specifying topic, tag and message body.
            Message msg = new Message("topic-005" /* Topic */, "TagA" /* Tag */,
                    ("Hello OneWay " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);

            producer.sendOneway(msg);
        }

        producer.shutdown();
    }

延时消息

消息发送时并不直接发送到消息服务器,而是根据设定的时间到达,起到延时到达的缓冲作用

msg.setDelayTimeLevel(3);

messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

producer

public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException,
        InterruptedException, MQBrokerException {
    DefaultMQProducer producer = new DefaultMQProducer("rocketmq-producer-group-001");
    producer.setNamesrvAddr("master:9876");

    producer.start();
    producer.setRetryTimesWhenSendAsyncFailed(0);

    System.out.println("producer has started!");

    int messageCount = 10;

    for (int i = 0; i < messageCount; i++) {
        //Create a message instance, specifying topic, tag and message body.
        Message msg = new Message("topic-005" /* Topic */, "TagA" /* Tag */,
                ("Hello DealyTime " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);

        msg.setDelayTimeLevel(3);
        SendResult sendResult = producer.send(msg);
        System.out.printf("%s%n", sendResult);
    }

    producer.shutdown();
}

consumer

public static void main(String[] args) throws MQClientException {
        // Instantiate with specified consumer group name.
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("rocketmq-consumer-group-003");

        // Specify name server addresses.
        consumer.setNamesrvAddr("master:9876");

        // Subscribe one more more topics to consume.
        consumer.subscribe("topic-005", "*");

        // 默认早集群模式,如果改为广播模式,同组的不同消费将会消费到生产者生产的全部消息
        consumer.setMessageModel(MessageModel.BROADCASTING);

        // Register callback to execute on arrival of messages fetched from brokers.
        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
            for (MessageExt msg : msgs) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msg);
                String msg_str = new String(msg.getBody());
                // Print approximate delay time period
                System.out.println("Receive message[msghljs-string" style="color: #d69d85; line-height: 160%; box-sizing: content-box;">",msg_str=] " + msg_str + "," + (System.currentTimeMillis() - msg.getStoreTimestamp()) + "ms later");


            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });

        //Launch the consumer instance.
        consumer.start();

        System.out.printf("Consumer Started.%n");
    }

批量消息

一次发送多条消息,节约网络开销

注意:

  1. 这些批量消息应该有相同的topic

  2. 相同的waitStoreMsgOK

  3. 不能是延时消息

  4. 消息内容总长度不超过4M

    Besides, the total size of the messages in one batch should be no more than 1MiB.

    消息内容总长度包含如下:

    • topic 字符串字节数

    • body字节数组长度

    • 消息追加属性(key与value对应字符串字节数)

    • 日志(固定20字节)

List<Message> msgList = CollUtil.newArrayList();
for (int i = 0; i < 10; i++) {
    //Create a message instance, specifying topic, tag and message body.
    Message msg = new Message("topic-006" /* Topic */, "TagA" /* Tag */,
                              ("Hello Message in Batch " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);
    msgList.add(msg);
}
//批量发送同步消息
SendResult sendResult = producer.send(msgList);
SendResult [sendStatus=SEND_OK, msgId=7F00000143AC18B4AAC27F0FDDBA0000,7F00000143AC18B4AAC27F0FDDBA0001,7F00000143AC18B4AAC27F0FDDBA0002,7F00000143AC18B4AAC27F0FDDBA0003,7F00000143AC18B4AAC27F0FDDBA0004,7F00000143AC18B4AAC27F0FDDBB0005,7F00000143AC18B4AAC27F0FDDBB0006,7F00000143AC18B4AAC27F0FDDBB0007,7F00000143AC18B4AAC27F0FDDBB0008,7F00000143AC18B4AAC27F0FDDBB0009, offsetMsgId=C0A8657F00002A9F000000000003F28C,C0A8657F00002A9F000000000003F367,C0A8657F00002A9F000000000003F442,C0A8657F00002A9F000000000003F51D,C0A8657F00002A9F000000000003F5F8,C0A8657F00002A9F000000000003F6D3,C0A8657F00002A9F000000000003F7AE,C0A8657F00002A9F000000000003F889,C0A8657F00002A9F000000000003F964,C0A8657F00002A9F000000000003FA3F, messageQueue=MessageQueue [topic=topic-006, brokerName=master, queueId=0], queueOffset=0]

消息的过滤

按tag进行消息过滤

生产者分别生产 tag类型为 customer 和 vip的消息

 for (int i = 0; i < 10; i++) {
     //Create a message instance, specifying topic, tag and message body.
     Message msg = new Message("topic-006" /* Topic */, "customer" /* Tag */,
                               ("Hello vip " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);
     //Call send message to deliver message to one of brokers.
     //发送同步消息
     SendResult sendResult = producer.send(msg);
     System.out.printf("%s%n", sendResult);
}
 for (int i = 0; i < 10; i++) {
     //Create a message instance, specifying topic, tag and message body.
     Message msg = new Message("topic-006" /* Topic */, "vip" /* Tag */,
                               ("Hello vip " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);
     //Call send message to deliver message to one of brokers.
     //发送同步消息
     SendResult sendResult = producer.send(msg);
     System.out.printf("%s%n", sendResult);
}

消息者分别订阅tag为customer和 tag为 customer || vip的消息

 consumer1.subscribe("topic-006", "customer");
 consumer2.subscribe("topic-006", "customer || vip");

结果:

consumer1 和 consumer2可以分别消费到tag=customer类型的不同消息,总数为customer类型消息的总和

consumer2除了可以消费到customer的消息外,还可以消费到全部的tag=vip的消息

SQL过滤

运算符

数值比较: >, >=, <, <=, BETWEEN, =

字符比较: =, <>, IN

IS NULL or IS NOT NULL;

逻辑比较: AND, OR, NOT;

常量支持类型为

  1. 数值, 比如 123, 3.1415;
  2. 字符,比如 ‘abc’, 必须用单引号引用;
  3. NULL, 特殊的常量
  4. 布尔值, TRUEFALSE;
开启sql过滤
/opt/rocketmq/conf
vi broker.conf
enablePropertyFilter=true

修改完成后重启namerserver和broker

sh bin/mqshutdown broker
sh bin/mqshutdown namesrv

nohup sh bin/mqnamesrv &
nohup sh bin/mqbroker -n master:9876 &

查看集群配置属性

如果值没有变更为true 需要执行如下命令

[root@master rocketmq]# sh bin/mqadmin updateBrokerConfig -b master:10911 -k enablePropertyFilter -v true
RocketMQLog:WARN No appenders could be found for logger (io.netty.util.internal.PlatformDependent0).
RocketMQLog:WARN Please initialize the logger system properly.
update broker config success, master:10911

生产者

msg.putUserProperty("vip", String.valueOf(i));

for (int i = 0; i < 10; i++) {
    //Create a message instance, specifying topic, tag and message body.
    Message msg = new Message("topic-006" /* Topic */, "vip" /* Tag */,
            ("Hello vip " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);

    msg.putUserProperty("vip", String.valueOf(i));
    msg.putUserProperty("number", String.valueOf(i));

    //Call send message to deliver message to one of brokers.
    //发送同步消息
    SendResult sendResult = producer.send(msg);
    System.out.printf("%s%n", sendResult);
}

消息者
MessageSelector.bySql("number between 3 and 7 and vip > 4")

// only subsribe messages have property vip and number, also number between 3 and 7 and vip > 4
consumer.subscribe("topic-006", MessageSelector.bySql("number between 3 and 7 and vip > 4"));
ConsumeMessageThread_2 Receive New Messages: MessageExt [brokerName=master, queueId=1, storeSize=210, queueOffset=19, sysFlag=0, bornTimestamp=1648205009964, bornHost=/192.168.101.1:53854, storeTimestamp=1648204988448, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000043BAC, commitLogOffset=277420, bodyCRC=1358519611, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-006', flag=0, properties={MIN_OFFSET=0, number=5, MAX_OFFSET=20, CONSUME_START_TIME=1648205011754, vip=5, UNIQ_KEY=7F0000013D9018B4AAC27F9D382B0005, CLUSTER=DefaultCluster, WAIT=true, TAGS=vip}, body=[72, 101, 108, 108, 111, 32, 118, 105, 112, 32, 53], transaction}] 
Hello vip 5
ConsumeMessageThread_3 Receive New Messages: MessageExt [brokerName=master, queueId=2, storeSize=210, queueOffset=26, sysFlag=0, bornTimestamp=1648205011737, bornHost=/192.168.101.1:53854, storeTimestamp=1648204988466, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000043C7E, commitLogOffset=277630, bodyCRC=1240468609, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-006', flag=0, properties={MIN_OFFSET=0, number=6, MAX_OFFSET=27, CONSUME_START_TIME=1648205012407, vip=6, UNIQ_KEY=7F0000013D9018B4AAC27F9D3F190006, CLUSTER=DefaultCluster, WAIT=true, TAGS=vip}, body=[72, 101, 108, 108, 111, 32, 118, 105, 112, 32, 54], transaction}] 
Hello vip 6
ConsumeMessageThread_4 Receive New Messages: MessageExt [brokerName=master, queueId=3, storeSize=210, queueOffset=16, sysFlag=0, bornTimestamp=1648205011752, bornHost=/192.168.101.1:53854, storeTimestamp=1648204988477, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F0000000000043D50, commitLogOffset=277840, bodyCRC=1056390167, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='topic-006', flag=0, properties={MIN_OFFSET=0, number=7, MAX_OFFSET=17, CONSUME_START_TIME=1648205012500, vip=7, UNIQ_KEY=7F0000013D9018B4AAC27F9D3F280007, CLUSTER=DefaultCluster, WAIT=true, TAGS=vip}, body=[72, 101, 108, 108, 111, 32, 118, 105, 112, 32, 55], transaction}] 
Hello vip 7
http://localhost:8081/rocketmq/send/sendMessage

//存入rocketmq中的结果
{"name":"Chris","age":32}

集成SpringBoot

建module rocketmqcloud2022

改pom

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.22</version>
        </dependency>

        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.2.1</version>
        </dependency>

    </dependencies>

写yml

spring:
  application:
    name: rocketmqcloud2022
server:
  port: 8081
  servlet:
    encoding:
      charset: UTF-8
    context-path: /rocketmq
  tomcat:
    uri-encoding: UTF-8


rocketmq:
  name-server: master:9876
  producer:
    group: rocketmq-producer-group-001

生产者

@RestController
@RequestMapping("/send")
public class SendController {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @PostMapping("/sendMessage")
    public String sendMsg(@RequestBody @Validated User user) {
        rocketMQTemplate.convertAndSend("cloud001", user);
        return "success";
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    @NotNull(message = "name can't be null")
    private String name;
    @Range(max = 100, min = 1, message = "age between 1 and 100")
    private Integer age;
}

消费者

RocketMQListener

@RocketMQMessageListener

package com.chris.rocketmq.rocketmqcloud2022.service;

import cn.hutool.json.JSONUtil;
import com.chris.rocketmq.rocketmqcloud2022.bean.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.annotation.SelectorType;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@RocketMQMessageListener(consumerGroup = "cloud-consume-001",topic = "cloud001", 
                         selectorType = SelectorType.TAG, selectorExpression = "*")
public class UserConsumer implements RocketMQListener<User> {
    @Override
    public void onMessage(User user) {
        log.info("rocketmq msg:{}", JSONUtil.toJsonStr(user));
    }
}

顺序消费

无序消息

@PostMapping("/sendOrderMessage")
    public SendResult sendOrderMessage() {
        List<OrderInfo> orderInfos = CollUtil.newArrayList();
        orderInfos.add(new OrderInfo(1L, "create"));
        orderInfos.add(new OrderInfo(2L, "create"));
        orderInfos.add(new OrderInfo(1L, "send"));
        orderInfos.add(new OrderInfo(3L, "create"));
        orderInfos.add(new OrderInfo(2L, "send"));
        orderInfos.add(new OrderInfo(4L, "create"));
        orderInfos.add(new OrderInfo(1L, "pay"));
        orderInfos.add(new OrderInfo(1L, "finish"));
        orderInfos.add(new OrderInfo(3L, "send"));
        orderInfos.add(new OrderInfo(2L, "pay"));
        orderInfos.add(new OrderInfo(4L, "send"));
        orderInfos.add(new OrderInfo(3L, "pay"));
        orderInfos.add(new OrderInfo(2L, "finish"));
        orderInfos.add(new OrderInfo(4L, "pay"));
        orderInfos.add(new OrderInfo(3L, "finish"));
        orderInfos.add(new OrderInfo(4L, "finish"));

        List<Message<OrderInfo>> messageList = CollUtil.newArrayList();
        for (OrderInfo orderInfo : orderInfos) {
            Message<OrderInfo> message = MessageBuilder.withPayload(orderInfo).build();
            messageList.add(message);
        }

        SendResult sendResult = rocketMQTemplate.syncSend(String.join(":", topic, order_tag), messageList, 10000);
        log.info("sendOrderMessage sendResult:{}", sendResult);
        return sendResult;
    }
2022-03-27 11:57:17.531 [MessageThread_8] : consume orderInfo msg:{"orderId":1,"desc":"finish"}
2022-03-27 11:57:17.531 [MessageThread_1] : consume orderInfo msg:{"orderId":1,"desc":"create"}
2022-03-27 11:57:17.531 [MessageThread_5] : consume orderInfo msg:{"orderId":2,"desc":"send"}
2022-03-27 11:57:17.531 [essageThread_13] : consume orderInfo msg:{"orderId":2,"desc":"finish"}
2022-03-27 11:57:17.531 [essageThread_16] : consume orderInfo msg:{"orderId":4,"desc":"finish"}
2022-03-27 11:57:17.531 [essageThread_11] : consume orderInfo msg:{"orderId":4,"desc":"send"}
2022-03-27 11:57:17.531 [MessageThread_7] : consume orderInfo msg:{"orderId":1,"desc":"pay"}
2022-03-27 11:57:17.532 [essageThread_14] : consume orderInfo msg:{"orderId":4,"desc":"pay"}
2022-03-27 11:57:17.532 [MessageThread_3] : consume orderInfo msg:{"orderId":1,"desc":"send"}
2022-03-27 11:57:17.532 [MessageThread_6] : consume orderInfo msg:{"orderId":4,"desc":"create"}
2022-03-27 11:57:17.532 [MessageThread_4] : consume orderInfo msg:{"orderId":3,"desc":"create"}
2022-03-27 11:57:17.532 [essageThread_15] : consume orderInfo msg:{"orderId":3,"desc":"finish"}
2022-03-27 11:57:17.532 [MessageThread_9] : consume orderInfo msg:{"orderId":3,"desc":"send"}
2022-03-27 11:57:17.533 [MessageThread_2] : consume orderInfo msg:{"orderId":2,"desc":"create"}
2022-03-27 11:57:17.533 [essageThread_12] : consume orderInfo msg:{"orderId":3,"desc":"pay"}
2022-03-27 11:57:17.533 [essageThread_10] : consume orderInfo msg:{"orderId":2,"desc":"pay"}

有序消息

原生实现

生产者
new MessageQueueSelector()

public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException,
            InterruptedException, MQBrokerException {
        DefaultMQProducer producer = new DefaultMQProducer("rocketmq-producer-group-002");
        producer.setNamesrvAddr("master:9876");

        producer.start();
        System.out.println("producer has started!");

        List<OrderInfo> orderInfos = getOrderInfos();
        for (OrderInfo orderInfo : orderInfos) {
            Message message = new Message("topic-008", "order", orderInfo.toString().getBytes(StandardCharsets.UTF_8));
            SendResult sendResult = producer.send(message, new MessageQueueSelector() {
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                    System.out.println("message queue selector, arg:" + arg);
                    int size = mqs.size();
                    long id = (long) arg;
                    long queue_inx = id % size;
                    return mqs.get(new Long(queue_inx).intValue());
                }
            }, orderInfo.getId(), 10000);
            System.out.println("send result:" + sendResult);
        }

        //Shut down once the producer instance is not longer in use.
        producer.shutdown();
    }

    private static List<OrderInfo> getOrderInfos() {
        List<OrderInfo> orderInfos = CollUtil.newArrayList();
        orderInfos.add(new OrderInfo(1L, "create"));
        orderInfos.add(new OrderInfo(2L, "create"));
        orderInfos.add(new OrderInfo(1L, "send"));
        orderInfos.add(new OrderInfo(3L, "create"));
        orderInfos.add(new OrderInfo(2L, "send"));
        orderInfos.add(new OrderInfo(4L, "create"));
        orderInfos.add(new OrderInfo(1L, "pay"));
        orderInfos.add(new OrderInfo(1L, "finish"));
        orderInfos.add(new OrderInfo(3L, "send"));
        orderInfos.add(new OrderInfo(2L, "pay"));
        orderInfos.add(new OrderInfo(4L, "send"));
        orderInfos.add(new OrderInfo(3L, "pay"));
        orderInfos.add(new OrderInfo(2L, "finish"));
        orderInfos.add(new OrderInfo(4L, "pay"));
        orderInfos.add(new OrderInfo(3L, "finish"));
        orderInfos.add(new OrderInfo(4L, "finish"));
        return orderInfos;
    }
message queue selector, arg:1
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9350000, offsetMsgId=C0A8657F00002A9F0000000000058C95, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=1], queueOffset=12]
message queue selector, arg:2
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B93F0001, offsetMsgId=C0A8657F00002A9F0000000000058D6B, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=2], queueOffset=12]
message queue selector, arg:1
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9430002, offsetMsgId=C0A8657F00002A9F0000000000058E41, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=1], queueOffset=13]
message queue selector, arg:3
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9460003, offsetMsgId=C0A8657F00002A9F0000000000058F15, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=3], queueOffset=12]
message queue selector, arg:2
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9600004, offsetMsgId=C0A8657F00002A9F0000000000058FEB, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=2], queueOffset=13]
message queue selector, arg:4
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9640005, offsetMsgId=C0A8657F00002A9F00000000000590BF, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=0], queueOffset=12]
message queue selector, arg:1
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9690006, offsetMsgId=C0A8657F00002A9F0000000000059195, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=1], queueOffset=14]
message queue selector, arg:1
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B96E0007, offsetMsgId=C0A8657F00002A9F0000000000059268, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=1], queueOffset=15]
message queue selector, arg:3
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9720008, offsetMsgId=C0A8657F00002A9F000000000005933E, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=3], queueOffset=13]
message queue selector, arg:2
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9770009, offsetMsgId=C0A8657F00002A9F0000000000059412, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=2], queueOffset=14]
message queue selector, arg:4
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B986000A, offsetMsgId=C0A8657F00002A9F00000000000594E5, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=0], queueOffset=13]
message queue selector, arg:3
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B999000B, offsetMsgId=C0A8657F00002A9F00000000000595B9, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=3], queueOffset=14]
message queue selector, arg:2
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B99D000C, offsetMsgId=C0A8657F00002A9F000000000005968C, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=2], queueOffset=15]
message queue selector, arg:4
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9A2000D, offsetMsgId=C0A8657F00002A9F0000000000059762, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=0], queueOffset=14]
message queue selector, arg:3
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9AB000E, offsetMsgId=C0A8657F00002A9F0000000000059835, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=3], queueOffset=15]
message queue selector, arg:4
send result:SendResult [sendStatus=SEND_OK, msgId=7F000001159418B4AAC289A4B9AE000F, offsetMsgId=C0A8657F00002A9F000000000005990B, messageQueue=MessageQueue [topic=topic-008, brokerName=master, queueId=0], queueOffset=15]

消息者

new MessageListenerOrderly()

// Register MessageListenerOrderly to execute on arrival of messages fetched from brokers, receive messages 
// orderly One queue by one thread.
consumer.registerMessageListener((MessageListenerOrderly) (msgs, context) -> {
    for (MessageExt msg : msgs) {
        String msg_str = new String(msg.getBody());
        System.out.println(msg_str);
    }
    return ConsumeOrderlyStatus.SUCCESS;
});

可以看出消息都是从create - send - pay - finish 这几个状态顺序消费

OrderInfo(id=1, desc=create)
OrderInfo(id=2, desc=create)
OrderInfo(id=1, desc=send)
OrderInfo(id=3, desc=create)
OrderInfo(id=2, desc=send)
OrderInfo(id=4, desc=create)
OrderInfo(id=1, desc=pay)
OrderInfo(id=1, desc=finish)
OrderInfo(id=3, desc=send)
OrderInfo(id=2, desc=pay)
OrderInfo(id=4, desc=send)
OrderInfo(id=3, desc=pay)
OrderInfo(id=2, desc=finish)
OrderInfo(id=4, desc=pay)
OrderInfo(id=3, desc=finish)
OrderInfo(id=4, desc=finish)
SpringBoot 实现

生产者

@PostMapping("/sendOrderMessageOrderly")
public String sendOrderMessageOrderly() {
    List<OrderInfo> orderInfos = getOrderInfos();
    for (OrderInfo orderInfo : orderInfos) {
        Message<OrderInfo> message = MessageBuilder.withPayload(orderInfo).build();
        SendResult sendResult = rocketMQTemplate.syncSendOrderly(String.join(":", topic, order_tag), message, String.valueOf(orderInfo.getOrderId()));
        log.info("send orderly result:{}", sendResult);
    }
    return "success";
}

消息者
consumeMode = ConsumeMode.ORDERLY

@Service
@Slf4j
@RocketMQMessageListener(topic = "cloud006", selectorType = SelectorType.TAG, selectorExpression = "order",
        consumerGroup = "cloud-consume-group-006", consumeMode = ConsumeMode.ORDERLY)
public class OrderConsumer implements RocketMQListener<OrderInfo> {
    @Override
    public void onMessage(OrderInfo orderInfo) {
        log.info("consume orderInfo msg:{}", JSONUtil.toJsonStr(orderInfo));
    }
}

@Service
@Slf4j
@RocketMQMessageListener(topic = "cloud006", selectorType = SelectorType.TAG, selectorExpression = "order",
        consumerGroup = "cloud-consume-group-006", consumeMode = ConsumeMode.ORDERLY)
public class OrderConsumer2 implements RocketMQListener<OrderInfo> {
    @Override
    public void onMessage(OrderInfo orderInfo) {
        log.info("consume orderInfo msg:{}", JSONUtil.toJsonStr(orderInfo));
    }
}

可以看出如果启动两个消费者consumerconsumer2

consumerconsumer2 按顺序分别消息 topic cloud006里面的消息

[MessageThread_2] OrderConsumer2 : consume orderInfo msg:{"orderId":2,"desc":"create"}
[MessageThread_1] OrderConsumer2 : consume orderInfo msg:{"orderId":3,"desc":"create"}
[MessageThread_2] OrderConsumer2 : consume orderInfo msg:{"orderId":2,"desc":"send"}
[MessageThread_1] OrderConsumer2 : consume orderInfo msg:{"orderId":3,"desc":"send"}
[MessageThread_1] OrderConsumer2 : consume orderInfo msg:{"orderId":3,"desc":"pay"}
[MessageThread_2] OrderConsumer2 : consume orderInfo msg:{"orderId":2,"desc":"pay"}
[MessageThread_1] OrderConsumer2 : consume orderInfo msg:{"orderId":3,"desc":"finish"}
[MessageThread_2] OrderConsumer2 : consume orderInfo msg:{"orderId":2,"desc":"finish"}

[MessageThread_1] OrderConsumer  : consume orderInfo msg:{"orderId":4,"desc":"create"}
[MessageThread_1] OrderConsumer  : consume orderInfo msg:{"orderId":4,"desc":"send"}
[MessageThread_1] OrderConsumer  : consume orderInfo msg:{"orderId":4,"desc":"pay"}
[MessageThread_1] OrderConsumer  : consume orderInfo msg:{"orderId":4,"desc":"finish"}
[MessageThread_2] OrderConsumer  : consume orderInfo msg:{"orderId":1,"desc":"create"}
[MessageThread_2] OrderConsumer  : consume orderInfo msg:{"orderId":1,"desc":"send"}
[MessageThread_2] OrderConsumer  : consume orderInfo msg:{"orderId":1,"desc":"pay"}
[MessageThread_2] OrderConsumer  : consume orderInfo msg:{"orderId":1,"desc":"finish"}

文件存储时间源码分析

https://blog.csdn.net/qq_34930488/article/details/101293178

org.apache.rocketmq.store.DefaultMessageStore#addScheduleTask

https://rocketmq.apache.org/zh/docs/4.x/bestPractice/01bestpractice

long fileReservedTime = DefaultMessageStore.this.getMessageStoreConfig().getFileReservedTime();
int deletePhysicFilesInterval = DefaultMessageStore.this.getMessageStoreConfig().getDeleteCommitLogFilesInterval();
int destroyMapedFileIntervalForcibly = DefaultMessageStore.this.getMessageStoreConfig().getDestroyMapedFileIntervalForcibly();

fileReservedTime:文件过期时间,也就是从文件最后一次的更新时间到现在为止,如果超过该时间,则是过期文件可被删除

deletePhysicFilesInterval:删除物理文件的时间间隔,在一次定时任务触发时,可能会有多个物理文件超过过期时间可被删除,因此删除一个文件后需要间隔deletePhysicFilesInterval这个时间再删除另外一个文件,我猜测可能是由于删除文件是一个非常耗费IO的操作,会引起消息插入消费的延迟(相比于正常情况下),所以不建议直接删除所有过期文件

destroyMapedFileIntervalForcibly:在删除文件时,如果该文件还被线程引用,此时会阻止此次删除操作,同时将该文件标记不可用并且纪录当前时间戳destroyMapedFileIntervalForcibly这个表示文件在第一次删除拒绝后,文件保存的最大时间,在此时间内一直会被拒绝删除,当超过这个时间时,会将引用每次减少1000,直到引用 小于等于 0为止,即可删除该文件,实现代码如下:

public void shutdown(final long intervalForcibly) {
        if (this.available) {
            this.available = false;
            this.firstShutdownTimestamp = System.currentTimeMillis();
            this.release();
        } else if (this.getRefCount() > 0) {
            if ((System.currentTimeMillis() - this.firstShutdownTimestamp) >= intervalForcibly) {
                this.refCount.set(-1000 - this.getRefCount());
                this.release();
            }
        }
    }
%5Btoc%5D%0A%0A%3E%20https%3A%2F%2Fbright-boy.gitee.io%2Ftechnical-notes%0A%3E%20https%3A%2F%2Fblog.csdn.net%2Fqq_34930488%2Farticle%2Fdetails%2F101293178%0A%0A%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5%0A%3E%20https%3A%2F%2Frocketmq.apache.org%2Fzh%2Fdocs%2F4.x%2FbestPractice%2F01bestpractice%0A%0A%23%23%20%E4%BB%80%E4%B9%88%E6%98%AFMQ%0A%3E%20MQ%E5%85%A8%E7%A7%B0message%20queue(%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97)%EF%BC%8C%E6%98%AF%E5%9C%A8%E6%B6%88%E6%81%AF%E4%BC%A0%E8%BE%93%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%E4%BF%9D%E5%AD%98%E6%B6%88%E6%81%AF%E7%9A%84%E5%AE%B9%E5%99%A8%E3%80%82%0A%3E%20%E5%A4%9A%E7%94%A8%E4%BA%8E%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E9%97%B4%E8%BF%9B%E8%A1%8C%E9%80%9A%E4%BF%A1%0A%3E%20queue%EF%BC%88%E9%98%9F%E5%88%97%EF%BC%89%EF%BC%9A%E4%B8%80%E7%A7%8D%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%EF%BC%8C%E7%89%B9%E5%BE%81%E4%B8%BA%E2%80%98%E5%85%88%E8%BF%9B%E5%85%88%E5%87%BA%E2%80%99%0A%0A%23%23%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%201.%20%E5%BA%94%E7%94%A8%E8%A7%A3%E8%80%A6%0A%3E%202.%20%E5%BC%82%E6%AD%A5%E6%8F%90%E9%80%9F%0A%3E%203.%20%E5%89%8A%E5%B3%B0%E5%A1%AB%E8%B0%B7%0A%0A!%5Bec156d2600586cb3b2eec8cbcf06fccb.png%5D(en-resource%3A%2F%2Fdatabase%2F889%3A1)%0A%0A%0A%23%23%23%23%20%E5%BA%94%E7%94%A8%E8%A7%A3%E8%80%A6%0A%3E%20%E5%BD%93%E7%94%9F%E4%BA%A7%E8%80%85%E7%94%9F%E4%BA%A7%E5%AE%8C%E6%B6%88%E6%81%AF%E5%90%8E%EF%BC%8C%E6%97%A0%E9%9C%80%E7%AD%89%E5%BE%85%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%BF%9B%E8%A1%8C%E4%B8%8B%E4%B8%80%E6%AD%A5%E4%B8%9A%E5%8A%A1%E9%80%BB%E8%BE%91%E3%80%82%0A%3E%20%E9%9C%80%E8%A6%81%E6%A0%B9%E6%8D%AE%E6%B6%88%E6%81%AF%E5%AE%8C%E6%88%90%E7%89%B9%E5%AE%9A%E5%8A%9F%E8%83%BD%E7%9A%84%E4%B8%9A%E5%8A%A1%E7%BB%84%E4%BB%B6%E5%8F%AA%E9%9C%80%E8%A6%81%E7%AE%80%E5%8D%95%E8%AE%A2%E9%98%85%E6%B6%88%E6%81%AF%E5%8D%B3%E5%8F%AF%E5%AE%8C%E6%88%90%E5%AF%B9%E6%B6%88%E6%81%AF%E7%9A%84%E6%B6%88%E8%B4%B9%E3%80%82%0A%3E%20%E5%8D%B3%E4%BD%BF%E5%90%8E%E9%9D%A2%E6%9C%89%E6%96%B0%E5%A2%9E%E7%9A%84%E4%B8%9A%E5%8A%A1%E7%BB%84%E4%BB%B6%EF%BC%8C%E4%B9%9F%E5%8F%AA%E9%9C%80%E8%A6%81%E7%AE%80%E5%8D%95%E8%AE%A2%E9%98%85%E6%B6%88%E6%81%AF%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%AE%8C%E6%88%90%E5%B9%B3%E6%BB%91%E7%9A%84%E6%8E%A5%E5%85%A5%E3%80%82%0A%0A%0A%23%23%23%23%20%E5%89%8A%E5%B3%B0%E5%A1%AB%E8%B0%B7%0A%3E%20%E5%AF%B9%E8%B6%85%E9%87%8F%E8%AF%B7%E6%B1%82%E5%8F%AF%E4%BB%A5%E6%9A%82%E5%AD%98%E5%85%B6%E4%B8%AD%EF%BC%8C%E4%BB%A5%E4%BE%BF%E7%B3%BB%E7%BB%9F%E5%90%8E%E7%BB%AD%E5%8F%AF%E4%BB%A5%E6%85%A2%E6%85%A2%E5%A4%84%E7%90%86%EF%BC%8C%E4%BB%8E%E8%80%8C%E9%81%BF%E5%85%8D%E8%AF%B7%E6%B1%82%E4%B8%A2%E5%A4%B1%E6%88%96%E7%B3%BB%E7%BB%9F%E8%A2%AB%E5%8E%8B%E5%9E%AE%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%9A%E4%BD%BF%E7%94%A8MQ%E4%B9%8B%E5%90%8E%EF%BC%8C%E9%99%90%E5%88%B6%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E7%9A%84%E9%80%9F%E5%BA%A6%E4%B8%BA1000%E6%9D%A1%2Fs%2C%20%E8%BF%99%E6%A0%B7%E4%B8%80%E6%9D%A5%EF%BC%8C%E9%AB%98%E5%B3%B0%E6%9C%9F%E4%BA%A7%E7%94%9F%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8A%BF%E5%BF%85%E4%BC%9A%E7%A7%AF%E5%8E%8B%E5%9C%A8MQ%E4%B8%AD%EF%BC%8C%E8%BF%99%E6%A0%B7%E9%AB%98%E5%B3%B0%E5%B0%B1%E8%A2%AB%E5%89%8A%E6%8E%89%EF%BC%8C%E4%BD%86%E5%9B%A0%E4%B8%BA%E6%B6%88%E6%81%AF%E7%9A%84%E7%A7%AF%E5%8E%8B%EF%BC%8C%E9%AB%98%E5%B3%B0%E6%9C%9F%E8%BF%87%E5%90%8E%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%E5%86%85%EF%BC%8C%E6%B6%88%E8%B4%B9%E6%B6%88%E6%81%AF%E7%9A%84%E9%80%9F%E5%BA%A6%E8%BF%98%E5%9C%A8%E7%BB%B4%E6%8C%81%E5%9C%A81000%2Fs%E7%9B%B4%E5%88%B0%E6%B6%88%E8%B4%B9%E5%90%8E%E7%A7%AF%E5%8E%8B%E7%9A%84%E6%B6%88%E6%81%AF%E4%B8%BA%E8%87%B3%EF%BC%8C%E8%BF%99%E5%B0%B1%E5%8F%AB%E5%A1%AB%E8%B0%B7%E3%80%82%0A%0A%0A%20%23%23%20MQ%E7%9A%84%E5%8A%A3%E5%8A%BF%0A%0A%23%23%23%23%20%E7%B3%BB%E7%BB%9F%E5%8F%AF%E7%94%A8%E6%80%A7%E9%99%8D%E4%BD%8E%0A%3E%20%E5%BC%95%E5%85%A5%E7%9A%84%E5%A4%96%E9%83%A8%E4%BE%9D%E8%B5%96%E8%B6%8A%E5%A4%9A%EF%BC%8C%E7%B3%BB%E7%BB%9F%E7%9A%84%E7%A8%B3%E5%AE%9A%E6%80%A7%E5%B0%B1%E4%BC%9A%E8%B6%8A%E5%B7%AE%EF%BC%8C%E5%BC%95%E5%85%A5%E7%9A%84MQ%20%E5%AE%95%E6%9C%BA%E5%B0%B1%E4%BC%9A%E5%AF%B9%E4%B8%9A%E5%8A%A1%E9%80%A0%E6%88%90%E5%BD%B1%E5%93%8D%0A%3E%20%E9%9C%80%E8%A6%81%E8%A7%A3%E5%86%B3%E4%BF%9D%E8%AF%81MQ%E7%9A%84%E9%AB%98%E5%8F%AF%E7%94%A8%E9%97%AE%E9%A2%98%0A%0A%23%23%23%23%20%E7%B3%BB%E7%BB%9F%E5%A4%8D%E6%9D%82%E5%BA%A6%E6%8F%90%E9%AB%98%0A%3E%20MQ%E7%9A%84%E5%8A%A0%E5%85%A5%E5%A2%9E%E5%8A%A0%E4%BA%86%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%A4%8D%E6%9D%82%E6%80%A7%EF%BC%8C%E4%B9%8B%E5%89%8D%E7%B3%BB%E7%BB%9F%E9%97%B4%E6%98%AF%E5%90%8C%E6%AD%A5%E7%9A%84%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8%EF%BC%8C%E7%8E%B0%E5%9C%A8%E6%98%AF%E9%80%9A%E8%BF%87MQ%E8%BF%9B%E8%A1%8C%E5%BC%82%E6%AD%A5%E8%B0%83%E7%94%A8%E3%80%82%0A%3E%20%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E6%B6%88%E6%81%AF%E6%B2%A1%E6%9C%89%E8%A2%AB%E9%87%8D%E5%A4%8D%E6%B6%88%E8%B4%B9%0A%3E%20%E6%80%8E%E4%B9%88%E5%A4%84%E7%90%86%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%0A%3E%20%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E6%B6%88%E6%81%AF%E4%BC%A0%E9%80%92%E7%9A%84%E9%A1%BA%E5%BA%8F%E6%80%A7%0A%0A%23%23%23%23%20%E4%B8%80%E8%87%B4%E6%80%A7%E9%97%AE%E9%A2%98%0A%3E%20A%E7%B3%BB%E7%BB%9F%E5%A4%84%E7%90%86%E5%AE%8C%E4%B8%9A%E5%8A%A1%E9%80%9A%E8%BF%87MQ%E7%BB%99%20B%EF%BC%8CC%EF%BC%8CD%E4%B8%89%E4%B8%AA%E7%B3%BB%E7%BB%9F%E5%8F%91%E6%B6%88%E6%81%AF%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E6%9E%9CB%EF%BC%8CC%E5%A4%84%E7%90%86%E6%88%90%E5%8A%9F%EF%BC%8C%E4%BD%86%E6%98%AFD%E7%B3%BB%E7%BB%9F%E5%A4%84%E7%90%86%E5%A4%B1%E8%B4%A5%E3%80%82%0A%3E%20%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E6%B6%88%E6%81%AF%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%9F%0A%0A%23%23%20MQ%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D%0A%23%23%23%23%20ActiveMQ%0A%3E%20ActiveMQ%E6%98%AF%E4%BD%BF%E7%94%A8Java%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91%E4%B8%80%E6%AC%BEMQ%E4%BA%A7%E5%93%81%E3%80%82%E6%97%A9%E6%9C%9F%E5%BE%88%E5%A4%9A%E5%85%AC%E5%8F%B8%E4%B8%8E%E9%A1%B9%E7%9B%AE%E4%B8%AD%E9%83%BD%E5%9C%A8%E4%BD%BF%E7%94%A8%E3%80%82%E4%BD%86%E7%8E%B0%E5%9C%A8%E7%9A%84%E7%A4%BE%E5%8C%BA%E6%B4%BB%E8%B7%83%E5%BA%A6%E5%B7%B2%E7%BB%8F%E5%BE%88%E4%BD%8E%E3%80%82%E7%8E%B0%E5%9C%A8%E7%9A%84%E9%A1%B9%E7%9B%AE%E4%B8%AD%E5%B7%B2%E7%BB%8F%E5%BE%88%E5%B0%91%E4%BD%BF%E7%94%A8%E4%BA%86%E3%80%82%0A%0A%23%23%23%23%20RabbitMQ%0A%3E%20RabbitMQ%E6%98%AF%E4%BD%BF%E7%94%A8ErLang%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E6%AC%BEMQ%E4%BA%A7%E5%93%81%E3%80%82%E5%85%B6%E5%90%9E%E5%90%90%E9%87%8F%E8%BE%83Kafka%E4%B8%8ERocketMQ%E8%A6%81%E4%BD%8E%EF%BC%8C%E4%B8%94%E7%94%B1%E4%BA%8E%E5%85%B6%E4%B8%8D%E6%98%AFJava%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91%EF%BC%8C%E6%89%80%E4%BB%A5%E5%85%AC%E5%8F%B8%E5%86%85%E9%83%A8%E5%AF%B9%E5%85%B6%E5%AE%9E%E7%8E%B0%E5%AE%9A%E5%88%B6%E5%8C%96%E5%BC%80%E5%8F%91%E9%9A%BE%E5%BA%A6%E8%BE%83%E5%A4%A7%E3%80%82%0A%0A%23%23%23%23%20Kafka%0A%3E%20Kafka%E6%98%AF%E4%BD%BF%E7%94%A8Scala%2FJava%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E6%AC%BEMQ%E4%BA%A7%E5%93%81%E3%80%82%E5%85%B6%E6%9C%80%E5%A4%A7%E7%9A%84%E7%89%B9%E7%82%B9%E5%B0%B1%E6%98%AF%E9%AB%98%E5%90%9E%E5%90%90%E7%8E%87%EF%BC%8C%E5%B8%B8%E7%94%A8%E4%BA%8E%E5%A4%A7%E6%95%B0%E6%8D%AE%E9%A2%86%E5%9F%9F%E7%9A%84%E5%AE%9E%E6%97%B6%E8%AE%A1%E7%AE%97%E3%80%81%E6%97%A5%E5%BF%97%E9%87%87%E9%9B%86%E7%AD%89%E5%9C%BA%E6%99%AF%E3%80%82%E5%85%B6%E6%B2%A1%E6%9C%89%E9%81%B5%E5%BE%AA%E4%BB%BB%E4%BD%95%E5%B8%B8%E8%A7%81%E7%9A%84MQ%E5%8D%8F%E8%AE%AE%EF%BC%8C%E8%80%8C%E6%98%AF%E4%BD%BF%E7%94%A8%E8%87%AA%E7%A0%94%E5%8D%8F%E8%AE%AE%E3%80%82%E5%AF%B9%E4%BA%8ESpring%20Cloud%20Netfix%EF%BC%8C%E5%85%B6%E4%BB%85%E6%94%AF%E6%8C%81RabbitMQ%E4%B8%8EKafka%E3%80%82%0A%0A%23%23%23%23%20RocketMQ%0A%3E%20RocketMQ%E6%98%AF%E4%BD%BF%E7%94%A8Java%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E6%AC%BEMQ%E4%BA%A7%E5%93%81%E3%80%82%E7%BB%8F%E8%BF%87%E6%95%B0%E5%B9%B4%E9%98%BF%E9%87%8C%E5%8F%8C%2011%20%E7%9A%84%E8%80%83%E9%AA%8C%EF%BC%8C%E6%80%A7%E8%83%BD%E4%B8%8E%E7%A8%B3%E5%AE%9A%E6%80%A7%E9%9D%9E%E5%B8%B8%E9%AB%98%E3%80%82%E5%85%B6%E6%B2%A1%E6%9C%89%E9%81%B5%E5%BE%AA%E4%BB%BB%E4%BD%95%E5%B8%B8%E8%A7%81%E7%9A%84MQ%E5%8D%8F%E8%AE%AE%EF%BC%8C%E8%80%8C%E6%98%AF%E4%BD%BF%E7%94%A8%E8%87%AA%E7%A0%94%E5%8D%8F%E8%AE%AE%E3%80%82%E5%AF%B9%E4%BA%8ESpring%20Cloud%20Alibaba%EF%BC%8C%E5%85%B6%E6%94%AF%E6%8C%81RabbitMQ%E3%80%81Kafka%EF%BC%8C%E4%BD%86%E6%8F%90%E5%80%A1%E4%BD%BF%E7%94%A8RocketMQ%E3%80%82%0A%0A%3E%20Ali%E6%8A%80%E6%9C%AF%E5%9B%A2%E9%98%9F%E5%9C%A8Kafka%E5%BC%80%E6%BA%90%E5%90%8E%E5%AF%B9%E5%85%B6%E6%8A%80%E6%9C%AF%E8%BF%9B%E8%A1%8C%E4%BA%86%E6%B7%B1%E5%85%A5%E7%9A%84%E7%A0%94%E7%A9%B6%E5%BC%80%E5%8F%91%E5%87%BA%E4%B8%80%E6%AC%BE%E6%96%B0%E7%9A%84MQ%E5%8F%ABMetaMQ%2C%20%E5%90%8E%E6%9D%A5%E5%AF%B9MetaMQ%E8%BF%9B%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%88%90%E4%B8%BA%E5%90%8E%E9%9D%A2%E7%9A%84RocketMQ%E3%80%82%0A%0A%0A%23%23%23%23%20%E5%AF%B9%E6%AF%94%0A%0A!%5B183c7f3cd3dfc24927a2e97fd7ee0f39.png%5D(en-resource%3A%2F%2Fdatabase%2F887%3A1)%0A%0A%0A%23%23%20%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%0A%0A%23%23%23%23%20%E7%94%9F%E4%BA%A7%E8%80%85(Producer)%0A%0A%3E%20%20%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E8%80%85%EF%BC%8C%E8%B4%9F%E8%B4%A3%E7%94%9F%E4%BA%A7%E6%B6%88%E6%81%AF%E3%80%82%0A%3E%20Producer%E9%80%9A%E8%BF%87MQ%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%A8%A1%E5%9D%97%E9%80%89%E6%8B%A9%E7%9B%B8%E5%BA%94%E7%9A%84Broker%E9%9B%86%E7%BE%A4%E9%98%9F%E5%88%97%E8%BF%9B%E8%A1%8C%E6%B6%88%E6%81%AF%E6%8A%95%E9%80%92%EF%BC%8C%E6%8A%95%E9%80%92%E7%9A%84%E8%BF%87%E7%A8%8B%E6%94%AF%E6%8C%81%E5%BF%AB%E9%80%9F%E5%A4%B1%E8%B4%A5%E5%B9%B6%E4%B8%94%E4%BD%8E%E5%BB%B6%E8%BF%9F%E3%80%82%0A%3E%0A%3E%20RocketMQ%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E8%80%85%E9%83%BD%E6%98%AF%E4%BB%A5%60%E7%94%9F%E4%BA%A7%E8%80%85%E7%BB%84%EF%BC%88Producer%20Group%EF%BC%89%60%E7%9A%84%E5%BD%A2%E5%BC%8F%E5%87%BA%E7%8E%B0%E7%9A%84%E3%80%82%0A%3E%20%E7%94%9F%E4%BA%A7%E8%80%85%E7%BB%84%E6%98%AF%E5%90%8C%E4%B8%80%E7%B1%BB%E7%94%9F%E4%BA%A7%E8%80%85%E7%9A%84%E9%9B%86%E5%90%88%EF%BC%8C%E8%BF%99%E7%B1%BBProducer%E5%8F%91%E9%80%81%E7%9B%B8%E5%90%8CTopic%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%B6%88%E6%81%AF%E3%80%82%0A%3E%20%0A%3E%20%E4%B8%80%E4%B8%AA%E7%94%9F%E4%BA%A7%E8%80%85%E7%BB%84%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E5%8F%91%E9%80%81%E5%A4%9A%E4%B8%AA%E4%B8%BB%E9%A2%98%E7%9A%84%E6%B6%88%E6%81%AF%E3%80%82%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%8C%E4%B8%9A%E5%8A%A1%E7%B3%BB%E7%BB%9F%E4%BA%A7%E7%94%9F%E7%9A%84%E6%97%A5%E5%BF%97%E5%86%99%E5%85%A5%E5%88%B0MQ%E7%9A%84%E8%BF%87%E7%A8%8B%EF%BC%8C%E5%B0%B1%E6%98%AF%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E7%9A%84%E8%BF%87%E7%A8%8B%0A%3E%20%E5%86%8D%E5%A6%82%EF%BC%8C%E7%94%B5%E5%95%86%E5%B9%B3%E5%8F%B0%E4%B8%AD%E7%94%A8%E6%88%B7%E6%8F%90%E4%BA%A4%E7%9A%84%E7%A7%92%E6%9D%80%E8%AF%B7%E6%B1%82%E5%86%99%E5%85%A5%E5%88%B0MQ%E7%9A%84%E8%BF%87%E7%A8%8B%EF%BC%8C%E5%B0%B1%E6%98%AF%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E7%9A%84%E8%BF%87%E7%A8%8B%0A%0A%23%23%23%23%20%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A%3E%20%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E8%80%85%EF%BC%8C%E8%B4%9F%E8%B4%A3%E6%B6%88%E8%B4%B9%E6%B6%88%E6%81%AF%E3%80%82%E4%B8%80%E4%B8%AA%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E8%80%85%E4%BC%9A%E4%BB%8EBroker%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%88%B0%E6%B6%88%E6%81%AF%EF%BC%8C%E5%B9%B6%E5%AF%B9%E6%B6%88%E6%81%AF%E8%BF%9B%E8%A1%8C%E7%9B%B8%E5%85%B3%E4%B8%9A%E5%8A%A1%E5%A4%84%E7%90%86%E3%80%82%0A%3E%0A%3E%20RocketMQ%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E8%80%85%E9%83%BD%E6%98%AF%E4%BB%A5%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%EF%BC%88Consumer%20Group%EF%BC%89%E7%9A%84%E5%BD%A2%E5%BC%8F%E5%87%BA%E7%8E%B0%E7%9A%84%E3%80%82%0A%3E%20%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E6%98%AF%E5%90%8C%E4%B8%80%E7%B1%BB%E6%B6%88%E8%B4%B9%E8%80%85%E7%9A%84%E9%9B%86%E5%90%88%EF%BC%8C%E8%BF%99%E7%B1%BBConsumer%E6%B6%88%E8%B4%B9%E7%9A%84%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AATopic%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%B6%88%E6%81%AF%E3%80%82%E4%B8%8D%E8%BF%87%EF%BC%8C%E4%B8%80%E4%B8%AATopic%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%B6%88%E6%81%AF%E5%8F%AF%E4%BB%A5%E8%A2%AB%E5%A4%9A%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E5%90%8C%E6%97%B6%E6%B6%88%E8%B4%B9%0A%3E%0A%3E%20%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E4%BD%BF%E5%BE%97%E5%9C%A8%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E6%96%B9%E9%9D%A2%EF%BC%8C%E5%AE%9E%E7%8E%B0%60%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%60%EF%BC%88%E5%B0%86%E4%B8%80%E4%B8%AATopic%E4%B8%AD%E7%9A%84%E4%B8%8D%E5%90%8C%E7%9A%84Queue%E5%B9%B3%E5%9D%87%E5%88%86%E9%85%8D%E7%BB%99%E5%90%8C%E4%B8%80%E4%B8%AAConsumer%20Group%E7%9A%84%E4%B8%8D%E5%90%8C%E7%9A%84Consumer%EF%BC%8C%E6%B3%A8%E6%84%8F%EF%BC%8C%E5%B9%B6%E4%B8%8D%E6%98%AF%E5%B0%86%E6%B6%88%E6%81%AF%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%EF%BC%89%E5%92%8C%60%E5%AE%B9%E9%94%99%60%EF%BC%88%E4%B8%80%E4%B8%AAConsmer%E6%8C%82%E4%BA%86%EF%BC%8C%E8%AF%A5Consumer%20Group%E4%B8%AD%E7%9A%84%E5%85%B6%E5%AE%83Consumer%E5%8F%AF%E4%BB%A5%E6%8E%A5%E7%9D%80%E6%B6%88%E8%B4%B9%E5%8E%9FConsumer%E6%B6%88%E8%B4%B9%E7%9A%84Queue%EF%BC%89%E7%9A%84%E7%9B%AE%E6%A0%87%E5%8F%98%E5%BE%97%E9%9D%9E%E5%B8%B8%E5%AE%B9%E6%98%93%E3%80%82%0A%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%8CQoS%E7%B3%BB%E7%BB%9F%E4%BB%8EMQ%E4%B8%AD%E8%AF%BB%E5%8F%96%E6%97%A5%E5%BF%97%EF%BC%8C%E5%B9%B6%E5%AF%B9%E6%97%A5%E5%BF%97%E8%BF%9B%E8%A1%8C%E8%A7%A3%E6%9E%90%E5%A4%84%E7%90%86%E7%9A%84%E8%BF%87%E7%A8%8B%E5%B0%B1%E6%98%AF%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E7%9A%84%E8%BF%87%E7%A8%8B%E3%80%82%0A%3E%0A%3E%20%E5%86%8D%E5%A6%82%EF%BC%8C%E7%94%B5%E5%95%86%E5%B9%B3%E5%8F%B0%E7%9A%84%E4%B8%9A%E5%8A%A1%E7%B3%BB%E7%BB%9F%E4%BB%8EMQ%E4%B8%AD%E8%AF%BB%E5%8F%96%E5%88%B0%E7%A7%92%E6%9D%80%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%B9%B6%E5%AF%B9%E8%AF%B7%E6%B1%82%E8%BF%9B%E8%A1%8C%E5%A4%84%E7%90%86%E7%9A%84%E8%BF%87%E7%A8%8B%E5%B0%B1%E6%98%AF%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E7%9A%84%E8%BF%87%E7%A8%8B%E3%80%82%0A%0A%3E%20%60%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E4%B8%ADConsumer%E7%9A%84%E6%95%B0%E9%87%8F%E5%BA%94%E8%AF%A5%E5%B0%8F%E4%BA%8E%E7%AD%89%E4%BA%8E%E8%AE%A2%E9%98%85Topic%E7%9A%84Queue%E6%95%B0%E9%87%8F%E3%80%82%60%0A%3E%0A%3E%20%60%E5%A6%82%E6%9E%9C%E8%B6%85%E5%87%BAQueue%E6%95%B0%E9%87%8F%EF%BC%8C%E5%88%99%E5%A4%9A%E5%87%BA%E7%9A%84Consumer%E5%B0%86%E4%B8%8D%E8%83%BD%E6%B6%88%E8%B4%B9%E6%B6%88%E6%81%AF%E3%80%82%60%0A%0A!%5Bc863fe4af68cfc916bc024719248e567.png%5D(en-resource%3A%2F%2Fdatabase%2F888%3A1)%0A%0A%0A%3E%20%E6%B3%A8%E6%84%8F%EF%BC%8C%0A%3E%0A%3E%20-%201%20%20%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E5%8F%AA%E8%83%BD%E6%B6%88%E8%B4%B9%E4%B8%80%E4%B8%AATopic%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%8C%E4%B8%8D%E8%83%BD%E5%90%8C%E6%97%B6%E6%B6%88%E8%B4%B9%E5%A4%9A%E4%B8%AATopic%E6%B6%88%E6%81%AF%0A%3E%20-%202%20%20%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E4%B8%AD%E7%9A%84%E6%B6%88%E8%B4%B9%E8%80%85%E5%BF%85%E9%A1%BB%E8%AE%A2%E9%98%85%E5%AE%8C%E5%85%A8%E7%9B%B8%E5%90%8C%E7%9A%84Topic%0A%0A%23%23%23%23%20Name%20Server%0A%0A%23%23%23%23%23%20%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D%0A%0A%3E%20NameServer%E6%98%AFBroker%E4%B8%8ETopic%E8%B7%AF%E7%94%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%94%AF%E6%8C%81Broker%E7%9A%84%E5%8A%A8%E6%80%81%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0%0A%3E%0A%3E%20RocketMQ%E7%9A%84%E6%80%9D%E6%83%B3%E6%9D%A5%E8%87%AA%E4%BA%8EKafka%EF%BC%8C%E8%80%8CKafka%E6%98%AF%E4%BE%9D%E8%B5%96zookeeper%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E5%9C%A8RocketMQ%E6%97%A9%E6%9C%9F%E7%89%88%E6%9C%AC%E4%B8%AD%E4%B9%9F%E4%BE%9D%E8%B5%96zookeeper%E3%80%82%E4%BB%8EMetaQ%20v3.0%E5%BC%80%E5%A7%8B%EF%BC%8CRocketMQ%E5%8E%BB%E6%8E%89%E4%BA%86zookeeper%E7%9A%84%E4%BE%9D%E8%B5%96%EF%BC%8C%E4%BD%BF%E7%94%A8b%E4%BA%86%E8%87%AA%E5%B7%B1%E7%9A%84NameServer%0A%3E%0A%3E%20%E4%B8%BB%E8%A6%81%E5%8A%9F%E8%83%BD%E6%9C%89%E4%B8%A4%E4%B8%AA%EF%BC%9A%0A%3E%0A%3E%20-%20%60Broker%E7%AE%A1%E7%90%86%EF%BC%9A%60%E6%8E%A5%E5%8F%97Broker%E9%9B%86%E7%BE%A4%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%E5%B9%B6%E4%B8%94%E4%BF%9D%E5%AD%98%E4%B8%8B%E6%9D%A5%E4%BD%9C%E4%B8%BA%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%EF%BC%9B%E6%8F%90%E4%BE%9B%E5%BF%83%E8%B7%B3%E6%A3%80%E6%B5%8B%E6%9C%BA%E5%88%B6%EF%BC%8C%E6%A3%80%E6%9F%A5Broker%E6%98%AF%E5%90%A6%E8%BF%98%E5%AD%98%E6%B4%BB%E3%80%82%0A%3E%20-%20%60%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E7%AE%A1%E7%90%86%EF%BC%9A%60%E6%AF%8F%E4%B8%AANameServer%E4%B8%AD%E9%83%BD%E4%BF%9D%E5%AD%98%E7%9D%80Broker%E9%9B%86%E7%BE%A4%E7%9A%84%E6%95%B4%E4%B8%AA%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E5%92%8C%E7%94%A8%E4%BA%8E%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9F%A5%E8%AF%A2%E7%9A%84%E9%98%9F%E5%88%97%E4%BF%A1%E6%81%AF%E3%80%82Producer%E5%92%8CConumser%E9%80%9A%E8%BF%87NameServer%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%8F%96%E6%95%B4%E4%B8%AABroker%E9%9B%86%E7%BE%A4%E7%9A%84%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%EF%BC%8C%E4%BB%8E%E8%80%8C%E8%BF%9B%E8%A1%8C%E6%B6%88%E6%81%AF%E7%9A%84%E6%8A%95%E9%80%92%E5%92%8C%E6%B6%88%E8%B4%B9%E3%80%82%0A%0A%23%23%23%23%23%20%E8%B7%AF%E7%94%B1%E6%B3%A8%E5%86%8C%0A%0A%3E%20NameServer%E9%80%9A%E5%B8%B8%E4%B9%9F%E6%98%AF%E4%BB%A5%E9%9B%86%E7%BE%A4%E7%9A%84%E6%96%B9%E5%BC%8F%E9%83%A8%E7%BD%B2%EF%BC%8C%E4%B8%8D%E8%BF%87%EF%BC%8CNameServer%E6%98%AF%E6%97%A0%E7%8A%B6%E6%80%81%E7%9A%84%EF%BC%8C%E5%8D%B3NameServer%E9%9B%86%E7%BE%A4%E4%B8%AD%E7%9A%84%E5%90%84%E4%B8%AA%E8%8A%82%E7%82%B9%E9%97%B4%E6%98%AF%E6%97%A0%E5%B7%AE%E5%BC%82%E7%9A%84%EF%BC%8C%60%E5%90%84%E8%8A%82%E7%82%B9%E9%97%B4%E7%9B%B8%E4%BA%92%E4%B8%8D%E8%BF%9B%E8%A1%8C%E4%BF%A1%E6%81%AF%E9%80%9A%E8%AE%AF%60%E3%80%82%0A%3E%0A%3E%20%E9%82%A3%E5%90%84%E8%8A%82%E7%82%B9%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E6%98%AF%E5%A6%82%E4%BD%95%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5%E7%9A%84%E5%91%A2%EF%BC%9F%0A%3E%0A%3E%20%E5%9C%A8Broker%E8%8A%82%E7%82%B9%E5%90%AF%E5%8A%A8%E6%97%B6%EF%BC%8C%E8%BD%AE%E8%AF%A2NameServer%E5%88%97%E8%A1%A8%EF%BC%8C%E4%B8%8E%E6%AF%8F%E4%B8%AANameServer%E8%8A%82%E7%82%B9%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%8F%91%E8%B5%B7%E6%B3%A8%E5%86%8C%E8%AF%B7%E6%B1%82%E3%80%82%E5%9C%A8NameServer%E5%86%85%E9%83%A8%E7%BB%B4%E6%8A%A4%E7%9D%80%E4%B8%80%E4%B8%AABroker%E5%88%97%E8%A1%A8%EF%BC%8C%E7%94%A8%E6%9D%A5%E5%8A%A8%E6%80%81%E5%AD%98%E5%82%A8Broker%E7%9A%84%E4%BF%A1%E6%81%AF%E3%80%82%0A%0A%3E%20%E6%B3%A8%E6%84%8F%EF%BC%8C%E8%BF%99%E6%98%AF%E4%B8%8E%E5%85%B6%E5%AE%83%E5%83%8Fzk%E3%80%81Eureka%E3%80%81Nacos%E7%AD%89%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E4%B8%8D%E5%90%8C%E7%9A%84%E5%9C%B0%E6%96%B9%E3%80%82%0A%3E%20%E8%BF%99%E7%A7%8DNameServer%E7%9A%84%E6%97%A0%E7%8A%B6%E6%80%81%E6%96%B9%E5%BC%8F%EF%BC%8C%E6%9C%89%E4%BB%80%E4%B9%88%E4%BC%98%E7%BC%BA%E7%82%B9%EF%BC%9A%0A%3E%20%E4%BC%98%E7%82%B9%EF%BC%9ANameServer%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA%E7%AE%80%E5%8D%95%EF%BC%8C%E6%89%A9%E5%AE%B9%E7%AE%80%E5%8D%95%E3%80%82%0A%3E%20%E7%BC%BA%E7%82%B9%EF%BC%9A%E5%AF%B9%E4%BA%8EBroker%EF%BC%8C%E5%BF%85%E9%A1%BB%E6%98%8E%E7%A1%AE%E6%8C%87%E5%87%BA%E6%89%80%E6%9C%89NameServer%E5%9C%B0%E5%9D%80%E3%80%82%E5%90%A6%E5%88%99%E6%9C%AA%E6%8C%87%E5%87%BA%E7%9A%84%E5%B0%86%E4%B8%8D%E4%BC%9A%E5%8E%BB%E6%B3%A8%E5%86%8C%E3%80%82%E4%B9%9F%E6%AD%A3%E5%9B%A0%E4%B8%BA%E5%A6%82%E6%AD%A4%EF%BC%8CNameServer%E5%B9%B6%E4%B8%8D%E8%83%BD%E9%9A%8F%E4%BE%BF%E6%89%A9%E5%AE%B9%E3%80%82%E5%9B%A0%E4%B8%BA%EF%BC%8C%E8%8B%A5Broker%E4%B8%8D%E9%87%8D%E6%96%B0%E9%85%8D%E7%BD%AE%EF%BC%8C%E6%96%B0%E5%A2%9E%E7%9A%84NameServer%E5%AF%B9%E4%BA%8EBroker%E6%9D%A5%E8%AF%B4%E6%98%AF%E4%B8%8D%E5%8F%AF%E8%A7%81%E7%9A%84%EF%BC%8C%E5%85%B6%E4%B8%8D%E4%BC%9A%E5%90%91%E8%BF%99%E4%B8%AANameServer%E8%BF%9B%E8%A1%8C%E6%B3%A8%E5%86%8C%E3%80%82%0A%0A%3E%20Broker%E8%8A%82%E7%82%B9%E4%B8%BA%E4%BA%86%E8%AF%81%E6%98%8E%E8%87%AA%E5%B7%B1%E6%98%AF%E6%B4%BB%E7%9D%80%E7%9A%84%EF%BC%8C%E4%B8%BA%E4%BA%86%E7%BB%B4%E6%8A%A4%E4%B8%8ENameServer%E9%97%B4%E7%9A%84%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E4%BC%9A%E5%B0%86%E6%9C%80%E6%96%B0%E7%9A%84%E4%BF%A1%E6%81%AF%E4%BB%A5%E5%BF%83%E8%B7%B3%E5%8C%85%E7%9A%84%E6%96%B9%E5%BC%8F%E4%B8%8A%E6%8A%A5%E7%BB%99NameServer%EF%BC%8C%E6%AF%8F%2030%20%E7%A7%92%E5%8F%91%E9%80%81%E4%B8%80%E6%AC%A1%E5%BF%83%E8%B7%B3%E3%80%82%E5%BF%83%E8%B7%B3%E5%8C%85%E4%B8%AD%E5%8C%85%E5%90%AB%20BrokerId%E3%80%81Broker%E5%9C%B0%E5%9D%80(IP%2BPort)%E3%80%81Broker%E5%90%8D%E7%A7%B0%E3%80%81Broker%E6%89%80%E5%B1%9E%E9%9B%86%E7%BE%A4%E5%90%8D%E7%A7%B0%E7%AD%89%E7%AD%89%E3%80%82NameServer%E5%9C%A8%E6%8E%A5%E6%94%B6%E5%88%B0%E5%BF%83%E8%B7%B3%E5%8C%85%E5%90%8E%EF%BC%8C%E4%BC%9A%E6%9B%B4%E6%96%B0%E5%BF%83%E8%B7%B3%E6%97%B6%E9%97%B4%E6%88%B3%EF%BC%8C%E8%AE%B0%E5%BD%95%E8%BF%99%E4%B8%AABroker%E7%9A%84%E6%9C%80%E6%96%B0%E5%AD%98%E6%B4%BB%E6%97%B6%E9%97%B4%E3%80%82%0A%0A%23%23%23%23%23%20%E8%B7%AF%E7%94%B1%E5%89%94%E9%99%A4%0A%0A%3E%20%E7%94%B1%E4%BA%8EBroker%E5%85%B3%E6%9C%BA%E3%80%81%E5%AE%95%E6%9C%BA%E6%88%96%E7%BD%91%E7%BB%9C%E6%8A%96%E5%8A%A8%E7%AD%89%E5%8E%9F%E5%9B%A0%EF%BC%8CNameServer%E6%B2%A1%E6%9C%89%E6%94%B6%E5%88%B0Broker%E7%9A%84%E5%BF%83%E8%B7%B3%EF%BC%8CNameServer%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%B0%86%E5%85%B6%E4%BB%8EBroker%E5%88%97%E8%A1%A8%E4%B8%AD%E5%89%94%E9%99%A4%E3%80%82%0A%3E%0A%3E%20NameServer%E4%B8%AD%E6%9C%89%E4%B8%80%E4%B8%AA%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%EF%BC%8C%E6%AF%8F%E9%9A%94%2010%20%E7%A7%92%E5%B0%B1%E4%BC%9A%E6%89%AB%E6%8F%8F%E4%B8%80%E6%AC%A1Broker%E8%A1%A8%EF%BC%8C%E6%9F%A5%E7%9C%8B%E6%AF%8F%E4%B8%80%E4%B8%AABroker%E7%9A%84%E6%9C%80%E6%96%B0%E5%BF%83%E8%B7%B3%E6%97%B6%E9%97%B4%E6%88%B3%E8%B7%9D%E7%A6%BB%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4%E6%98%AF%E5%90%A6%E8%B6%85%E8%BF%87%20120%20%E7%A7%92%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%B6%85%E8%BF%87%EF%BC%8C%E5%88%99%E4%BC%9A%E5%88%A4%E5%AE%9ABroker%E5%A4%B1%E6%95%88%EF%BC%8C%E7%84%B6%E5%90%8E%E5%B0%86%E5%85%B6%E4%BB%8EBroker%E5%88%97%E8%A1%A8%E4%B8%AD%E5%89%94%E9%99%A4%E3%80%82%0A%0A%3E%20%E6%89%A9%E5%B1%95%EF%BC%9A%0A%3E%0A%3E%20%E5%AF%B9%E4%BA%8ERocketMQ%E6%97%A5%E5%B8%B8%E8%BF%90%E7%BB%B4%E5%B7%A5%E4%BD%9C%EF%BC%8C%E4%BE%8B%E5%A6%82Broker%E5%8D%87%E7%BA%A7%EF%BC%8C%E9%9C%80%E8%A6%81%E5%81%9C%E6%8E%89Broker%E7%9A%84%E5%B7%A5%E4%BD%9C%E3%80%82%0A%3E%0A%3E%20OP%E9%9C%80%E8%A6%81%E6%80%8E%E4%B9%88%E5%81%9A%EF%BC%9F%0A%3E%20OP%E9%9C%80%E8%A6%81%E5%B0%86Broker%E7%9A%84%E8%AF%BB%E5%86%99%E6%9D%83%E9%99%90%E7%A6%81%E6%8E%89%E3%80%82%E4%B8%80%E6%97%A6client(Consumer%E6%88%96Producer)%E5%90%91broker%E5%8F%91%E9%80%81%E8%AF%B7%E6%B1%82%EF%BC%8C%E9%83%BD%E4%BC%9A%E6%94%B6%E5%88%B0broker%E7%9A%84NO_PERMISSION%E5%93%8D%E5%BA%94%EF%BC%8C%E7%84%B6%E5%90%8Eclient%E4%BC%9A%E8%BF%9B%E8%A1%8C%E5%AF%B9%E5%85%B6%E5%AE%83Broker%E7%9A%84%E9%87%8D%E8%AF%95%E3%80%82%0A%3E%20%E5%BD%93OP%E8%A7%82%E5%AF%9F%E5%88%B0%E8%BF%99%E4%B8%AABroker%E6%B2%A1%E6%9C%89%E6%B5%81%E9%87%8F%E5%90%8E%EF%BC%8C%E5%86%8D%E5%85%B3%E9%97%AD%E5%AE%83%EF%BC%8C%E5%AE%9E%E7%8E%B0Broker%E4%BB%8ENameServer%E7%9A%84%E7%A7%BB%E9%99%A4%E3%80%82%0A%3E%20OP%EF%BC%9A%E8%BF%90%E7%BB%B4%E5%B7%A5%E7%A8%8B%E5%B8%88%0A%3E%20SRE%EF%BC%9ASite%20Reliability%20Engineer%EF%BC%8C%E7%8E%B0%E5%9C%BA%E5%8F%AF%E9%9D%A0%E6%80%A7%E5%B7%A5%E7%A8%8B%E5%B8%88%0A%0A%23%23%23%23%23%20%E8%B7%AF%E7%94%B1%E5%8F%91%E7%8E%B0%0A%0A%3E%20RocketMQ%E7%9A%84%E8%B7%AF%E7%94%B1%E5%8F%91%E7%8E%B0%E9%87%87%E7%94%A8%E7%9A%84%E6%98%AF%60Pull%E6%A8%A1%E5%9E%8B%60%E3%80%82%0A%3E%20%E5%9C%A8RocketMQ%E8%99%BD%E7%84%B6%E6%9C%89%E5%AF%B9%E4%BA%8E%E6%B6%88%E8%B4%B9%E8%80%85%E6%9C%89%60DefaultMQPullConsumer%60%E5%92%8C%60DefaultMQPushConsumer%60%E4%B8%A4%E4%B8%AAApi%E5%8F%AF%E4%BE%9B%E9%80%89%E6%8B%A9%EF%BC%8C%E4%BD%86%E6%98%AF%E5%BA%95%E5%B1%82%E5%85%B6%E5%AE%9E%E9%83%BD%E4%BD%BF%E7%94%A8%60PullAPIWrapper%60%E8%BF%99%E4%B8%AA%E7%B1%BB%E8%BF%9B%E8%A1%8C%E6%B6%88%E6%81%AF%E6%8B%89%E5%8F%96%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8CRocketMQ%E4%BD%BF%E7%94%A8%E7%9A%84%E6%B6%88%E8%B4%B9%E4%BC%A0%E9%80%92%E6%A8%A1%E5%9E%8B%E6%98%AFPull%E6%A8%A1%E5%9E%8B%E3%80%82%0A%0A%3E%20%E5%BD%93Topic%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E5%87%BA%E7%8E%B0%E5%8F%98%E5%8C%96%E6%97%B6%EF%BC%8CNameServer%E4%B8%8D%E4%BC%9A%E4%B8%BB%E5%8A%A8%E6%8E%A8%E9%80%81%E7%BB%99%E5%AE%A2%E6%88%B7%E7%AB%AF%EF%BC%8C%E8%80%8C%E6%98%AF%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%AE%9A%E6%97%B6%E6%8B%89%E5%8F%96%E4%B8%BB%E9%A2%98%E6%9C%80%E6%96%B0%E7%9A%84%E8%B7%AF%E7%94%B1%E3%80%82%0A%3E%20%E9%BB%98%E8%AE%A4%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%AF%8F%2030%20%E7%A7%92%E4%BC%9A%E6%8B%89%E5%8F%96%E4%B8%80%E6%AC%A1%E6%9C%80%E6%96%B0%E7%9A%84%E8%B7%AF%E7%94%B1%E3%80%82%0A%0A%23%23%23%23%23%23%20Push%E6%A8%A1%E5%9E%8B%0A%0A%3E%20%20%60Push%E6%A8%A1%E5%9E%8B%60%EF%BC%9A%E6%8E%A8%E9%80%81%E6%A8%A1%E5%9E%8B%E3%80%82%E5%85%B6%E5%AE%9E%E6%97%B6%E6%80%A7%E8%BE%83%E5%A5%BD%EF%BC%8C%E6%98%AF%E4%B8%80%E4%B8%AA%60%E5%8F%91%E5%B8%83-%E8%AE%A2%E9%98%85%60%E6%A8%A1%E5%9E%8B%EF%BC%8C%E9%9C%80%E8%A6%81%E7%BB%B4%E6%8A%A4%E4%B8%80%E4%B8%AA%E9%95%BF%E8%BF%9E%E6%8E%A5%E3%80%82%E8%80%8C%E9%95%BF%E8%BF%9E%E6%8E%A5%E7%9A%84%E7%BB%B4%E6%8A%A4%E6%98%AF%E9%9C%80%E8%A6%81%E8%B5%84%E6%BA%90%E6%88%90%E6%9C%AC%E7%9A%84%E3%80%82%E8%AF%A5%E6%A8%A1%E5%9E%8B%E9%80%82%E5%90%88%E4%BA%8E%E7%9A%84%E5%9C%BA%E6%99%AF%EF%BC%9A%0A%3E%0A%3E%20%20-%20%E5%AE%9E%E6%97%B6%E6%80%A7%E8%A6%81%E6%B1%82%E8%BE%83%E9%AB%98%0A%3E%0A%3E%20%20-%20Client%E6%95%B0%E9%87%8F%E4%B8%8D%E5%A4%9A%EF%BC%8CServer%E6%95%B0%E6%8D%AE%E5%8F%98%E5%8C%96%E8%BE%83%E9%A2%91%E7%B9%81%0A%0A%23%23%23%23%23%23%20Pull%E6%A8%A1%E5%9E%8B%20%0A%3E%60Pull%E6%A8%A1%E5%9E%8B%60%EF%BC%9A%E6%8B%89%E5%8F%96%E6%A8%A1%E5%9E%8B%E3%80%82%E5%AD%98%E5%9C%A8%E7%9A%84%E9%97%AE%E9%A2%98%E6%98%AF%EF%BC%8C%E5%AE%9E%E6%97%B6%E6%80%A7%E8%BE%83%E5%B7%AE%E3%80%82%0A%0A%23%23%23%23%23%23%20Long%20Polling%E6%A8%A1%E5%9E%8B%0A%3E%20%60Long%20Polling%E6%A8%A1%E5%9E%8B%60%EF%BC%9A%E9%95%BF%E8%BD%AE%E8%AF%A2%E6%A8%A1%E5%9E%8B%E3%80%82%E5%85%B6%E6%98%AF%E5%AF%B9Push%E4%B8%8EPull%E6%A8%A1%E5%9E%8B%E7%9A%84%E6%95%B4%E5%90%88%EF%BC%8C%E5%85%85%E5%88%86%E5%88%A9%E7%94%A8%E4%BA%86%E8%BF%99%E4%B8%A4%E7%A7%8D%E6%A8%A1%E5%9E%8B%E7%9A%84%E4%BC%98%E5%8A%BF%EF%BC%8C%E5%B1%8F%E8%94%BD%E4%BA%86%E5%AE%83%E4%BB%AC%E7%9A%84%E5%8A%A3%E5%8A%BF%E3%80%82%20%0A%3E%20%5BRocketMQ%E6%BA%90%E7%A0%81%E4%B9%8B%E9%95%BF%E8%BD%AE%E8%AF%A2%E5%AE%9E%E7%8E%B0%5D(https%3A%2F%2Fwww.jianshu.com%2Fp%2Fc717cb26752e)%0A%0A%23%23%23%23%20Broker%0A%0A%23%23%23%23%23%20%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D%0A%0ABroker%E5%85%85%E5%BD%93%E7%9D%80%E6%B6%88%E6%81%AF%E4%B8%AD%E8%BD%AC%E8%A7%92%E8%89%B2%EF%BC%8C%E8%B4%9F%E8%B4%A3%E5%AD%98%E5%82%A8%E6%B6%88%E6%81%AF%E3%80%81%E8%BD%AC%E5%8F%91%E6%B6%88%E6%81%AF%E3%80%82Broker%E5%9C%A8RocketMQ%E7%B3%BB%E7%BB%9F%E4%B8%AD%E8%B4%9F%E8%B4%A3%E6%8E%A5%E6%94%B6%E5%B9%B6%E5%AD%98%E5%82%A8%E4%BB%8E%E7%94%9F%E4%BA%A7%E8%80%85%E5%8F%91%E9%80%81%E6%9D%A5%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%8C%E5%90%8C%E6%97%B6%E4%B8%BA%E6%B6%88%E8%B4%B9%E8%80%85%E7%9A%84%E6%8B%89%E5%8F%96%E8%AF%B7%E6%B1%82%E4%BD%9C%E5%87%86%E5%A4%87%E3%80%82Broker%E5%90%8C%E6%97%B6%E4%B9%9F%E5%AD%98%E5%82%A8%E7%9D%80%E6%B6%88%E6%81%AF%E7%9B%B8%E5%85%B3%E7%9A%84%E5%85%83%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%8C%85%E6%8B%AC%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E6%B6%88%E8%B4%B9%E8%BF%9B%E5%BA%A6%E5%81%8F%E7%A7%BBoffset%E3%80%81%E4%B8%BB%E9%A2%98%E3%80%81%E9%98%9F%E5%88%97%E7%AD%89%E3%80%82%0A%0A%3E%20Kafka%200.8%E7%89%88%E6%9C%AC%E4%B9%8B%E5%90%8E%EF%BC%8Coffset%E6%98%AF%E5%AD%98%E6%94%BE%E5%9C%A8Broker%E4%B8%AD%E7%9A%84%EF%BC%8C%E4%B9%8B%E5%89%8D%E7%89%88%E6%9C%AC%E6%98%AF%E5%AD%98%E6%94%BE%E5%9C%A8Zookeeper%E4%B8%AD%E7%9A%84%E3%80%82%0A%0A%23%23%23%23%23%20%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2%0A%0A%3E%20%E4%B8%BA%E4%BA%86%E5%A2%9E%E5%BC%BABroker%E6%80%A7%E8%83%BD%E4%B8%8E%E5%90%9E%E5%90%90%E9%87%8F%EF%BC%8CBroker%E4%B8%80%E8%88%AC%E9%83%BD%E6%98%AF%E4%BB%A5%E9%9B%86%E7%BE%A4%E5%BD%A2%E5%BC%8F%E5%87%BA%E7%8E%B0%E7%9A%84%E3%80%82%E5%90%84%E9%9B%86%E7%BE%A4%E8%8A%82%E7%82%B9%E4%B8%AD%E5%8F%AF%E8%83%BD%E5%AD%98%E6%94%BE%E7%9D%80%E7%9B%B8%E5%90%8CTopic%E7%9A%84%E4%B8%8D%E5%90%8CQueue%E3%80%82%E4%B8%8D%E8%BF%87%EF%BC%8C%E8%BF%99%E9%87%8C%E6%9C%89%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9F%90Broker%E8%8A%82%E7%82%B9%E5%AE%95%E6%9C%BA%EF%BC%8C%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E6%95%B0%E6%8D%AE%E4%B8%8D%E4%B8%A2%E5%A4%B1%E5%91%A2%EF%BC%9F%E5%85%B6%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%E6%98%AF%EF%BC%8C%E5%B0%86%E6%AF%8F%E4%B8%AABroker%E9%9B%86%E7%BE%A4%E8%8A%82%E7%82%B9%E8%BF%9B%E8%A1%8C%E6%A8%AA%E5%90%91%E6%89%A9%E5%B1%95%EF%BC%8C%E5%8D%B3%E5%B0%86Broker%E8%8A%82%E7%82%B9%E5%86%8D%E5%BB%BA%E4%B8%BA%E4%B8%80%E4%B8%AAHA%E9%9B%86%E7%BE%A4%EF%BC%8C%E8%A7%A3%E5%86%B3%E5%8D%95%E7%82%B9%E9%97%AE%E9%A2%98%E3%80%82%0A%0A%3E%20Broker%E8%8A%82%E7%82%B9%E9%9B%86%E7%BE%A4%E6%98%AF%E4%B8%80%E4%B8%AA%E4%B8%BB%E4%BB%8E%E9%9B%86%E7%BE%A4%EF%BC%8C%E5%8D%B3%E9%9B%86%E7%BE%A4%E4%B8%AD%E5%85%B7%E6%9C%89Master%E4%B8%8ESlave%E4%B8%A4%E7%A7%8D%E8%A7%92%E8%89%B2%E3%80%82Master%E8%B4%9F%E8%B4%A3%E5%A4%84%E7%90%86%E8%AF%BB%E5%86%99%E6%93%8D%E4%BD%9C%E8%AF%B7%E6%B1%82%EF%BC%8CSlave%E8%B4%9F%E8%B4%A3%E5%AF%B9Master%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E8%BF%9B%E8%A1%8C%E5%A4%87%E4%BB%BD%E3%80%82%0A%3E%0A%3E%20%60%E5%BD%93Master%E6%8C%82%E6%8E%89%E4%BA%86%EF%BC%8CSlave%E5%88%99%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%88%87%E6%8D%A2%E4%B8%BAMaster%E5%8E%BB%E5%B7%A5%E4%BD%9C%E3%80%82%60%0A%3E%0A%3E%20%E6%89%80%E4%BB%A5%E8%BF%99%E4%B8%AABroker%E9%9B%86%E7%BE%A4%E6%98%AF%E4%B8%BB%E5%A4%87%E9%9B%86%E7%BE%A4%E3%80%82%E4%B8%80%E4%B8%AAMaster%E5%8F%AF%E4%BB%A5%E5%8C%85%E5%90%AB%E5%A4%9A%E4%B8%AASlave%EF%BC%8C%E4%BD%86%E4%B8%80%E4%B8%AASlave%E5%8F%AA%E8%83%BD%E9%9A%B6%E5%B1%9E%E4%BA%8E%E4%B8%80%E4%B8%AAMaster%E3%80%82%0A%3E%0A%3E%20%60Master%E4%B8%8ESlave%20%E7%9A%84%E5%AF%B9%E5%BA%94%E5%85%B3%E7%B3%BB%E6%98%AF%E9%80%9A%E8%BF%87%E6%8C%87%E5%AE%9A%E7%9B%B8%E5%90%8C%E7%9A%84BrokerName%E3%80%81%E4%B8%8D%E5%90%8C%E7%9A%84BrokerId%20%E6%9D%A5%E7%A1%AE%E5%AE%9A%E7%9A%84%E3%80%82%60BrokerId%E4%B8%BA%200%20%E8%A1%A8%E7%A4%BAMaster%EF%BC%8C%E9%9D%9E%200%20%E8%A1%A8%E7%A4%BASlave%E3%80%82%E6%AF%8F%E4%B8%AABroker%E4%B8%8ENameServer%E9%9B%86%E7%BE%A4%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E8%8A%82%E7%82%B9%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%AE%9A%E6%97%B6%E6%B3%A8%E5%86%8CTopic%E4%BF%A1%E6%81%AF%E5%88%B0%E6%89%80%E6%9C%89NameServer%E3%80%82%0A%0A!%5Bf6eea702f2764f35c045d6ec7ebda709.png%5D(en-resource%3A%2F%2Fdatabase%2F897%3A1)%0A%0A%0A%0A%23%23%23%23%20%E8%AF%BB%2F%E5%86%99%E9%98%9F%E5%88%97%0A%0A%23%23%23%23%23%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E4%BB%8E%E7%89%A9%E7%90%86%E4%B8%8A%E6%9D%A5%E8%AE%B2%EF%BC%8C%E8%AF%BB%2F%E5%86%99%E9%98%9F%E5%88%97%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AA%E9%98%9F%E5%88%97%E3%80%82%E6%89%80%E4%BB%A5%EF%BC%8C%E4%B8%8D%E5%AD%98%E5%9C%A8%E8%AF%BB%2F%E5%86%99%E9%98%9F%E5%88%97%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5%E9%97%AE%E9%A2%98%E3%80%82%E8%AF%BB%2F%E5%86%99%E9%98%9F%E5%88%97%E6%98%AF%E9%80%BB%E8%BE%91%E4%B8%8A%E8%BF%9B%E8%A1%8C%E5%8C%BA%E5%88%86%E7%9A%84%E6%A6%82%E5%BF%B5%E3%80%82%E4%B8%80%E8%88%AC%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E8%AF%BB%2F%E5%86%99%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E6%98%AF%E7%9B%B8%E5%90%8C%E7%9A%84%E3%80%82%0A%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%8C%E5%88%9B%E5%BB%BATopic%E6%97%B6%E8%AE%BE%E7%BD%AE%E7%9A%84%E5%86%99%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E4%B8%BA%208%20%EF%BC%8C%E8%AF%BB%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E4%B8%BA%204%20%EF%BC%8C%E6%AD%A4%E6%97%B6%E7%B3%BB%E7%BB%9F%E4%BC%9A%E5%88%9B%E5%BB%BA%208%20%E4%B8%AAQueue%EF%BC%8C%E5%88%86%E5%88%AB%E6%98%AF0%201%202%203%204%205%206%207%E3%80%82Producer%E4%BC%9A%E5%B0%86%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5%E5%88%B0%E8%BF%99%208%20%E4%B8%AA%E9%98%9F%E5%88%97%EF%BC%8C%E4%BD%86Consumer%E5%8F%AA%E4%BC%9A%E6%B6%88%E8%B4%B90%201%202%203%E8%BF%99%204%20%E4%B8%AA%E9%98%9F%E5%88%97%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%8C4%205%206%207%20%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%E6%98%AF%E4%B8%8D%E4%BC%9A%E8%A2%AB%E6%B6%88%E8%B4%B9%E5%88%B0%E7%9A%84%E3%80%82%0A%0A%3E%20%E5%86%8D%E5%A6%82%EF%BC%8C%E5%88%9B%E5%BB%BATopic%E6%97%B6%E8%AE%BE%E7%BD%AE%E7%9A%84%E5%86%99%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E4%B8%BA%204%20%EF%BC%8C%E8%AF%BB%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E4%B8%BA%208%20%EF%BC%8C%E6%AD%A4%E6%97%B6%E7%B3%BB%E7%BB%9F%E4%BC%9A%E5%88%9B%E5%BB%BA%208%20%E4%B8%AAQueue%EF%BC%8C%E5%88%86%E5%88%AB%E6%98%AF0%201%202%203%204%205%206%207%E3%80%82Producer%E4%BC%9A%E5%B0%86%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5%E5%88%B00%201%202%203%20%E8%BF%99%204%20%E4%B8%AA%E9%98%9F%E5%88%97%EF%BC%8C%E4%BD%86Consumer%E5%8F%AA%E4%BC%9A%E6%B6%88%E8%B4%B90%201%202%203%204%205%206%207%E8%BF%99%208%20%E4%B8%AA%E9%98%9F%E5%88%97%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%8C%E4%BD%86%E6%98%AF4%205%206%207%E4%B8%AD%E6%98%AF%E6%B2%A1%E6%9C%89%E6%B6%88%E6%81%AF%E7%9A%84%E3%80%82%E6%AD%A4%E6%97%B6%E5%81%87%E8%AE%BEConsumer%20Group%E4%B8%AD%E5%8C%85%E5%90%AB%E4%B8%A4%E4%B8%AAConsumer%EF%BC%8CConsumer1%E6%B6%88%E8%B4%B90%201%202%203%EF%BC%8C%E8%80%8CConsumer2%E6%B6%88%E8%B4%B94%205%206%207%E3%80%82%E4%BD%86%E5%AE%9E%E9%99%85%E6%83%85%E5%86%B5%E6%98%AF%EF%BC%8CConsumer2%E6%98%AF%E6%B2%A1%E6%9C%89%E6%B6%88%E6%81%AF%E5%8F%AF%E6%B6%88%E8%B4%B9%E7%9A%84%E3%80%82%0A%0A%3E%20%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E5%BD%93%E8%AF%BB%2F%E5%86%99%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E8%AE%BE%E7%BD%AE%E4%B8%8D%E5%90%8C%E6%97%B6%EF%BC%8C%E6%80%BB%E6%98%AF%E6%9C%89%E9%97%AE%E9%A2%98%E7%9A%84%E3%80%82%E9%82%A3%E4%B9%88%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E8%BF%99%E6%A0%B7%E8%AE%BE%E8%AE%A1%E5%91%A2%EF%BC%9F%E5%85%B6%E8%BF%99%E6%A0%B7%E8%AE%BE%E8%AE%A1%E7%9A%84%E7%9B%AE%E7%9A%84%E6%98%AF%E4%B8%BA%E4%BA%86%EF%BC%8C%60%E6%96%B9%E4%BE%BFTopic%E7%9A%84Queue%E7%9A%84%E7%BC%A9%E5%AE%B9%E3%80%82%60%0A%0A!%5Be7898d5400cea40199d4f202f95aed7d.png%5D(en-resource%3A%2F%2Fdatabase%2F900%3A1)%0A%0A%3E%20%E4%BE%8B%E5%A6%82%EF%BC%8C%E5%8E%9F%E6%9D%A5%E5%88%9B%E5%BB%BA%E7%9A%84Topic%E4%B8%AD%E5%8C%85%E5%90%AB%2016%20%E4%B8%AAQueue%EF%BC%8C%E5%A6%82%E4%BD%95%E8%83%BD%E5%A4%9F%E4%BD%BF%E5%85%B6Queue%E7%BC%A9%E5%AE%B9%E4%B8%BA%208%20%E4%B8%AA%EF%BC%8C%E8%BF%98%E4%B8%8D%E4%BC%9A%E4%B8%A2%E5%A4%B1%E6%B6%88%E6%81%AF%EF%BC%9F%E5%8F%AF%E4%BB%A5%E5%8A%A8%E6%80%81%E4%BF%AE%E6%94%B9%E5%86%99%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E4%B8%BA%208%20%EF%BC%8C%E8%AF%BB%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E4%B8%8D%E5%8F%98%E3%80%82%E6%AD%A4%E6%97%B6%E6%96%B0%E7%9A%84%E6%B6%88%E6%81%AF%E5%8F%AA%E8%83%BD%E5%86%99%E5%85%A5%E5%88%B0%E5%89%8D%208%20%E4%B8%AA%E9%98%9F%E5%88%97%EF%BC%8C%E8%80%8C%E6%B6%88%E8%B4%B9%E9%83%BD%E6%B6%88%E8%B4%B9%E7%9A%84%E5%8D%B4%E6%98%AF16%20%E4%B8%AA%E9%98%9F%E5%88%97%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%E5%BD%93%E5%8F%91%E7%8E%B0%E5%90%8E%208%20%E4%B8%AAQueue%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E5%AE%8C%E6%AF%95%E5%90%8E%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%86%8D%E5%B0%86%E8%AF%BB%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F%E5%8A%A8%E6%80%81%E8%AE%BE%E7%BD%AE%E4%B8%BA%208%20%E3%80%82%E6%95%B4%E4%B8%AA%E7%BC%A9%E5%AE%B9%E8%BF%87%E7%A8%8B%EF%BC%8C%E6%B2%A1%E6%9C%89%E4%B8%A2%E5%A4%B1%E4%BB%BB%E4%BD%95%E6%B6%88%E6%81%AF%E3%80%82%0A%0A%23%23%23%23%23%20%E6%9D%83%E9%99%90%0A%3E%20perm%E7%94%A8%E4%BA%8E%E8%AE%BE%E7%BD%AE%E5%AF%B9%E5%BD%93%E5%89%8D%E5%88%9B%E5%BB%BATopic%E7%9A%84%E6%93%8D%E4%BD%9C%E6%9D%83%E9%99%90%EF%BC%9A%60%202%20%E8%A1%A8%E7%A4%BA%E5%8F%AA%E5%86%99%EF%BC%8C%204%20%E8%A1%A8%E7%A4%BA%E5%8F%AA%E8%AF%BB%EF%BC%8C%206%20%E8%A1%A8%E7%A4%BA%E8%AF%BB%E5%86%99%E3%80%82%60%0A%0A%23%23%23%23%20%E6%B6%88%E6%81%AF%EF%BC%88Message%EF%BC%89%0A%3E%20%E6%B6%88%E6%81%AF%E6%98%AF%E6%8C%87%EF%BC%8C%E6%B6%88%E6%81%AF%E7%B3%BB%E7%BB%9F%E6%89%80%E4%BC%A0%E8%BE%93%E4%BF%A1%E6%81%AF%E7%9A%84%E7%89%A9%E7%90%86%E8%BD%BD%E4%BD%93%EF%BC%8C%E7%94%9F%E4%BA%A7%E5%92%8C%E6%B6%88%E8%B4%B9%E6%95%B0%E6%8D%AE%E7%9A%84%E6%9C%80%E5%B0%8F%E5%8D%95%E4%BD%8D%EF%BC%8C%60%E6%AF%8F%E6%9D%A1%E6%B6%88%E6%81%AF%E5%BF%85%E9%A1%BB%E5%B1%9E%E4%BA%8E%E4%B8%80%E4%B8%AA%E4%B8%BB%E9%A2%98%60%E3%80%82%0A%0A%23%23%23%23%20Topics%0A%0A%23%23%23%23%23%20%E6%A6%82%E5%BF%B5%E4%BB%8B%E7%BB%8D%0A%3E%20topic%E8%A1%A8%E7%A4%BA%E4%B8%80%E7%B1%BB%E6%B6%88%E6%81%AF%E7%9A%84%E9%9B%86%E5%90%88%EF%BC%8C%E6%AF%8F%E4%B8%AA%E4%B8%BB%E9%A2%98%E5%8C%85%E5%90%AB%E8%8B%A5%E5%B9%B2%E6%9D%A1%E6%B6%88%E6%81%AF%EF%BC%8C%60%E6%AF%8F%E6%9D%A1%E6%B6%88%E6%81%AF%E5%8F%AA%E8%83%BD%E5%B1%9E%E4%BA%8E%E4%B8%80%E4%B8%AA%E4%B8%BB%E9%A2%98%60%EF%BC%8C%E6%98%AF%0A%3E%20RocketMQ%E8%BF%9B%E8%A1%8C%E6%B6%88%E6%81%AF%E8%AE%A2%E9%98%85%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%8D%95%E4%BD%8D%E3%80%82%20%0A%3E%20%E4%B8%80%E4%B8%AA%E7%94%9F%E4%BA%A7%E8%80%85%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E5%8F%91%E9%80%81%E5%A4%9A%E7%A7%8DTopic%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%9B%0A%3E%20%E8%80%8C%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E5%8F%AA%E5%AF%B9%E6%9F%90%E7%A7%8D%E7%89%B9%E5%AE%9A%E7%9A%84Topic%E6%84%9F%E5%85%B4%E8%B6%A3%EF%BC%8C%E5%8D%B3%E5%8F%AA%E5%8F%AF%E4%BB%A5%E8%AE%A2%E9%98%85%E5%92%8C%E6%B6%88%E8%B4%B9%E4%B8%80%E7%A7%8DTopic%E7%9A%84%E6%B6%88%E6%81%AF%E3%80%82%20%0A%3E%20%E5%AF%B9%E5%BA%94%E5%85%B3%E7%B3%BB%0A%60%60%60%0Atopic%3Amessage%201%3An%20%20%20message%3Atopic%201%3A1%0Aproducer%3Atopic%201%3An%20%20consumer%3Atopic%201%3A1%0A%60%60%60%0A!%5B85aefde093c9ac497909bf186d2201cc.png%5D(en-resource%3A%2F%2Fdatabase%2F894%3A1)%0A%0A%0A%23%23%23%23%23%20%E5%88%9B%E5%BB%BA%E6%A8%A1%E5%BC%8F%0A%0A%3E%20%E6%89%8B%E5%8A%A8%E5%88%9B%E5%BB%BATopic%E6%97%B6%EF%BC%8C%E6%9C%89%E4%B8%A4%E7%A7%8D%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%3E%0A%3E%20-%20%E9%9B%86%E7%BE%A4%E6%A8%A1%E5%BC%8F%EF%BC%9A%E8%AF%A5%E6%A8%A1%E5%BC%8F%E4%B8%8B%E5%88%9B%E5%BB%BA%E7%9A%84Topic%E5%9C%A8%E8%AF%A5%E9%9B%86%E7%BE%A4%E4%B8%AD%EF%BC%8C%E6%89%80%E6%9C%89Broker%E4%B8%AD%E7%9A%84Queue%E6%95%B0%E9%87%8F%E6%98%AF%E7%9B%B8%E5%90%8C%E7%9A%84%E3%80%82%0A%3E%20-%20Broker%E6%A8%A1%E5%BC%8F%EF%BC%9A%E8%AF%A5%E6%A8%A1%E5%BC%8F%E4%B8%8B%E5%88%9B%E5%BB%BA%E7%9A%84Topic%E5%9C%A8%E8%AF%A5%E9%9B%86%E7%BE%A4%E4%B8%AD%EF%BC%8C%E6%AF%8F%E4%B8%AABroker%E4%B8%AD%E7%9A%84Queue%E6%95%B0%E9%87%8F%E5%8F%AF%E4%BB%A5%E4%B8%8D%E5%90%8C%E3%80%82%0A%0A%3E%20%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BATopic%E6%97%B6%EF%BC%8C%E9%BB%98%E8%AE%A4%E9%87%87%E7%94%A8%E7%9A%84%E6%98%AFBroker%E6%A8%A1%E5%BC%8F%EF%BC%8C%E4%BC%9A%E4%B8%BA%E6%AF%8F%E4%B8%AABroker%E9%BB%98%E8%AE%A4%E5%88%9B%E5%BB%BA%204%20%E4%B8%AAQueue%E3%80%82%0A%0A%23%23%23%23%20%E6%A0%87%E7%AD%BE%EF%BC%88Tag%EF%BC%89%0A%0A%E4%B8%BA%E6%B6%88%E6%81%AF%E8%AE%BE%E7%BD%AE%E7%9A%84%E6%A0%87%E7%AD%BE%EF%BC%8C%E7%94%A8%E4%BA%8E%E5%90%8C%E4%B8%80%E4%B8%BB%E9%A2%98%E4%B8%8B%E5%8C%BA%E5%88%86%E4%B8%8D%E5%90%8C%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%B6%88%E6%81%AF%E3%80%82%E6%9D%A5%E8%87%AA%E5%90%8C%E4%B8%80%E4%B8%9A%E5%8A%A1%E5%8D%95%E5%85%83%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E4%B8%8D%E5%90%8C%E4%B8%9A%E5%8A%A1%E7%9B%AE%E7%9A%84%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%BB%E9%A2%98%E4%B8%8B%E8%AE%BE%E7%BD%AE%E4%B8%8D%E5%90%8C%E6%A0%87%E7%AD%BE%E3%80%82%E6%A0%87%E7%AD%BE%E8%83%BD%E5%A4%9F%E6%9C%89%E6%95%88%E5%9C%B0%E4%BF%9D%E6%8C%81%E4%BB%A3%E7%A0%81%E7%9A%84%E6%B8%85%E6%99%B0%E5%BA%A6%E5%92%8C%E8%BF%9E%E8%B4%AF%E6%80%A7%EF%BC%8C%E5%B9%B6%E4%BC%98%E5%8C%96RocketMQ%E6%8F%90%E4%BE%9B%E7%9A%84%E6%9F%A5%E8%AF%A2%E7%B3%BB%E7%BB%9F%E3%80%82%E6%B6%88%E8%B4%B9%E8%80%85%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AETag%E5%AE%9E%E7%8E%B0%E5%AF%B9%E4%B8%8D%E5%90%8C%E5%AD%90%E4%B8%BB%E9%A2%98%E7%9A%84%E4%B8%8D%E5%90%8C%E6%B6%88%E8%B4%B9%E9%80%BB%E8%BE%91%EF%BC%8C%E5%AE%9E%E7%8E%B0%E6%9B%B4%E5%A5%BD%E7%9A%84%E6%89%A9%E5%B1%95%E6%80%A7%E3%80%82%0A%0A%3E%20Topic%E6%98%AF%E6%B6%88%E6%81%AF%E7%9A%84%E4%B8%80%E7%BA%A7%E5%88%86%E7%B1%BB%EF%BC%8CTag%E6%98%AF%E6%B6%88%E6%81%AF%E7%9A%84%E4%BA%8C%E7%BA%A7%E5%88%86%E7%B1%BB%E3%80%82%0A%0A%60%60%60%0ATopic%EF%BC%9A%E8%B4%A7%E7%89%A9%0Atag%3D%E4%B8%8A%E6%B5%B7%0Atag%3D%E6%B1%9F%E8%8B%8F%0Atag%3D%E6%B5%99%E6%B1%9F%0A-------%20%E6%B6%88%E8%B4%B9%E8%80%85%20-----%0Atopic%3D%E8%B4%A7%E7%89%A9%20tag%20%3D%20%E4%B8%8A%E6%B5%B7%0Atopic%3D%E8%B4%A7%E7%89%A9%20tag%20%3D%20%E4%B8%8A%E6%B5%B7%7C%E6%B5%99%E6%B1%9F%0Atopic%3D%E8%B4%A7%E7%89%A9%20tag%20%3D%20*%0A%60%60%60%0A%0A%23%23%23%23%20%E9%98%9F%E5%88%97%EF%BC%88Queue%EF%BC%89%0A%3E%20%E5%AD%98%E5%82%A8%E6%B6%88%E6%81%AF%E7%9A%84%E7%89%A9%E7%90%86%E5%AE%9E%E4%BD%93%E3%80%82%0A%3E%20%E4%B8%80%E4%B8%AATopic%E4%B8%AD%E5%8F%AF%E4%BB%A5%E5%8C%85%E5%90%AB%E5%A4%9A%E4%B8%AAQueue%EF%BC%8C%E6%AF%8F%E4%B8%AAQueue%E4%B8%AD%E5%AD%98%E6%94%BE%E7%9A%84%E5%B0%B1%E6%98%AF%E8%AF%A5Topic%E7%9A%84%E6%B6%88%E6%81%AF%E3%80%82%0A%3E%20%E4%B8%80%E4%B8%AATopic%E7%9A%84Queue%E4%B9%9F%E8%A2%AB%E7%A7%B0%E4%B8%BA%E4%B8%80%E4%B8%AATopic%E4%B8%AD%E6%B6%88%E6%81%AF%E7%9A%84%E5%88%86%E5%8C%BA%EF%BC%88Partition%EF%BC%89%E3%80%82%0A%3E%20%E4%B8%80%E4%B8%AATopic%E7%9A%84Queue%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%E5%8F%AA%E8%83%BD%E8%A2%AB%60%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E6%B6%88%E8%B4%B9%60%E3%80%82%0A%3E%20%E4%B8%80%E4%B8%AAQueue%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%60%E4%B8%8D%E5%85%81%E8%AE%B8%E8%A2%AB%E5%90%8C%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%84%E4%B8%AD%E7%9A%84%E5%A4%9A%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E5%90%8C%E6%97%B6%E6%B6%88%E8%B4%B9%60%E3%80%82%0A%0A!%5B7df0aefc72a6ebeee16dec51d14a4e00.png%5D(en-resource%3A%2F%2Fdatabase%2F893%3A1)%0A%0A!%5Bffb3a4577fb1c6973ede56b70e3fb753.png%5D(en-resource%3A%2F%2Fdatabase%2F898%3A1)%0A%0A%0A%23%23%23%23%20%E5%88%86%E7%89%87%EF%BC%88Sharding%EF%BC%89%0A%3E%20%E5%9C%A8%E5%AD%A6%E4%B9%A0%E5%8F%82%E8%80%83%E5%85%B6%E5%AE%83%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99%E6%97%B6%EF%BC%8C%E8%BF%98%E4%BC%9A%E7%9C%8B%E5%88%B0%E4%B8%80%E4%B8%AA%E6%A6%82%E5%BF%B5%EF%BC%9A%E5%88%86%E7%89%87%EF%BC%88Sharding%EF%BC%89%E3%80%82%E5%88%86%E7%89%87%E4%B8%8D%E5%90%8C%E4%BA%8E%E5%88%86%E5%8C%BA%E3%80%82%E5%9C%A8RocketMQ%E4%B8%AD%EF%BC%8C%E5%88%86%E7%89%87%E6%8C%87%E7%9A%84%E6%98%AF%E5%AD%98%E6%94%BE%E7%9B%B8%E5%BA%94Topic%E7%9A%84Broker%E3%80%82%E6%AF%8F%E4%B8%AA%E5%88%86%E7%89%87%E4%B8%AD%E4%BC%9A%E5%88%9B%E5%BB%BA%E5%87%BA%E7%9B%B8%E5%BA%94%E6%95%B0%E9%87%8F%E7%9A%84%E5%88%86%E5%8C%BA%EF%BC%8C%E5%8D%B3Queue%EF%BC%8C%E6%AF%8F%E4%B8%AAQueue%E7%9A%84%E5%A4%A7%E5%B0%8F%E9%83%BD%E6%98%AF%E7%9B%B8%E5%90%8C%E7%9A%84%E3%80%82%0A%3E%20%0A!%5Bf577e6ebc52e2ca8dc72bb1ab841a420.png%5D(en-resource%3A%2F%2Fdatabase%2F896%3A1)%0A%0A%23%23%23%23%20%E6%B6%88%E6%81%AF%E6%A0%87%E8%AF%86%EF%BC%88MessageId%2FKey%EF%BC%89%0A%3E%20RocketMQ%E4%B8%AD%E6%AF%8F%E4%B8%AA%E6%B6%88%E6%81%AF%E6%8B%A5%E6%9C%89%E5%94%AF%E4%B8%80%E7%9A%84MessageId%EF%BC%8C%E4%B8%94%E5%8F%AF%E4%BB%A5%E6%90%BA%E5%B8%A6%E5%85%B7%E6%9C%89%60%E4%B8%9A%E5%8A%A1%E6%A0%87%E8%AF%86%E7%9A%84Key%60%EF%BC%8C%E4%BB%A5%E6%96%B9%E4%BE%BF%E5%AF%B9%E6%B6%88%E6%81%AF%E7%9A%84%E6%9F%A5%E8%AF%A2%E3%80%82%20%0A%3E%20%E4%B8%8D%E8%BF%87%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%EF%BC%8CMessageId%E6%9C%89%E4%B8%A4%E4%B8%AA%EF%BC%9A%E5%9C%A8%E7%94%9F%E4%BA%A7%E8%80%85send()%E6%B6%88%E6%81%AF%E6%97%B6%E4%BC%9A%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AAMessageId%EF%BC%88%60msgId%60)%0A%3E%20%E5%BD%93%E6%B6%88%E6%81%AF%E5%88%B0%E8%BE%BEBroker%E5%90%8E%EF%BC%8CBroker%E4%B9%9F%E4%BC%9A%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AAMessageId(%60offsetMsgId%60)%E3%80%82%0A%3E%20msgId%E3%80%81offsetMsgId%E4%B8%8Ekey%E9%83%BD%E7%A7%B0%E4%B8%BA%E6%B6%88%E6%81%AF%E6%A0%87%E8%AF%86%E3%80%82%0A%0A%3E%20msgId%EF%BC%9A%0A%3E%0A%3E%20-%20%E7%94%B1producer%E7%AB%AF%E7%94%9F%E6%88%90%EF%BC%8C%E5%85%B6%E7%94%9F%E6%88%90%E8%A7%84%E5%88%99%E4%B8%BA%EF%BC%9AproducerIp%20%2B%20%E8%BF%9B%E7%A8%8Bpid%20%2B%20MessageClientIDSetter%E7%B1%BB%E7%9A%84ClassLoader%E7%9A%84hashCode%20%2B%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4%20%2B%20AutomicInteger%E8%87%AA%E5%A2%9E%E8%AE%A1%E6%95%B0%E5%99%A8%0A%0A%3EoffsetMsgId%EF%BC%9A%0A%3E%0A%3E-%20%E7%94%B1broker%E7%AB%AF%E7%94%9F%E6%88%90%EF%BC%8C%E5%85%B6%E7%94%9F%E6%88%90%E8%A7%84%E5%88%99%E4%B8%BA%EF%BC%9AbrokerIp%20%2B%20%E7%89%A9%E7%90%86%E5%88%86%E5%8C%BA%E7%9A%84offset%EF%BC%88Queue%E4%B8%AD%E7%9A%84%E5%81%8F%E7%A7%BB%E9%87%8F%EF%BC%89%0A%0A%3E%20key%EF%BC%9A%E7%94%B1%E7%94%A8%E6%88%B7%E6%8C%87%E5%AE%9A%E7%9A%84%E4%B8%9A%E5%8A%A1%E7%9B%B8%E5%85%B3%E7%9A%84%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86%0A%0A%23%23%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%0A%0A!%5B1642f85f520b503aa1748048d067f952.png%5D(en-resource%3A%2F%2Fdatabase%2F891%3A1)%0A%0A%3E%20NamerServer%20%E5%AD%98%E6%94%BEbroker%E7%9A%84IP%E5%9C%B0%E5%9D%80%E4%BF%A1%E6%81%AF%0A%3E%20broker%20%E9%83%A8%E7%BD%B2%E7%9D%80rocketmq%E7%9A%84%E6%9C%BA%E5%99%A8%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AAbroker%0A%0A1.%20%E7%94%9F%E4%BA%A7%E8%80%85%EF%BC%8C%E6%B6%88%E6%81%AF%E8%80%85%EF%BC%8Cbroker%E5%90%AF%E5%8A%A8%E4%B9%8B%E5%90%8E%E9%83%BD%E4%BC%9A%E6%8A%8A%E5%90%84%E8%87%AA%E7%9A%84IP%E4%BF%A1%E6%81%AF%E6%B3%A8%E5%86%8C%E5%88%B0NamerServer%E9%87%8C%E9%9D%A2%EF%BC%8C%E5%B9%B6%E4%B8%8ENameServer%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%2C%20%0A%0A%20%20%20%3E%20Producer%E5%90%AF%E5%8A%A8%E6%97%B6%E5%85%88%E8%B7%9FNameServer%E9%9B%86%E7%BE%A4%E4%B8%AD%E7%9A%84%E5%85%B6%E4%B8%AD%E4%B8%80%E5%8F%B0%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%B9%B6%E4%BB%8ENameServer%E4%B8%AD%E8%8E%B7%E5%8F%96%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%8D%B3%E5%BD%93%E5%89%8D%E5%8F%91%E9%80%81%E7%9A%84Topic%E6%B6%88%E6%81%AF%E7%9A%84Queue%E4%B8%8EBroker%E7%9A%84%E5%9C%B0%E5%9D%80%EF%BC%88IP%2BPort%EF%BC%89%E7%9A%84%E6%98%A0%E5%B0%84%E5%85%B3%E7%B3%BB%E3%80%82%E7%84%B6%E5%90%8E%E6%A0%B9%E6%8D%AE%E7%AE%97%E6%B3%95%E7%AD%96%E7%95%A5%E4%BB%8E%E9%98%9F%E9%80%89%E6%8B%A9%E4%B8%80%E4%B8%AAQueue%EF%BC%8C%E4%B8%8E%E9%98%9F%E5%88%97%E6%89%80%E5%9C%A8%E7%9A%84Broker%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%E4%BB%8E%E8%80%8C%E5%90%91Broker%E5%8F%91%E6%B6%88%E6%81%AF%E3%80%82%E5%BD%93%E7%84%B6%EF%BC%8C%E5%9C%A8%E8%8E%B7%E5%8F%96%E5%88%B0%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E5%90%8E%EF%BC%8CProducer%E4%BC%9A%E9%A6%96%E5%85%88%E5%B0%86%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E7%BC%93%E5%AD%98%E5%88%B0%E6%9C%AC%E5%9C%B0%EF%BC%8C%E5%86%8D%E6%AF%8F%2030%20%E7%A7%92%E4%BB%8ENameServer%E6%9B%B4%E6%96%B0%E4%B8%80%E6%AC%A1%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E3%80%82%0A%0A%20%20%20%3E%20Consumer%E8%B7%9FProducer%E7%B1%BB%E4%BC%BC%EF%BC%8C%E8%B7%9F%E5%85%B6%E4%B8%AD%E4%B8%80%E5%8F%B0NameServer%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E8%8E%B7%E5%8F%96%E5%85%B6%E6%89%80%E8%AE%A2%E9%98%85Topic%E7%9A%84%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%EF%BC%8C%E7%84%B6%E5%90%8E%E6%A0%B9%E6%8D%AE%E7%AE%97%E6%B3%95%E7%AD%96%E7%95%A5%E4%BB%8E%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%88%B0%E5%85%B6%E6%89%80%E8%A6%81%E6%B6%88%E8%B4%B9%E7%9A%84Queue%EF%BC%8C%E7%84%B6%E5%90%8E%E7%9B%B4%E6%8E%A5%E8%B7%9FBroker%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%BC%80%E5%A7%8B%E6%B6%88%E8%B4%B9%E5%85%B6%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%E3%80%82Consumer%E5%9C%A8%E8%8E%B7%E5%8F%96%E5%88%B0%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E5%90%8E%EF%BC%8C%E5%90%8C%E6%A0%B7%E4%B9%9F%E4%BC%9A%E6%AF%8F%2030%20%E7%A7%92%E4%BB%8ENameServer%E6%9B%B4%E6%96%B0%E4%B8%80%E6%AC%A1%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%E3%80%82%E4%B8%8D%E8%BF%87%E4%B8%8D%E5%90%8C%E4%BA%8EProducer%E7%9A%84%E6%98%AF%EF%BC%8CConsumer%E8%BF%98%E4%BC%9A%E5%90%91Broker%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%EF%BC%8C%E4%BB%A5%E7%A1%AE%E4%BF%9DBroker%E7%9A%84%E5%AD%98%E6%B4%BB%E7%8A%B6%E6%80%81%E3%80%82%0A%0A%20%20%20%3E%20Broker%E5%90%AF%E5%8A%A8%E5%90%8E%E4%BC%9A%E4%B8%8E%E9%85%8D%E7%BD%AE%E4%B8%AD%E7%9A%84%E6%AF%8F%E4%B8%80%E4%B8%AANameServer%E4%BF%9D%E6%8C%81%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%B9%B6%E6%AF%8F30%E7%A7%92%E5%90%91NameServer%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E5%8C%85%E3%80%82%0A%0A2.%20NamerServer%E9%99%A4%E4%BA%86%E8%AE%B0%E5%BD%95IP%E4%BF%A1%E6%81%AF%E5%A4%96%E8%BF%98%E8%B4%9F%E8%B4%A3%E9%80%9A%E8%BF%87%E5%BF%83%E8%B7%B3%E7%9B%91%E5%90%AC%E4%B8%8E%E5%90%84%E7%BB%84%E4%BB%B6%E4%B9%8B%E9%97%B4%E7%9A%84%E8%BF%9E%E9%80%9A%E6%80%A7%0A%0A3.%20%E5%BD%93%E7%94%9F%E4%BA%A7%E8%80%85%E7%94%9F%E4%BA%A7%E6%B6%88%E6%81%AF%E6%97%B6%EF%BC%8C%E5%85%88%E9%80%9A%E8%BF%87NamerServer%E6%89%BE%E5%88%B0%E5%8F%AF%E7%94%A8%E7%9A%84borker%EF%BC%8C%E7%84%B6%E5%90%8E%E6%8A%8A%E6%B6%88%E6%81%AF%E5%AD%98%E5%85%A5%E5%8F%AF%E7%94%A8boker%E9%87%8C%E9%9D%A2%E5%AF%B9%E5%BA%94topic%E9%87%8C%E9%9D%A2%0A%0A4.%20%E6%B6%88%E6%81%AF%E8%80%85%E9%80%9A%E8%BF%87%E6%8B%89%E5%8F%96%E6%A8%A1%E5%BC%8F%E6%88%96%E7%9B%91%E5%90%AC%E6%A8%A1%E5%BC%8F%E6%9D%A5%E8%8E%B7%E5%8F%96boker%E9%87%8C%E9%9D%A2%E5%AF%B9%E5%BA%94topic%E9%87%8C%E9%9D%A2%E7%9A%84%E6%B6%88%E6%81%AF%0A%0A%3E%20%E6%B6%88%E6%81%AF%E8%80%85%E5%A6%82%E4%BD%95%E7%9F%A5%E9%81%93MQ%E9%87%8C%E9%9D%A2%E6%9C%89%E6%B6%88%E6%81%AF%0A-%20%E6%8B%89%E5%8F%96%E6%A8%A1%E5%BC%8F%0A%E6%B6%88%E8%B4%B9%E8%80%85%E5%90%AF%E5%8A%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%EF%BC%8C%E6%AF%8F%E9%9A%94%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%E5%8E%BB%E6%9F%A5%E8%AF%A2MQ%E9%87%8C%E9%9D%A2%E6%98%AF%E5%90%A6%E6%9C%89%E8%87%AA%E5%B7%B1%E9%9C%80%E8%A6%81%E7%9A%84%E6%B6%88%E6%81%AF%0A-%20%E7%9B%91%E5%90%AC%E6%A8%A1%E5%BC%8F%0A%E6%B6%88%E8%B4%B9%E8%80%85%E4%B8%8EMQ%E5%BB%BA%E7%AB%8B%E4%B8%80%E4%B8%AA%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E4%B8%80%E6%97%A6MQ%E9%87%8C%E9%9D%A2%E6%9C%89%E6%B6%88%E6%81%AF%EF%BC%8Crocketmq%E5%B0%B1%E4%BC%9A%E6%8A%8A%E6%B6%88%E6%81%AF%E6%8E%A8%E9%80%81%E7%BB%99%E8%AE%A2%E9%98%85%E4%BA%86%E6%AD%A4%E6%B6%88%E6%81%AF%E7%9A%84%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A%0A%0A%23%23%20%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA%E7%90%86%E8%AE%BA%0A%0A%23%23%23%23%20%E6%95%B0%E6%8D%AE%E5%A4%8D%E5%88%B6%E4%B8%8E%E5%88%B7%E7%9B%98%E7%AD%96%E7%95%A5%0A%0A!%5B4a725625965ea8eb2462b63fce31ac3a.png%5D(en-resource%3A%2F%2Fdatabase%2F892%3A1)%0A%0A%0A%23%23%23%23%23%20%E5%A4%8D%E5%88%B6%E7%AD%96%E7%95%A5%0A%0A%3E%20**%E5%A4%8D%E5%88%B6%E7%AD%96%E7%95%A5%E6%98%AFBroker%E7%9A%84Master%E4%B8%8ESlave%E9%97%B4%E7%9A%84%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5%E6%96%B9%E5%BC%8F**%E3%80%82%0A%3E%0A%3E%20%E5%88%86%E4%B8%BA%E5%90%8C%E6%AD%A5%E5%A4%8D%E5%88%B6%E4%B8%8E%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%EF%BC%9A%0A%3E%0A%3E%20-%20%60%E5%90%8C%E6%AD%A5%E5%A4%8D%E5%88%B6%60%EF%BC%9A%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5master%E5%90%8E%EF%BC%8Cmaster%E4%BC%9A%E7%AD%89%E5%BE%85slave%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE%E6%88%90%E5%8A%9F%E5%90%8E%E6%89%8D%E5%90%91producer%E8%BF%94%E5%9B%9E%E6%88%90%E5%8A%9FACK%0A%3E%0A%3E%20-%20%60%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%60%EF%BC%9A%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5master%E5%90%8E%EF%BC%8Cmaster%E7%AB%8B%E5%8D%B3%E5%90%91producer%E8%BF%94%E5%9B%9E%E6%88%90%E5%8A%9FACK%EF%BC%8C%E6%97%A0%E9%9C%80%E7%AD%89%E5%BE%85slave%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE%E6%88%90%E5%8A%9F%0A%0A%3E%20%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%E7%AD%96%E7%95%A5%E4%BC%9A%E9%99%8D%E4%BD%8E%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%86%99%E5%85%A5%E5%BB%B6%E8%BF%9F%EF%BC%8CRT%E5%8F%98%E5%B0%8F%EF%BC%8C%E6%8F%90%E9%AB%98%E4%BA%86%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%90%9E%E5%90%90%E9%87%8F%0A%0A%23%23%23%23%23%20%E5%88%B7%E7%9B%98%E7%AD%96%E7%95%A5%0A%0A%3E%20%E5%88%B7%E7%9B%98%E7%AD%96%E7%95%A5%E6%8C%87%E7%9A%84%E6%98%AFbroker%E4%B8%AD%E6%B6%88%E6%81%AF%E7%9A%84%60%E8%90%BD%E7%9B%98%60%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%8D%B3%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E5%88%B0broker%E5%86%85%E5%AD%98%E5%90%8E%E6%B6%88%E6%81%AF%E6%8C%81%E4%B9%85%E5%8C%96%E5%88%B0%E7%A3%81%E7%9B%98%E7%9A%84%E6%96%B9%E5%BC%8F%E3%80%82%0A%3E%0A%3E%20%E5%88%86%E4%B8%BA%E5%90%8C%E6%AD%A5%E5%88%B7%E7%9B%98%E4%B8%8E%E5%BC%82%E6%AD%A5%E5%88%B7%E7%9B%98.%0A%3E%0A%3E%20-%20%60%E5%90%8C%E6%AD%A5%E5%88%B7%E7%9B%98%60%EF%BC%9A%E5%BD%93%E6%B6%88%E6%81%AF%E6%8C%81%E4%B9%85%E5%8C%96%E5%88%B0broker%E7%9A%84%E7%A3%81%E7%9B%98%E5%90%8E%E6%89%8D%E7%AE%97%E6%98%AF%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5%E6%88%90%E5%8A%9F%E3%80%82%0A%3E%20-%20%60%E5%BC%82%E6%AD%A5%E5%88%B7%E7%9B%98%60%EF%BC%9A%E5%BD%93%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5%E5%88%B0broker%E7%9A%84%E5%86%85%E5%AD%98%E5%90%8E%E5%8D%B3%E8%A1%A8%E7%A4%BA%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5%E6%88%90%E5%8A%9F%EF%BC%8C%E6%97%A0%E9%9C%80%E7%AD%89%E5%BE%85%E6%B6%88%E6%81%AF%E6%8C%81%E4%B9%85%E5%8C%96%E5%88%B0%E7%A3%81%E7%9B%98%E3%80%82%0A%0A%3E%201%20.%20%20%E5%BC%82%E6%AD%A5%E5%88%B7%E7%9B%98%E7%AD%96%E7%95%A5%E4%BC%9A%E9%99%8D%E4%BD%8E%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%86%99%E5%85%A5%E5%BB%B6%E8%BF%9F%EF%BC%8CRT%E5%8F%98%E5%B0%8F%EF%BC%8C%E6%8F%90%E9%AB%98%E4%BA%86%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%90%9E%E5%90%90%E9%87%8F%0A%3E%202%20.%20%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5%E5%88%B0Broker%E7%9A%84%E5%86%85%E5%AD%98%EF%BC%8C%E4%B8%80%E8%88%AC%E6%98%AF%E5%86%99%E5%85%A5%E5%88%B0%E4%BA%86%60PageCache%60%0A%3E%203%20.%20%E5%AF%B9%E4%BA%8E%E5%BC%82%E6%AD%A5%20%E5%88%B7%E7%9B%98%E7%AD%96%E7%95%A5%EF%BC%8C%E6%B6%88%E6%81%AF%E4%BC%9A%E5%86%99%E5%85%A5%E5%88%B0%60PageCache%60%E5%90%8E%E7%AB%8B%E5%8D%B3%E8%BF%94%E5%9B%9E%E6%88%90%E5%8A%9FACK%E3%80%82%E4%BD%86%E5%B9%B6%E4%B8%8D%E4%BC%9A%E7%AB%8B%E5%8D%B3%E5%81%9A%E8%90%BD%E7%9B%98%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%80%8C%E6%98%AF%E5%BD%93PageCache%E5%88%B0%E8%BE%BE%E4%B8%80%E5%AE%9A%E9%87%8F%E6%97%B6%E4%BC%9A%E8%87%AA%E5%8A%A8%E8%BF%9B%E8%A1%8C%E8%90%BD%E7%9B%98%E3%80%82%0A%0A%23%23%23%23%20Broker%E9%9B%86%E7%BE%A4%E6%A8%A1%E5%BC%8F%0A%0A%23%23%23%23%23%20%E5%8D%95Master%0A%0A%3E%20%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AAbroker%EF%BC%88%E5%85%B6%E6%9C%AC%E8%B4%A8%E4%B8%8A%E5%B0%B1%E4%B8%8D%E8%83%BD%E7%A7%B0%E4%B8%BA%E9%9B%86%E7%BE%A4%EF%BC%89%E3%80%82%0A%3E%0A%3E%20%E8%BF%99%E7%A7%8D%E6%96%B9%E5%BC%8F%E4%B9%9F%E5%8F%AA%E8%83%BD%E6%98%AF%E5%9C%A8%E6%B5%8B%E8%AF%95%E6%97%B6%E4%BD%BF%E7%94%A8%EF%BC%8C%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%8B%E4%B8%8D%E8%83%BD%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%AD%98%E5%9C%A8%E5%8D%95%E7%82%B9%E9%97%AE%E9%A2%98%E3%80%82%0A%0A%23%23%23%23%23%20%E5%A4%9AMaster%0A%0A%3E%20broker%E9%9B%86%E7%BE%A4%E4%BB%85%E7%94%B1%E5%A4%9A%E4%B8%AAmaster%E6%9E%84%E6%88%90%EF%BC%8C%E4%B8%8D%E5%AD%98%E5%9C%A8Slave%E3%80%82%E5%90%8C%E4%B8%80Topic%E7%9A%84%E5%90%84%E4%B8%AAQueue%E4%BC%9A%E5%B9%B3%E5%9D%87%E5%88%86%E5%B8%83%E5%9C%A8%E5%90%84%E4%B8%AAmaster%E8%8A%82%E7%82%B9%E4%B8%8A%E3%80%82%0A%3E%0A%3E%20-%20%E4%BC%98%E7%82%B9%EF%BC%9A%E9%85%8D%E7%BD%AE%E7%AE%80%E5%8D%95%EF%BC%8C%E5%8D%95%E4%B8%AAMaster%E5%AE%95%E6%9C%BA%E6%88%96%E9%87%8D%E5%90%AF%E7%BB%B4%E6%8A%A4%E5%AF%B9%E5%BA%94%E7%94%A8%E6%97%A0%E5%BD%B1%E5%93%8D%EF%BC%8C%E5%9C%A8%E7%A3%81%E7%9B%98%E9%85%8D%E7%BD%AE%E4%B8%BARAID10%E6%97%B6%EF%BC%8C%E5%8D%B3%E4%BD%BF%E6%9C%BA%E5%99%A8%E5%AE%95%E6%9C%BA%E4%B8%8D%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E7%94%B1%E4%BA%8ERAID10%E7%A3%81%E7%9B%98%E9%9D%9E%E5%B8%B8%E5%8F%AF%E9%9D%A0%EF%BC%8C%E6%B6%88%E6%81%AF%E4%B9%9F%E4%B8%8D%E4%BC%9A%E4%B8%A2%EF%BC%88%E5%BC%82%E6%AD%A5%E5%88%B7%E7%9B%98%E4%B8%A2%E5%A4%B1%E5%B0%91%E9%87%8F%E6%B6%88%E6%81%AF%EF%BC%8C%E5%90%8C%E6%AD%A5%E5%88%B7%E7%9B%98%E4%B8%80%E6%9D%A1%E4%B8%8D%E4%B8%A2%EF%BC%89%EF%BC%8C%E6%80%A7%E8%83%BD%E6%9C%80%E9%AB%98%EF%BC%9B%0A%3E%20-%20%E7%BC%BA%E7%82%B9%EF%BC%9A%E5%8D%95%E5%8F%B0%E6%9C%BA%E5%99%A8%E5%AE%95%E6%9C%BA%E6%9C%9F%E9%97%B4%EF%BC%8C%E8%BF%99%E5%8F%B0%E6%9C%BA%E5%99%A8%E4%B8%8A%E6%9C%AA%E8%A2%AB%E6%B6%88%E8%B4%B9%E7%9A%84%E6%B6%88%E6%81%AF%E5%9C%A8%E6%9C%BA%E5%99%A8%E6%81%A2%E5%A4%8D%E4%B9%8B%E5%89%8D%E4%B8%8D%E5%8F%AF%E8%AE%A2%E9%98%85%EF%BC%88%E4%B8%8D%E5%8F%AF%E6%B6%88%E8%B4%B9%EF%BC%89%EF%BC%8C%E6%B6%88%E6%81%AF%E5%AE%9E%E6%97%B6%E6%80%A7%E4%BC%9A%E5%8F%97%E5%88%B0%E5%BD%B1%E5%93%8D%E3%80%82%0A%0A%3E%20%E4%BB%A5%E4%B8%8A%E4%BC%98%E7%82%B9%E7%9A%84%E5%89%8D%E6%8F%90%E6%98%AF%EF%BC%8C%E8%BF%99%E4%BA%9BMaster%E9%83%BD%E9%85%8D%E7%BD%AE%E4%BA%86RAID10%E7%A3%81%E7%9B%98%E9%98%B5%E5%88%97%E3%80%82%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E9%85%8D%E7%BD%AE%EF%BC%8C%E4%B8%80%E6%97%A6%E5%87%BA%E7%8E%B0%E6%9F%90Master%E5%AE%95%E6%9C%BA%EF%BC%8C%E5%88%99%E4%BC%9A%E5%8F%91%E7%94%9F%E5%A4%A7%E9%87%8F%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%0A%0A%23%23%23%23%23%20%E5%A4%9AMaster%E5%A4%9ASlave%E6%A8%A1%E5%BC%8F-%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%0A%0A%3E%20broker%E9%9B%86%E7%BE%A4%E7%94%B1%E5%A4%9A%E4%B8%AAmaster%E6%9E%84%E6%88%90%EF%BC%8C%E6%AF%8F%E4%B8%AAmaster%E5%8F%88%E9%85%8D%E7%BD%AE%E4%BA%86%E5%A4%9A%E4%B8%AAslave%EF%BC%88%E5%9C%A8%E9%85%8D%E7%BD%AE%E4%BA%86RAID%E7%A3%81%E7%9B%98%E9%98%B5%E5%88%97%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E4%B8%80%E4%B8%AAmaster%E4%B8%80%E8%88%AC%E9%85%8D%E7%BD%AE%E4%B8%80%E4%B8%AAslave%E5%8D%B3%E5%8F%AF%EF%BC%89%E3%80%82%0A%3E%0A%3E%20master%E4%B8%8Eslave%E7%9A%84%E5%85%B3%E7%B3%BB%E6%98%AF%E4%B8%BB%E5%A4%87%E5%85%B3%E7%B3%BB%EF%BC%8C%E5%8D%B3master%E8%B4%9F%E8%B4%A3%E5%A4%84%E7%90%86%E6%B6%88%E6%81%AF%E7%9A%84%E8%AF%BB%E5%86%99%E8%AF%B7%E6%B1%82%EF%BC%8C%E8%80%8Cslave%E4%BB%85%E8%B4%9F%E8%B4%A3%E6%B6%88%E6%81%AF%E7%9A%84%E5%A4%87%E4%BB%BD%E4%B8%8Emaster%E5%AE%95%E6%9C%BA%E5%90%8E%E7%9A%84%E8%A7%92%E8%89%B2%E5%88%87%E6%8D%A2%E3%80%82%0A%0A%3E%20%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%E5%8D%B3%E5%89%8D%E9%9D%A2%E6%89%80%E8%AE%B2%E7%9A%84%60%E5%A4%8D%E5%88%B6%E7%AD%96%E7%95%A5%60%E4%B8%AD%E7%9A%84%60%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%E7%AD%96%E7%95%A5%60%EF%BC%8C%E5%8D%B3%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5master%E6%88%90%E5%8A%9F%E5%90%8E%EF%BC%8Cmaster%E7%AB%8B%E5%8D%B3%E5%90%91producer%E8%BF%94%E5%9B%9E%E6%88%90%E5%8A%9FACK%EF%BC%8C%E6%97%A0%E9%9C%80%E7%AD%89%E5%BE%85slave%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE%E6%88%90%E5%8A%9F%E3%80%82%0A%0A%3E%20%E8%AF%A5%E6%A8%A1%E5%BC%8F%E7%9A%84%E6%9C%80%E5%A4%A7%E7%89%B9%E7%82%B9%E4%B9%8B%E4%B8%80%E6%98%AF%EF%BC%8C%E5%BD%93master%E5%AE%95%E6%9C%BA%E5%90%8Eslave%E8%83%BD%E5%A4%9F%60%E8%87%AA%E5%8A%A8%E5%88%87%E6%8D%A2%60%E4%B8%BAmaster%E3%80%82%E4%B8%8D%E8%BF%87%E7%94%B1%E4%BA%8Eslave%E4%BB%8Emaster%E7%9A%84%E5%90%8C%E6%AD%A5%E5%85%B7%E6%9C%89%E7%9F%AD%E6%9A%82%E7%9A%84%E5%BB%B6%E8%BF%9F%60(%E6%AF%AB%E7%A7%92%E7%BA%A7)%60%EF%BC%8C%E6%89%80%E4%BB%A5%E5%BD%93master%E5%AE%95%E6%9C%BA%E5%90%8E%EF%BC%8C%E8%BF%99%E7%A7%8D%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%E6%96%B9%E5%BC%8F%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%AD%98%E5%9C%A8%E5%B0%91%E9%87%8F%E6%B6%88%E6%81%AF%E7%9A%84%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98%E3%80%82%0A%0A%3E%20Slave%E4%BB%8EMaster%E5%90%8C%E6%AD%A5%E7%9A%84%E5%BB%B6%E8%BF%9F%E8%B6%8A%E7%9F%AD%EF%BC%8C%E5%85%B6%E5%8F%AF%E8%83%BD%E4%B8%A2%E5%A4%B1%E7%9A%84%E6%B6%88%E6%81%AF%E5%B0%B1%E8%B6%8A%E5%B0%91%0A%3E%0A%3E%20%E5%AF%B9%E4%BA%8EMaster%E7%9A%84RAID%E7%A3%81%E7%9B%98%E9%98%B5%E5%88%97%EF%BC%8C%E8%8B%A5%E4%BD%BF%E7%94%A8%E7%9A%84%E4%B9%9F%E6%98%AF%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%E7%AD%96%E7%95%A5%EF%BC%8C%E5%90%8C%E6%A0%B7%E4%B9%9F%E5%AD%98%E5%9C%A8%E5%BB%B6%E8%BF%9F%E9%97%AE%E9%A2%98%EF%BC%8C%E5%90%8C%E6%A0%B7%E4%B9%9F%E5%8F%AF%E8%83%BD%E4%BC%9A%E4%B8%A2%E5%A4%B1%E6%B6%88%E6%81%AF%E3%80%82%E4%BD%86RAID%E9%98%B5%E5%88%97%E7%9A%84%E7%A7%98%E8%AF%80%E6%98%AF%60(%E5%BE%AE%E7%A7%92%E7%BA%A7)%60%E7%9A%84%EF%BC%88%E5%9B%A0%E4%B8%BA%E6%98%AF%E7%94%B1%E7%A1%AC%E7%9B%98%E6%94%AF%E6%8C%81%E7%9A%84%EF%BC%89%EF%BC%8C%E6%89%80%E4%BB%A5%E5%85%B6%E4%B8%A2%E5%A4%B1%E7%9A%84%E6%95%B0%E6%8D%AE%E9%87%8F%E4%BC%9A%E6%9B%B4%E5%B0%91%E3%80%82%0A%0A%23%23%23%23%23%20%E5%A4%9AMaster%E5%A4%9ASlave%E6%A8%A1%E5%BC%8F-%E5%90%8C%E6%AD%A5%E5%8F%8C%E5%86%99%0A%0A%3E%20%E8%AF%A5%E6%A8%A1%E5%BC%8F%E6%98%AF%60%E5%A4%9AMaster%E5%A4%9ASlave%E6%A8%A1%E5%BC%8F%60%E7%9A%84%60%E5%90%8C%E6%AD%A5%E5%A4%8D%E5%88%B6%60%E5%AE%9E%E7%8E%B0%E3%80%82%E6%89%80%E8%B0%93%60%E5%90%8C%E6%AD%A5%E5%8F%8C%E5%86%99%60%EF%BC%8C%E6%8C%87%E7%9A%84%E6%98%AF%E6%B6%88%E6%81%AF%E5%86%99%E5%85%A5master%E6%88%90%E5%8A%9F%E5%90%8E%EF%BC%8Cmaster%E4%BC%9A%E7%AD%89%E5%BE%85slave%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE%E6%88%90%E5%8A%9F%E5%90%8E%E6%89%8D%E5%90%91producer%E8%BF%94%E5%9B%9E%E6%88%90%E5%8A%9FACK%EF%BC%8C%E5%8D%B3master%E4%B8%8Eslave%E9%83%BD%E8%A6%81%E5%86%99%E5%85%A5%E6%88%90%E5%8A%9F%E5%90%8E%E6%89%8D%E4%BC%9A%E8%BF%94%E5%9B%9E%E6%88%90%E5%8A%9FACK%EF%BC%8C%E4%B9%9F%E5%8D%B3%60%E5%8F%8C%E5%86%99%60%E3%80%82%0A%3E%0A%3E%20%E8%AF%A5%E6%A8%A1%E5%BC%8F%E4%B8%8E%60%E5%BC%82%E6%AD%A5%E5%A4%8D%E5%88%B6%E6%A8%A1%E5%BC%8F%E7%9B%B8%E6%AF%94%60%EF%BC%8C%E4%BC%98%E7%82%B9%E6%98%AF%E6%B6%88%E6%81%AF%E7%9A%84%E5%AE%89%E5%85%A8%E6%80%A7%E6%9B%B4%E9%AB%98%EF%BC%8C%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%E4%BD%86%E5%8D%95%E4%B8%AA%E6%B6%88%E6%81%AF%E7%9A%84RT%E7%95%A5%E9%AB%98%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%AF%BC%E8%87%B4%E6%80%A7%E8%83%BD%E8%A6%81%E7%95%A5%E4%BD%8E%EF%BC%88%E5%A4%A7%E7%BA%A6%E4%BD%8E10%25%EF%BC%89%E3%80%82%0A%3E%0A%3E%20%E8%AF%A5%E6%A8%A1%E5%BC%8F%E5%AD%98%E5%9C%A8%E4%B8%80%E4%B8%AA%E5%A4%A7%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%9A%E5%AF%B9%E4%BA%8E%E7%9B%AE%E5%89%8D%E7%9A%84%60%E7%89%88%E6%9C%AC4.9.0%60%EF%BC%8CMaster%E5%AE%95%E6%9C%BA%E5%90%8E%EF%BC%8CSlave%60%E4%B8%8D%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%88%87%E6%8D%A2%60%E5%88%B0Master%E3%80%82%0A%0A%60%E9%83%A8%E7%BD%B2%E9%85%8D%E7%BD%AE%3A%E5%90%8C%E6%AD%A5%E5%8F%8C%E5%86%99-%E5%BC%82%E6%AD%A5%E5%88%B7%E7%9B%98%60%0A%0A%23%23%20%E7%94%9F%E4%BA%A7-%E6%B6%88%E8%B4%B9%E6%A8%A1%E5%BC%8F%0A%0A%23%23%23%23%20%E5%8D%95%E7%94%9F%E4%BA%A7%E8%80%85-%E5%A4%9A%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%BC%8F%0A%0A%23%23%23%23%23%20%E5%90%8C%E4%B8%80%E7%BB%84%E5%A4%9A%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A%3E%20%E5%88%9B%E5%BB%BA%E7%94%9F%E4%BA%A7%E8%80%85%0A%0A%60%60%60java%0Apackage%20com.chris.rocketmq%3B%0A%0Aimport%20org.apache.rocketmq.client.exception.MQBrokerException%3B%0Aimport%20org.apache.rocketmq.client.exception.MQClientException%3B%0Aimport%20org.apache.rocketmq.client.producer.DefaultMQProducer%3B%0Aimport%20org.apache.rocketmq.client.producer.SendResult%3B%0Aimport%20org.apache.rocketmq.common.message.Message%3B%0Aimport%20org.apache.rocketmq.remoting.common.RemotingHelper%3B%0Aimport%20org.apache.rocketmq.remoting.exception.RemotingException%3B%0A%0Aimport%20java.io.UnsupportedEncodingException%3B%0A%0A%2F**%0A%20*%20%40author%20Chris%0A%20*%20%40date%202022-03-24%206%3A35%20PM%0A%20*%2F%0Apublic%20class%20Producer%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20MQClientException%2C%20UnsupportedEncodingException%2C%20RemotingException%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20InterruptedException%2C%20MQBrokerException%20%7B%0A%20%20%20%20%20%20%20%20DefaultMQProducer%20producer%20%3D%20new%20DefaultMQProducer(%22rocketmq-producer-group-001%22)%3B%0A%20%20%20%20%20%20%20%20producer.setNamesrvAddr(%22master%3A9876%22)%3B%0A%0A%20%20%20%20%20%20%20%20producer.start()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22producer%20has%20started!%22)%3B%0A%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FCreate%20a%20message%20instance%2C%20specifying%20topic%2C%20tag%20and%20message%20body.%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%20msg%20%3D%20new%20Message(%22topic-001%22%20%2F*%20Topic%20*%2F%2C%20%22TagA%22%20%2F*%20Tag%20*%2F%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%22Hello%20Chris%20%22%20%2B%20i).getBytes(RemotingHelper.DEFAULT_CHARSET)%20%2F*%20Message%20body%20*%2F)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FCall%20send%20message%20to%20deliver%20message%20to%20one%20of%20brokers.%0A%20%20%20%20%20%20%20%20%20%20%20%20SendResult%20sendResult%20%3D%20producer.send(msg)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.printf(%22%25s%25n%22%2C%20sendResult)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%2F%2FShut%20down%20once%20the%20producer%20instance%20is%20not%20longer%20in%20use.%0A%20%20%20%20%20%20%20%20producer.shutdown()%3B%0A%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%3E%20%E5%88%9B%E5%BB%BA%E6%B6%88%E6%81%AF%E8%80%85%EF%BC%8C%20%E5%9C%A8%E6%B6%88%E8%B4%B9%E7%BB%84%60rocketmq-consumer-group-001%60%20%E5%90%AF%E5%8A%A8%E4%B8%A4%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E5%AE%9E%E4%BE%8B%0A%3E%0A%3E%20%60%20consumer.registerMessageListener%60%0A%3E%0A%3E%20%60new%20MessageListenerConcurrently%60%0A%0A%60%60%60java%0Apackage%20com.chris.rocketmq%3B%0A%0Aimport%20org.apache.rocketmq.client.consumer.DefaultMQPushConsumer%3B%0Aimport%20org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus%3B%0Aimport%20org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently%3B%0Aimport%20org.apache.rocketmq.client.exception.MQClientException%3B%0Aimport%20org.apache.rocketmq.common.message.MessageExt%3B%0A%0A%2F**%0A%20*%20%40author%20Chris%0A%20*%20%40date%202022-03-24%206%3A40%20PM%0A%20*%2F%0Apublic%20class%20Consumer%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20MQClientException%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20Instantiate%20with%20specified%20consumer%20group%20name.%0A%20%20%20%20%20%20%20%20DefaultMQPushConsumer%20consumer%20%3D%20new%20DefaultMQPushConsumer(%22rocketmq-consumer-group-001%22)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Specify%20name%20server%20addresses.%0A%20%20%20%20%20%20%20%20consumer.setNamesrvAddr(%22master%3A9876%22)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Subscribe%20one%20more%20more%20topics%20to%20consume.%0A%20%20%20%20%20%20%20%20consumer.subscribe(%22topic-001%22%2C%20%22*%22)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20Register%20callback%20to%20execute%20on%20arrival%20of%20messages%20fetched%20from%20brokers.%0A%20%20%20%20%20%20%20%20consumer.registerMessageListener((MessageListenerConcurrently)%20(msgs%2C%20context)%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(MessageExt%20msg%20%3A%20msgs)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.printf(%22%25s%20Receive%20New%20Messages%3A%20%25s%20%25n%22%2C%20Thread.currentThread().getName()%2C%20msg)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20msg_str%20%3D%20new%20String(msg.getBody())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(msg_str)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20ConsumeConcurrentlyStatus.CONSUME_SUCCESS%3B%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2FLaunch%20the%20consumer%20instance.%0A%20%20%20%20%20%20%20%20consumer.start()%3B%0A%0A%20%20%20%20%20%20%20%20System.out.printf(%22Consumer%20Started.%25n%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A!%5Bb6fb31976532b2dcd0061dfdbadd5d37.png%5D(en-resource%3A%2F%2Fdatabase%2F895%3A1)%0A%0A%3E%20%E5%85%88%E5%90%AF%E5%8A%A8conusmer1%0A%3E%0A%3E%20%E5%86%8D%E5%90%AF%E5%8A%A8consumer2%0A%3E%0A%3E%20%E6%9C%80%E5%90%8E%E5%90%AF%E5%8A%A8%E7%94%9F%E4%BA%A7%E8%80%85%E7%94%9F%E4%BA%A710%E6%9D%A1%E6%B6%88%E6%81%AF%0A%0A%3E%20conumser1%E6%B6%88%E8%B4%B9%E7%BB%93%E6%9E%9C%0A%0A%60%60%60%0AConsumer%20Started.%0AConsumeMessageThread_1%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D198%2C%20queueOffset%3D25%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648123970750%2C%20bornHost%3D%2F192.168.101.1%3A61608%2C%20storeTimestamp%3D1648123374262%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036768%2C%20commitLogOffset%3D223080%2C%20bodyCRC%3D35715212%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D26%2C%20CONSUME_START_TIME%3D1648123971053%2C%20UNIQ_KEY%3D7F000001445418B4AAC27AC8A8BD0000%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2067%2C%20104%2C%20114%2C%20105%2C%20115%2C%2032%2C%2048%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20Chris%200%0AConsumeMessageThread_2%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D198%2C%20queueOffset%3D26%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648123971007%2C%20bornHost%3D%2F192.168.101.1%3A61608%2C%20storeTimestamp%3D1648123374472%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036A80%2C%20commitLogOffset%3D223872%2C%20bodyCRC%3D88947861%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D27%2C%20CONSUME_START_TIME%3D1648123971083%2C%20UNIQ_KEY%3D7F000001445418B4AAC27AC8A9BE0004%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2067%2C%20104%2C%20114%2C%20105%2C%20115%2C%2032%2C%2052%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20Chris%204%0AConsumeMessageThread_3%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D198%2C%20queueOffset%3D27%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648123971138%2C%20bornHost%3D%2F192.168.101.1%3A61608%2C%20storeTimestamp%3D1648123374560%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036D98%2C%20commitLogOffset%3D224664%2C%20bodyCRC%3D217804990%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D28%2C%20CONSUME_START_TIME%3D1648123971162%2C%20UNIQ_KEY%3D7F000001445418B4AAC27AC8AA420008%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2067%2C%20104%2C%20114%2C%20105%2C%20115%2C%2032%2C%2056%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20Chris%208%0A%60%60%60%0A%0A%0A%0A%3E%20conumser2%E6%B6%88%E8%B4%B9%E7%BB%93%E6%9E%9C%0A%0A%60%60%60%0AConsumeMessageThread_1%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D1%2C%20storeSize%3D198%2C%20queueOffset%3D25%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648123970904%2C%20bornHost%3D%2F192.168.101.1%3A61608%2C%20storeTimestamp%3D1648123374326%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F00000000000368F4%2C%20commitLogOffset%3D223476%2C%20bodyCRC%3D1814993312%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D26%2C%20CONSUME_START_TIME%3D1648123971089%2C%20UNIQ_KEY%3D7F000001445418B4AAC27AC8A9580002%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2067%2C%20104%2C%20114%2C%20105%2C%20115%2C%2032%2C%2050%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20Chris%202%0AConsumeMessageThread_2%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D0%2C%20storeSize%3D198%2C%20queueOffset%3D25%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648123970885%2C%20bornHost%3D%2F192.168.101.1%3A61608%2C%20storeTimestamp%3D1648123374306%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F000000000003682E%2C%20commitLogOffset%3D223278%2C%20bodyCRC%3D1965541402%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D26%2C%20CONSUME_START_TIME%3D1648123971117%2C%20UNIQ_KEY%3D7F000001445418B4AAC27AC8A9450001%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2067%2C%20104%2C%20114%2C%20105%2C%20115%2C%2032%2C%2049%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20Chris%201%0AConsumeMessageThread_3%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D1%2C%20storeSize%3D198%2C%20queueOffset%3D26%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648123971100%2C%20bornHost%3D%2F192.168.101.1%3A61608%2C%20storeTimestamp%3D1648123374527%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036C0C%2C%20commitLogOffset%3D224268%2C%20bodyCRC%3D1799577017%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D27%2C%20CONSUME_START_TIME%3D1648123971140%2C%20UNIQ_KEY%3D7F000001445418B4AAC27AC8AA1C0006%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2067%2C%20104%2C%20114%2C%20105%2C%20115%2C%2032%2C%2054%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20Chris%206%0AConsumeMessageThread_4%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D0%2C%20storeSize%3D198%2C%20queueOffset%3D26%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648123971080%2C%20bornHost%3D%2F192.168.101.1%3A61608%2C%20storeTimestamp%3D1648123374507%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036B46%2C%20commitLogOffset%3D224070%2C%20bodyCRC%3D1917455363%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D27%2C%20CONSUME_START_TIME%3D1648123971148%2C%20UNIQ_KEY%3D7F000001445418B4AAC27AC8AA080005%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2067%2C%20104%2C%20114%2C%20105%2C%20115%2C%2032%2C%2053%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20Chris%205%0AConsumeMessageThread_5%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D0%2C%20storeSize%3D198%2C%20queueOffset%3D27%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648123971148%2C%20bornHost%3D%2F192.168.101.1%3A61608%2C%20storeTimestamp%3D1648123374575%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036E5E%2C%20commitLogOffset%3D224862%2C%20bodyCRC%3D2080129064%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D28%2C%20CONSUME_START_TIME%3D1648123971169%2C%20UNIQ_KEY%3D7F000001445418B4AAC27AC8AA4C0009%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2067%2C%20104%2C%20114%2C%20105%2C%20115%2C%2032%2C%2057%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20Chris%209%0A%60%60%60%0A%0A%23%23%23%23%23%20%E4%B8%8D%E5%90%8C%E7%BB%84%E5%A4%9A%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A%3E%20%E5%88%9B%E5%BB%BA%E6%B6%88%E6%81%AF%E8%80%85%0A%3E%0A%3E%20%E5%9C%A8%E6%B6%88%E8%B4%B9%E7%BB%84%60rocketmq-consumer-group-001%60%20%E5%90%AF%E5%8A%A8%E4%B8%A4%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E5%AE%9E%E4%BE%8B%20%60consumer1%60%E5%92%8C%60consumer2%60%0A%3E%0A%3E%20%E7%84%B6%E5%90%8E%E5%86%8D%E6%8A%8A%E6%B6%88%E8%B4%B9%E7%BB%84%E6%94%B9%E4%B8%BA%60rocketmq-consumer-group-002%60%20%E5%90%AF%E5%8A%A8%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E5%AE%9E%E4%BE%8B%20%60consuemer3%60%0A%0A%60%60%60java%0A%2F%2F%20Instantiate%20with%20specified%20consumer%20group%20name.%0ADefaultMQPushConsumer%20consumer1%20%3D%20new%20DefaultMQPushConsumer(%22rocketmq-consumer-group-001%22)%3B%0ADefaultMQPushConsumer%20consumer2%20%3D%20new%20DefaultMQPushConsumer(%22rocketmq-consumer-group-001%22)%3B%0A%60%60%60%0A%0A%60%60%60java%0A%2F%2F%20Instantiate%20with%20specified%20consumer%20group%20name.%0ADefaultMQPushConsumer%20consumer3%20%3D%20new%20DefaultMQPushConsumer(%22rocketmq-consumer-group-002%22)%3B%0A%60%60%60%0A%0A%3E%20%E5%90%AF%E5%8A%A8%E7%94%9F%E4%BA%A7%E8%80%85%EF%BC%8C%E5%B9%B6%E5%90%91%60topic-001%60%E4%B8%AD%E7%94%9F%E4%BA%A710%E6%9D%A1%E6%B6%88%E6%81%AF%0A%0A%3E%20consumer1%E6%B6%88%E8%B4%B9%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%0A%60%60%60%0AConsumer%20Started.%0AConsumeMessageThread_1%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D0%2C%20storeSize%3D197%2C%20queueOffset%3D28%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413362%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813214%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F00000000000370AE%2C%20commitLogOffset%3D225454%2C%20bodyCRC%3D267036076%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D29%2C%20CONSUME_START_TIME%3D1648125413415%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEABF20002%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2050%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%202%0AConsumeMessageThread_2%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D1%2C%20storeSize%3D197%2C%20queueOffset%3D27%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413408%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813248%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000037173%2C%20commitLogOffset%3D225651%2C%20bodyCRC%3D2028836154%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D28%2C%20CONSUME_START_TIME%3D1648125413417%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC200003%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2051%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%203%0AConsumeMessageThread_3%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D0%2C%20storeSize%3D197%2C%20queueOffset%3D29%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413438%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813282%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F00000000000373C2%2C%20commitLogOffset%3D226242%2C%20bodyCRC%3D143090101%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D30%2C%20CONSUME_START_TIME%3D1648125413468%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC3E0006%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2054%5D%2C%20transactionId%3D'null'%7D%5D%20%0AConsumeMessageThread_4%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D1%2C%20storeSize%3D197%2C%20queueOffset%3D28%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413447%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813294%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000037487%2C%20commitLogOffset%3D226439%2C%20bodyCRC%3D2139115811%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D29%2C%20CONSUME_START_TIME%3D1648125413468%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC470007%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2055%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%207%0AHello%20John%206%0A%60%60%60%0A%0A%3E%20consumer2%E6%B6%88%E8%B4%B9%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%0A%60%60%60%0AConsumer%20Started.%0AConsumeMessageThread_1%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D2%2C%20storeSize%3D197%2C%20queueOffset%3D27%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413323%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813167%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036F24%2C%20commitLogOffset%3D225060%2C%20bodyCRC%3D1642382464%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D28%2C%20CONSUME_START_TIME%3D1648125413347%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEABCA0000%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2048%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%200%0AConsumeMessageThread_2%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D197%2C%20queueOffset%3D28%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413333%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813186%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036FE9%2C%20commitLogOffset%3D225257%2C%20bodyCRC%3D384037910%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D29%2C%20CONSUME_START_TIME%3D1648125413378%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEABD50001%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2049%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%201%0AConsumeMessageThread_3%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D2%2C%20storeSize%3D197%2C%20queueOffset%3D28%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413413%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813256%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000037238%2C%20commitLogOffset%3D225848%2C%20bodyCRC%3D1720254617%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D29%2C%20CONSUME_START_TIME%3D1648125413440%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC250004%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2052%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%204%0AConsumeMessageThread_4%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D197%2C%20queueOffset%3D29%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413431%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813272%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F00000000000372FD%2C%20commitLogOffset%3D226045%2C%20bodyCRC%3D294531087%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D30%2C%20CONSUME_START_TIME%3D1648125413447%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC370005%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2053%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%205%0AConsumeMessageThread_5%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D2%2C%20storeSize%3D197%2C%20queueOffset%3D29%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413459%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813305%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F000000000003754C%2C%20commitLogOffset%3D226636%2C%20bodyCRC%3D1866419378%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D30%2C%20CONSUME_START_TIME%3D1648125413477%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC530008%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2056%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%208%0AConsumeMessageThread_6%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D197%2C%20queueOffset%3D30%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413470%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813310%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000037611%2C%20commitLogOffset%3D226833%2C%20bodyCRC%3D406354980%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D31%2C%20CONSUME_START_TIME%3D1648125413494%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC5E0009%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2057%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%209%0A%60%60%60%0A%0A%3E%20consumer3%E6%B6%88%E8%B4%B9%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%0A%60%60%60%0AHello%20John%200%0AConsumeMessageThread_13%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D197%2C%20queueOffset%3D28%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413333%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813186%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000036FE9%2C%20commitLogOffset%3D225257%2C%20bodyCRC%3D384037910%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D29%2C%20CONSUME_START_TIME%3D1648125413366%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEABD50001%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2049%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%201%0AConsumeMessageThread_9%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D0%2C%20storeSize%3D197%2C%20queueOffset%3D28%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413362%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813214%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F00000000000370AE%2C%20commitLogOffset%3D225454%2C%20bodyCRC%3D267036076%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D29%2C%20CONSUME_START_TIME%3D1648125413407%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEABF20002%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2050%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%202%0AConsumeMessageThread_5%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D1%2C%20storeSize%3D197%2C%20queueOffset%3D27%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413408%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813248%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000037173%2C%20commitLogOffset%3D225651%2C%20bodyCRC%3D2028836154%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D28%2C%20CONSUME_START_TIME%3D1648125413419%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC200003%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2051%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%203%0AConsumeMessageThread_10%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D2%2C%20storeSize%3D197%2C%20queueOffset%3D28%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413413%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813256%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000037238%2C%20commitLogOffset%3D225848%2C%20bodyCRC%3D1720254617%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D29%2C%20CONSUME_START_TIME%3D1648125413435%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC250004%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2052%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%204%0AConsumeMessageThread_8%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D197%2C%20queueOffset%3D29%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413431%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813272%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F00000000000372FD%2C%20commitLogOffset%3D226045%2C%20bodyCRC%3D294531087%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D30%2C%20CONSUME_START_TIME%3D1648125413443%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC370005%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2053%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%205%0AConsumeMessageThread_7%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D0%2C%20storeSize%3D197%2C%20queueOffset%3D29%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413438%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813282%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F00000000000373C2%2C%20commitLogOffset%3D226242%2C%20bodyCRC%3D143090101%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D30%2C%20CONSUME_START_TIME%3D1648125413460%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC3E0006%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2054%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%206%0AConsumeMessageThread_6%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D1%2C%20storeSize%3D197%2C%20queueOffset%3D28%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413447%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813294%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000037487%2C%20commitLogOffset%3D226439%2C%20bodyCRC%3D2139115811%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D29%2C%20CONSUME_START_TIME%3D1648125413464%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC470007%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2055%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%207%0AConsumeMessageThread_19%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D2%2C%20storeSize%3D197%2C%20queueOffset%3D29%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413459%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813305%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F000000000003754C%2C%20commitLogOffset%3D226636%2C%20bodyCRC%3D1866419378%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D30%2C%20CONSUME_START_TIME%3D1648125413474%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC530008%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2056%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%208%0AConsumeMessageThread_1%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D197%2C%20queueOffset%3D30%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648125413470%2C%20bornHost%3D%2F192.168.101.1%3A61991%2C%20storeTimestamp%3D1648124813310%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000037611%2C%20commitLogOffset%3D226833%2C%20bodyCRC%3D406354980%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-001'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D31%2C%20CONSUME_START_TIME%3D1648125413492%2C%20UNIQ_KEY%3D7F000001535C18B4AAC27ADEAC5E0009%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2074%2C%20111%2C%20104%2C%20110%2C%2032%2C%2057%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20John%209%0A%60%60%60%0A%0A%3E%20%E7%BB%93%E8%AE%BA%0A%3E%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BAconsumer1%E5%92%8Cconsumer2%E5%88%86%E6%91%8A%60topic-001%60%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%8C%20%E5%8D%B3%E4%B8%A4%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E6%89%80%E6%B6%88%E8%B4%B9%E7%9A%84%E6%B6%88%E6%81%AF%E6%80%BB%E5%92%8C%E4%B8%BA10%E6%9D%A1%0A%3E%0A%3E%20%E8%80%8Cconsumer3%E5%B0%86%60topic-001%60%E4%B8%AD%E7%9A%84%E6%B6%88%E6%81%AF%E5%85%A8%E9%83%A8%E6%B6%88%E6%81%AF%E6%8E%89%0A%0A%23%23%23%23%23%20%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%BC%8F%0A%0A%3E%20%0A%3E%0A%3E%20%60%E9%9B%86%E7%BE%A4%E6%A8%A1%E5%BC%8F%60%E5%92%8C%20%60%E5%B9%BF%E6%92%AD%E6%A8%A1%E5%BC%8F%60%0A%3E%0A%3E%20%E9%BB%98%E8%AE%A4%E9%9B%86%E7%BE%A4%E6%A8%A1%E5%BC%8F%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E6%94%B9%E4%B8%BA%E5%B9%BF%E6%92%AD%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%8D%B3%E4%BD%BF%E6%98%AF%E5%90%8C%E4%B8%80%E7%BB%84%E7%9A%84%E4%B8%8D%E5%90%8C%E6%B6%88%E8%B4%B9%E8%80%85%E4%B9%9F%E4%BC%9A%E6%B6%88%E8%B4%B9%E5%88%B0%E7%94%9F%E4%BA%A7%E8%80%85%E7%94%9F%E4%BA%A7%E7%9A%84%E5%85%A8%E9%83%A8%E6%B6%88%E6%81%AF%0A%0A%60%60%60java%0A%0Aconsumer.setMessageModel(MessageModel.BROADCASTING)%3B%0A%0A%2F**%0A%20*%20broadcast%0A%20*%2F%0ABROADCASTING(%22BROADCASTING%22)%2C%0A%2F**%0A%20*%20clustering%0A%20*%2F%0ACLUSTERING(%22CLUSTERING%22)%3B%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%90%8C%E6%AD%A5%E6%B6%88%E6%81%AF%0A%0A%3E%20%60SendResult%20sendResult%20%3D%20producer.send(msg)%3B%60%0A%0A%60%60%60java%0A%2F%2F%E5%8F%91%E9%80%81%E5%90%8C%E6%AD%A5%E6%B6%88%E6%81%AF%0ASendResult%20sendResult%20%3D%20producer.send(msg)%3B%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%BC%82%E6%AD%A5%E6%B6%88%E6%81%AF%0A%0A%3E%20%60producer.send(msg%2C%20new%20SendCallback()%20%60%0A%0A%60%60%60java%0Apackage%20com.chris.rocketmq%3B%0A%0Aimport%20org.apache.rocketmq.client.exception.MQClientException%3B%0Aimport%20org.apache.rocketmq.client.producer.DefaultMQProducer%3B%0Aimport%20org.apache.rocketmq.client.producer.SendCallback%3B%0Aimport%20org.apache.rocketmq.client.producer.SendResult%3B%0Aimport%20org.apache.rocketmq.common.message.Message%3B%0Aimport%20org.apache.rocketmq.remoting.common.RemotingHelper%3B%0Aimport%20org.apache.rocketmq.remoting.exception.RemotingException%3B%0A%0Aimport%20java.io.UnsupportedEncodingException%3B%0Aimport%20java.util.concurrent.CountDownLatch%3B%0A%0A%2F**%0A%20*%20%40author%20Chris%0A%20*%20%40date%202022-03-24%206%3A35%20PM%0A%20*%2F%0Apublic%20class%20ProducerAsync%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20MQClientException%2C%20UnsupportedEncodingException%2C%20RemotingException%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20DefaultMQProducer%20producer%20%3D%20new%20DefaultMQProducer(%22rocketmq-producer-group-001%22)%3B%0A%20%20%20%20%20%20%20%20producer.setNamesrvAddr(%22master%3A9876%22)%3B%0A%0A%20%20%20%20%20%20%20%20producer.start()%3B%0A%20%20%20%20%20%20%20%20producer.setRetryTimesWhenSendAsyncFailed(0)%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(%22producer%20has%20started!%22)%3B%0A%0A%20%20%20%20%20%20%20%20int%20messageCount%20%3D%2010%3B%0A%20%20%20%20%20%20%20%20CountDownLatch%20countDownLatch%20%3D%20new%20CountDownLatch(messageCount)%3B%0A%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20messageCount%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FCreate%20a%20message%20instance%2C%20specifying%20topic%2C%20tag%20and%20message%20body.%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%20msg%20%3D%20new%20Message(%22topic-003%22%20%2F*%20Topic%20*%2F%2C%20%22TagA%22%20%2F*%20Tag%20*%2F%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%22Hello%20Async%20%22%20%2B%20i).getBytes(RemotingHelper.DEFAULT_CHARSET)%20%2F*%20Message%20body%20*%2F)%3B%0A%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FSend%20Messages%20Asynchronously%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FAsynchronous%20transmission%20is%20generally%20used%20in%20response%20time%20sensitive%20business%20scenarios.%0A%20%20%20%20%20%20%20%20%20%20%20%20producer.send(msg%2C%20new%20SendCallback()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20public%20void%20onSuccess(SendResult%20sendResult)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20countDownLatch.countDown()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.printf(%22%25s%25n%22%2C%20sendResult)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20public%20void%20onException(Throwable%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20countDownLatch.countDown()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22exception%3A%22%20%2B%20e.getMessage())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20countDownLatch.await()%3B%0A%20%20%20%20%20%20%20%20producer.shutdown()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%8D%95%E5%90%91%E6%B6%88%E6%81%AF%0A%0A%3E%20%E4%B8%8D%E9%9C%80%E8%A6%81%E6%9C%89%E5%9B%9E%E6%89%A7%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%8C%E6%AF%94%E5%A6%82%E8%AF%B4%E6%97%A5%E5%BF%97%E7%B1%BB%E6%B6%88%E6%81%AF%0A%3E%0A%3E%20%60%20producer.sendOneway(msg)%3B%60%0A%0A%60%60%60java%0Apublic%20static%20void%20main(String%5B%5D%20args)%20throws%20MQClientException%2C%20UnsupportedEncodingException%2C%20RemotingException%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20DefaultMQProducer%20producer%20%3D%20new%20DefaultMQProducer(%22rocketmq-producer-group-001%22)%3B%0A%20%20%20%20%20%20%20%20producer.setNamesrvAddr(%22master%3A9876%22)%3B%0A%0A%20%20%20%20%20%20%20%20producer.start()%3B%0A%20%20%20%20%20%20%20%20producer.setRetryTimesWhenSendAsyncFailed(0)%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(%22producer%20has%20started!%22)%3B%0A%0A%20%20%20%20%20%20%20%20int%20messageCount%20%3D%2010%3B%0A%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20messageCount%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FCreate%20a%20message%20instance%2C%20specifying%20topic%2C%20tag%20and%20message%20body.%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%20msg%20%3D%20new%20Message(%22topic-005%22%20%2F*%20Topic%20*%2F%2C%20%22TagA%22%20%2F*%20Tag%20*%2F%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%22Hello%20OneWay%20%22%20%2B%20i).getBytes(RemotingHelper.DEFAULT_CHARSET)%20%2F*%20Message%20body%20*%2F)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20producer.sendOneway(msg)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20producer.shutdown()%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%23%23%23%23%20%E5%BB%B6%E6%97%B6%E6%B6%88%E6%81%AF%0A%0A%3E%20%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E6%97%B6%E5%B9%B6%E4%B8%8D%E7%9B%B4%E6%8E%A5%E5%8F%91%E9%80%81%E5%88%B0%E6%B6%88%E6%81%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E8%80%8C%E6%98%AF%E6%A0%B9%E6%8D%AE%E8%AE%BE%E5%AE%9A%E7%9A%84%E6%97%B6%E9%97%B4%E5%88%B0%E8%BE%BE%EF%BC%8C%E8%B5%B7%E5%88%B0%E5%BB%B6%E6%97%B6%E5%88%B0%E8%BE%BE%E7%9A%84%E7%BC%93%E5%86%B2%E4%BD%9C%E7%94%A8%0A%3E%0A%3E%20%60%20msg.setDelayTimeLevel(3)%3B%60%0A%3E%0A%3E%20%60messageDelayLevel%3D1s%205s%2010s%2030s%201m%202m%203m%204m%205m%206m%207m%208m%209m%2010m%2020m%2030m%201h%202h%20%60%0A%0A%3E%20producer%0A%0A%60%60%60java%0Apublic%20static%20void%20main(String%5B%5D%20args)%20throws%20MQClientException%2C%20UnsupportedEncodingException%2C%20RemotingException%2C%0A%20%20%20%20%20%20%20%20InterruptedException%2C%20MQBrokerException%20%7B%0A%20%20%20%20DefaultMQProducer%20producer%20%3D%20new%20DefaultMQProducer(%22rocketmq-producer-group-001%22)%3B%0A%20%20%20%20producer.setNamesrvAddr(%22master%3A9876%22)%3B%0A%0A%20%20%20%20producer.start()%3B%0A%20%20%20%20producer.setRetryTimesWhenSendAsyncFailed(0)%3B%0A%0A%20%20%20%20System.out.println(%22producer%20has%20started!%22)%3B%0A%0A%20%20%20%20int%20messageCount%20%3D%2010%3B%0A%0A%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20messageCount%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2FCreate%20a%20message%20instance%2C%20specifying%20topic%2C%20tag%20and%20message%20body.%0A%20%20%20%20%20%20%20%20Message%20msg%20%3D%20new%20Message(%22topic-005%22%20%2F*%20Topic%20*%2F%2C%20%22TagA%22%20%2F*%20Tag%20*%2F%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%22Hello%20DealyTime%20%22%20%2B%20i).getBytes(RemotingHelper.DEFAULT_CHARSET)%20%2F*%20Message%20body%20*%2F)%3B%0A%0A%20%20%20%20%20%20%20%20msg.setDelayTimeLevel(3)%3B%0A%20%20%20%20%20%20%20%20SendResult%20sendResult%20%3D%20producer.send(msg)%3B%0A%20%20%20%20%20%20%20%20System.out.printf(%22%25s%25n%22%2C%20sendResult)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20producer.shutdown()%3B%0A%7D%0A%60%60%60%0A%0A%3E%20consumer%0A%60%60%60java%0Apublic%20static%20void%20main(String%5B%5D%20args)%20throws%20MQClientException%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20Instantiate%20with%20specified%20consumer%20group%20name.%0A%20%20%20%20%20%20%20%20DefaultMQPushConsumer%20consumer%20%3D%20new%20DefaultMQPushConsumer(%22rocketmq-consumer-group-003%22)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Specify%20name%20server%20addresses.%0A%20%20%20%20%20%20%20%20consumer.setNamesrvAddr(%22master%3A9876%22)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Subscribe%20one%20more%20more%20topics%20to%20consume.%0A%20%20%20%20%20%20%20%20consumer.subscribe(%22topic-005%22%2C%20%22*%22)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%E9%BB%98%E8%AE%A4%E6%97%A9%E9%9B%86%E7%BE%A4%E6%A8%A1%E5%BC%8F%2C%E5%A6%82%E6%9E%9C%E6%94%B9%E4%B8%BA%E5%B9%BF%E6%92%AD%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%90%8C%E7%BB%84%E7%9A%84%E4%B8%8D%E5%90%8C%E6%B6%88%E8%B4%B9%E5%B0%86%E4%BC%9A%E6%B6%88%E8%B4%B9%E5%88%B0%E7%94%9F%E4%BA%A7%E8%80%85%E7%94%9F%E4%BA%A7%E7%9A%84%E5%85%A8%E9%83%A8%E6%B6%88%E6%81%AF%0A%20%20%20%20%20%20%20%20consumer.setMessageModel(MessageModel.BROADCASTING)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20Register%20callback%20to%20execute%20on%20arrival%20of%20messages%20fetched%20from%20brokers.%0A%20%20%20%20%20%20%20%20consumer.registerMessageListener((MessageListenerConcurrently)%20(msgs%2C%20context)%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(MessageExt%20msg%20%3A%20msgs)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.printf(%22%25s%20Receive%20New%20Messages%3A%20%25s%20%25n%22%2C%20Thread.currentThread().getName()%2C%20msg)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20msg_str%20%3D%20new%20String(msg.getBody())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Print%20approximate%20delay%20time%20period%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22Receive%20message%5BmsgId%3D%22%20%2B%20msg.getMsgId()%20%2B%20%22%2Cmsg_str%3D%5D%20%22%20%2B%20msg_str%20%2B%20%22%2C%22%20%2B%20(System.currentTimeMillis()%20-%20msg.getStoreTimestamp())%20%2B%20%22ms%20later%22)%3B%0A%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20ConsumeConcurrentlyStatus.CONSUME_SUCCESS%3B%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2FLaunch%20the%20consumer%20instance.%0A%20%20%20%20%20%20%20%20consumer.start()%3B%0A%0A%20%20%20%20%20%20%20%20System.out.printf(%22Consumer%20Started.%25n%22)%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%23%23%23%23%20%E6%89%B9%E9%87%8F%E6%B6%88%E6%81%AF%0A%0A%3E%20%E4%B8%80%E6%AC%A1%E5%8F%91%E9%80%81%E5%A4%9A%E6%9D%A1%E6%B6%88%E6%81%AF%EF%BC%8C%E8%8A%82%E7%BA%A6%E7%BD%91%E7%BB%9C%E5%BC%80%E9%94%80%0A%0A%3E%20%E6%B3%A8%E6%84%8F%EF%BC%9A%0A%3E%0A%3E%201.%20%E8%BF%99%E4%BA%9B%E6%89%B9%E9%87%8F%E6%B6%88%E6%81%AF%E5%BA%94%E8%AF%A5%E6%9C%89%E7%9B%B8%E5%90%8C%E7%9A%84topic%0A%3E%0A%3E%202.%20%E7%9B%B8%E5%90%8C%E7%9A%84waitStoreMsgOK%0A%3E%0A%3E%203.%20%E4%B8%8D%E8%83%BD%E6%98%AF%E5%BB%B6%E6%97%B6%E6%B6%88%E6%81%AF%0A%3E%0A%3E%204.%20%E6%B6%88%E6%81%AF%E5%86%85%E5%AE%B9%E6%80%BB%E9%95%BF%E5%BA%A6%E4%B8%8D%E8%B6%85%E8%BF%874M%0A%3E%0A%3E%20%20%20%20%0A%3E%0A%3E%20%20%20%20%60Besides%2C%20the%20total%20size%20of%20the%20messages%20in%20one%20batch%20should%20be%20no%20more%20than%201MiB.%60%0A%3E%0A%3E%20%20%20%20%E6%B6%88%E6%81%AF%E5%86%85%E5%AE%B9%E6%80%BB%E9%95%BF%E5%BA%A6%E5%8C%85%E5%90%AB%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%3E%0A%3E%20%20%20%20-%20topic%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%AD%97%E8%8A%82%E6%95%B0%0A%3E%0A%3E%20%20%20%20-%20body%E5%AD%97%E8%8A%82%E6%95%B0%E7%BB%84%E9%95%BF%E5%BA%A6%0A%3E%0A%3E%20%20%20%20-%20%E6%B6%88%E6%81%AF%E8%BF%BD%E5%8A%A0%E5%B1%9E%E6%80%A7%EF%BC%88key%E4%B8%8Evalue%E5%AF%B9%E5%BA%94%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%AD%97%E8%8A%82%E6%95%B0%EF%BC%89%0A%3E%0A%3E%20%20%20%20-%20%E6%97%A5%E5%BF%97%EF%BC%88%E5%9B%BA%E5%AE%9A20%E5%AD%97%E8%8A%82%EF%BC%89%0A%0A%60%60%60java%0AList%3CMessage%3E%20msgList%20%3D%20CollUtil.newArrayList()%3B%0Afor%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%2F%2FCreate%20a%20message%20instance%2C%20specifying%20topic%2C%20tag%20and%20message%20body.%0A%20%20%20%20Message%20msg%20%3D%20new%20Message(%22topic-006%22%20%2F*%20Topic%20*%2F%2C%20%22TagA%22%20%2F*%20Tag%20*%2F%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%22Hello%20Message%20in%20Batch%20%22%20%2B%20i).getBytes(RemotingHelper.DEFAULT_CHARSET)%20%2F*%20Message%20body%20*%2F)%3B%0A%20%20%20%20msgList.add(msg)%3B%0A%7D%0A%2F%2F%E6%89%B9%E9%87%8F%E5%8F%91%E9%80%81%E5%90%8C%E6%AD%A5%E6%B6%88%E6%81%AF%0ASendResult%20sendResult%20%3D%20producer.send(msgList)%3B%0A%60%60%60%0A%0A%60%60%60%0ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F00000143AC18B4AAC27F0FDDBA0000%2C7F00000143AC18B4AAC27F0FDDBA0001%2C7F00000143AC18B4AAC27F0FDDBA0002%2C7F00000143AC18B4AAC27F0FDDBA0003%2C7F00000143AC18B4AAC27F0FDDBA0004%2C7F00000143AC18B4AAC27F0FDDBB0005%2C7F00000143AC18B4AAC27F0FDDBB0006%2C7F00000143AC18B4AAC27F0FDDBB0007%2C7F00000143AC18B4AAC27F0FDDBB0008%2C7F00000143AC18B4AAC27F0FDDBB0009%2C%20offsetMsgId%3DC0A8657F00002A9F000000000003F28C%2CC0A8657F00002A9F000000000003F367%2CC0A8657F00002A9F000000000003F442%2CC0A8657F00002A9F000000000003F51D%2CC0A8657F00002A9F000000000003F5F8%2CC0A8657F00002A9F000000000003F6D3%2CC0A8657F00002A9F000000000003F7AE%2CC0A8657F00002A9F000000000003F889%2CC0A8657F00002A9F000000000003F964%2CC0A8657F00002A9F000000000003FA3F%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-006%2C%20brokerName%3Dmaster%2C%20queueId%3D0%5D%2C%20queueOffset%3D0%5D%0A%60%60%60%0A%0A%0A%0A%23%23%20%E6%B6%88%E6%81%AF%E7%9A%84%E8%BF%87%E6%BB%A4%0A%0A%23%23%23%23%20%E6%8C%89tag%E8%BF%9B%E8%A1%8C%E6%B6%88%E6%81%AF%E8%BF%87%E6%BB%A4%0A%0A%3E%20%E7%94%9F%E4%BA%A7%E8%80%85%E5%88%86%E5%88%AB%E7%94%9F%E4%BA%A7%20tag%E7%B1%BB%E5%9E%8B%E4%B8%BA%20customer%20%E5%92%8C%20vip%E7%9A%84%E6%B6%88%E6%81%AF%0A%0A%60%60%60java%0A%20for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%2F%2FCreate%20a%20message%20instance%2C%20specifying%20topic%2C%20tag%20and%20message%20body.%0A%20%20%20%20%20Message%20msg%20%3D%20new%20Message(%22topic-006%22%20%2F*%20Topic%20*%2F%2C%20%22customer%22%20%2F*%20Tag%20*%2F%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%22Hello%20vip%20%22%20%2B%20i).getBytes(RemotingHelper.DEFAULT_CHARSET)%20%2F*%20Message%20body%20*%2F)%3B%0A%20%20%20%20%20%2F%2FCall%20send%20message%20to%20deliver%20message%20to%20one%20of%20brokers.%0A%20%20%20%20%20%2F%2F%E5%8F%91%E9%80%81%E5%90%8C%E6%AD%A5%E6%B6%88%E6%81%AF%0A%20%20%20%20%20SendResult%20sendResult%20%3D%20producer.send(msg)%3B%0A%20%20%20%20%20System.out.printf(%22%25s%25n%22%2C%20sendResult)%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%60%60%60java%0A%20for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%2F%2FCreate%20a%20message%20instance%2C%20specifying%20topic%2C%20tag%20and%20message%20body.%0A%20%20%20%20%20Message%20msg%20%3D%20new%20Message(%22topic-006%22%20%2F*%20Topic%20*%2F%2C%20%22vip%22%20%2F*%20Tag%20*%2F%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%22Hello%20vip%20%22%20%2B%20i).getBytes(RemotingHelper.DEFAULT_CHARSET)%20%2F*%20Message%20body%20*%2F)%3B%0A%20%20%20%20%20%2F%2FCall%20send%20message%20to%20deliver%20message%20to%20one%20of%20brokers.%0A%20%20%20%20%20%2F%2F%E5%8F%91%E9%80%81%E5%90%8C%E6%AD%A5%E6%B6%88%E6%81%AF%0A%20%20%20%20%20SendResult%20sendResult%20%3D%20producer.send(msg)%3B%0A%20%20%20%20%20System.out.printf(%22%25s%25n%22%2C%20sendResult)%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%3E%20%E6%B6%88%E6%81%AF%E8%80%85%E5%88%86%E5%88%AB%E8%AE%A2%E9%98%85tag%E4%B8%BAcustomer%E5%92%8C%20tag%E4%B8%BA%20customer%20%7C%7C%20vip%E7%9A%84%E6%B6%88%E6%81%AF%0A%0A%60%60%60java%0A%20consumer1.subscribe(%22topic-006%22%2C%20%22customer%22)%3B%0A%20consumer2.subscribe(%22topic-006%22%2C%20%22customer%20%7C%7C%20vip%22)%3B%0A%60%60%60%0A%0A%3E%20%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%3E%0A%3E%20consumer1%20%E5%92%8C%20consumer2%E5%8F%AF%E4%BB%A5%E5%88%86%E5%88%AB%E6%B6%88%E8%B4%B9%E5%88%B0tag%3Dcustomer%E7%B1%BB%E5%9E%8B%E7%9A%84%E4%B8%8D%E5%90%8C%E6%B6%88%E6%81%AF%EF%BC%8C%E6%80%BB%E6%95%B0%E4%B8%BAcustomer%E7%B1%BB%E5%9E%8B%E6%B6%88%E6%81%AF%E7%9A%84%E6%80%BB%E5%92%8C%0A%3E%0A%3E%20consumer2%E9%99%A4%E4%BA%86%E5%8F%AF%E4%BB%A5%E6%B6%88%E8%B4%B9%E5%88%B0customer%E7%9A%84%E6%B6%88%E6%81%AF%E5%A4%96%EF%BC%8C%E8%BF%98%E5%8F%AF%E4%BB%A5%E6%B6%88%E8%B4%B9%E5%88%B0%E5%85%A8%E9%83%A8%E7%9A%84tag%3Dvip%E7%9A%84%E6%B6%88%E6%81%AF%0A%0A%23%23%23%23%20SQL%E8%BF%87%E6%BB%A4%0A%0A%23%23%23%23%23%20%E8%BF%90%E7%AE%97%E7%AC%A6%0A%0A%3E%20%E6%95%B0%E5%80%BC%E6%AF%94%E8%BE%83%EF%BC%9A%20%60%3E%60%2C%20%60%3E%3D%60%2C%20%60%3C%60%2C%20%60%3C%3D%60%2C%20%60BETWEEN%60%2C%20%60%3D%60%0A%3E%0A%3E%20%E5%AD%97%E7%AC%A6%E6%AF%94%E8%BE%83%EF%BC%9A%20%60%3D%60%2C%20%60%3C%3E%60%2C%20%60IN%60%0A%3E%0A%3E%20%60IS%20NULL%60%20or%20%60IS%20NOT%20NULL%60%3B%0A%3E%0A%3E%20%E9%80%BB%E8%BE%91%E6%AF%94%E8%BE%83%3A%20%60AND%60%2C%20%60OR%60%2C%20%60NOT%60%3B%0A%3E%0A%3E%20%E5%B8%B8%E9%87%8F%E6%94%AF%E6%8C%81%E7%B1%BB%E5%9E%8B%E4%B8%BA%0A%3E%0A%3E%201.%20%E6%95%B0%E5%80%BC%2C%20%E6%AF%94%E5%A6%82%20123%2C%203.1415%3B%0A%3E%202.%20%E5%AD%97%E7%AC%A6%EF%BC%8C%E6%AF%94%E5%A6%82%20%E2%80%98abc%E2%80%99%2C%20%E5%BF%85%E9%A1%BB%E7%94%A8%E5%8D%95%E5%BC%95%E5%8F%B7%E5%BC%95%E7%94%A8%3B%0A%3E%203.%20%60NULL%60%2C%20%E7%89%B9%E6%AE%8A%E7%9A%84%E5%B8%B8%E9%87%8F%0A%3E%204.%20%E5%B8%83%E5%B0%94%E5%80%BC%2C%20%60TRUE%60%20%E6%88%96%20%60FALSE%60%3B%0A%0A%23%23%23%23%23%20%E5%BC%80%E5%90%AFsql%E8%BF%87%E6%BB%A4%0A%0A%60%60%60shell%0A%2Fopt%2Frocketmq%2Fconf%0Avi%20broker.conf%0AenablePropertyFilter%3Dtrue%0A%60%60%60%0A%0A%3E%20%E4%BF%AE%E6%94%B9%E5%AE%8C%E6%88%90%E5%90%8E%E9%87%8D%E5%90%AFnamerserver%E5%92%8Cbroker%0A%0A%60%60%60shell%0Ash%20bin%2Fmqshutdown%20broker%0Ash%20bin%2Fmqshutdown%20namesrv%0A%0Anohup%20sh%20bin%2Fmqnamesrv%20%26%0Anohup%20sh%20bin%2Fmqbroker%20-n%20master%3A9876%20%26%0A%60%60%60%0A%0A%3E%20%E6%9F%A5%E7%9C%8B%E9%9B%86%E7%BE%A4%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%0A%0A!%5B733abb9b9fadb4a9669af054e7c588eb.png%5D(en-resource%3A%2F%2Fdatabase%2F899%3A1)%0A%0A%0A%E5%A6%82%E6%9E%9C%E5%80%BC%E6%B2%A1%E6%9C%89%E5%8F%98%E6%9B%B4%E4%B8%BA%60true%60%20%E9%9C%80%E8%A6%81%E6%89%A7%E8%A1%8C%E5%A6%82%E4%B8%8B%E5%91%BD%E4%BB%A4%0A%0A%60%60%60shell%0A%5Broot%40master%20rocketmq%5D%23%20sh%20bin%2Fmqadmin%20updateBrokerConfig%20-b%20master%3A10911%20-k%20enablePropertyFilter%20-v%20true%0ARocketMQLog%3AWARN%20No%20appenders%20could%20be%20found%20for%20logger%20(io.netty.util.internal.PlatformDependent0).%0ARocketMQLog%3AWARN%20Please%20initialize%20the%20logger%20system%20properly.%0Aupdate%20broker%20config%20success%2C%20master%3A10911%0A%60%60%60%0A%0A%3E%20%E7%94%9F%E4%BA%A7%E8%80%85%0A%3E%0A%3E%20%60msg.putUserProperty(%22vip%22%2C%20String.valueOf(i))%3B%60%0A%0A%60%60%60java%0Afor%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%2F%2FCreate%20a%20message%20instance%2C%20specifying%20topic%2C%20tag%20and%20message%20body.%0A%20%20%20%20Message%20msg%20%3D%20new%20Message(%22topic-006%22%20%2F*%20Topic%20*%2F%2C%20%22vip%22%20%2F*%20Tag%20*%2F%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20(%22Hello%20vip%20%22%20%2B%20i).getBytes(RemotingHelper.DEFAULT_CHARSET)%20%2F*%20Message%20body%20*%2F)%3B%0A%0A%20%20%20%20msg.putUserProperty(%22vip%22%2C%20String.valueOf(i))%3B%0A%20%20%20%20msg.putUserProperty(%22number%22%2C%20String.valueOf(i))%3B%0A%0A%20%20%20%20%2F%2FCall%20send%20message%20to%20deliver%20message%20to%20one%20of%20brokers.%0A%20%20%20%20%2F%2F%E5%8F%91%E9%80%81%E5%90%8C%E6%AD%A5%E6%B6%88%E6%81%AF%0A%20%20%20%20SendResult%20sendResult%20%3D%20producer.send(msg)%3B%0A%20%20%20%20System.out.printf(%22%25s%25n%22%2C%20sendResult)%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%B6%88%E6%81%AF%E8%80%85%0A%3E%20%60MessageSelector.bySql(%22number%20between%203%20and%207%20and%20vip%20%3E%204%22)%60%0A%60%60%60java%0A%2F%2F%20only%20subsribe%20messages%20have%20property%20vip%20and%20number%2C%20also%20number%20between%203%20and%207%20and%20vip%20%3E%204%0Aconsumer.subscribe(%22topic-006%22%2C%20MessageSelector.bySql(%22number%20between%203%20and%207%20and%20vip%20%3E%204%22))%3B%0A%60%60%60%0A%0A%60%60%60%0AConsumeMessageThread_2%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D1%2C%20storeSize%3D210%2C%20queueOffset%3D19%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648205009964%2C%20bornHost%3D%2F192.168.101.1%3A53854%2C%20storeTimestamp%3D1648204988448%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000043BAC%2C%20commitLogOffset%3D277420%2C%20bodyCRC%3D1358519611%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-006'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20number%3D5%2C%20MAX_OFFSET%3D20%2C%20CONSUME_START_TIME%3D1648205011754%2C%20vip%3D5%2C%20UNIQ_KEY%3D7F0000013D9018B4AAC27F9D382B0005%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3Dvip%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%20118%2C%20105%2C%20112%2C%2032%2C%2053%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20vip%205%0AConsumeMessageThread_3%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D2%2C%20storeSize%3D210%2C%20queueOffset%3D26%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648205011737%2C%20bornHost%3D%2F192.168.101.1%3A53854%2C%20storeTimestamp%3D1648204988466%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000043C7E%2C%20commitLogOffset%3D277630%2C%20bodyCRC%3D1240468609%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-006'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20number%3D6%2C%20MAX_OFFSET%3D27%2C%20CONSUME_START_TIME%3D1648205012407%2C%20vip%3D6%2C%20UNIQ_KEY%3D7F0000013D9018B4AAC27F9D3F190006%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3Dvip%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%20118%2C%20105%2C%20112%2C%2032%2C%2054%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20vip%206%0AConsumeMessageThread_4%20Receive%20New%20Messages%3A%20MessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D210%2C%20queueOffset%3D16%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1648205011752%2C%20bornHost%3D%2F192.168.101.1%3A53854%2C%20storeTimestamp%3D1648204988477%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F0000000000043D50%2C%20commitLogOffset%3D277840%2C%20bodyCRC%3D1056390167%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'topic-006'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20number%3D7%2C%20MAX_OFFSET%3D17%2C%20CONSUME_START_TIME%3D1648205012500%2C%20vip%3D7%2C%20UNIQ_KEY%3D7F0000013D9018B4AAC27F9D3F280007%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3Dvip%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%20118%2C%20105%2C%20112%2C%2032%2C%2055%5D%2C%20transactionId%3D'null'%7D%5D%20%0AHello%20vip%207%0A%60%60%60%0A%60%60%60%0Ahttp%3A%2F%2Flocalhost%3A8081%2Frocketmq%2Fsend%2FsendMessage%0A%0A%2F%2F%E5%AD%98%E5%85%A5rocketmq%E4%B8%AD%E7%9A%84%E7%BB%93%E6%9E%9C%0A%7B%22name%22%3A%22Chris%22%2C%22age%22%3A32%7D%0A%60%60%60%0A%0A%0A%0A%23%23%20%E9%9B%86%E6%88%90SpringBoot%0A%0A%3E%20%E5%BB%BAmodule%20%60rocketmqcloud2022%60%0A%0A%3E%20%E6%94%B9pom%0A%0A%60%60%60xml%0A%3Cdependencies%3E%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-devtools%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-test%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Etest%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecn.hutool%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ehutool-all%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E5.7.22%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.rocketmq%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Erocketmq-spring-boot-starter%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E2.2.1%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%0A%20%20%20%20%3C%2Fdependencies%3E%0A%60%60%60%0A%0A%3E%20%E5%86%99yml%0A%0A%60%60%60yml%0Aspring%3A%0A%20%20application%3A%0A%20%20%20%20name%3A%20rocketmqcloud2022%0Aserver%3A%0A%20%20port%3A%208081%0A%20%20servlet%3A%0A%20%20%20%20encoding%3A%0A%20%20%20%20%20%20charset%3A%20UTF-8%0A%20%20%20%20context-path%3A%20%2Frocketmq%0A%20%20tomcat%3A%0A%20%20%20%20uri-encoding%3A%20UTF-8%0A%0A%0Arocketmq%3A%0A%20%20name-server%3A%20master%3A9876%0A%20%20producer%3A%0A%20%20%20%20group%3A%20rocketmq-producer-group-001%0A%60%60%60%0A%0A%3E%20%E7%94%9F%E4%BA%A7%E8%80%85%0A%0A%60%60%60java%0A%40RestController%0A%40RequestMapping(%22%2Fsend%22)%0Apublic%20class%20SendController%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20RocketMQTemplate%20rocketMQTemplate%3B%0A%0A%20%20%20%20%40PostMapping(%22%2FsendMessage%22)%0A%20%20%20%20public%20String%20sendMsg(%40RequestBody%20%40Validated%20User%20user)%20%7B%0A%20%20%20%20%20%20%20%20rocketMQTemplate.convertAndSend(%22cloud001%22%2C%20user)%3B%0A%20%20%20%20%20%20%20%20return%20%22success%22%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%40Data%0A%40AllArgsConstructor%0A%40NoArgsConstructor%0Apublic%20class%20User%20implements%20Serializable%20%7B%0A%20%20%20%20%40NotNull(message%20%3D%20%22name%20can't%20be%20null%22)%0A%20%20%20%20private%20String%20name%3B%0A%20%20%20%20%40Range(max%20%3D%20100%2C%20min%20%3D%201%2C%20message%20%3D%20%22age%20between%201%20and%20100%22)%0A%20%20%20%20private%20Integer%20age%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%3E%20%E6%B6%88%E8%B4%B9%E8%80%85%0A%3E%0A%3E%20%60RocketMQListener%60%0A%3E%0A%3E%20%60%40RocketMQMessageListener%60%0A%0A%60%60%60java%0Apackage%20com.chris.rocketmq.rocketmqcloud2022.service%3B%0A%0Aimport%20cn.hutool.json.JSONUtil%3B%0Aimport%20com.chris.rocketmq.rocketmqcloud2022.bean.User%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.apache.rocketmq.spring.annotation.RocketMQMessageListener%3B%0Aimport%20org.apache.rocketmq.spring.annotation.SelectorType%3B%0Aimport%20org.apache.rocketmq.spring.core.RocketMQListener%3B%0Aimport%20org.springframework.stereotype.Service%3B%0A%0A%40Service%0A%40Slf4j%0A%40RocketMQMessageListener(consumerGroup%20%3D%20%22cloud-consume-001%22%2Ctopic%20%3D%20%22cloud001%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectorType%20%3D%20SelectorType.TAG%2C%20selectorExpression%20%3D%20%22*%22)%0Apublic%20class%20UserConsumer%20implements%20RocketMQListener%3CUser%3E%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20onMessage(User%20user)%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22rocketmq%20msg%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(user))%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%20%E9%A1%BA%E5%BA%8F%E6%B6%88%E8%B4%B9%0A%0A%23%23%23%23%20%E6%97%A0%E5%BA%8F%E6%B6%88%E6%81%AF%0A%0A%60%60%60java%0A%40PostMapping(%22%2FsendOrderMessage%22)%0A%20%20%20%20public%20SendResult%20sendOrderMessage()%20%7B%0A%20%20%20%20%20%20%20%20List%3COrderInfo%3E%20orderInfos%20%3D%20CollUtil.newArrayList()%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(1L%2C%20%22create%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(2L%2C%20%22create%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(1L%2C%20%22send%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(3L%2C%20%22create%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(2L%2C%20%22send%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(4L%2C%20%22create%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(1L%2C%20%22pay%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(1L%2C%20%22finish%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(3L%2C%20%22send%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(2L%2C%20%22pay%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(4L%2C%20%22send%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(3L%2C%20%22pay%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(2L%2C%20%22finish%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(4L%2C%20%22pay%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(3L%2C%20%22finish%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(4L%2C%20%22finish%22))%3B%0A%0A%20%20%20%20%20%20%20%20List%3CMessage%3COrderInfo%3E%3E%20messageList%20%3D%20CollUtil.newArrayList()%3B%0A%20%20%20%20%20%20%20%20for%20(OrderInfo%20orderInfo%20%3A%20orderInfos)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%3COrderInfo%3E%20message%20%3D%20MessageBuilder.withPayload(orderInfo).build()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20messageList.add(message)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20SendResult%20sendResult%20%3D%20rocketMQTemplate.syncSend(String.join(%22%3A%22%2C%20topic%2C%20order_tag)%2C%20messageList%2C%2010000)%3B%0A%20%20%20%20%20%20%20%20log.info(%22sendOrderMessage%20sendResult%3A%7B%7D%22%2C%20sendResult)%3B%0A%20%20%20%20%20%20%20%20return%20sendResult%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%60%60%60%0A2022-03-27%2011%3A57%3A17.531%20%5BMessageThread_8%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A1%2C%22desc%22%3A%22finish%22%7D%0A2022-03-27%2011%3A57%3A17.531%20%5BMessageThread_1%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A1%2C%22desc%22%3A%22create%22%7D%0A2022-03-27%2011%3A57%3A17.531%20%5BMessageThread_5%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A2%2C%22desc%22%3A%22send%22%7D%0A2022-03-27%2011%3A57%3A17.531%20%5BessageThread_13%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A2%2C%22desc%22%3A%22finish%22%7D%0A2022-03-27%2011%3A57%3A17.531%20%5BessageThread_16%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A4%2C%22desc%22%3A%22finish%22%7D%0A2022-03-27%2011%3A57%3A17.531%20%5BessageThread_11%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A4%2C%22desc%22%3A%22send%22%7D%0A2022-03-27%2011%3A57%3A17.531%20%5BMessageThread_7%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A1%2C%22desc%22%3A%22pay%22%7D%0A2022-03-27%2011%3A57%3A17.532%20%5BessageThread_14%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A4%2C%22desc%22%3A%22pay%22%7D%0A2022-03-27%2011%3A57%3A17.532%20%5BMessageThread_3%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A1%2C%22desc%22%3A%22send%22%7D%0A2022-03-27%2011%3A57%3A17.532%20%5BMessageThread_6%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A4%2C%22desc%22%3A%22create%22%7D%0A2022-03-27%2011%3A57%3A17.532%20%5BMessageThread_4%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A3%2C%22desc%22%3A%22create%22%7D%0A2022-03-27%2011%3A57%3A17.532%20%5BessageThread_15%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A3%2C%22desc%22%3A%22finish%22%7D%0A2022-03-27%2011%3A57%3A17.532%20%5BMessageThread_9%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A3%2C%22desc%22%3A%22send%22%7D%0A2022-03-27%2011%3A57%3A17.533%20%5BMessageThread_2%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A2%2C%22desc%22%3A%22create%22%7D%0A2022-03-27%2011%3A57%3A17.533%20%5BessageThread_12%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A3%2C%22desc%22%3A%22pay%22%7D%0A2022-03-27%2011%3A57%3A17.533%20%5BessageThread_10%5D%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A2%2C%22desc%22%3A%22pay%22%7D%0A%60%60%60%0A%0A%20%0A%0A%23%23%23%23%20%E6%9C%89%E5%BA%8F%E6%B6%88%E6%81%AF%0A%0A%23%23%23%23%23%20%E5%8E%9F%E7%94%9F%E5%AE%9E%E7%8E%B0%0A%0A%3E%20%E7%94%9F%E4%BA%A7%E8%80%85%0A%3E%20%60%20new%20MessageQueueSelector()%60%0A%0A%60%60%60java%0Apublic%20static%20void%20main(String%5B%5D%20args)%20throws%20MQClientException%2C%20UnsupportedEncodingException%2C%20RemotingException%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20InterruptedException%2C%20MQBrokerException%20%7B%0A%20%20%20%20%20%20%20%20DefaultMQProducer%20producer%20%3D%20new%20DefaultMQProducer(%22rocketmq-producer-group-002%22)%3B%0A%20%20%20%20%20%20%20%20producer.setNamesrvAddr(%22master%3A9876%22)%3B%0A%0A%20%20%20%20%20%20%20%20producer.start()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22producer%20has%20started!%22)%3B%0A%0A%20%20%20%20%20%20%20%20List%3COrderInfo%3E%20orderInfos%20%3D%20getOrderInfos()%3B%0A%20%20%20%20%20%20%20%20for%20(OrderInfo%20orderInfo%20%3A%20orderInfos)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%20message%20%3D%20new%20Message(%22topic-008%22%2C%20%22order%22%2C%20orderInfo.toString().getBytes(StandardCharsets.UTF_8))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20SendResult%20sendResult%20%3D%20producer.send(message%2C%20new%20MessageQueueSelector()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20public%20MessageQueue%20select(List%3CMessageQueue%3E%20mqs%2C%20Message%20msg%2C%20Object%20arg)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22message%20queue%20selector%2C%20arg%3A%22%20%2B%20arg)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20int%20size%20%3D%20mqs.size()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20long%20id%20%3D%20(long)%20arg%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20long%20queue_inx%20%3D%20id%20%25%20size%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20mqs.get(new%20Long(queue_inx).intValue())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%20orderInfo.getId()%2C%2010000)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22send%20result%3A%22%20%2B%20sendResult)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%2F%2FShut%20down%20once%20the%20producer%20instance%20is%20not%20longer%20in%20use.%0A%20%20%20%20%20%20%20%20producer.shutdown()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20private%20static%20List%3COrderInfo%3E%20getOrderInfos()%20%7B%0A%20%20%20%20%20%20%20%20List%3COrderInfo%3E%20orderInfos%20%3D%20CollUtil.newArrayList()%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(1L%2C%20%22create%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(2L%2C%20%22create%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(1L%2C%20%22send%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(3L%2C%20%22create%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(2L%2C%20%22send%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(4L%2C%20%22create%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(1L%2C%20%22pay%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(1L%2C%20%22finish%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(3L%2C%20%22send%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(2L%2C%20%22pay%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(4L%2C%20%22send%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(3L%2C%20%22pay%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(2L%2C%20%22finish%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(4L%2C%20%22pay%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(3L%2C%20%22finish%22))%3B%0A%20%20%20%20%20%20%20%20orderInfos.add(new%20OrderInfo(4L%2C%20%22finish%22))%3B%0A%20%20%20%20%20%20%20%20return%20orderInfos%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%60%60%60%0Amessage%20queue%20selector%2C%20arg%3A1%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9350000%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000058C95%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D1%5D%2C%20queueOffset%3D12%5D%0Amessage%20queue%20selector%2C%20arg%3A2%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B93F0001%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000058D6B%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D2%5D%2C%20queueOffset%3D12%5D%0Amessage%20queue%20selector%2C%20arg%3A1%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9430002%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000058E41%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D1%5D%2C%20queueOffset%3D13%5D%0Amessage%20queue%20selector%2C%20arg%3A3%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9460003%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000058F15%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D3%5D%2C%20queueOffset%3D12%5D%0Amessage%20queue%20selector%2C%20arg%3A2%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9600004%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000058FEB%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D2%5D%2C%20queueOffset%3D13%5D%0Amessage%20queue%20selector%2C%20arg%3A4%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9640005%2C%20offsetMsgId%3DC0A8657F00002A9F00000000000590BF%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D0%5D%2C%20queueOffset%3D12%5D%0Amessage%20queue%20selector%2C%20arg%3A1%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9690006%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000059195%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D1%5D%2C%20queueOffset%3D14%5D%0Amessage%20queue%20selector%2C%20arg%3A1%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B96E0007%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000059268%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D1%5D%2C%20queueOffset%3D15%5D%0Amessage%20queue%20selector%2C%20arg%3A3%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9720008%2C%20offsetMsgId%3DC0A8657F00002A9F000000000005933E%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D3%5D%2C%20queueOffset%3D13%5D%0Amessage%20queue%20selector%2C%20arg%3A2%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9770009%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000059412%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D2%5D%2C%20queueOffset%3D14%5D%0Amessage%20queue%20selector%2C%20arg%3A4%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B986000A%2C%20offsetMsgId%3DC0A8657F00002A9F00000000000594E5%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D0%5D%2C%20queueOffset%3D13%5D%0Amessage%20queue%20selector%2C%20arg%3A3%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B999000B%2C%20offsetMsgId%3DC0A8657F00002A9F00000000000595B9%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D3%5D%2C%20queueOffset%3D14%5D%0Amessage%20queue%20selector%2C%20arg%3A2%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B99D000C%2C%20offsetMsgId%3DC0A8657F00002A9F000000000005968C%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D2%5D%2C%20queueOffset%3D15%5D%0Amessage%20queue%20selector%2C%20arg%3A4%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9A2000D%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000059762%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D0%5D%2C%20queueOffset%3D14%5D%0Amessage%20queue%20selector%2C%20arg%3A3%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9AB000E%2C%20offsetMsgId%3DC0A8657F00002A9F0000000000059835%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D3%5D%2C%20queueOffset%3D15%5D%0Amessage%20queue%20selector%2C%20arg%3A4%0Asend%20result%3ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001159418B4AAC289A4B9AE000F%2C%20offsetMsgId%3DC0A8657F00002A9F000000000005990B%2C%20messageQueue%3DMessageQueue%20%5Btopic%3Dtopic-008%2C%20brokerName%3Dmaster%2C%20queueId%3D0%5D%2C%20queueOffset%3D15%5D%0A%60%60%60%0A%0A%0A%0A%3E%20%E6%B6%88%E6%81%AF%E8%80%85%0A%3E%0A%3E%20%60new%20MessageListenerOrderly()%60%0A%0A%60%60%60java%0A%2F%2F%20Register%20MessageListenerOrderly%20to%20execute%20on%20arrival%20of%20messages%20fetched%20from%20brokers%2C%20receive%20messages%20%0A%2F%2F%20orderly%20One%20queue%20by%20one%20thread.%0Aconsumer.registerMessageListener((MessageListenerOrderly)%20(msgs%2C%20context)%20-%3E%20%7B%0A%20%20%20%20for%20(MessageExt%20msg%20%3A%20msgs)%20%7B%0A%20%20%20%20%20%20%20%20String%20msg_str%20%3D%20new%20String(msg.getBody())%3B%0A%20%20%20%20%20%20%20%20System.out.println(msg_str)%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20ConsumeOrderlyStatus.SUCCESS%3B%0A%7D)%3B%0A%60%60%60%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BA%E6%B6%88%E6%81%AF%E9%83%BD%E6%98%AF%E4%BB%8E%60create%20-%20send%20-%20pay%20-%20finish%60%20%E8%BF%99%E5%87%A0%E4%B8%AA%E7%8A%B6%E6%80%81%E9%A1%BA%E5%BA%8F%E6%B6%88%E8%B4%B9%0A%0A%60%60%60%0AOrderInfo(id%3D1%2C%20desc%3Dcreate)%0AOrderInfo(id%3D2%2C%20desc%3Dcreate)%0AOrderInfo(id%3D1%2C%20desc%3Dsend)%0AOrderInfo(id%3D3%2C%20desc%3Dcreate)%0AOrderInfo(id%3D2%2C%20desc%3Dsend)%0AOrderInfo(id%3D4%2C%20desc%3Dcreate)%0AOrderInfo(id%3D1%2C%20desc%3Dpay)%0AOrderInfo(id%3D1%2C%20desc%3Dfinish)%0AOrderInfo(id%3D3%2C%20desc%3Dsend)%0AOrderInfo(id%3D2%2C%20desc%3Dpay)%0AOrderInfo(id%3D4%2C%20desc%3Dsend)%0AOrderInfo(id%3D3%2C%20desc%3Dpay)%0AOrderInfo(id%3D2%2C%20desc%3Dfinish)%0AOrderInfo(id%3D4%2C%20desc%3Dpay)%0AOrderInfo(id%3D3%2C%20desc%3Dfinish)%0AOrderInfo(id%3D4%2C%20desc%3Dfinish)%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20SpringBoot%20%E5%AE%9E%E7%8E%B0%0A%0A%3E%20%E7%94%9F%E4%BA%A7%E8%80%85%0A%0A%60%60%60java%0A%40PostMapping(%22%2FsendOrderMessageOrderly%22)%0Apublic%20String%20sendOrderMessageOrderly()%20%7B%0A%20%20%20%20List%3COrderInfo%3E%20orderInfos%20%3D%20getOrderInfos()%3B%0A%20%20%20%20for%20(OrderInfo%20orderInfo%20%3A%20orderInfos)%20%7B%0A%20%20%20%20%20%20%20%20Message%3COrderInfo%3E%20message%20%3D%20MessageBuilder.withPayload(orderInfo).build()%3B%0A%20%20%20%20%20%20%20%20SendResult%20sendResult%20%3D%20rocketMQTemplate.syncSendOrderly(String.join(%22%3A%22%2C%20topic%2C%20order_tag)%2C%20message%2C%20String.valueOf(orderInfo.getOrderId()))%3B%0A%20%20%20%20%20%20%20%20log.info(%22send%20orderly%20result%3A%7B%7D%22%2C%20sendResult)%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20%22success%22%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%B6%88%E6%81%AF%E8%80%85%0A%3E%20%60consumeMode%20%3D%20ConsumeMode.ORDERLY%60%0A%0A%60%60%60java%0A%40Service%0A%40Slf4j%0A%40RocketMQMessageListener(topic%20%3D%20%22cloud006%22%2C%20selectorType%20%3D%20SelectorType.TAG%2C%20selectorExpression%20%3D%20%22order%22%2C%0A%20%20%20%20%20%20%20%20consumerGroup%20%3D%20%22cloud-consume-group-006%22%2C%20consumeMode%20%3D%20ConsumeMode.ORDERLY)%0Apublic%20class%20OrderConsumer%20implements%20RocketMQListener%3COrderInfo%3E%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20onMessage(OrderInfo%20orderInfo)%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22consume%20orderInfo%20msg%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(orderInfo))%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%40Service%0A%40Slf4j%0A%40RocketMQMessageListener(topic%20%3D%20%22cloud006%22%2C%20selectorType%20%3D%20SelectorType.TAG%2C%20selectorExpression%20%3D%20%22order%22%2C%0A%20%20%20%20%20%20%20%20consumerGroup%20%3D%20%22cloud-consume-group-006%22%2C%20consumeMode%20%3D%20ConsumeMode.ORDERLY)%0Apublic%20class%20OrderConsumer2%20implements%20RocketMQListener%3COrderInfo%3E%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20onMessage(OrderInfo%20orderInfo)%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22consume%20orderInfo%20msg%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(orderInfo))%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BA%E5%A6%82%E6%9E%9C%E5%90%AF%E5%8A%A8%E4%B8%A4%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%60consumer%60%20%E5%92%8C%20%60consumer2%60%0A%3E%0A%3E%20%E5%88%99%60consumer%60%20%E5%92%8C%20%60consumer2%60%20%E6%8C%89%E9%A1%BA%E5%BA%8F%E5%88%86%E5%88%AB%E6%B6%88%E6%81%AF%20%60topic%20cloud006%60%E9%87%8C%E9%9D%A2%E7%9A%84%E6%B6%88%E6%81%AF%0A%0A%60%60%60%0A%5BMessageThread_2%5D%20OrderConsumer2%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A2%2C%22desc%22%3A%22create%22%7D%0A%5BMessageThread_1%5D%20OrderConsumer2%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A3%2C%22desc%22%3A%22create%22%7D%0A%5BMessageThread_2%5D%20OrderConsumer2%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A2%2C%22desc%22%3A%22send%22%7D%0A%5BMessageThread_1%5D%20OrderConsumer2%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A3%2C%22desc%22%3A%22send%22%7D%0A%5BMessageThread_1%5D%20OrderConsumer2%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A3%2C%22desc%22%3A%22pay%22%7D%0A%5BMessageThread_2%5D%20OrderConsumer2%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A2%2C%22desc%22%3A%22pay%22%7D%0A%5BMessageThread_1%5D%20OrderConsumer2%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A3%2C%22desc%22%3A%22finish%22%7D%0A%5BMessageThread_2%5D%20OrderConsumer2%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A2%2C%22desc%22%3A%22finish%22%7D%0A%0A%5BMessageThread_1%5D%20OrderConsumer%20%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A4%2C%22desc%22%3A%22create%22%7D%0A%5BMessageThread_1%5D%20OrderConsumer%20%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A4%2C%22desc%22%3A%22send%22%7D%0A%5BMessageThread_1%5D%20OrderConsumer%20%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A4%2C%22desc%22%3A%22pay%22%7D%0A%5BMessageThread_1%5D%20OrderConsumer%20%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A4%2C%22desc%22%3A%22finish%22%7D%0A%5BMessageThread_2%5D%20OrderConsumer%20%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A1%2C%22desc%22%3A%22create%22%7D%0A%5BMessageThread_2%5D%20OrderConsumer%20%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A1%2C%22desc%22%3A%22send%22%7D%0A%5BMessageThread_2%5D%20OrderConsumer%20%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A1%2C%22desc%22%3A%22pay%22%7D%0A%5BMessageThread_2%5D%20OrderConsumer%20%20%3A%20consume%20orderInfo%20msg%3A%7B%22orderId%22%3A1%2C%22desc%22%3A%22finish%22%7D%0A%60%60%60%0A%0A%0A%0A%23%23%20%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8%E6%97%B6%E9%97%B4%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%0A%3E%20https%3A%2F%2Fblog.csdn.net%2Fqq_34930488%2Farticle%2Fdetails%2F101293178%0A%0A%60%60%60java%0Aorg.apache.rocketmq.store.DefaultMessageStore%23addScheduleTask%0A%60%60%60%0A%0A%3E%20https%3A%2F%2Frocketmq.apache.org%2Fzh%2Fdocs%2F4.x%2FbestPractice%2F01bestpractice%0A%0A!%5Ba38a6d616100c342a6d54ab343bf40d7.png%5D(en-resource%3A%2F%2Fdatabase%2F1387%3A1)%0A%0A%60%60%60java%0Along%20fileReservedTime%20%3D%20DefaultMessageStore.this.getMessageStoreConfig().getFileReservedTime()%3B%0Aint%20deletePhysicFilesInterval%20%3D%20DefaultMessageStore.this.getMessageStoreConfig().getDeleteCommitLogFilesInterval()%3B%0Aint%20destroyMapedFileIntervalForcibly%20%3D%20DefaultMessageStore.this.getMessageStoreConfig().getDestroyMapedFileIntervalForcibly()%3B%0A%60%60%60%0A%0A%0A%3E%20fileReservedTime%EF%BC%9A%E6%96%87%E4%BB%B6%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E4%BB%8E%E6%96%87%E4%BB%B6%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E7%9A%84%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4%E5%88%B0%E7%8E%B0%E5%9C%A8%E4%B8%BA%E6%AD%A2%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%B6%85%E8%BF%87%E8%AF%A5%E6%97%B6%E9%97%B4%EF%BC%8C%E5%88%99%E6%98%AF%E8%BF%87%E6%9C%9F%E6%96%87%E4%BB%B6%E5%8F%AF%E8%A2%AB%E5%88%A0%E9%99%A4%0A%0A%3E%20deletePhysicFilesInterval%EF%BC%9A%E5%88%A0%E9%99%A4%E7%89%A9%E7%90%86%E6%96%87%E4%BB%B6%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E5%9C%A8%E4%B8%80%E6%AC%A1%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E8%A7%A6%E5%8F%91%E6%97%B6%EF%BC%8C%E5%8F%AF%E8%83%BD%E4%BC%9A%E6%9C%89%E5%A4%9A%E4%B8%AA%E7%89%A9%E7%90%86%E6%96%87%E4%BB%B6%E8%B6%85%E8%BF%87%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%E5%8F%AF%E8%A2%AB%E5%88%A0%E9%99%A4%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%88%A0%E9%99%A4%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E5%90%8E%E9%9C%80%E8%A6%81%E9%97%B4%E9%9A%94deletePhysicFilesInterval%E8%BF%99%E4%B8%AA%E6%97%B6%E9%97%B4%E5%86%8D%E5%88%A0%E9%99%A4%E5%8F%A6%E5%A4%96%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%EF%BC%8C%E6%88%91%E7%8C%9C%E6%B5%8B%E5%8F%AF%E8%83%BD%E6%98%AF%E7%94%B1%E4%BA%8E%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E6%98%AF%E4%B8%80%E4%B8%AA%E9%9D%9E%E5%B8%B8%E8%80%97%E8%B4%B9IO%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%BC%9A%E5%BC%95%E8%B5%B7%E6%B6%88%E6%81%AF%E6%8F%92%E5%85%A5%E6%B6%88%E8%B4%B9%E7%9A%84%E5%BB%B6%E8%BF%9F%EF%BC%88%E7%9B%B8%E6%AF%94%E4%BA%8E%E6%AD%A3%E5%B8%B8%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%89%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%8D%E5%BB%BA%E8%AE%AE%E7%9B%B4%E6%8E%A5%E5%88%A0%E9%99%A4%E6%89%80%E6%9C%89%E8%BF%87%E6%9C%9F%E6%96%87%E4%BB%B6%0A%0A%3E%20destroyMapedFileIntervalForcibly%EF%BC%9A%E5%9C%A8%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E6%97%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AF%A5%E6%96%87%E4%BB%B6%E8%BF%98%E8%A2%AB%E7%BA%BF%E7%A8%8B%E5%BC%95%E7%94%A8%EF%BC%8C%E6%AD%A4%E6%97%B6%E4%BC%9A%E9%98%BB%E6%AD%A2%E6%AD%A4%E6%AC%A1%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%90%8C%E6%97%B6%E5%B0%86%E8%AF%A5%E6%96%87%E4%BB%B6%E6%A0%87%E8%AE%B0%E4%B8%8D%E5%8F%AF%E7%94%A8%E5%B9%B6%E4%B8%94%E7%BA%AA%E5%BD%95%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4%E6%88%B3destroyMapedFileIntervalForcibly%E8%BF%99%E4%B8%AA%E8%A1%A8%E7%A4%BA%E6%96%87%E4%BB%B6%E5%9C%A8%E7%AC%AC%E4%B8%80%E6%AC%A1%E5%88%A0%E9%99%A4%E6%8B%92%E7%BB%9D%E5%90%8E%EF%BC%8C%E6%96%87%E4%BB%B6%E4%BF%9D%E5%AD%98%E7%9A%84%E6%9C%80%E5%A4%A7%E6%97%B6%E9%97%B4%EF%BC%8C%E5%9C%A8%E6%AD%A4%E6%97%B6%E9%97%B4%E5%86%85%E4%B8%80%E7%9B%B4%E4%BC%9A%E8%A2%AB%E6%8B%92%E7%BB%9D%E5%88%A0%E9%99%A4%EF%BC%8C%E5%BD%93%E8%B6%85%E8%BF%87%E8%BF%99%E4%B8%AA%E6%97%B6%E9%97%B4%E6%97%B6%EF%BC%8C%E4%BC%9A%E5%B0%86%E5%BC%95%E7%94%A8%E6%AF%8F%E6%AC%A1%E5%87%8F%E5%B0%911000%EF%BC%8C%E7%9B%B4%E5%88%B0%E5%BC%95%E7%94%A8%20%E5%B0%8F%E4%BA%8E%E7%AD%89%E4%BA%8E%200%E4%B8%BA%E6%AD%A2%EF%BC%8C%E5%8D%B3%E5%8F%AF%E5%88%A0%E9%99%A4%E8%AF%A5%E6%96%87%E4%BB%B6%EF%BC%8C%E5%AE%9E%E7%8E%B0%E4%BB%A3%E7%A0%81%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60java%0Apublic%20void%20shutdown(final%20long%20intervalForcibly)%20%7B%0A%20%20%20%20%20%20%20%20if%20(this.available)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.available%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.firstShutdownTimestamp%20%3D%20System.currentTimeMillis()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.release()%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(this.getRefCount()%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20((System.currentTimeMillis()%20-%20this.firstShutdownTimestamp)%20%3E%3D%20intervalForcibly)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.refCount.set(-1000%20-%20this.getRefCount())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.release()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%60%60%60

git

创建时间:2020/9/2 15:24
更新时间:2022/3/29 22:52
作者:Chris

安装

sudo -s
apt-get install git

git help config

配置文件就是Git全局配置的文件,一般配置方法是git config --global <配置名称> <配置的值>

git config --global user.name "chris"
git config --global user.email "lilunlogic@163.com"

会在家目录(/home/chris)下建立一个叫.gitconfig 的文件(该文件为隐藏文件,需要使用ls -al查看到)

git config --list

git clone https://github.com/ApeTogether/DemoTest

mkdir repo1

cd repo1

git init 或 git init --bare
Initialized empty Git repository in /home/chris/githome/repo1/.git/
touch file1 file2 file3
echo "test file" >> file1
echo "test file" >> file2
echo "test file" >> file3

此时可以使用git status命令查看当前git仓库的状态

git status

使用git add命令添加新创建或修改的文件到本地的缓存区(Index)

git add file1 file2 file 3

仅监控已经被add的文件(即tracked file),会将被修改的文件提交到暂存区。add -u 不会提交新文件(untracked file)

git add -u

把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件

git add . 

是上面两个功能的合集

git add -A
git reset

This form resets the index entries for all <paths> to their state at <tree-ish>. (It does not affect the working tree or the current branch.)

This means that git reset <paths> is the opposite of git add <paths>.

使用 git diff 命令再加上 --cached 参数,看看缓存区中哪些文件被修改了。

进入到git diff --cached界面后需要输入q才可以退出:

git diff --cached

如果没有--cached参数,git diff 会显示当前你所有已做的但没有加入到索引里的修改

使用git commit命令提交到本地代码库, 需要使用-m添加本次修改的注释

git commit -m "add 3 files"

[master (root-commit) 054c93f] add 3 files

3 files changed, 5 insertions(+)

create mode 100644 file1

create mode 100644 file2

create mode 100644 file3

从暂存区移除文件

 git rm --cached filename

强制从工作区和暂存区移除文件

 git rm -f filename

如果没有指定快照名字则从暂存区检出文件到工作区

 git checkout -- filename

如果指定了快照名字则从仓库检出文件到暂存区和工作区

 git checkout HEAD~ filename

除了用git add 命令,我们还可以用下面的命令将所有没有加到缓存区的修改也一起提交,但-a命令不会添加新建的文件。

 git commit -am "add 3 files"

修改最新一次提交时的批注信息

git commit --amend
git commit --amend -m "fix the comment for last submittion"

如果是删除文件,则直接使用git rm命令删除后会自动将已删除文件的信息添加到缓存区,

git commit提交后就会将本地仓库中的对应文件删除

只删除工作区和暂存区的文件,也就是取消跟踪.

git rm file3

将file1的名字改为file2

git mv file1 file2

移动HEAD的指向将其指向上一个版本并将上一个版本回滚到暂存区

git reset [--mixed] HEAD~

移动HEAD的指向将其指向上一个版本并将上上一个版本回滚到暂存区

git reset HEAD~2

移动HEAD的指向将其指向上一个版本,相当于回滚了一次错误的commit

git reset --soft HEAD~

回滚到指定版本

git reset 753e10 即可以回滚又可以向前滚,但只滚到暂存区

git reset --hard 753e10 一步回滚到仓库区

将HEAD指向的分支及HEAD本身切到目标分支

git reset -- hard branchName

创建分支

git branch branchName

创建并切换到新分支

git checkout -b branchName

切换分支f

git checkout branchName
1:修改快照指针
2:将当前快照的内容还原到工作区和暂存区
git checkout branchId
或
git checkout HEAD~
git log --decorate --oneline --graph --all
git merge branchName

比较两个不同版本

git diff versionId1 versionId2

比较工作区与某一版本

git diff versionId

比较工作区和不同版本

git diff HEAD

要查看当前配置有哪些远程仓库

git remote -v

在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库.

将本地仓库关联到远端服务器,我们可以使用 git remote 命令,不同于刚刚的 git clone 命令,直接将远端的仓库克隆下来。 我们当前的仓库是使用 git init 初始化的本地仓库,所以我们需要将本地仓库与远程仓库关联,使用如下命令(需要修改下面的远程仓库地址为自己的仓库地址):

git remote add origin https://github.com/ApeTogether/repo1.git
git remote add origin git@github.com:ApeTogether/repo1.git
git push -u origin master
git push -u origin branch_001

这个时候如果本地的仓库连接到了远程Git服务器,可以使用下面的命令将本地仓库同步到远端服务器:

# 需要输入仓库对应的用户名和密码

$ git push -u origin master

git push https://github.com/ApeTogether/RepoTest01.git master

## create a new repository on the command line

echo "# RepoTest01" >> README.md

git init

git add README.md

git commit -m "first commit"

git remote add origin git@github.com:ApeTogether/RepoTest01.git

git push -u origin master

## push an existing repository from the command line

git remote add origin git@github.com:ApeTogether/RepoTest01.git

git push -u origin master

通过.gitignore将文件不纳入版本控制

​ touch .gitignore

​ index.*

​ .gitignore

*匹配零个或任意多个字符

[abc]匹配任意一下在括号内的字符

?只匹配一个任意字符

[0-9][a-z]匹配范围

git help git-command
cd "D:\AI_Project\final-report-service"
git log
git status
git stash == git stash push
git stash list
git stash show
git stash pop
git checkout [branch name]
git pull

delete a local branch

git branch [-d or -D] develop

If during the merge you get a conflict, the best way to undo the merge is:

git merge --abort

merge the hotfix branch back into your master branch

$ git checkout master 
$ git checkout -b hotfix origin/hotfix [将远程hotfix拉到本地并检出]
$ git merge hotfix

git push <remote> localbranch:remotebranch

$git push origin master:master

在local repository中找到名字为master的branch,使用它去更新remote repository下名字为master的branch,如果remote repository下不存在名字是master的branch,那么新建一个

冒号前表示local branch的名字,冒号后表示remote repository下 branch的名字。注意,如果你省略了<dst>,git就认为你想push到remote repository下和local branch相同名字的branch

关联之后再执行git pull, git push操作时就不需要指定对应的远程分支

git push --set-upstream origin CFT-73 == git push -u origin CFT-73

forch push the commits into remote branch FU-382

git push -f -u origin FU-382

you get a far more simplified output from the command

git status -s

unstaging the staged file

git reset HEAD CONTRIBUTING.md

unmodifying a Modified File

git checkout -- CONTRIBUTING.md

which shows you the URLs that Git has stored for the shortname to be used when reading and writing to that remote

$ git remote -v origin https://github.com/schacon/ticgit (fetch) origin https://github.com/schacon/ticgit (push)

git fetch orgin master //将远程仓库的master分支下载到本地当前branch中

the git fetch origin command only downloads the data to your local repository — it doesn’t automatically merge it with any of your work or modify what you’re currently working on

You have to merge it manually into your work when you’re ready.

change the remtoe url in local repository

git remote set-url origin git://new.url.here

git remote set-url origin https://github.com/ChrisLi716/myhadoopdemo.git

执行如下命令记住提交时的帐号和密码

git config --global credential.helper store

%0A%0A%E5%AE%89%E8%A3%85%0A%0A%60%60%60shell%0Asudo%20-s%0Aapt-get%20install%20git%0A%60%60%60%0A%0A%60git%20help%20config%60%0A%0A!%5B14e841c5ec8c70b01bfb687a8e86e03f.png%5D(en-resource%3A%2F%2Fdatabase%2F524%3A1)%0A%0A!%5B3669f2e37c7c78cf9fa9f5d4f504473d.png%5D(en-resource%3A%2F%2Fdatabase%2F525%3A1)%0A%0A%0A%0A%0A%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%B0%B1%E6%98%AFGit%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E7%9A%84%E6%96%87%E4%BB%B6%EF%BC%8C%E4%B8%80%E8%88%AC%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95%E6%98%AFgit%20config%20--global%20%3C%E9%85%8D%E7%BD%AE%E5%90%8D%E7%A7%B0%3E%20%3C%E9%85%8D%E7%BD%AE%E7%9A%84%E5%80%BC%3E%0A%0A%60%60%60shell%0Agit%20config%20--global%20user.name%20%22chris%22%0Agit%20config%20--global%20user.email%20%22lilunlogic%40163.com%22%0A%60%60%60%0A%0A%E4%BC%9A%E5%9C%A8%E5%AE%B6%E7%9B%AE%E5%BD%95(%2Fhome%2Fchris)%E4%B8%8B%E5%BB%BA%E7%AB%8B%E4%B8%80%E4%B8%AA%E5%8F%AB.gitconfig%20%E7%9A%84%E6%96%87%E4%BB%B6%EF%BC%88%E8%AF%A5%E6%96%87%E4%BB%B6%E4%B8%BA%E9%9A%90%E8%97%8F%E6%96%87%E4%BB%B6%EF%BC%8C%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8ls%20-al%E6%9F%A5%E7%9C%8B%E5%88%B0%EF%BC%89%0A%0A%60%60%60shell%0Agit%20config%20--list%0A%60%60%60%0A%0Agit%20clone%20https%3A%2F%2Fgithub.com%2FApeTogether%2FDemoTest%0A%0Amkdir%20repo1%0A%0Acd%20repo1%0A%0A%60%60%60shell%0Agit%20init%20%E6%88%96%20git%20init%20--bare%0AInitialized%20empty%20Git%20repository%20in%20%2Fhome%2Fchris%2Fgithome%2Frepo1%2F.git%2F%0A%60%60%60%0A%0A%0A%60%60%60%0Atouch%20file1%20file2%20file3%0Aecho%20%22test%20file%22%20%3E%3E%20file1%0Aecho%20%22test%20file%22%20%3E%3E%20file2%0Aecho%20%22test%20file%22%20%3E%3E%20file3%0A%60%60%60%0A%0A%3E%20%E6%AD%A4%E6%97%B6%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8git%20status%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8Dgit%E4%BB%93%E5%BA%93%E7%9A%84%E7%8A%B6%E6%80%81%0A%0A%60%60%60shell%0Agit%20status%0A%60%60%60%0A%0A%3E%20%E4%BD%BF%E7%94%A8git%20add%E5%91%BD%E4%BB%A4%E6%B7%BB%E5%8A%A0%E6%96%B0%E5%88%9B%E5%BB%BA%E6%88%96%E4%BF%AE%E6%94%B9%E7%9A%84%E6%96%87%E4%BB%B6%E5%88%B0%E6%9C%AC%E5%9C%B0%E7%9A%84%E7%BC%93%E5%AD%98%E5%8C%BA%EF%BC%88Index%EF%BC%89%0A%0A%60%60%60shell%0Agit%20add%20file1%20file2%20file%203%0A%60%60%60%0A%0A%3E%20%E4%BB%85%E7%9B%91%E6%8E%A7%E5%B7%B2%E7%BB%8F%E8%A2%ABadd%E7%9A%84%E6%96%87%E4%BB%B6%EF%BC%88%E5%8D%B3tracked%20file%EF%BC%89%EF%BC%8C%E4%BC%9A%E5%B0%86%E8%A2%AB%E4%BF%AE%E6%94%B9%E7%9A%84%E6%96%87%E4%BB%B6%E6%8F%90%E4%BA%A4%E5%88%B0%E6%9A%82%E5%AD%98%E5%8C%BA%E3%80%82add%20-u%20%E4%B8%8D%E4%BC%9A%E6%8F%90%E4%BA%A4%E6%96%B0%E6%96%87%E4%BB%B6%EF%BC%88untracked%20file%EF%BC%89%0A%0A%60%60%60shell%0Agit%20add%20-u%0A%60%60%60%0A%0A%3E%20%E6%8A%8A%E5%B7%A5%E4%BD%9C%E6%97%B6%E7%9A%84%E6%89%80%E6%9C%89%E5%8F%98%E5%8C%96%E6%8F%90%E4%BA%A4%E5%88%B0%E6%9A%82%E5%AD%98%E5%8C%BA%EF%BC%8C%E5%8C%85%E6%8B%AC%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E4%BF%AE%E6%94%B9(modified)%E4%BB%A5%E5%8F%8A%E6%96%B0%E6%96%87%E4%BB%B6(new)%EF%BC%8C%E4%BD%86%E4%B8%8D%E5%8C%85%E6%8B%AC%E8%A2%AB%E5%88%A0%E9%99%A4%E7%9A%84%E6%96%87%E4%BB%B6%0A%0A%60%60%60shell%0Agit%20add%20.%20%0A%60%60%60%0A%0A%3E%20%E6%98%AF%E4%B8%8A%E9%9D%A2%E4%B8%A4%E4%B8%AA%E5%8A%9F%E8%83%BD%E7%9A%84%E5%90%88%E9%9B%86%0A%0A%60%60%60shell%0Agit%20add%20-A%0A%60%60%60%0A%0A%0A%0A%60%60%60shell%0Agit%20reset%0A%60%60%60%0A%0AThis%20form%20resets%20the%20index%20entries%20for%20all%20%3Cpaths%3E%20to%20their%20state%20at%20%3Ctree-ish%3E.%20(It%20does%20not%20affect%20the%20working%20tree%20or%20the%20current%20branch.)%0A%0AThis%20means%20that%20git%20reset%20%3Cpaths%3E%20is%20the%20opposite%20of%20git%20add%20%3Cpaths%3E.%0A%0A%0A%0A%3E%20%E4%BD%BF%E7%94%A8%20git%20diff%20%E5%91%BD%E4%BB%A4%E5%86%8D%E5%8A%A0%E4%B8%8A%20--cached%20%E5%8F%82%E6%95%B0%EF%BC%8C%E7%9C%8B%E7%9C%8B%E7%BC%93%E5%AD%98%E5%8C%BA%E4%B8%AD%E5%93%AA%E4%BA%9B%E6%96%87%E4%BB%B6%E8%A2%AB%E4%BF%AE%E6%94%B9%E4%BA%86%E3%80%82%0A%3E%0A%3E%20%E8%BF%9B%E5%85%A5%E5%88%B0git%20diff%20--cached%E7%95%8C%E9%9D%A2%E5%90%8E%E9%9C%80%E8%A6%81%E8%BE%93%E5%85%A5q%E6%89%8D%E5%8F%AF%E4%BB%A5%E9%80%80%E5%87%BA%EF%BC%9A%0A%0A%60%60%60shell%0Agit%20diff%20--cached%0A%60%60%60%0A%0A%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89--cached%E5%8F%82%E6%95%B0%EF%BC%8Cgit%20diff%20%E4%BC%9A%E6%98%BE%E7%A4%BA%E5%BD%93%E5%89%8D%E4%BD%A0%E6%89%80%E6%9C%89%E5%B7%B2%E5%81%9A%E7%9A%84%E4%BD%86%E6%B2%A1%E6%9C%89%E5%8A%A0%E5%85%A5%E5%88%B0%E7%B4%A2%E5%BC%95%E9%87%8C%E7%9A%84%E4%BF%AE%E6%94%B9%0A%0A%E4%BD%BF%E7%94%A8git%20commit%E5%91%BD%E4%BB%A4%E6%8F%90%E4%BA%A4%E5%88%B0%E6%9C%AC%E5%9C%B0%E4%BB%A3%E7%A0%81%E5%BA%93%2C%20%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8-m%E6%B7%BB%E5%8A%A0%E6%9C%AC%E6%AC%A1%E4%BF%AE%E6%94%B9%E7%9A%84%E6%B3%A8%E9%87%8A%0A%0A%60%60%60shell%0Agit%20commit%20-m%20%22add%203%20files%22%0A%60%60%60%0A%0A%20%5Bmaster%20(root-commit)%20054c93f%5D%20add%203%20files%0A%0A%203%20files%20changed%2C%205%20insertions(%2B)%0A%0A%20create%20mode%20100644%20file1%0A%0A%20create%20mode%20100644%20file2%0A%0A%20create%20mode%20100644%20file3%0A%0A%20%0A%0A%20%E4%BB%8E%E6%9A%82%E5%AD%98%E5%8C%BA%E7%A7%BB%E9%99%A4%E6%96%87%E4%BB%B6%0A%0A%60%60%60shell%0A%20git%20rm%20--cached%20filename%0A%60%60%60%0A%0A%20%E5%BC%BA%E5%88%B6%E4%BB%8E%E5%B7%A5%E4%BD%9C%E5%8C%BA%E5%92%8C%E6%9A%82%E5%AD%98%E5%8C%BA%E7%A7%BB%E9%99%A4%E6%96%87%E4%BB%B6%0A%0A%60%60%60shell%0A%20git%20rm%20-f%20filename%0A%60%60%60%0A%0A%20%0A%0A%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E6%8C%87%E5%AE%9A%E5%BF%AB%E7%85%A7%E5%90%8D%E5%AD%97%E5%88%99%E4%BB%8E%E6%9A%82%E5%AD%98%E5%8C%BA%E6%A3%80%E5%87%BA%E6%96%87%E4%BB%B6%E5%88%B0%E5%B7%A5%E4%BD%9C%E5%8C%BA%0A%0A%60%60%60shell%0A%20git%20checkout%20--%20filename%0A%60%60%60%0A%0A%E5%A6%82%E6%9E%9C%E6%8C%87%E5%AE%9A%E4%BA%86%E5%BF%AB%E7%85%A7%E5%90%8D%E5%AD%97%E5%88%99%E4%BB%8E%E4%BB%93%E5%BA%93%E6%A3%80%E5%87%BA%E6%96%87%E4%BB%B6%E5%88%B0%E6%9A%82%E5%AD%98%E5%8C%BA%E5%92%8C%E5%B7%A5%E4%BD%9C%E5%8C%BA%0A%0A%60%60%60shell%0A%20git%20checkout%20HEAD~%20filename%0A%60%60%60%0A%0A%20%0A%0A%E9%99%A4%E4%BA%86%E7%94%A8git%20add%20%E5%91%BD%E4%BB%A4%EF%BC%8C%E6%88%91%E4%BB%AC%E8%BF%98%E5%8F%AF%E4%BB%A5%E7%94%A8%E4%B8%8B%E9%9D%A2%E7%9A%84%E5%91%BD%E4%BB%A4%E5%B0%86%E6%89%80%E6%9C%89%E6%B2%A1%E6%9C%89%E5%8A%A0%E5%88%B0%E7%BC%93%E5%AD%98%E5%8C%BA%E7%9A%84%E4%BF%AE%E6%94%B9%E4%B9%9F%E4%B8%80%E8%B5%B7%E6%8F%90%E4%BA%A4%EF%BC%8C%E4%BD%86-a%E5%91%BD%E4%BB%A4%E4%B8%8D%E4%BC%9A%E6%B7%BB%E5%8A%A0%E6%96%B0%E5%BB%BA%E7%9A%84%E6%96%87%E4%BB%B6%E3%80%82%0A%0A%60%60%60shell%0A%20git%20commit%20-am%20%22add%203%20files%22%0A%60%60%60%0A%0A%0A%0A%E4%BF%AE%E6%94%B9%E6%9C%80%E6%96%B0%E4%B8%80%E6%AC%A1%E6%8F%90%E4%BA%A4%E6%97%B6%E7%9A%84%E6%89%B9%E6%B3%A8%E4%BF%A1%E6%81%AF%0A%0A%60%60%60shell%0Agit%20commit%20--amend%0Agit%20commit%20--amend%20-m%20%22fix%20the%20comment%20for%20last%20submittion%22%0A%60%60%60%0A%0A%20%0A%0A%E5%A6%82%E6%9E%9C%E6%98%AF%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%EF%BC%8C%E5%88%99%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8git%20rm%E5%91%BD%E4%BB%A4%E5%88%A0%E9%99%A4%E5%90%8E%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%B0%86%E5%B7%B2%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E7%9A%84%E4%BF%A1%E6%81%AF%E6%B7%BB%E5%8A%A0%E5%88%B0%E7%BC%93%E5%AD%98%E5%8C%BA%EF%BC%8C%0A%0Agit%20commit%E6%8F%90%E4%BA%A4%E5%90%8E%E5%B0%B1%E4%BC%9A%E5%B0%86%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E4%B8%AD%E7%9A%84%E5%AF%B9%E5%BA%94%E6%96%87%E4%BB%B6%E5%88%A0%E9%99%A4%0A%0A%E5%8F%AA%E5%88%A0%E9%99%A4%E5%B7%A5%E4%BD%9C%E5%8C%BA%E5%92%8C%E6%9A%82%E5%AD%98%E5%8C%BA%E7%9A%84%E6%96%87%E4%BB%B6%2C%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%8F%96%E6%B6%88%E8%B7%9F%E8%B8%AA.%0A%0A%60%60%60shell%0Agit%20rm%20file3%0A%60%60%60%0A%0A%E5%B0%86file1%E7%9A%84%E5%90%8D%E5%AD%97%E6%94%B9%E4%B8%BAfile2%0A%0A%60%60%60shell%0Agit%20mv%20file1%20file2%0A%60%60%60%0A%0A%E7%A7%BB%E5%8A%A8HEAD%E7%9A%84%E6%8C%87%E5%90%91%E5%B0%86%E5%85%B6%E6%8C%87%E5%90%91%E4%B8%8A%E4%B8%80%E4%B8%AA%E7%89%88%E6%9C%AC%E5%B9%B6%E5%B0%86%E4%B8%8A%E4%B8%80%E4%B8%AA%E7%89%88%E6%9C%AC%E5%9B%9E%E6%BB%9A%E5%88%B0%E6%9A%82%E5%AD%98%E5%8C%BA%0A%0A%60%60%60shell%0Agit%20reset%20%5B--mixed%5D%20HEAD~%0A%60%60%60%0A%0A%E7%A7%BB%E5%8A%A8HEAD%E7%9A%84%E6%8C%87%E5%90%91%E5%B0%86%E5%85%B6%E6%8C%87%E5%90%91%E4%B8%8A%E4%B8%80%E4%B8%AA%E7%89%88%E6%9C%AC%E5%B9%B6%E5%B0%86%E4%B8%8A%E4%B8%8A%E4%B8%80%E4%B8%AA%E7%89%88%E6%9C%AC%E5%9B%9E%E6%BB%9A%E5%88%B0%E6%9A%82%E5%AD%98%E5%8C%BA%0A%0A%60%60%60shell%0Agit%20reset%20HEAD~2%0A%60%60%60%0A%0A%E7%A7%BB%E5%8A%A8HEAD%E7%9A%84%E6%8C%87%E5%90%91%E5%B0%86%E5%85%B6%E6%8C%87%E5%90%91%E4%B8%8A%E4%B8%80%E4%B8%AA%E7%89%88%E6%9C%AC%2C%E7%9B%B8%E5%BD%93%E4%BA%8E%E5%9B%9E%E6%BB%9A%E4%BA%86%E4%B8%80%E6%AC%A1%E9%94%99%E8%AF%AF%E7%9A%84commit%0A%0A%60%60%60shell%0Agit%20reset%20--soft%20HEAD~%0A%60%60%60%0A%0A%E5%9B%9E%E6%BB%9A%E5%88%B0%E6%8C%87%E5%AE%9A%E7%89%88%E6%9C%AC%0A%0Agit%20reset%20753e10%20%E5%8D%B3%E5%8F%AF%E4%BB%A5%E5%9B%9E%E6%BB%9A%E5%8F%88%E5%8F%AF%E4%BB%A5%E5%90%91%E5%89%8D%E6%BB%9A%2C%E4%BD%86%E5%8F%AA%E6%BB%9A%E5%88%B0%E6%9A%82%E5%AD%98%E5%8C%BA%0A%0A%60%60%60shell%0Agit%20reset%20--hard%20753e10%20%E4%B8%80%E6%AD%A5%E5%9B%9E%E6%BB%9A%E5%88%B0%E4%BB%93%E5%BA%93%E5%8C%BA%0A%60%60%60%0A%0A%E5%B0%86HEAD%E6%8C%87%E5%90%91%E7%9A%84%E5%88%86%E6%94%AF%E5%8F%8AHEAD%E6%9C%AC%E8%BA%AB%E5%88%87%E5%88%B0%E7%9B%AE%E6%A0%87%E5%88%86%E6%94%AF%0A%0Agit%20reset%20--%20hard%20branchName%20%0A%0A%3E%20%E5%88%9B%E5%BB%BA%E5%88%86%E6%94%AF%0A%0A%60%60%60shell%0Agit%20branch%20branchName%0A%60%60%60%0A%0A%E5%88%9B%E5%BB%BA%E5%B9%B6%E5%88%87%E6%8D%A2%E5%88%B0%E6%96%B0%E5%88%86%E6%94%AF%0A%0A%60%60%60shell%0Agit%20checkout%20-b%20branchName%0A%60%60%60%0A%0A%3E%20%E5%88%87%E6%8D%A2%E5%88%86%E6%94%AFf%0A%0A%60%60%60%0Agit%20checkout%20branchName%0A1%3A%E4%BF%AE%E6%94%B9%E5%BF%AB%E7%85%A7%E6%8C%87%E9%92%88%0A2%3A%E5%B0%86%E5%BD%93%E5%89%8D%E5%BF%AB%E7%85%A7%E7%9A%84%E5%86%85%E5%AE%B9%E8%BF%98%E5%8E%9F%E5%88%B0%E5%B7%A5%E4%BD%9C%E5%8C%BA%E5%92%8C%E6%9A%82%E5%AD%98%E5%8C%BA%0Agit%20checkout%20branchId%0A%E6%88%96%0Agit%20checkout%20HEAD~%0A%60%60%60%0A%0A%60%60%60shell%0Agit%20log%20--decorate%20--oneline%20--graph%20--all%0A%60%60%60%0A%0A%60%60%60shell%0Agit%20merge%20branchName%0A%60%60%60%0A%0A%3E%20%E6%AF%94%E8%BE%83%E4%B8%A4%E4%B8%AA%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%0A%0A%60%60%60shell%0Agit%20diff%20versionId1%20versionId2%0A%60%60%60%0A%0A%3E%20%E6%AF%94%E8%BE%83%E5%B7%A5%E4%BD%9C%E5%8C%BA%E4%B8%8E%E6%9F%90%E4%B8%80%E7%89%88%E6%9C%AC%0A%0A%60%60%60shell%0Agit%20diff%20versionId%0A%60%60%60%0A%0A%E6%AF%94%E8%BE%83%E5%B7%A5%E4%BD%9C%E5%8C%BA%E5%92%8C%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%0A%0Agit%20diff%20HEAD%0A%0A%3E%20%E8%A6%81%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8D%E9%85%8D%E7%BD%AE%E6%9C%89%E5%93%AA%E4%BA%9B%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%0A%0A%60%60%60%0Agit%20remote%20-v%0A%60%60%60%0A%0A%E5%9C%A8%E5%85%8B%E9%9A%86%E5%AE%8C%E6%9F%90%E4%B8%AA%E9%A1%B9%E7%9B%AE%E5%90%8E%EF%BC%8C%E8%87%B3%E5%B0%91%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E4%B8%80%E4%B8%AA%E5%90%8D%E4%B8%BA%20origin%20%E7%9A%84%E8%BF%9C%E7%A8%8B%E5%BA%93%EF%BC%8CGit%20%E9%BB%98%E8%AE%A4%E4%BD%BF%E7%94%A8%E8%BF%99%E4%B8%AA%E5%90%8D%E5%AD%97%E6%9D%A5%E6%A0%87%E8%AF%86%E4%BD%A0%E6%89%80%E5%85%8B%E9%9A%86%E7%9A%84%E5%8E%9F%E5%A7%8B%E4%BB%93%E5%BA%93.%0A%0A%E5%B0%86%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E5%85%B3%E8%81%94%E5%88%B0%E8%BF%9C%E7%AB%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20git%20remote%20%E5%91%BD%E4%BB%A4%EF%BC%8C%E4%B8%8D%E5%90%8C%E4%BA%8E%E5%88%9A%E5%88%9A%E7%9A%84%20git%20clone%20%E5%91%BD%E4%BB%A4%EF%BC%8C%E7%9B%B4%E6%8E%A5%E5%B0%86%E8%BF%9C%E7%AB%AF%E7%9A%84%E4%BB%93%E5%BA%93%E5%85%8B%E9%9A%86%E4%B8%8B%E6%9D%A5%E3%80%82%20%E6%88%91%E4%BB%AC%E5%BD%93%E5%89%8D%E7%9A%84%E4%BB%93%E5%BA%93%E6%98%AF%E4%BD%BF%E7%94%A8%20git%20init%20%E5%88%9D%E5%A7%8B%E5%8C%96%E7%9A%84%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%EF%BC%8C%E6%89%80%E4%BB%A5%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E5%B0%86%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E4%B8%8E%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E5%85%B3%E8%81%94%EF%BC%8C%E4%BD%BF%E7%94%A8%E5%A6%82%E4%B8%8B%E5%91%BD%E4%BB%A4%EF%BC%88%E9%9C%80%E8%A6%81%E4%BF%AE%E6%94%B9%E4%B8%8B%E9%9D%A2%E7%9A%84%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E5%9C%B0%E5%9D%80%E4%B8%BA%E8%87%AA%E5%B7%B1%E7%9A%84%E4%BB%93%E5%BA%93%E5%9C%B0%E5%9D%80%EF%BC%89%EF%BC%9A%0A%0A%60%60%60shell%0Agit%20remote%20add%20origin%20https%3A%2F%2Fgithub.com%2FApeTogether%2Frepo1.git%0Agit%20remote%20add%20origin%20git%40github.com%3AApeTogether%2Frepo1.git%0Agit%20push%20-u%20origin%20master%0Agit%20push%20-u%20origin%20branch_001%0A%60%60%60%0A%0A%E8%BF%99%E4%B8%AA%E6%97%B6%E5%80%99%E5%A6%82%E6%9E%9C%E6%9C%AC%E5%9C%B0%E7%9A%84%E4%BB%93%E5%BA%93%E8%BF%9E%E6%8E%A5%E5%88%B0%E4%BA%86%E8%BF%9C%E7%A8%8BGit%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E4%B8%8B%E9%9D%A2%E7%9A%84%E5%91%BD%E4%BB%A4%E5%B0%86%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E5%90%8C%E6%AD%A5%E5%88%B0%E8%BF%9C%E7%AB%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%9A%0A%0A%5C%23%20%E9%9C%80%E8%A6%81%E8%BE%93%E5%85%A5%E4%BB%93%E5%BA%93%E5%AF%B9%E5%BA%94%E7%9A%84%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E5%AF%86%E7%A0%81%0A%0A%24%20git%20push%20-u%20origin%20master%0A%0Agit%20push%20https%3A%2F%2Fgithub.com%2FApeTogether%2FRepoTest01.git%20master%0A%0A%5C%23%23%20create%20a%20new%20repository%20on%20the%20command%20line%0A%0Aecho%20%22%23%20RepoTest01%22%20%3E%3E%20README.md%0A%0Agit%20init%0A%0Agit%20add%20README.md%0A%0Agit%20commit%20-m%20%22first%20commit%22%0A%0Agit%20remote%20add%20origin%20git%40github.com%3AApeTogether%2FRepoTest01.git%0A%0Agit%20push%20-u%20origin%20master%0A%0A%5C%23%23%20push%20an%20existing%20repository%20from%20the%20command%20line%0A%0Agit%20remote%20add%20origin%20git%40github.com%3AApeTogether%2FRepoTest01.git%0A%0Agit%20push%20-u%20origin%20master%0A%0A%E9%80%9A%E8%BF%87.gitignore%E5%B0%86%E6%96%87%E4%BB%B6%E4%B8%8D%E7%BA%B3%E5%85%A5%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%0A%0A%E2%80%8B%09touch%20.gitignore%0A%0A%E2%80%8B%09index.*%0A%0A%E2%80%8B%09.gitignore%0A%0A*%E5%8C%B9%E9%85%8D%E9%9B%B6%E4%B8%AA%E6%88%96%E4%BB%BB%E6%84%8F%E5%A4%9A%E4%B8%AA%E5%AD%97%E7%AC%A6%0A%0A%5Babc%5D%E5%8C%B9%E9%85%8D%E4%BB%BB%E6%84%8F%E4%B8%80%E4%B8%8B%E5%9C%A8%E6%8B%AC%E5%8F%B7%E5%86%85%E7%9A%84%E5%AD%97%E7%AC%A6%0A%0A%3F%E5%8F%AA%E5%8C%B9%E9%85%8D%E4%B8%80%E4%B8%AA%E4%BB%BB%E6%84%8F%E5%AD%97%E7%AC%A6%0A%0A%5B0-9%5D%5Ba-z%5D%E5%8C%B9%E9%85%8D%E8%8C%83%E5%9B%B4%0A%0A%60%60%60shell%0Agit%20help%20git-command%0Acd%20%22D%3A%5CAI_Project%5Cfinal-report-service%22%0Agit%20log%0Agit%20status%0Agit%20stash%20%3D%3D%20git%20stash%20push%0Agit%20stash%20list%0Agit%20stash%20show%0Agit%20stash%20pop%0Agit%20checkout%20%5Bbranch%20name%5D%0Agit%20pull%0A%60%60%60%0A%0A%0A%0A%3E%20delete%20a%20local%20branch%0A%0A%60%60%60shell%0Agit%20branch%20%5B-d%20or%20-D%5D%20develop%0A%60%60%60%0A%0AIf%20during%20the%20merge%20you%20get%20a%20conflict%2C%20the%20best%20way%20to%20undo%20the%20merge%20is%3A%0A%0A%60%60%60shell%0Agit%20merge%20--abort%0A%60%60%60%0A%0A%0A%0A%3E%20merge%20the%20hotfix%20branch%20back%20into%20your%20master%20branch%20%0A%0A%60%60%60shell%0A%24%20git%20checkout%20master%20%0A%24%20git%20checkout%20-b%20hotfix%20origin%2Fhotfix%20%5B%E5%B0%86%E8%BF%9C%E7%A8%8Bhotfix%E6%8B%89%E5%88%B0%E6%9C%AC%E5%9C%B0%E5%B9%B6%E6%A3%80%E5%87%BA%5D%0A%24%20git%20merge%20hotfix%0A%60%60%60%0A%0Agit%20push%20%3Cremote%3E%20%3Clocalbranch%3Aremotebranch%3E%0A%0A%60%60%60%0A%24git%20push%20origin%20master%3Amaster%0A%60%60%60%0A%0A%3E%20%E5%9C%A8local%20repository%E4%B8%AD%E6%89%BE%E5%88%B0%E5%90%8D%E5%AD%97%E4%B8%BAmaster%E7%9A%84branch%EF%BC%8C%E4%BD%BF%E7%94%A8%E5%AE%83%E5%8E%BB%E6%9B%B4%E6%96%B0remote%20repository%E4%B8%8B%E5%90%8D%E5%AD%97%E4%B8%BAmaster%E7%9A%84branch%EF%BC%8C%E5%A6%82%E6%9E%9Cremote%20repository%E4%B8%8B%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%90%8D%E5%AD%97%E6%98%AFmaster%E7%9A%84branch%EF%BC%8C%E9%82%A3%E4%B9%88%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AA%0A%0A%3E%20%E5%86%92%E5%8F%B7%E5%89%8D%E8%A1%A8%E7%A4%BAlocal%20branch%E7%9A%84%E5%90%8D%E5%AD%97%EF%BC%8C%E5%86%92%E5%8F%B7%E5%90%8E%E8%A1%A8%E7%A4%BAremote%20repository%E4%B8%8B%20branch%E7%9A%84%E5%90%8D%E5%AD%97%E3%80%82%E6%B3%A8%E6%84%8F%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%BD%A0%E7%9C%81%E7%95%A5%E4%BA%86%3Cdst%3E%EF%BC%8Cgit%E5%B0%B1%E8%AE%A4%E4%B8%BA%E4%BD%A0%E6%83%B3push%E5%88%B0remote%20repository%E4%B8%8B%E5%92%8Clocal%20branch%E7%9B%B8%E5%90%8C%E5%90%8D%E5%AD%97%E7%9A%84branch%0A%0A%3E%E5%85%B3%E8%81%94%E4%B9%8B%E5%90%8E%E5%86%8D%E6%89%A7%E8%A1%8Cgit%20pull%2C%20git%20push%E6%93%8D%E4%BD%9C%E6%97%B6%E5%B0%B1%E4%B8%8D%E9%9C%80%E8%A6%81%E6%8C%87%E5%AE%9A%E5%AF%B9%E5%BA%94%E7%9A%84%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF%0A%60%60%60shell%0Agit%20push%20--set-upstream%20origin%20CFT-73%20%3D%3D%20git%20push%20-u%20origin%20CFT-73%0A%60%60%60%0A%0A%0A%0A%3E%20forch%20push%20the%20commits%20into%20remote%20branch%20FU-382%0A%0A%60%60%60shell%0Agit%20push%20-f%20-u%20origin%20FU-382%0A%60%60%60%0A%0Ayou%20get%20a%20far%20more%20simplified%20output%20from%20the%20command%0A%0A%0A%0Agit%20status%20-s%20%0A%0Aunstaging%20the%20staged%20file%0A%0Agit%20reset%20HEAD%20CONTRIBUTING.md%0A%0Aunmodifying%20a%20Modified%20File%0A%0Agit%20checkout%20--%20CONTRIBUTING.md%0A%0A%0A%0Awhich%20shows%20you%20the%20URLs%20that%20Git%20has%20stored%20for%20the%20shortname%20to%20be%20used%20when%20reading%20and%20writing%20to%20that%20remote%0A%0A%24%20git%20remote%20-v%20origin%09https%3A%2F%2Fgithub.com%2Fschacon%2Fticgit%20(fetch)%20origin%09https%3A%2F%2Fgithub.com%2Fschacon%2Fticgit%20(push)%0A%0A**git%20fetch%20orgin%20master**%20%2F%2F%E5%B0%86%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E7%9A%84master%E5%88%86%E6%94%AF%E4%B8%8B%E8%BD%BD%E5%88%B0%E6%9C%AC%E5%9C%B0%E5%BD%93%E5%89%8Dbranch%E4%B8%AD%0A%0Athe%20git%20fetch%20origin%20command%20only%20downloads%20the%20data%20to%20your%20local%20repository%E2%80%89%E2%80%94%E2%80%89it%20doesn%E2%80%99t%20automatically%20merge%20it%20with%20any%20of%20your%20work%20or%20modify%20what%20you%E2%80%99re%20currently%20working%20on%0A%0AYou%20have%20to%20merge%20it%20manually%20into%20your%20work%20when%20you%E2%80%99re%20ready.%0A%0Achange%20the%20remtoe%20url%20in%20local%20repository%0A%0Agit%20remote%20set-url%20origin%20git%3A%2F%2Fnew.url.here%0A%0Agit%20remote%20set-url%20origin%20%5Bhttps%3A%2F%2Fgithub.com%2FChrisLi716%2Fmyhadoopdemo.git%5D(https%3A%2F%2Fgithub.com%2FChrisLi716%2Fjavademo.git)%0A%0A%0A%0A%23%23%23%23%23%20%E6%89%A7%E8%A1%8C%E5%A6%82%E4%B8%8B%E5%91%BD%E4%BB%A4%E8%AE%B0%E4%BD%8F%E6%8F%90%E4%BA%A4%E6%97%B6%E7%9A%84%E5%B8%90%E5%8F%B7%E5%92%8C%E5%AF%86%E7%A0%81%0A%0Agit%20config%20--global%20credential.helper%20store

Validator

创建时间:2021/12/25 14:23
更新时间:2022/3/28 21:53
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzI4NTM1NDgwNw==&mid=2247500777&idx=2&sn=793458ee125e5112555b73b0a9d21164&chksm=ebeffdb1dc9874a780c1a9afc52d37c138d6d6b585f77380cb4ae451d8008e16f312e51dbbd4&mpshare=1&scene=24&srcid=1224pjqgZtXA64921sHaWJBa&sharer_sharetime=1640309675045&sharer_shareid=cfcd208495d565ef66e7dff9f98764da&key=756768bae9c758c235ac8f86ed0fd9616c085c1e1a0b6044ab0e7ffdb95f9cd3b7e7720872cea7b1fa7d6156d0eef8ffa72611ef4ebe3b60821af566e2775d43316ffde07a0f274d1963426af551307e1202c47e89670f8ab7b7274b68de814d3f138576803826efab42788602ca7a0ae6b93d3e2c39db3e662bb7d8782e125f&ascene=14&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=63030073&lang=en&exportkey=AfaoKaJ0RO4z%2FOO5DPwEugM%3D&pass_ticket=ByAZBBus39Rmg9zs8xvlwPzql0eVYFNu8My9oInP9uPNwUCNOGbrfo8vrD0jxk3T&wx_header=0&fontgear=2

1 为什么要用validator

javax.validation的一系列注解可以帮我们完成参数校验,免去繁琐的串行校验

1.1 什么是 javax.validation

JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面(面向注解编程的时代),就可以在需要校验的时候进行校验了

1.2 引入 javax.validation

在SpringBoot中已经包含在starter-web中
在其他项目中可以引用依赖,并自行调整版本:

<!--jsr 303-->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
<!-- hibernate validator-->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.2.0.Final</version>
</dependency>

此处只列出Hibernate Validator提供的大部分验证约束注解,请参考hibernate validator官方文档了解其他验证约束注解和进行自定义的验证约束注解定义。

2 怎么玩

2.1 @Validated 声明要检查的参数

/**
 * 走参数校验注解
 *
 * @param userDTO
 * @return
 */
@PostMapping("/save/valid")
public RspDTO save(@RequestBody @Validated UserDTO userDTO) {
    userService.save(userDTO);
    return RspDTO.success();
}

2.2 对参数的字段进行注解标注

import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.Date;

@Data
public class UserDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    /*** 用户ID*/
    @NotNull(message = "用户id不能为空")
    private Long userId;
    
    /** 用户名*/
    @NotBlank(message = "用户名不能为空")
    @Length(max = 20, message = "用户名不能超过20个字符")
    @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用户昵称限制:最多20字符,包含文字、字母和数字")
    private String username;
    
    /** 手机号*/
    @NotBlank(message = "手机号不能为空")
    @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
    private String mobile;

    /**性别*/
    private String sex;

    /** 邮箱*/
    @NotBlank(message = "联系邮箱不能为空")
    @Email(message = "邮箱格式不对")
    private String email;

    /** 密码*/
    private String password;

    /*** 创建时间 */
    @Future(message = "时间必须是将来时间")
    private Date createTime;

}

2.3 在全局校验中增加校验异常

MethodArgumentNotValidException 是springBoot中进行绑定参数校验时的异常,需要在springBoot中处理
其他需要处理 ConstraintViolationException 异常进行处理.

import com.boot.lea.mybot.dto.RspDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;


/**
 * @author Lilun
 * @ClassName: GlobalExceptionHandler
 * @Description: 全局异常处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private static int DUPLICATE_KEY_CODE = 1001;
    private static int PARAM_FAIL_CODE = 1002;
    private static int VALIDATION_CODE = 1003;

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(BizException.class)
    public RspDTO handleRRException(BizException e) {
        logger.error(e.getMessage(), e);
        return new RspDTO(e.getCode(), e.getMessage());
    }

    /**
     * 方法参数校验
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public RspDTO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        logger.error(e.getMessage(), e);
        return new RspDTO(PARAM_FAIL_CODE, e.getBindingResult().getFieldError().getDefaultMessage());
    }
    
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultVo<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
        logger.error("参数错误,异常信息->{}", ex.getMessage());
        String message = ex.getBindingResult().getAllErrors().stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return fail(HttpStatus.BAD_REQUEST.value(), message, ex);
    }   

    /**
     * ValidationException
     */
    @ExceptionHandler(ValidationException.class)
    public RspDTO handleValidationException(ValidationException e) {
        logger.error(e.getMessage(), e);
        return new RspDTO(VALIDATION_CODE, e.getCause().getMessage());
    }

    /**
     * ConstraintViolationException
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public RspDTO handleConstraintViolationException(ConstraintViolationException e) {
        logger.error(e.getMessage(), e);
        return new RspDTO(PARAM_FAIL_CODE, e.getMessage());
    }

    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultVo<?> constraintViolationExceptionHandler(ConstraintViolationException ex) {
      logger.error("参数错误,异常信息->{}", ex.getMessage());
      String message = ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
      return fail(HttpStatus.BAD_REQUEST.value(), message, ex);
    }
    @ExceptionHandler(NoHandlerFoundException.class)
    public RspDTO handlerNoFoundException(Exception e) {
        logger.error(e.getMessage(), e);
        return new RspDTO(404, "路径不存在,请检查路径是否正确");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public RspDTO handleDuplicateKeyException(DuplicateKeyException e) {
        logger.error(e.getMessage(), e);
        return new RspDTO(DUPLICATE_KEY_CODE, "数据重复,请检查后提交");
    }


    @ExceptionHandler(Exception.class)
    public RspDTO handleException(Exception e) {
        logger.error(e.getMessage(), e);
        return new RspDTO(500, "系统繁忙,请稍后再试");
    }
}

在ValidationMessages.properties 就是校验的message,有着已经写好的默认的message,且是支持i18n的,大家可以阅读源码赏析

3 自定义参数注解

3.1 自定义身份证校验注解

@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdentityCardNumberValidator.class)
public @interface IdentityCardNumber {

    String message() default "身份证号码不合法";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

这个注解是作用在Field字段上,运行时生效,
触发的是IdentityCardNumber这个验证类。

  • message 定制化的提示信息,主要是从ValidationMessages.properties里提取,也可以依据实际情况进行定制
  • groups 这里主要进行将validator进行分类,不同的类group中会执行不同的validator操作
  • payload 主要是针对bean的,使用不多。

3.2 然后自定义Validator

这个是真正进行验证的逻辑代码

public class IdentityCardNumberValidator implements ConstraintValidator<IdentityCardNumber, Object> {

    @Override
    public void initialize(IdentityCardNumber identityCardNumber) {
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        return IdCardValidatorUtils.isValidate18Idcard(o.toString());
    }
}

3.3 使用自定义的注解

 @NotBlank(message = "身份证号不能为空")    
 @IdentityCardNumber(message = "身份证信息有误,请核对后提交")
 private String clientCardNo;

3.4 使用groups的校验

如果同一个对象要复用,比如 UserDTO 在更新时候要校验userId,在保存的时候不需要校验userId,在两种情况下都要校验username,那就用上groups了
先定义groups的分组接口Create和Update

import javax.validation.groups.Default;

public interface Create extends Default {
}
import javax.validation.groups.Default;

public interface Update extends Default{
}

再在需要校验的地方@Validated 声明校验组

/**
 * 走参数校验注解的 groups 组合校验
 *
 * @param userDTO
 * @return
 */
@PostMapping("/update/groups")
public RspDTO update(@RequestBody @Validated(Update.class) UserDTO userDTO) {
    userService.updateById(userDTO);
    return RspDTO.success();
}

在DTO中的字段上定义好groups = {}的分组类型

@Data
public class UserDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    /*** 用户ID*/
    @NotNull(message = "用户id不能为空", groups = Update.class)
    private Long userId;

    /**
     * 用户名
     */
    @NotBlank(message = "用户名不能为空")
    @Length(max = 20, message = "用户名不能超过20个字符", groups = {Create.class, Update.class})
    @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用户昵称限制:最多20字符,包含文字、字母和数字")
    private String username;

    /**
     * 手机号
     */
    @NotBlank(message = "手机号不能为空")
    @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误", groups = {Create.class, Update.class})
    private String mobile;

    /**
     * 性别
     */
    private String sex;

    /**
     * 邮箱
     */
    @NotBlank(message = "联系邮箱不能为空")
    @Email(message = "邮箱格式不对")
    private String email;

    /**
     * 密码
     */
    private String password;

    /*** 创建时间 */
    @Future(message = "时间必须是将来时间", groups = {Create.class})
    private Date createTime;
}

注意:在声明分组的时候尽量加上 extend javax.validation.groups.Default 
否则,在你声明 @Validated(Update.class) 的时候,就会出现你在默认没添加groups = {} 的时候的校验组@Email(message = "邮箱格式不对"), 会不去校验, 因为默认的校验组是groups = {Default.class}.

3.5 restful风格用法

在多个参数校验,或者@RequestParam 形式时候,需要在controller上加注@Validated

@RestController
@RequestMapping("user/")
@Validated
public class UserController extends AbstractController {

    @GetMapping("/get")
    public RspDTO getUser(@RequestParam("userId") @NotNull(message = "用户id不能为空") Long userId) {
        User user = userService.selectById(userId);
        if (user == null) {
            return new RspDTO<User>().nonAbsent("用户不存在");
        }
        return new RspDTO<User>().success(user);
      }

}    
%5Btoc%5D%0A%23%23%201%20%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8validator%0A%3E%20%60javax.validation%60%E7%9A%84%E4%B8%80%E7%B3%BB%E5%88%97%E6%B3%A8%E8%A7%A3%E5%8F%AF%E4%BB%A5%E5%B8%AE%E6%88%91%E4%BB%AC%E5%AE%8C%E6%88%90%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%2C%E5%85%8D%E5%8E%BB%E7%B9%81%E7%90%90%E7%9A%84%E4%B8%B2%E8%A1%8C%E6%A0%A1%E9%AA%8C%0A%0A%0A%23%23%23%23%201.1%20%E4%BB%80%E4%B9%88%E6%98%AF%20%60javax.validation%60%0A%3E%20%60JSR303%60%20%E6%98%AF%E4%B8%80%E5%A5%97JavaBean%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%E7%9A%84%E6%A0%87%E5%87%86%EF%BC%8C%E5%AE%83%E5%AE%9A%E4%B9%89%E4%BA%86%E5%BE%88%E5%A4%9A%E5%B8%B8%E7%94%A8%E7%9A%84%E6%A0%A1%E9%AA%8C%E6%B3%A8%E8%A7%A3%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E5%B0%86%E8%BF%99%E4%BA%9B%E6%B3%A8%E8%A7%A3%E5%8A%A0%E5%9C%A8%E6%88%91%E4%BB%ACJavaBean%E7%9A%84%E5%B1%9E%E6%80%A7%E4%B8%8A%E9%9D%A2(%E9%9D%A2%E5%90%91%E6%B3%A8%E8%A7%A3%E7%BC%96%E7%A8%8B%E7%9A%84%E6%97%B6%E4%BB%A3)%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%9C%A8%E9%9C%80%E8%A6%81%E6%A0%A1%E9%AA%8C%E7%9A%84%E6%97%B6%E5%80%99%E8%BF%9B%E8%A1%8C%E6%A0%A1%E9%AA%8C%E4%BA%86%0A%0A%23%23%23%23%201.2%20%E5%BC%95%E5%85%A5%20%60javax.validation%60%0A%3E%20%E5%9C%A8SpringBoot%E4%B8%AD%E5%B7%B2%E7%BB%8F%E5%8C%85%E5%90%AB%E5%9C%A8starter-web%E4%B8%AD%0A%3E%20%E5%9C%A8%E5%85%B6%E4%BB%96%E9%A1%B9%E7%9B%AE%E4%B8%AD%E5%8F%AF%E4%BB%A5%E5%BC%95%E7%94%A8%E4%BE%9D%E8%B5%96%2C%E5%B9%B6%E8%87%AA%E8%A1%8C%E8%B0%83%E6%95%B4%E7%89%88%E6%9C%AC%3A%0A%60%60%60xml%0A%3C!--jsr%20303--%3E%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Ejavax.validation%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Evalidation-api%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E1.1.0.Final%3C%2Fversion%3E%0A%3C%2Fdependency%3E%0A%3C!--%20hibernate%20validator--%3E%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Eorg.hibernate%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Ehibernate-validator%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E5.2.0.Final%3C%2Fversion%3E%0A%3C%2Fdependency%3E%0A%60%60%60%0A!%5B6b9cdb64eab9dbfee8258bc8364cf936.png%5D(en-resource%3A%2F%2Fdatabase%2F1173%3A1)%0A%0A!%5B0fec5c6e6f0eda20c5dbab59d68a3c36.png%5D(en-resource%3A%2F%2Fdatabase%2F1177%3A1)%0A%0A%0A%0A%3E%20%E6%AD%A4%E5%A4%84%E5%8F%AA%E5%88%97%E5%87%BAHibernate%20Validator%E6%8F%90%E4%BE%9B%E7%9A%84%E5%A4%A7%E9%83%A8%E5%88%86%E9%AA%8C%E8%AF%81%E7%BA%A6%E6%9D%9F%E6%B3%A8%E8%A7%A3%EF%BC%8C%E8%AF%B7%E5%8F%82%E8%80%83hibernate%20validator%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%E4%BA%86%E8%A7%A3%E5%85%B6%E4%BB%96%E9%AA%8C%E8%AF%81%E7%BA%A6%E6%9D%9F%E6%B3%A8%E8%A7%A3%E5%92%8C%E8%BF%9B%E8%A1%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E9%AA%8C%E8%AF%81%E7%BA%A6%E6%9D%9F%E6%B3%A8%E8%A7%A3%E5%AE%9A%E4%B9%89%E3%80%82%0A%0A%0A%23%23%202%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%202.1%20%60%40Validated%60%20%E5%A3%B0%E6%98%8E%E8%A6%81%E6%A3%80%E6%9F%A5%E7%9A%84%E5%8F%82%E6%95%B0%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E8%B5%B0%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%E6%B3%A8%E8%A7%A3%0A%20*%0A%20*%20%40param%20userDTO%0A%20*%20%40return%0A%20*%2F%0A%40PostMapping(%22%2Fsave%2Fvalid%22)%0Apublic%20RspDTO%20save(%40RequestBody%20%40Validated%20UserDTO%20userDTO)%20%7B%0A%20%20%20%20userService.save(userDTO)%3B%0A%20%20%20%20return%20RspDTO.success()%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202.2%20%E5%AF%B9%E5%8F%82%E6%95%B0%E7%9A%84%E5%AD%97%E6%AE%B5%E8%BF%9B%E8%A1%8C%E6%B3%A8%E8%A7%A3%E6%A0%87%E6%B3%A8%0A%60%60%60java%0Aimport%20lombok.Data%3B%0Aimport%20org.hibernate.validator.constraints.Length%3B%0A%0Aimport%20javax.validation.constraints.*%3B%0Aimport%20java.io.Serializable%3B%0Aimport%20java.util.Date%3B%0A%0A%40Data%0Apublic%20class%20UserDTO%20implements%20Serializable%20%7B%0A%0A%20%20%20%20private%20static%20final%20long%20serialVersionUID%20%3D%201L%3B%0A%0A%20%20%20%20%2F***%20%E7%94%A8%E6%88%B7ID*%2F%0A%20%20%20%20%40NotNull(message%20%3D%20%22%E7%94%A8%E6%88%B7id%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%0A%20%20%20%20private%20Long%20userId%3B%0A%20%20%20%20%0A%20%20%20%20%2F**%20%E7%94%A8%E6%88%B7%E5%90%8D*%2F%0A%20%20%20%20%40NotBlank(message%20%3D%20%22%E7%94%A8%E6%88%B7%E5%90%8D%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%0A%20%20%20%20%40Length(max%20%3D%2020%2C%20message%20%3D%20%22%E7%94%A8%E6%88%B7%E5%90%8D%E4%B8%8D%E8%83%BD%E8%B6%85%E8%BF%8720%E4%B8%AA%E5%AD%97%E7%AC%A6%22)%0A%20%20%20%20%40Pattern(regexp%20%3D%20%22%5E%5B%5C%5Cu4E00-%5C%5Cu9FA5A-Za-z0-9%5C%5C*%5D*%24%22%2C%20message%20%3D%20%22%E7%94%A8%E6%88%B7%E6%98%B5%E7%A7%B0%E9%99%90%E5%88%B6%EF%BC%9A%E6%9C%80%E5%A4%9A20%E5%AD%97%E7%AC%A6%EF%BC%8C%E5%8C%85%E5%90%AB%E6%96%87%E5%AD%97%E3%80%81%E5%AD%97%E6%AF%8D%E5%92%8C%E6%95%B0%E5%AD%97%22)%0A%20%20%20%20private%20String%20username%3B%0A%20%20%20%20%0A%20%20%20%20%2F**%20%E6%89%8B%E6%9C%BA%E5%8F%B7*%2F%0A%20%20%20%20%40NotBlank(message%20%3D%20%22%E6%89%8B%E6%9C%BA%E5%8F%B7%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%0A%20%20%20%20%40Pattern(regexp%20%3D%20%22%5E%5B1%5D%5B3%2C4%2C5%2C6%2C7%2C8%2C9%5D%5B0-9%5D%7B9%7D%24%22%2C%20message%20%3D%20%22%E6%89%8B%E6%9C%BA%E5%8F%B7%E6%A0%BC%E5%BC%8F%E6%9C%89%E8%AF%AF%22)%0A%20%20%20%20private%20String%20mobile%3B%0A%0A%20%20%20%20%2F**%E6%80%A7%E5%88%AB*%2F%0A%20%20%20%20private%20String%20sex%3B%0A%0A%20%20%20%20%2F**%20%E9%82%AE%E7%AE%B1*%2F%0A%20%20%20%20%40NotBlank(message%20%3D%20%22%E8%81%94%E7%B3%BB%E9%82%AE%E7%AE%B1%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%0A%20%20%20%20%40Email(message%20%3D%20%22%E9%82%AE%E7%AE%B1%E6%A0%BC%E5%BC%8F%E4%B8%8D%E5%AF%B9%22)%0A%20%20%20%20private%20String%20email%3B%0A%0A%20%20%20%20%2F**%20%E5%AF%86%E7%A0%81*%2F%0A%20%20%20%20private%20String%20password%3B%0A%0A%20%20%20%20%2F***%20%E5%88%9B%E5%BB%BA%E6%97%B6%E9%97%B4%20*%2F%0A%20%20%20%20%40Future(message%20%3D%20%22%E6%97%B6%E9%97%B4%E5%BF%85%E9%A1%BB%E6%98%AF%E5%B0%86%E6%9D%A5%E6%97%B6%E9%97%B4%22)%0A%20%20%20%20private%20Date%20createTime%3B%0A%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%202.3%20%E5%9C%A8%E5%85%A8%E5%B1%80%E6%A0%A1%E9%AA%8C%E4%B8%AD%E5%A2%9E%E5%8A%A0%E6%A0%A1%E9%AA%8C%E5%BC%82%E5%B8%B8%0A%3E%20%60MethodArgumentNotValidException%60%20%E6%98%AFspringBoot%E4%B8%AD%E8%BF%9B%E8%A1%8C%E7%BB%91%E5%AE%9A%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%E6%97%B6%E7%9A%84%E5%BC%82%E5%B8%B8%2C%E9%9C%80%E8%A6%81%E5%9C%A8springBoot%E4%B8%AD%E5%A4%84%E7%90%86%0A%3E%20%E5%85%B6%E4%BB%96%E9%9C%80%E8%A6%81%E5%A4%84%E7%90%86%20%60ConstraintViolationException%60%20%E5%BC%82%E5%B8%B8%E8%BF%9B%E8%A1%8C%E5%A4%84%E7%90%86.%0A%0A%60%60%60java%0Aimport%20com.boot.lea.mybot.dto.RspDTO%3B%0Aimport%20org.slf4j.Logger%3B%0Aimport%20org.slf4j.LoggerFactory%3B%0Aimport%20org.springframework.dao.DuplicateKeyException%3B%0Aimport%20org.springframework.web.bind.MethodArgumentNotValidException%3B%0Aimport%20org.springframework.web.bind.annotation.ExceptionHandler%3B%0Aimport%20org.springframework.web.bind.annotation.RestControllerAdvice%3B%0Aimport%20org.springframework.web.servlet.NoHandlerFoundException%3B%0A%0Aimport%20javax.validation.ConstraintViolationException%3B%0Aimport%20javax.validation.ValidationException%3B%0A%0A%0A%2F**%0A%20*%20%40author%20Lilun%0A%20*%20%40ClassName%3A%20GlobalExceptionHandler%0A%20*%20%40Description%3A%20%E5%85%A8%E5%B1%80%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E5%99%A8%0A%20*%2F%0A%40RestControllerAdvice%0Apublic%20class%20GlobalExceptionHandler%20%7B%0A%0A%20%20%20%20private%20Logger%20logger%20%3D%20LoggerFactory.getLogger(getClass())%3B%0A%0A%20%20%20%20private%20static%20int%20DUPLICATE_KEY_CODE%20%3D%201001%3B%0A%20%20%20%20private%20static%20int%20PARAM_FAIL_CODE%20%3D%201002%3B%0A%20%20%20%20private%20static%20int%20VALIDATION_CODE%20%3D%201003%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%A4%84%E7%90%86%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BC%82%E5%B8%B8%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40ExceptionHandler(BizException.class)%0A%20%20%20%20public%20RspDTO%20handleRRException(BizException%20e)%20%7B%0A%20%20%20%20%20%20%20%20logger.error(e.getMessage()%2C%20e)%3B%0A%20%20%20%20%20%20%20%20return%20new%20RspDTO(e.getCode()%2C%20e.getMessage())%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40ExceptionHandler(MethodArgumentNotValidException.class)%0A%20%20%20%20public%20RspDTO%20handleMethodArgumentNotValidException(MethodArgumentNotValidException%20e)%20%7B%0A%20%20%20%20%20%20%20%20logger.error(e.getMessage()%2C%20e)%3B%0A%20%20%20%20%20%20%20%20return%20new%20RspDTO(PARAM_FAIL_CODE%2C%20e.getBindingResult().getFieldError().getDefaultMessage())%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20%40ExceptionHandler(value%20%3D%20MethodArgumentNotValidException.class)%0A%20%20%20%20%40ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)%0A%20%20%20%20public%20ResultVo%3C%3F%3E%20methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException%20ex)%20%7B%0A%20%20%20%20%20%20%20%20logger.error(%22%E5%8F%82%E6%95%B0%E9%94%99%E8%AF%AF%2C%E5%BC%82%E5%B8%B8%E4%BF%A1%E6%81%AF-%3E%7B%7D%22%2C%20ex.getMessage())%3B%0A%20%20%20%20%20%20%20%20String%20message%20%3D%20ex.getBindingResult().getAllErrors().stream()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.map(DefaultMessageSourceResolvable%3A%3AgetDefaultMessage).collect(Collectors.joining())%3B%0A%20%20%20%20%20%20%20%20return%20fail(HttpStatus.BAD_REQUEST.value()%2C%20message%2C%20ex)%3B%0A%20%20%20%20%7D%20%20%20%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20ValidationException%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40ExceptionHandler(ValidationException.class)%0A%20%20%20%20public%20RspDTO%20handleValidationException(ValidationException%20e)%20%7B%0A%20%20%20%20%20%20%20%20logger.error(e.getMessage()%2C%20e)%3B%0A%20%20%20%20%20%20%20%20return%20new%20RspDTO(VALIDATION_CODE%2C%20e.getCause().getMessage())%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20ConstraintViolationException%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40ExceptionHandler(ConstraintViolationException.class)%0A%20%20%20%20public%20RspDTO%20handleConstraintViolationException(ConstraintViolationException%20e)%20%7B%0A%20%20%20%20%20%20%20%20logger.error(e.getMessage()%2C%20e)%3B%0A%20%20%20%20%20%20%20%20return%20new%20RspDTO(PARAM_FAIL_CODE%2C%20e.getMessage())%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40ExceptionHandler(value%20%3D%20ConstraintViolationException.class)%0A%20%20%20%20%40ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)%0A%20%20%20%20public%20ResultVo%3C%3F%3E%20constraintViolationExceptionHandler(ConstraintViolationException%20ex)%20%7B%0A%20%20%20%20%20%20logger.error(%22%E5%8F%82%E6%95%B0%E9%94%99%E8%AF%AF%2C%E5%BC%82%E5%B8%B8%E4%BF%A1%E6%81%AF-%3E%7B%7D%22%2C%20ex.getMessage())%3B%0A%20%20%20%20%20%20String%20message%20%3D%20ex.getConstraintViolations().stream().map(ConstraintViolation%3A%3AgetMessage).collect(Collectors.joining())%3B%0A%20%20%20%20%20%20return%20fail(HttpStatus.BAD_REQUEST.value()%2C%20message%2C%20ex)%3B%0A%20%20%20%20%7D%0A%20%20%20%20%40ExceptionHandler(NoHandlerFoundException.class)%0A%20%20%20%20public%20RspDTO%20handlerNoFoundException(Exception%20e)%20%7B%0A%20%20%20%20%20%20%20%20logger.error(e.getMessage()%2C%20e)%3B%0A%20%20%20%20%20%20%20%20return%20new%20RspDTO(404%2C%20%22%E8%B7%AF%E5%BE%84%E4%B8%8D%E5%AD%98%E5%9C%A8%EF%BC%8C%E8%AF%B7%E6%A3%80%E6%9F%A5%E8%B7%AF%E5%BE%84%E6%98%AF%E5%90%A6%E6%AD%A3%E7%A1%AE%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40ExceptionHandler(DuplicateKeyException.class)%0A%20%20%20%20public%20RspDTO%20handleDuplicateKeyException(DuplicateKeyException%20e)%20%7B%0A%20%20%20%20%20%20%20%20logger.error(e.getMessage()%2C%20e)%3B%0A%20%20%20%20%20%20%20%20return%20new%20RspDTO(DUPLICATE_KEY_CODE%2C%20%22%E6%95%B0%E6%8D%AE%E9%87%8D%E5%A4%8D%EF%BC%8C%E8%AF%B7%E6%A3%80%E6%9F%A5%E5%90%8E%E6%8F%90%E4%BA%A4%22)%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%40ExceptionHandler(Exception.class)%0A%20%20%20%20public%20RspDTO%20handleException(Exception%20e)%20%7B%0A%20%20%20%20%20%20%20%20logger.error(e.getMessage()%2C%20e)%3B%0A%20%20%20%20%20%20%20%20return%20new%20RspDTO(500%2C%20%22%E7%B3%BB%E7%BB%9F%E7%B9%81%E5%BF%99%2C%E8%AF%B7%E7%A8%8D%E5%90%8E%E5%86%8D%E8%AF%95%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%20%0A%0A%3E%20%E5%9C%A8ValidationMessages.properties%20%E5%B0%B1%E6%98%AF%E6%A0%A1%E9%AA%8C%E7%9A%84message%2C%E6%9C%89%E7%9D%80%E5%B7%B2%E7%BB%8F%E5%86%99%E5%A5%BD%E7%9A%84%E9%BB%98%E8%AE%A4%E7%9A%84message%2C%E4%B8%94%E6%98%AF%E6%94%AF%E6%8C%81i18n%E7%9A%84%2C%E5%A4%A7%E5%AE%B6%E5%8F%AF%E4%BB%A5%E9%98%85%E8%AF%BB%E6%BA%90%E7%A0%81%E8%B5%8F%E6%9E%90%0A%0A%0A%23%23%203%20%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%82%E6%95%B0%E6%B3%A8%E8%A7%A3%0A%0A%23%23%23%23%203.1%20%E8%87%AA%E5%AE%9A%E4%B9%89%E8%BA%AB%E4%BB%BD%E8%AF%81%E6%A0%A1%E9%AA%8C%E6%B3%A8%E8%A7%A3%0A%60%60%60java%0A%40Documented%0A%40Target(%7BElementType.PARAMETER%2C%20ElementType.FIELD%7D)%0A%40Retention(RetentionPolicy.RUNTIME)%0A%40Constraint(validatedBy%20%3D%20IdentityCardNumberValidator.class)%0Apublic%20%40interface%20IdentityCardNumber%20%7B%0A%0A%20%20%20%20String%20message()%20default%20%22%E8%BA%AB%E4%BB%BD%E8%AF%81%E5%8F%B7%E7%A0%81%E4%B8%8D%E5%90%88%E6%B3%95%22%3B%0A%0A%20%20%20%20Class%3C%3F%3E%5B%5D%20groups()%20default%20%7B%7D%3B%0A%0A%20%20%20%20Class%3C%3F%20extends%20Payload%3E%5B%5D%20payload()%20default%20%7B%7D%3B%0A%7D%0A%60%60%60%0A%0A%0A%3E%20%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E6%98%AF%E4%BD%9C%E7%94%A8%E5%9C%A8Field%E5%AD%97%E6%AE%B5%E4%B8%8A%EF%BC%8C%E8%BF%90%E8%A1%8C%E6%97%B6%E7%94%9F%E6%95%88%EF%BC%8C%0A%3E%20%E8%A7%A6%E5%8F%91%E7%9A%84%E6%98%AFIdentityCardNumber%E8%BF%99%E4%B8%AA%E9%AA%8C%E8%AF%81%E7%B1%BB%E3%80%82%0A%3E%20-%20message%20%E5%AE%9A%E5%88%B6%E5%8C%96%E7%9A%84%E6%8F%90%E7%A4%BA%E4%BF%A1%E6%81%AF%EF%BC%8C%E4%B8%BB%E8%A6%81%E6%98%AF%E4%BB%8EValidationMessages.properties%E9%87%8C%E6%8F%90%E5%8F%96%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E4%BE%9D%E6%8D%AE%E5%AE%9E%E9%99%85%E6%83%85%E5%86%B5%E8%BF%9B%E8%A1%8C%E5%AE%9A%E5%88%B6%0A%3E%20-%20groups%20%E8%BF%99%E9%87%8C%E4%B8%BB%E8%A6%81%E8%BF%9B%E8%A1%8C%E5%B0%86validator%E8%BF%9B%E8%A1%8C%E5%88%86%E7%B1%BB%EF%BC%8C%E4%B8%8D%E5%90%8C%E7%9A%84%E7%B1%BBgroup%E4%B8%AD%E4%BC%9A%E6%89%A7%E8%A1%8C%E4%B8%8D%E5%90%8C%E7%9A%84validator%E6%93%8D%E4%BD%9C%0A%3E%20-%20payload%20%E4%B8%BB%E8%A6%81%E6%98%AF%E9%92%88%E5%AF%B9bean%E7%9A%84%EF%BC%8C%E4%BD%BF%E7%94%A8%E4%B8%8D%E5%A4%9A%E3%80%82%0A%0A%23%23%23%23%203.2%20%E7%84%B6%E5%90%8E%E8%87%AA%E5%AE%9A%E4%B9%89Validator%0A%3E%20%E8%BF%99%E4%B8%AA%E6%98%AF%E7%9C%9F%E6%AD%A3%E8%BF%9B%E8%A1%8C%E9%AA%8C%E8%AF%81%E7%9A%84%E9%80%BB%E8%BE%91%E4%BB%A3%E7%A0%81%0A%0A%60%60%60java%0Apublic%20class%20IdentityCardNumberValidator%20implements%20ConstraintValidator%3CIdentityCardNumber%2C%20Object%3E%20%7B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20initialize(IdentityCardNumber%20identityCardNumber)%20%7B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20boolean%20isValid(Object%20o%2C%20ConstraintValidatorContext%20constraintValidatorContext)%20%7B%0A%20%20%20%20%20%20%20%20return%20IdCardValidatorUtils.isValidate18Idcard(o.toString())%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%203.3%20%E4%BD%BF%E7%94%A8%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E6%B3%A8%E8%A7%A3%0A%60%60%60java%0A%C2%A0%40NotBlank(message%C2%A0%3D%C2%A0%22%E8%BA%AB%E4%BB%BD%E8%AF%81%E5%8F%B7%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%C2%A0%C2%A0%C2%A0%C2%A0%0A%20%40IdentityCardNumber(message%C2%A0%3D%C2%A0%22%E8%BA%AB%E4%BB%BD%E8%AF%81%E4%BF%A1%E6%81%AF%E6%9C%89%E8%AF%AF%2C%E8%AF%B7%E6%A0%B8%E5%AF%B9%E5%90%8E%E6%8F%90%E4%BA%A4%22)%0A%20private%C2%A0String%C2%A0clientCardNo%3B%0A%60%60%60%0A%0A%23%23%23%23%203.4%20%E4%BD%BF%E7%94%A8groups%E7%9A%84%E6%A0%A1%E9%AA%8C%0A%3E%20%E5%A6%82%E6%9E%9C%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E8%A6%81%E5%A4%8D%E7%94%A8%2C%E6%AF%94%E5%A6%82%20%60UserDTO%60%20%E5%9C%A8%E6%9B%B4%E6%96%B0%E6%97%B6%E5%80%99%E8%A6%81%E6%A0%A1%E9%AA%8CuserId%2C%E5%9C%A8%E4%BF%9D%E5%AD%98%E7%9A%84%E6%97%B6%E5%80%99%E4%B8%8D%E9%9C%80%E8%A6%81%E6%A0%A1%E9%AA%8CuserId%2C%E5%9C%A8%E4%B8%A4%E7%A7%8D%E6%83%85%E5%86%B5%E4%B8%8B%E9%83%BD%E8%A6%81%E6%A0%A1%E9%AA%8Cusername%2C%E9%82%A3%E5%B0%B1%E7%94%A8%E4%B8%8Agroups%E4%BA%86%0A%3E%20%E5%85%88%E5%AE%9A%E4%B9%89groups%E7%9A%84%E5%88%86%E7%BB%84%E6%8E%A5%E5%8F%A3Create%E5%92%8CUpdate%0A%60%60%60java%0Aimport%20javax.validation.groups.Default%3B%0A%0Apublic%20interface%20Create%20extends%20Default%20%7B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0Aimport%20javax.validation.groups.Default%3B%0A%0Apublic%20interface%20Update%20extends%20Default%7B%0A%7D%0A%60%60%60%0A%3E%20%E5%86%8D%E5%9C%A8%E9%9C%80%E8%A6%81%E6%A0%A1%E9%AA%8C%E7%9A%84%E5%9C%B0%E6%96%B9%60%40Validated%60%20%E5%A3%B0%E6%98%8E%E6%A0%A1%E9%AA%8C%E7%BB%84%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E8%B5%B0%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%E6%B3%A8%E8%A7%A3%E7%9A%84%20groups%20%E7%BB%84%E5%90%88%E6%A0%A1%E9%AA%8C%0A%20*%0A%20*%20%40param%20userDTO%0A%20*%20%40return%0A%20*%2F%0A%40PostMapping(%22%2Fupdate%2Fgroups%22)%0Apublic%20RspDTO%20update(%40RequestBody%20%40Validated(Update.class)%20UserDTO%20userDTO)%20%7B%0A%20%20%20%20userService.updateById(userDTO)%3B%0A%20%20%20%20return%20RspDTO.success()%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E5%9C%A8DTO%E4%B8%AD%E7%9A%84%E5%AD%97%E6%AE%B5%E4%B8%8A%E5%AE%9A%E4%B9%89%E5%A5%BDgroups%20%3D%20%7B%7D%E7%9A%84%E5%88%86%E7%BB%84%E7%B1%BB%E5%9E%8B%0A%0A%60%60%60java%0A%40Data%0Apublic%20class%20UserDTO%20implements%20Serializable%20%7B%0A%0A%20%20%20%20private%20static%20final%20long%20serialVersionUID%20%3D%201L%3B%0A%0A%20%20%20%20%2F***%20%E7%94%A8%E6%88%B7ID*%2F%0A%20%20%20%20%40NotNull(message%20%3D%20%22%E7%94%A8%E6%88%B7id%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22%2C%20groups%20%3D%20Update.class)%0A%20%20%20%20private%20Long%20userId%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E7%94%A8%E6%88%B7%E5%90%8D%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40NotBlank(message%20%3D%20%22%E7%94%A8%E6%88%B7%E5%90%8D%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%0A%20%20%20%20%40Length(max%20%3D%2020%2C%20message%20%3D%20%22%E7%94%A8%E6%88%B7%E5%90%8D%E4%B8%8D%E8%83%BD%E8%B6%85%E8%BF%8720%E4%B8%AA%E5%AD%97%E7%AC%A6%22%2C%20groups%20%3D%20%7BCreate.class%2C%20Update.class%7D)%0A%20%20%20%20%40Pattern(regexp%20%3D%20%22%5E%5B%5C%5Cu4E00-%5C%5Cu9FA5A-Za-z0-9%5C%5C*%5D*%24%22%2C%20message%20%3D%20%22%E7%94%A8%E6%88%B7%E6%98%B5%E7%A7%B0%E9%99%90%E5%88%B6%EF%BC%9A%E6%9C%80%E5%A4%9A20%E5%AD%97%E7%AC%A6%EF%BC%8C%E5%8C%85%E5%90%AB%E6%96%87%E5%AD%97%E3%80%81%E5%AD%97%E6%AF%8D%E5%92%8C%E6%95%B0%E5%AD%97%22)%0A%20%20%20%20private%20String%20username%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%89%8B%E6%9C%BA%E5%8F%B7%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40NotBlank(message%20%3D%20%22%E6%89%8B%E6%9C%BA%E5%8F%B7%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%0A%20%20%20%20%40Pattern(regexp%20%3D%20%22%5E%5B1%5D%5B3%2C4%2C5%2C6%2C7%2C8%2C9%5D%5B0-9%5D%7B9%7D%24%22%2C%20message%20%3D%20%22%E6%89%8B%E6%9C%BA%E5%8F%B7%E6%A0%BC%E5%BC%8F%E6%9C%89%E8%AF%AF%22%2C%20groups%20%3D%20%7BCreate.class%2C%20Update.class%7D)%0A%20%20%20%20private%20String%20mobile%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%80%A7%E5%88%AB%0A%20%20%20%20%20*%2F%0A%20%20%20%20private%20String%20sex%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E9%82%AE%E7%AE%B1%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40NotBlank(message%20%3D%20%22%E8%81%94%E7%B3%BB%E9%82%AE%E7%AE%B1%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%0A%20%20%20%20%40Email(message%20%3D%20%22%E9%82%AE%E7%AE%B1%E6%A0%BC%E5%BC%8F%E4%B8%8D%E5%AF%B9%22)%0A%20%20%20%20private%20String%20email%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%AF%86%E7%A0%81%0A%20%20%20%20%20*%2F%0A%20%20%20%20private%20String%20password%3B%0A%0A%20%20%20%20%2F***%20%E5%88%9B%E5%BB%BA%E6%97%B6%E9%97%B4%20*%2F%0A%20%20%20%20%40Future(message%20%3D%20%22%E6%97%B6%E9%97%B4%E5%BF%85%E9%A1%BB%E6%98%AF%E5%B0%86%E6%9D%A5%E6%97%B6%E9%97%B4%22%2C%20groups%20%3D%20%7BCreate.class%7D)%0A%20%20%20%20private%20Date%20createTime%3B%0A%7D%0A%0A%60%60%60%0A%3E%20%E6%B3%A8%E6%84%8F%3A%E5%9C%A8%E5%A3%B0%E6%98%8E%E5%88%86%E7%BB%84%E7%9A%84%E6%97%B6%E5%80%99%E5%B0%BD%E9%87%8F%E5%8A%A0%E4%B8%8A%C2%A0%60extend%20javax.validation.groups.Default%60%C2%A0%20%0A%3E%20%E5%90%A6%E5%88%99%2C%E5%9C%A8%E4%BD%A0%E5%A3%B0%E6%98%8E%20%60%40Validated(Update.class)%60%C2%A0%E7%9A%84%E6%97%B6%E5%80%99%2C%E5%B0%B1%E4%BC%9A%E5%87%BA%E7%8E%B0%E4%BD%A0%E5%9C%A8%E9%BB%98%E8%AE%A4%E6%B2%A1%E6%B7%BB%E5%8A%A0groups%20%3D%20%7B%7D%20%E7%9A%84%E6%97%B6%E5%80%99%E7%9A%84%E6%A0%A1%E9%AA%8C%E7%BB%84%40Email(message%20%3D%20%22%E9%82%AE%E7%AE%B1%E6%A0%BC%E5%BC%8F%E4%B8%8D%E5%AF%B9%22)%2C%20%E4%BC%9A%E4%B8%8D%E5%8E%BB%E6%A0%A1%E9%AA%8C%2C%20%E5%9B%A0%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%9A%84%E6%A0%A1%E9%AA%8C%E7%BB%84%E6%98%AFgroups%20%3D%20%7BDefault.class%7D.%0A%0A%0A%23%23%23%23%203.5%20restful%E9%A3%8E%E6%A0%BC%E7%94%A8%E6%B3%95%0A%3E%20%E5%9C%A8%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%2C%E6%88%96%E8%80%85%40RequestParam%20%E5%BD%A2%E5%BC%8F%E6%97%B6%E5%80%99%2C%E9%9C%80%E8%A6%81%E5%9C%A8controller%E4%B8%8A%E5%8A%A0%E6%B3%A8%40Validated%0A%60%60%60java%0A%40RestController%0A%40RequestMapping(%22user%2F%22)%0A%40Validated%0Apublic%20class%20UserController%20extends%20AbstractController%20%7B%0A%0A%20%20%20%20%40GetMapping(%22%2Fget%22)%0A%20%20%20%20public%20RspDTO%20getUser(%40RequestParam(%22userId%22)%20%40NotNull(message%20%3D%20%22%E7%94%A8%E6%88%B7id%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%22)%20Long%20userId)%20%7B%0A%20%20%20%20%20%20%20%20User%20user%20%3D%20userService.selectById(userId)%3B%0A%20%20%20%20%20%20%20%20if%20(user%20%3D%3D%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20RspDTO%3CUser%3E().nonAbsent(%22%E7%94%A8%E6%88%B7%E4%B8%8D%E5%AD%98%E5%9C%A8%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20new%20RspDTO%3CUser%3E().success(user)%3B%0A%20%20%20%20%20%20%7D%0A%0A%7D%20%20%20%20%0A%60%60%60

springcloud2020

创建时间:2020/9/2 15:50
更新时间:2023/7/9 7:36
作者:Chris
来源:https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md

springcloud + springcloud alibaba

1. 微服务架构概述

1.1 什么是微服务

是一种架构,将单一应用分成一组小的服务,服务之间通过轻量级的机制相互调用,通常是基于http协议的restful api。
每个服务运行在独立的进程中,并且能够被独立的部署

1. small services
2. lightweigt mechanisms
3. own process 独立进程
4. independency deployable

2 SpringCloud

分步式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶

服务网关  > 服务注册发与发现 >  配置中心 
2.1 SpringBoot 2.x

git源码地址

https://github.com/spring-projects/spring-boot/releases

SpringBoot2.0 新特性

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Releases

2.2 SpringCloud H

git源码地址

https://github.com/spring-projects/spring-cloud/wiki

https://projects.spring.io/spring-cloud

2.3 兼容性关系

https://spring.io/projects/spring-cloud#overview

https://start.spring.io/actuator/info

https://tool.lu/

{
  "git": {
    "branch": "ee9d426af8dd722b791e1c5f0c612d2bf95a8682",
    "commit": {
      "id": "ee9d426",
      "time": "2020-08-16T20:32:04Z"
    }
  },
  "build": {
    "version": "0.0.1-SNAPSHOT",
    "artifact": "start-site",
    "versions": {
      "spring-boot": "2.3.1.RELEASE",
      "initializr": "0.9.1-SNAPSHOT"
    },
    "name": "start.spring.io website",
    "time": "2020-08-16T20:33:29.306Z",
    "group": "io.spring.start"
  },
  "bom-ranges": {
    "azure": {
      "2.0.10": "Spring Boot >=2.0.0.RELEASE and <2.1.0.RELEASE",
      "2.1.10": "Spring Boot >=2.1.0.RELEASE and <2.2.0.M1",
      "2.2.4": "Spring Boot >=2.2.0.M1 and <2.3.0.M1",
      "2.3.1": "Spring Boot >=2.3.0.M1"
    },
    "codecentric-spring-boot-admin": {
      "2.0.6": "Spring Boot >=2.0.0.M1 and <2.1.0.M1",
      "2.1.6": "Spring Boot >=2.1.0.M1 and <2.2.0.M1",
      "2.2.4": "Spring Boot >=2.2.0.M1 and <2.3.0.M1",
      "2.3.0": "Spring Boot >=2.3.0.M1 and <2.4.0-M1"
    },
    "solace-spring-boot": {
      "1.0.0": "Spring Boot >=2.2.0.RELEASE and <2.3.0.M1",
      "1.1.0": "Spring Boot >=2.3.0.M1"
    },
    "solace-spring-cloud": {
      "1.0.0": "Spring Boot >=2.2.0.RELEASE and <2.3.0.M1",
      "1.1.1": "Spring Boot >=2.3.0.M1"
    },
    "spring-cloud": {
      "Finchley.M2": "Spring Boot >=2.0.0.M3 and <2.0.0.M5",
      "Finchley.M3": "Spring Boot >=2.0.0.M5 and <=2.0.0.M5",
      "Finchley.M4": "Spring Boot >=2.0.0.M6 and <=2.0.0.M6",
      "Finchley.M5": "Spring Boot >=2.0.0.M7 and <=2.0.0.M7",
      "Finchley.M6": "Spring Boot >=2.0.0.RC1 and <=2.0.0.RC1",
      "Finchley.M7": "Spring Boot >=2.0.0.RC2 and <=2.0.0.RC2",
      "Finchley.M9": "Spring Boot >=2.0.0.RELEASE and <=2.0.0.RELEASE",
      "Finchley.RC1": "Spring Boot >=2.0.1.RELEASE and <2.0.2.RELEASE",
      "Finchley.RC2": "Spring Boot >=2.0.2.RELEASE and <2.0.3.RELEASE",
      "Finchley.SR4": "Spring Boot >=2.0.3.RELEASE and <2.0.999.BUILD-SNAPSHOT",
      "Finchley.BUILD-SNAPSHOT": "Spring Boot >=2.0.999.BUILD-SNAPSHOT and <2.1.0.M3",
      "Greenwich.M1": "Spring Boot >=2.1.0.M3 and <2.1.0.RELEASE",
      "Greenwich.SR6": "Spring Boot >=2.1.0.RELEASE and <2.1.17.BUILD-SNAPSHOT",
      "Greenwich.BUILD-SNAPSHOT": "Spring Boot >=2.1.17.BUILD-SNAPSHOT and <2.2.0.M4",
      "Hoxton.SR7": "Spring Boot >=2.2.0.M4 and <2.3.4.BUILD-SNAPSHOT",
      "Hoxton.BUILD-SNAPSHOT": "Spring Boot >=2.3.4.BUILD-SNAPSHOT and <2.4.0.M1",
      "2020.0.0-SNAPSHOT": "Spring Boot >=2.4.0.M1"
    },
    "spring-cloud-alibaba": {
      "2.2.1.RELEASE": "Spring Boot >=2.2.0.RELEASE and <2.3.0.M1"
    },
    "spring-cloud-services": {
      "2.0.3.RELEASE": "Spring Boot >=2.0.0.RELEASE and <2.1.0.RELEASE",
      "2.1.7.RELEASE": "Spring Boot >=2.1.0.RELEASE and <2.2.0.RELEASE",
      "2.2.3.RELEASE": "Spring Boot >=2.2.0.RELEASE and <2.3.0.M1"
    },
    "spring-statemachine": {
      "2.0.0.M4": "Spring Boot >=2.0.0.RC1 and <=2.0.0.RC1",
      "2.0.0.M5": "Spring Boot >=2.0.0.RC2 and <=2.0.0.RC2",
      "2.0.1.RELEASE": "Spring Boot >=2.0.0.RELEASE"
    },
    "vaadin": {
      "10.0.17": "Spring Boot >=2.0.0.M1 and <2.1.0.M1",
      "14.3.3": "Spring Boot >=2.1.0.M1 and <2.4.0-M1"
    },
    "wavefront": {
      "2.0.0": "Spring Boot >=2.1.0.RELEASE"
    }
  },
  "dependency-ranges": {
    "okta": {
      "1.2.1": "Spring Boot >=2.1.2.RELEASE and <2.2.0.M1",
      "1.4.0": "Spring Boot >=2.2.0.M1 and <2.4.0-M1"
    },
    "mybatis": {
      "2.0.1": "Spring Boot >=2.0.0.RELEASE and <2.1.0.RELEASE",
      "2.1.3": "Spring Boot >=2.1.0.RELEASE and <2.4.0-M1"
    },
    "geode": {
      "1.2.9.RELEASE": "Spring Boot >=2.2.0.M5 and <2.3.0.M1",
      "1.3.2.RELEASE": "Spring Boot >=2.3.0.M1 and <2.4.0-M1",
      "1.4.0-M1": "Spring Boot >=2.4.0-M1"
    },
    "camel": {
      "2.22.4": "Spring Boot >=2.0.0.M1 and <2.1.0.M1",
      "2.25.2": "Spring Boot >=2.1.0.M1 and <2.2.0.M1",
      "3.3.0": "Spring Boot >=2.2.0.M1 and <2.3.0.M1",
      "3.4.3": "Spring Boot >=2.3.0.M1 and <2.4.0-M1"
    },
    "open-service-broker": {
      "2.1.3.RELEASE": "Spring Boot >=2.0.0.RELEASE and <2.1.0.M1",
      "3.0.4.RELEASE": "Spring Boot >=2.1.0.M1 and <2.2.0.M1",
      "3.1.1.RELEASE": "Spring Boot >=2.2.0.M1 and <2.4.0-M1"
    }
  }
}
 "Hoxton.BUILD-SNAPSHOT": "Spring Boot >=2.3.4.BUILD-SNAPSHOT and <2.4.0.M1",

https://docs.spring.io/spring-cloud/docs/Hoxton.SR7/reference/html/

3 组件的停更升级和替换

服务开发  SpringBoot
服务注册与发现 Eureka [已停止更新] , ZooKeeper, Consul, Alibaba Nacos
服务负载均衡与调用 Ribbon[趋于停止更新],LoadBanance, Feigh[趋于停止更新], OpenFeign
服务熔断 服务降级 Hystrix[趋于停止更新], Resilience4J, Alibaba Sentinel
服务消息队列
配置中心管理 Springcloud config, Alibaba Nacos
服务网关 Zuul [停止更新], Spring Gateway
服务总线 Spring Bus, Alibaba Nacos
服务监控
全链路追踪
自动化构建部署
服务定时任务调度操作

3.1 SpringCloud文档

https://docs.spring.io/spring-cloud/docs/Hoxton.SR7/reference/html/#features

https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md

4 编码构建

4.1 创建父工程

idea > new > project





4.2 创建微服务模块
1.建module: idea > new > module
2.改pom
3.写YML
4.启动类
5.业务类
4.3 热部署
  1. 添加DEV到pom.xml

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    
  2. 添加到父工程的pom.xml

    <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
              <fork>true</fork>
              <addResources>true</addResources>
            </configuration>
          </plugin>
        </plugins>
      </build>
    
  3. idea设置打开自动构建

  4. 更新设置
    ctrl+alt+shift+/
    构选这两项
    compiler.automake.allow.when.app.running
    actionSystem.assertFocusAccessFromEdt

4.4 RestTemplate

是Spring提供的用于访问Rest服务的客户模板工具类,提供了多种便捷访问远程http服务的方法

4.5 配置RunDashboard

工程目录 下的.idea文件夹

追加下面内容到worksapce.xml中

<component name="RunDashboard">
    <option name="configurationTypes">
      <set>
        <option value="SpringBootApplicationConfigurationType" />
      </set>
    </option>
 </component>

4.6 工程重构
  1. 新建module cloud-api-commons

  2. 提取其它module 里面的entities放到cloud-api-commons 里面的 com.chris.springcloud.entities

  3. 删除其它module里面的entities

  4. 在 中构建共用工程并放到本地仓库中

    cd cloud-api-commons
    mvn clean install -Dmaven.test.skip=true
    
  5. 在其它module里面加入依赖

    <dependency>
        <groupId>com.chris.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${common.api.version}</version>
    </dependency>
    
  6. 进入项目根目录构建项目

    cd cloud2020
    mvn clean package -Dmaven.test.skip=true
    
4.7 idea无法识别Application.yml

ctrl+shift+alt+s
选中对应的项目,右击选择Add
选择Spring

选中Spring, 选择 +
进入之后再选择 + 号,并选择 Other Files
选中需要添加的 Application.yml 文件


5 服务注册中心

5.1 服务制理

实现服务的注册与发现,管理服务之间依赖关系,调用,负载均衡及容错等

5.2 Eureka
  1. CS架构
  2. Eureke Server 作为服务注册功能的服务器,它是服务注册中心
  3. 系统中的其它服务使用Eureke Client连接到Eureke Server并维持心跳,这样就可以通过Eureke Server来监控系统中各个服务是否运行正常
  4. Eureke Client通过轮询(round-robin)默认每30秒向Eureke Server发送心跳,如果Eureke Server在多个心跳周期内(默认为90秒) 没有收到某个结点的心跳,会将这个服务节点从服务注册列表中移除.

5.2.1 IDEA生成Eureka服务注册中心
  1. 建module cloud-eureka-server7001

  2. 改pom

    <!-- 引入最新的eureka server-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  3. 建 yml

    server:
      port: 7001
      tomcat:
        uri-encoding: UTF-8
    eureka:
      instance:
        hostname: localhost #eureka服务端的实例名称
      client:
        # false 表示不向注册中心注册自己
        register-with-eureka: false
        # false 表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          # 设置与交互的地址,查询服务和注册服务都需要这依赖这个地址
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    
  4. 主启动

    @EnableEurekaServer 激活服务注册中心,用于管理服务的配置,登记和注册

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaMain {
        public static void main(String[] args) {
            SpringApplication.run(EurekaMain.class, args);
        }
    }
    
  5. 启动

    访问 http://localhost:7001/

5.2.2 注册服务到Eureka服务注册中心
  1. 改pom.xml

    在具体的服务module的pom.xml里面引入eureka-client

    <!--eureka client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  2. 改YML

    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true
        # 单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://localhost:7001/eureak
    
  3. 主启动

    @EnableEurekaClient 激活需要注册的服务本身

    @SpringBootApplication
    @EnableEurekaClient
    public class PaymentMain {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain.class, args);
        }
    }
    
  4. 服务注册成功后效果

5.2.3 Eureka集群

相互注册,相互监听

  1. 建 module cloud-eureka-server7002

  2. 改pom.xml

  3. 建yml,同理修改cloud-eureka-server7001中的yml

    eureka:
      instance:
        hostname: eureka7002.com #eureka服务端的实例名称
      client:
        # false 表示不向注册中心注册自己
        register-with-eureka: false
        # false 表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          # 设置与Eureka Serve交互的地址,查询服务和注册服务都需要这依赖这个地址
          # 相互注册
          defaultZone: http://eureka7001.com:7001/eureka/
    
  4. 改映射

    进入 C:\Windows\System32\drivers\etc

    修改hosts 添加如下内容

    ######## SpringCloud 2020 ###########
    127.0.0.1  eureka7001.com
    127.0.0.1  eureka7002.com
    
  5. 服务注册成功后效果

     http://eureka7001.com:7001/
     http://eureka7002.com:7002/
    

5.2.4 将服务注册到Eureka集群
  1. 修改服务提供者cloud-provider-payment8001的yml文件

    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
    
  2. 修改服务消息者cloud-consumer-order80的yml文件

    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
    
  3. 注册成功后的效果

5.2.5 服务提供者集群配置
  1. 建module cloud-provider-payment8002

  2. 改pom.xml

  3. 建yml

    cloud-provider-payment8001的yml一样, 只是端口号需要改为8002

    server:
      port: 8002
      servlet:
        context-path: /api
      tomcat:
        uri-encoding: UTF-8
    
  4. 启动类

    @SpringBootApplication
    @EnableEurekaClient
    public class PaymentMain8002 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8002.class, args);
        }
    }
    
  5. 将整个cloud-provider-payment8001的业务代码copy到cloud-provider-payment8002

  6. 启动成功后的效果

  7. 负载均衡

    修改服务消费者cloud-consumer-order80 > PAYMENT_URL> PAYMENT_URL

    // 集群版本 CLOUD-PAYMENT-SERVICE是在Eureka中注册的服务名称
    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
    
     "org.springframework.web.client.ResourceAccessException: I/O error on GET request for \"http://CLOUD-PAYMENT-SERVICE/api/payment/get/4\": CLOUD-PAYMENT-SERVICE; nested exception is java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE\r\n\tat org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:751)\r\n\tat org.springframework.web.client.RestTemplate.execute(RestTemplate.java:677)\r\n\tat org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:318)\r\n\tat com.springcloud.order.controller.OrderController.getPayment(OrderController.java:41)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat sun.
    

    需要使用 @LoadBalanced 注解赋予RestTemplate负载均衡能力

       @Configuration
       public class ApplicationContextConfig {
           @Bean
           @LoadBalanced
           public RestTemplate getRestTemplate() {
               return new RestTemplate();
           }
       }
    
5.2.6 修改服务名称和显示
  1. 修改服务提供者的yml文件

    增加

    instance-id: payment8001

    prefer-ip-address: true

    eureka:
       instance:
        instance-id: payment8002
        prefer-ip-address: true
    
  2. 修改成功后的效果

    鼠标放在服务名称上左下脚会有IP显示

5.2.7 服务发现
  1. 修改Controller
@Resource
private DiscoveryClient discoveryClient;

@GetMapping("/discovery")
    public Object discovery() {
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            log.info("service:" + service);
        }

        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance : instances) {
            log.info(instance.getInstanceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
        }

        return this.discoveryClient;
    }
  1. 修改启动类

    增加@EnableDiscoveryClient 激活服务发现

    @SpringBootApplication
    @EnableEurekaClient
    @EnableDiscoveryClient
    public class PaymentMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8001.class, args);
        }
    }
    
  2. 测试

    request:
    http://localhost:8001/api/payment/discovery
    
    response:
    {
        "services": [
            "cloud-payment-service",
            "cloud-order-service"
        ],
        "order": 0
    }
    
5.2.8 Eureka的自我保护
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

如果服务注册中心在一定时间内没有收到某个微服务的清求会将该服务的实现注销掉

因为网络等原因(延时,卡顿,拥挤)时,微服务与服务注册中心无法通信,但是微服务本身是健康的,这种情况下注销行为就变的非常危险

Eureka通过自我保护来解决这个问题,默认是开启状态
某个时刻微服务不能用了,Eureka不会立即清理,依旧会对该服务的信息进行保护

属于CAP里面的AP设计思想

关闭Eureka自我保护

  1. 修改服务注册中心的yml配置

    eureka:
      server:
        # 关闭自我保护,保证不可用的服务即时清理
        enable-self-preservation: false
        # 注销服务的心跳时间,默认为60秒
        eviction-interval-timer-in-ms: 2000
    

  2. 修改服务提供者的yml文件

    eureka:
      instance:
        # Eureka客户端向服务端发送心跳的时间间隔,默认为30秒
        lease-renewal-interval-in-seconds: 1
        # Eureka服务端收到客户端最后一次心跳后等待的时间上限,超时将注销服务,默认为90秒
        lease-expiration-duration-in-seconds: 2
    
5.2.9 停更说明

https://github.com/Netflix/eureka/wiki

5.3 ZooKeeper
5.3.1 Zookeeper安装

参考 Zookeeper Installment 笔记

5.3.2 支付服务注册到zookeeper
  1. 建module

    cloud-provider-payment8004

  2. 改pom

    引入zookeeper客户端

    <!--SpringBoot 整合 zookeeper client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    </dependency>
    
  3. 建yml

    server:
      port: 8004
      tomcat:
        uri-encoding: utf-8
      servlet:
        context-path: /api
    spring:
      application:
        name: cloud-provider-payment
      cloud:
        zookeeper:
          connect-string: master:2181
    
  4. 启动类

    @EnableDiscoveryClient //该注册向使用consul或者zookeeper作为注册中心时注册服务

    package com.chris.springcloud.payment;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    @EnableDiscoveryClient //该注册向使用consul或者zookeeper作为注册中心时注册服务
    public class PaymentMain8004 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8004.class, args);
        }
    }
    
  5. zookeeper jar包冲突的问题

    <!--SpringBoot 整合 zookeeper client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    
    <!--添加zookeeper 3.6.1 与服务器安装版本匹配一致-->
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.6.1</version>
    </dependency>
    

  6. 使用zkCli.sh查看

    cd bin
    ./zkCli.sh
    [zk: 127.0.0.1:2181(CONNECTED) 11] ls /
    [services, zookeeper]
    [zk: 127.0.0.1:2181(CONNECTED) 12] ls /services
    [cloud-provider-payment]
    
  7. 测试

    request:
    http://localhost:8004/api/payment/zk
    
    response:
    springcloud with zookeeper:8004	9cf857e1-e7e5-4329-bd7e-61ba7d9eb1f0
    
  8. 服务端查看注册信息

    cloud-provider-payment 为zookeeper内部的znode节点
    1bc5975a-13e6-42a8-8dae-519d0a3139be 为znode的唯一流水号
    
    [zk: 127.0.0.1:2181(CONNECTED) 11] ls /
    [services, zookeeper]
    [zk: 127.0.0.1:2181(CONNECTED) 12] ls /services
    [cloud-provider-payment]
    [zk: 127.0.0.1:2181(CONNECTED) 13] ls /services/cloud-provider-payment
    [1bc5975a-13e6-42a8-8dae-519d0a3139be]
    [zk: 127.0.0.1:2181(CONNECTED) 14] ls /services/cloud-provider-payment/1bc5975a-13e6-42a8-8dae-519d0a3139be
    []
    [zk: 127.0.0.1:2181(CONNECTED) 15] get /services/cloud-provider-payment/1bc5975a-13e6-42a8-8dae-519d0a3139be
    {"name":"cloud-provider-payment","id":"1bc5975a-13e6-42a8-8dae-519d0a3139be","address":"DESKTOP-L9SDH81","port":8004,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"cloud-provider-payment","metadata":{}},"registrationTimeUTC":1597988679352,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}
    
    
    {
      "name": "cloud-provider-payment",
      "id": "1bc5975a-13e6-42a8-8dae-519d0a3139be",
      "address": "DESKTOP-L9SDH81",
      "port": 8004,
      "sslPort": null,
      "payload": {
        "@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
        "id": "application-1",
        "name": "cloud-provider-payment",
        "metadata": {}
      },
      "registrationTimeUTC": 1597988679352,
      "serviceType": "DYNAMIC",
      "uriSpec": {
        "parts": [
          {
            "value": "scheme",
            "variable": true
          },
          {
            "value": "://",
            "variable": false
          },
          {
            "value": "address",
            "variable": true
          },
          {
            "value": ":",
            "variable": false
          },
          {
            "value": "port",
            "variable": true
          }
        ]
      }
    }
    
  9. Zookeeper临时节点和持久节点

    zookeeper在一定时间内(默认为90秒),会将没有收到心跳的服务注销

5.3.3 订单服务注册到zookeeper
  1. 建module

    cloud-consumerzk-order80

  2. 改pom

  3. 建yml

    server:
      port: 80
      tomcat:
        uri-encoding: utf-8
    spring:
      application:
        name: cloud-consumer-order
      cloud:
        zookeeper:
          connect-string: master:2181
    
  4. 主启动

    @SpringBootApplication
    @EnableDiscoveryClient
    public class OrderZKMain80 {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderZKMain80.class, args);
        }
    }
    
  5. 配置类

    @Configuration
    public class ApplicationContextConfig {
    
        @Bean("restTemplate")
        @LoadBalanced
        public RestTemplate getRestTemplate() {
            return new RestTemplate();
        }
    }
    
  6. 业务类

    @RestController
    @Slf4j
    @RequestMapping("/consumer")
    public class OrderZKController {
    
        //cloud-provider-payment 为在zookeeper中注册的znode节点名称
        private static final String PAYMENT_URL = "http://cloud-provider-payment";
    
    	@Resource
        private RestTemplate restTemplate;
    
        @GetMapping("/payment/zk")
        public String paymentInfo() {
            return restTemplate.getForObject(PAYMENT_URL + "/api/payment/zk", String.class);
        }
    }
    
5.4 Consul
5.4.1 简介
  1. 是什么?

    https://www.consul.io/intro

    用go开发的,开源的分布式服务发现和配置管理系统

    提供了微服务系统中的服务治理,配置中心,控制总线等功能,这些功能中的每一个都可以根据需要单独使用,也可以构建全方位的服务风格。

    支持HTTP和DNS协议,提供图形化界面,支持Linux,Mac, Windows

  2. 能干什么?

服务发现
健康检查
KV存储
多数据中心
可视化Web界面
  1. 下载

    https://www.consul.io/downloads

​ https://www.springcloud.cc/spring-cloud-consul.html

​ https://cloud.spring.io/spring-cloud-consul/reference/html/#spring-cloud-consul-bus

5.4.2 怎么玩
  1. ubuntu安装

    https://learn.hashicorp.com/tutorials/consul/get-started-install?in=consul/getting-started

    $ curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
    $ sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
    $ sudo apt-get update && sudo apt-get install consul
    
    consul --version
    ## 使用开发模式启动
    consul agent -dev -node machine -client 0.0.0.0
    
    ## 默认端口8500,也可以指定端口号 -http-port 8888
    consul agent -dev -node machine -http-port 8888 -ui -client 0.0.0.0
    
    ## 输出成员列表,成员有三种状态分别为  "alive", "left", or "failed"
    consul members
    
    
5.4.3 服务提供者注册到Consul
  1. 建modul

    cloud-providerconsul-payment8006

  2. 改pom

     <!--SpringBoot 整合 consul server -->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-consul-discovery</artifactId>
       </dependency>
    
  3. 建yml

    server:
      port: 8006
      tomcat:
        uri-encoding: UTF-8
      servlet:
        context-path: /api
    spring:
      application:
        name: consul-provider-payment
      cloud:
        consul:
          host: master
          port: 8500
          discovery:
            service-name: ${spring.application.name}
            health-check-path: ${server.servlet.context-path}/actuator/health
            #默认10s
            health-check-interval: 3s
    
  4. 主启动

    @EnableDiscoveryClient 激活服务发现

    @SpringBootApplication
    @EnableDiscoveryClient
    public class PaymentMain8006 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8006.class, args);
        }
    }
    
  5. 业务类

  6. 成功注册后的效果

    服务名称为 yml中的 service-name: ${spring.application.name}

  7. 测试

      request:
       http://localhost:8006/api/payment/consul
    
       response:
       spirngcloud with consul:8006	25c07bdc-7f97-4ef6-9d42-4fdc79c24126
    
5.4.4 服务消费者注册到Consul
  1. 建module

    cloud-consumer-consul-order80

  2. 改pom.xml

    <!--SpringBoot 整合 consul server -->
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-consul-discovery</artifactId>
     </dependency>
    
  3. 建yml

    server:
      port: 80
      tomcat:
        uri-encoding: UTF-8
    spring:
      application:
        name: consul-consumer-order
      cloud:
        consul:
          host: master
          port: 8500
          discovery:
            service-name: ${spring.application.name}
    
  4. 启动类

    @EnableDiscoveryClient 激活服务发现

    @SpringBootApplication
    @EnableDiscoveryClient
    public class OrderConsulMain80 {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderConsulMain80.class, args);
        }
    }
    
  5. 配置类

    package com.chris.springcloud.config;
    
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    @Configuration
    public class ApplicationContextConfig {
    
        @Bean("restTemplate")
        @LoadBalanced
        public RestTemplate getRestTemplate() {
            return new RestTemplate();
        }
    }
    
    
  6. 业务类

    @RestController
    @RequestMapping("/customer")
    public class OrderConsulController {
        private static final String PAYMENT_URL = "http://consul-provider-payment";
    
        @Resource
        private RestTemplate restTemplate;
    
        @GetMapping("/payment/consul")
        public String paymentInfo() {
            return restTemplate.getForObject(PAYMENT_URL + "api/payment/consul", String.class);
        }
    }
    
  7. 注册成功后效果

  8. 测试

       request:
       http://localhost/consumer/payment/consul
    
       response:
       spirngcloud with consul:8006	eb16d116-7849-4d8e-8782-0e13aa027a3f
    
5.4.5 HTTP健康检查

Consul实例的运行状况检查默认为“/ health”,

它是Spring Boot Actuator应用程序中有用端点的默认位置。

如果你使用了servlet路径(例如server.servletPath=/foo)则需要更改这些,即使是执行器应用程序

spring:
  application:
    name: consul-provider-payment
  cloud:
    consul:
      host: master
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        health-check-path: ${server.servlet.context-path}/actuator/health
        #默认10s
        health-check-interval: 3s 
5.5 总结
5.5.1 汇总
名称语言CAPHealth Check对外协议是否集成到SpringCloud
EurekajavaAP需配置已集成
ZooKeeperjavaCP支持无,只有Linux客户端已集成
ConsulgoCP支持HTTP、DNS已集成
5.5.2 CAP理论

CAP:关注的粒度是数据,而不是整体系统设计策略

Consistency 一致性

Availability 可用性

Partition Tolerance 分区容错性

6 服务调用和负载均衡

6.1 Ribbon
6.1.1 是什么

Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡和服务调用。

Ribbon客户端组件提供了一系列完善的配置项如连接超时,重试等

就是在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动基于某种规则(轮询,随机等)去连接这些机器

Ribbon同进可以使用实现自定义的负载均衡算法

官方资料:
https://github.com/Netflix/ribbon/wiki/Getting-Started
目前Ribbon已进入维护阶段

未来替换方案:
Spring Cloud Starter LoadBalancer

6.1.2 能干什么
  1. 什么是负载均衡

    将请求平均的分配到多个服务上,从而达到系统的高可用(HA)
    常见的负载均衡组件有,Nginx, LVS, 硬件F5等

  2. Ribbon本地负载均衡和Nginx服务端的负载均衡

    Nginx是服务器端的集成式的负载均衡,客户端所有请求都交给Nginx,然后由Nginx实现请求转发,即负载均衡是由服务器实现的。

    Ribbon是本地的进程内的负载均衡,在调用服务接口时,Ribbon会在服务注册中心获取服务注册信息,然后缓存在JVM本地,从而在本地实现RPC远程服务调用技术。
    Ribbon集成于消费方服务进程中,消费方通过它来获取服务提供方的地址

    Ribbon = 负载均衡算法 + RestTemplate

  3. 工作时分为两步

第一步先选择EurekaServer,优先选择同一区域内负载较少的server
第二步再根据用户指定的策略,从获取到的服务注册中心的服务列表中选择一个地址

Ribbon 提供了多种策略:

轮询

随机

根据响应时间加权

6.2 负载均衡和REST调用
6.2.1 Eureka已集成Ribbon
6.2.2 RestTemplate的使用
  1. 官网

    https://docs.spring.io/spring/docs/current/javadoc-api/
    https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

  2. postForObject & getForObject

    返回对象为JSON


public CommonResult<Payment> create(Payment payment) {
        return restTemplate.postForObject(PAYMENT_URL + "/api/payment/create", payment, CommonResult.class);
}

 public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
        return restTemplate.getForObject(PAYMENT_URL + "/api/payment/get/" + id, CommonResult.class);
 }
  1. postForEntity & getForEntity

    包含头信息,响应状态码,响应体

@GetMapping("/payment/create2")
    @SuppressWarnings("unchecked")
    public CommonResult<Payment> create2(Payment payment) {
        ResponseEntity<CommonResult> entity = restTemplate.postForEntity(PAYMENT_URL + "/api/payment/create",
                payment, CommonResult.class);
        log.info("status:" + entity.getStatusCode() + ",head:" + entity.getHeaders());
        if (entity.getStatusCode().is2xxSuccessful()) {
            return entity.getBody();
        } else {
            return new CommonResult<>(444, "create2 method operation fail");
        }
 }
@GetMapping("/payment/get2/{id}")
@SuppressWarnings("unchecked")
public CommonResult<Payment> getPayment2(@PathVariable("id") Long id) {
    ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/api/payment/get/" + id,
            CommonResult.class);
    log.info("status:" + entity.getStatusCode() + ",head:" + entity.getHeaders());
    if (entity.getStatusCode().is2xxSuccessful()) {
        return entity.getBody();
    } else {
        return new CommonResult(444, "get2 mothod opration fail");
    }
}
6.2.3 Ribbon 负载均衡算法
  1. IRule: 根据特定算法从服务列表中选取一个要访问的服务

    AbstractLoadBalancerRule

    BestAvailableRule
    RandomRule --随机
    RetryRule  
    RoundRobinRule --轮询
    ZoneAvoidanceRule
    AvailabilityFilteringRule --根据响应时间加权重
    WeightedResponseTimeRule
    
  2. 替换Ribbon负载均衡

    自定义负载均衡算法不能放在@ComponentScan所能扫描到的包里面

    https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-ribbon.html

    新增 com.springcloud.myrule.MySelfRule

    @Configuration
    public class MySelfRule {
        @Bean
        public IRule myRule() {
            // 随机负载均衡算法
            return new RandomRule();
        }
    }
    

    在主启动类上添加@RibbonClient

    name为在eureka里面注册的服务应用名称

    configuration为新增的负载均衡类

    @SpringBootApplication
    @EnableEurekaClient
    @RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)
    public class OrderMain {
        public static void main(String[] args) {
            SpringApplication.run(OrderMain.class, args);
        }
    }
    
  3. 算法

    Rest接口第几次请求数 % 服务器集群总数量=实际调用服务器位置下标

    每次服务重启后,rest接口计数从1开始

6.2.4 手写Ribbon负载均衡算法
  1. 原理

    JUC(CAS+自旋锁)

  2. 注释RestTemplate上的@LoadBalanced

    cloud-consumer-order80

    @Configuration
    public class ApplicationContextConfig {
     @Bean
        //手写Ribbon负载均衡算法时去掉@LoadBalanced
        //@LoadBalanced
        public RestTemplate getRestTemplate() {
            return new RestTemplate();
        }
    
    }
    
  3. 自定义LoadBanancerr接口

    public interface LoadBalancer {
        ServiceInstance instances(List<ServiceInstance> serviceInstances);
    }
    
  4. 实现自定义LoadBalancer接口

    @Component
    @Slf4j
    public class MyLB implements LoadBalancer {
    
        private AtomicInteger atomicInteger = new AtomicInteger(0);
    
        @Override
        public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
            int index = getAndIncrement() % serviceInstances.size();
            return serviceInstances.get(index);
        }
    
    
        public int getAndIncrement() {
            int current;
            int next;
    
            do {
                current = this.atomicInteger.get();
                next = current >= 2147483647 ? 0 : current + 1;
            }
            while (this.atomicInteger.compareAndSet(current, next));
            log.info("第几次访问,次数next:" + next);
            return next;
        }
    
  5. 实现Controller类

    @RestController
    @Slf4j
    @RequestMapping("/consumer")
    public class OrderController {
    
        @Resource
        private RestTemplate restTemplate;
    
        @Resource
        private LoadBalancer myLB;
    
        @Resource
        private DiscoveryClient discoveryClient;
    
        @GetMapping("/payment/lb")
        public String getPaymentLB() {
            List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
            if (CollectionUtils.isEmpty(instances)) {
                return null;
            }
            ServiceInstance serviceInstance = myLB.instances(instances);
            URI uri = serviceInstance.getUri();
            log.info("uri:" + uri);
            return restTemplate.getForObject(uri + "/payment/lb", String.class);
        }
    
    }
    
6.3 OpenFeign
6.3.1 是什么
https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/#spring-cloud-openfeign
https://github.com/spring-cloud/spring-cloud-openfeign

Feign是一个声明式的webservice客户端,使用Feign使编写webservice客户端更加简单
Feign的使用方法是定义一个服务接口然后在上面添加注解。
Feign可与Eureka和Ribbon组合使用以支持负载均衡
Feign自身集成Ribbon

6.3.2 能干什么
  1. 创建一个接口并使用注解配置它,就可以完成对服务提供方接口的绑定
  2. Feign集成了Ribbon
6.3.3 怎么玩
  1. 建module

    cloud-consumer-feign-order80

  2. 改pom

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.chris.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${common.api.version}</version>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--open feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
    
  3. 建yml

    server:
      port: 80
      tomcat:
        uri-encoding: utf-8
    
    spring:
      application:
        name: cloud-order-feign-service
    
    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
    
  4. 主启动

    @EnableFeignClients 激活Feign客户端

    @SpringBootApplication
    @EnableFeignClients
    public class OrderFeignMain80 {
        public static void main(String[] args) {
            SpringApplication.run(OrderFeignMain80.class, args);
        }
    }
    
  5. 业务类

    @FeignClient(value = "CLOUD-PAYMENT-SERVICE") 声明此接口使用feign作为负载均衡和服务调用接口, CLOUD-PAYMENT-SERVICE为服务注册中心中的服务名称

    PaymentFeignService 定义了服务提供者的服务接口PaymentController原样拷贝,URL,方法都需要一样,返回值因为是面向客户端所以需要返回CommonResult

    @Component
    @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
    @RequestMapping("/api/payment")
    public interface PaymentFeignService {
        @GetMapping("/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
    }
    
    @RestController
    @Slf4j
    @RequestMapping("/consumer")
    public class OrderFeignController {
        @Resource
        public PaymentFeignService paymentFeignService;
    
        @GetMapping("/payment/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
            return paymentFeignService.getPaymentById(id);
        }
    }
    
  6. 测试类

    http://localhost/consumer/payment/get/3

6.3.4 超时控制
  1. 超时原因

    消费端等待时间小于服务提供者处理时间
    openfeign-ribbon默认消费等待时间为1秒

    消费端:

    http://localhost/consumer/payment/feign/timeout

    服务端:

    http://localhost:8002/api/payment/feign/timeout
    http://localhost:8001/api/payment/feign/timeout

  2. 超时设置

    配置yml

    # 消费端超时控制
    ribbon:
      ReadTimeout: 5000 #建立连接所用的时间
      ConnectTimeout: 5000 #建立连接后服务端读取可用资源所用的时间
    
6.3.5 日志增强

Feign提供了日志打印功能,可以通过配置来调整日志级别,从而对请求进行监控来了解HTTP请求的细节,

从低到高分别是:

None: 默认,不显示任何日志
Basic: 仅记录请求方法,URL,响应状态码及执行时间
Headers: 除了Basic中的信息外,还有请求和响应的头信息
Full:  除了Headers中的信息外,还有请求和响应的正文及元数据
  1. 配置LoggerBean

    package com.chris.springcloud.config;
    
    import feign.Logger;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class FeignConfig {
        @Bean
        Logger.Level feignLoggerLevel() {
            return Logger.Level.FULL;
        }
    }
    
  2. 配置yml

    logging:
      level:
        # feign 以什么级别监控哪个接口
        com.chris.springcloud.service.PaymentFeignService: debug
    
  3. 测试

    http://localhost/consumer/payment/get/4

    2020-08-27 15:51:42.220 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] ---> GET http://CLOUD-PAYMENT-SERVICE/api/payment/get/4 HTTP/1.1
    2020-08-27 15:51:42.220 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] ---> END HTTP (0-byte body)
    2020-08-27 15:51:42.244 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] <--- HTTP/1.1 200 (24ms)
    2020-08-27 15:51:42.245 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] connection: keep-alive
    2020-08-27 15:51:42.245 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] content-type: application/json
    2020-08-27 15:51:42.245 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] date: Thu, 27 Aug 2020 07:51:42 GMT
    2020-08-27 15:51:42.245 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] keep-alive: timeout=60
    2020-08-27 15:51:42.245 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] transfer-encoding: chunked
    2020-08-27 15:51:42.245 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] 
    2020-08-27 15:51:42.245 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] {"code":200,"message":"query payment success.8001","data":{"id":4,"serial":"ethan"}}
    2020-08-27 15:51:42.245 DEBUG 469768 --- [p-nio-80-exec-2] c.c.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] <--- END HTTP (84-byte body)
    

7.服务降级和服务熔断

分布式系统中,一个服务有数十个依赖,每个依赖关系在某个时候不可避免地会出现失败

服务相互调用链路会很长,一个出差,整条链路会停用, 甚至服务雪崩。

7.1 服务降级

fallback: 对方系统不可用的情况下,向服务调用方返回一个符合预期的,可处理的备选响应(FallBack)

什么情况下会出现服务降级:

  1. 程序运行异常
  2. 超时
  3. 服务熔断触发服务降级
  4. 线程池信息量打满
7.2 服务熔断

服务降级 > 进而熔断 > 恢复调用链路

当服务达到最大访问负载后直接拒绝访问,然后调用服务降级的方法并返回友好提示

熔断机制是一种应对雪崩效应的一种服务链路保护机制

当检测到务调用响应正常后,恢复调用链路

当失败达到阀值时,默认5秒内20次调用失败,就会启用熔断机制

服务熔断有三种状态

  1. 打开

    请求不再调用当前服务,内部设置了时钟一般为MTTR(平均故障处理时间),当打开时长超过MTTR时钟时长后则进入半开状态

  2. 半开

    部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断。

  3. 关闭

    circuit breaker不会对服务进行熔断

7.3 服务限流

秒杀,高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行QPS

https://www.cnblogs.com/longxiaojiangi/p/9259745.html

7.4 Hystrix
7.4.1 是什么

一个处理分布式系统延迟和容错的开源库,在分布式系统中许多服务不可避免的会出现调用失败,如网络延时,卡顿,程序出错等。

Hystrix能够保证在一个服务出现错误的情况下,不全导致整体服务失败,避免级联故障,从而提升系统的高可用性。

断路器是一个开关装置,在某个服务单元故障之后,通过断路器的故障监控,向服务调用方返回一个符合预期的,可处理的备选响应(FallBack)

而不是长时间等待或者抛出一个调用方无法处理的异常,这样就可以保证服务调用方的线程不会长时间被占用,从而避免故障在分布式系统中蔓延,及至雪崩。

7.4.2 能干什么
  1. 服务降级

  2. 服务熔断

  3. 服务限流

  4. 接近实时监控

7.4.3 怎么玩

http://github.com/Netflix/Hystrix/wiki/How-To-Use

7.4.4 停止更新,进入维护

http://github.com/Netflix/Hystrix/

7.4.5 支付微服务构建
  1. 建module

    cloud-provider-hystrix-payment8001

  2. 改pom

    <!--Eureka client-->
    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
    <!--hystrix-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
  3. 建yml

    server:
      port: 8001
      tomcat:
        uri-encoding: UTF-8
      servlet:
        context-path: /api
    spring:
      application:
        name: cloud-provider-hystrix-payment
    
    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          #defaultZone: http://localhost:7001/eureka
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
      instance:
        instance-id: hystrix-payment8001
        prefer-ip-address: true
        # Eureka客户端向服务端发送心跳的时间间隔,默认为30秒
        lease-renewal-interval-in-seconds: 1
        # Eureka服务端收到客户端最后一次心跳后等待的时间上限,超时将注销服务,默认为90秒
        lease-expiration-duration-in-seconds: 2
    
  4. 主启动

    @SpringBootApplication
    @EnableEurekaClient
    public class PaymentHystrixMain8001 {
    
        public static void main(String[] args) {
            SpringApplication.run(PaymentHystrixMain8001.class, args);
        }
    
    }
    
  5. 业务类

    @RestController
    @Slf4j
    @RequestMapping("/payment/hystrix")
    public class PaymentController {
    
        @Resource
        private PaymentService paymentService;
    
        @Value("${server.port}")
        private String serverPort;
    
        @GetMapping("/timeout/{id}")
        public String paymentInfo_Ok(@PathVariable("id") int id) {
            String result = paymentService.paymentInfo_OK(id);
            log.info("result:" + result);
            return result;
        }
    }
    
    @Service
    @Slf4j
    public class PaymentService {
        /**
         * @param id
         * @return 正常访问
         */
        public String paymentInfo_OK(int id) {
            return "thread pool " + Thread.currentThread().getName() + " paymentInfo_OK, id:" + id + ".";
        }
    
        /**
         * @param id
         * @return 访问超时
         */
        public String paymentInfo_TimeOut(int id) {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                log.error("error happened paymentInfo_TimeOut ", e);
            }
            return "thread pool " + Thread.currentThread().getName() + " paymentInfo_TimeOut, id:" + id + ". waste time" + "seconds:" + 3;
        }
    
    }
    
  6. 测试

    request
    http://localhost:8001/api/payment/hystrix/ok/4
    response
    thread pool http-nio-8001-exec-3 paymentInfo_OK, id:4.
    
    request
    http://localhost:8001/api/payment/hystrix/timeout/4
    response
    thread pool http-nio-8001-exec-2 paymentInfo_TimeOut, id:4. waste timeseconds:3
    
  7. Jmeter高并发测试

7.4.6 订单微服务调用支付微服务
  1. 建module

    cloud-consumer-feign-hystrix-order80

  2. 改pom

    <!--eureka client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
    <!--open feign-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    <!--hystrix-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
  3. 建yml

    server:
      port: 80
      tomcat:
        uri-encoding: utf-8
    
    spring:
      application:
        name: cloud-order-feign-hystrix-service
    
    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
      instance:
        instance-id: feign-hystrix-order80
        prefer-ip-address: true
        # Eureka客户端向服务端发送心跳的时间间隔,默认为30秒
        lease-renewal-interval-in-seconds: 1
        # Eureka服务端收到客户端最后一次心跳后等待的时间上限,超时将注销服务,默认为90秒
        lease-expiration-duration-in-seconds: 2
    
    # 消费端超时控制
    ribbon:
      ReadTimeout: 5000 #建立连接所用的时间
      ConnectTimeout: 5000 #建立连接后服务端读取可用资源所用的时间
    
  4. 主启动

    @SpringBootApplication
    @EnableFeignClients
    public class OrderHystrixMain80 {
        public static void main(String[] args) {
            SpringApplication.run(OrderHystrixMain80.class, args);
        }
    }
    
  5. 业务类

    /**
     * PaymentFeignService 定义了服务提供者的服务接口[PaymentController]原样拷贝,URL,方法都需要一样
     */
    
    @Component
    @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
    @RequestMapping("/api/payment/hystrix")
    public interface PaymentHystrixService {
    
        @GetMapping("/ok/{id}")
        public String paymentInfo_Ok(@PathVariable("id") int id);
    
        @GetMapping("/timeout/{id}")
        public String paymentInfo_TimeOut(@PathVariable("id") int id);
    }
    
    @RestController
    @Slf4j
    @RequestMapping("/consumer/payment")
    public class OrderHystrixController {
        @Resource
        private PaymentHystrixService paymentHystrixService;
        @GetMapping("/ok/{id}")
        public String paymentInfo_Ok(@PathVariable("id") int id) {
            return paymentHystrixService.paymentInfo_Ok(id);
        }
    
        @GetMapping("/timeout/{id}")
        public String paymentInfo_TimeOut(@PathVariable("id") int id) {
            return paymentHystrixService.paymentInfo_TimeOut(id);
        }
    }
    
  6. 测试

    http://localhost/consumer/payment/ok/4
    http://localhost/consumer/payment/timeout/4
    
  7. Jmeter高并发测试

    对hystrix-payment8001开启高并发请求

    8001同一层级的其它接口服务被困死,因为Tomcat线程池里面的工作线程已经被占用完

    80此时调用8001,会出现客户端请求缓慢

7.5 如何处理服务降级
对方服务8001超时了,调用者80不能一直卡死等待,必须服务降级
对方服务8001 down机了,调用者80不能一直卡死等待,必须服务降级
对方服务8001 ok,但调用者80自己出故障或自己对服务响应有时间要求,必须服务降级
7.5.1 从服务提供侧解决
设置服务自身超时时间峰值,峰值以内可以正常运行
超过峰值要有兜底的方法,作为服务降级的fallback
  1. 业务类启动加 @HystrixCommand

    com.chris.springcloud.service.PaymentService

        /**
         * @param id
         * @return 访问超时
         */
        @HystrixCommand(fallbackMethod = "timeOutHandler", commandProperties = {@HystrixProperty(name =
                "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})
        public String paymentInfo_TimeOut(int id) {
            int sleepTime = 5;
            try {
                TimeUnit.SECONDS.sleep(sleepTime);
            } catch (InterruptedException e) {
                log.error("error happened paymentInfo_TimeOut ", e);
            }
            return "thread pool " + Thread.currentThread().getName() + " paymentInfo_TimeOut, id:" + id + ". waste time" + "seconds:" + sleepTime;
        }
    
        private String timeOutHandler(int id) {
            return "thread pool " + Thread.currentThread().getName() + " paymentInfo_TimeOutHandler, id:" + id;
        }
    
  2. 主启动

    添加@EnableCircuitBreaker

    @SpringBootApplication
    @EnableEurekaClient
    @EnableCircuitBreaker
    public class PaymentHystrixMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentHystrixMain8001.class, args);
        }
    }
    
  3. 测试

    request:
    http://localhost:8001/api/payment/hystrix/timeout/4
    
    response:
    thread pool hystrix-PaymentService-1 paymentInfo_TimeOutHandler, system busy or server callapse, id:4
    

    hystrix 使用自己的线程池对服务进行降级 HystrixTimer-1

  4. 更改业务类异常类型

    /**
     * @param id
     * @return 访问超时
     */
    @HystrixCommand(fallbackMethod = "timeOutHandler", commandProperties = {@HystrixProperty(name =
            "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})
    public String paymentInfo_TimeOut(int id) {
    
        int i = 10 / 0;
        /*int sleepTime = 5;
        try {
            TimeUnit.SECONDS.sleep(sleepTime);
        } catch (InterruptedException e) {
            log.error("error happened paymentInfo_TimeOut ", e);
        }
        return "thread pool " + Thread.currentThread().getName() + " paymentInfo_TimeOut, id:" + id + ". waste " +
                "time" + "seconds:" + sleepTime;
         */
        return "thread pool " + Thread.currentThread().getName() + " paymentInfo_TimeOut, id:" + id;
    }
    
    private String timeOutHandler(int id) {
        return "thread pool " + Thread.currentThread().getName() + " paymentInfo_TimeOutHandler, system busy or " +
                "server callapse, id:" + id;
    }
    
  5. 测试

    request:
    http://localhost:8001/api/payment/hystrix/timeout/4
    
    response:
    thread pool hystrix-PaymentService-1 paymentInfo_TimeOutHandler, system busy or server callapse, id:4
    
  6. 总结

    无论是超时异常或运行异常,只要当前服务不可用,就会作服务降级

7.2.2 从服务消费侧解决
一般服务降级都是放在消费端
热部署对Java代码的改动是非常敏感的,但是对于@HystrixCommand 内属性的修改建议重启微服务
  1. 修yml,允许feign使用hystrix进行服务降级

    feign:
      hystrix:
        enabled: true
    
  2. 主启动

    配置@EnableHystrix 激活Hystrix

    @SpringBootApplication
    @EnableFeignClients
    @EnableHystrix
    public class OrderHystrixMain80 {
        public static void main(String[] args) {
            SpringApplication.run(OrderHystrixMain80.class, args);
        }
    }
    
  3. 修改业务类

    添加@HystrixCommand

    @GetMapping("/timeout/{id}")
    @HystrixCommand(fallbackMethod = "timeOutHandler", commandProperties = {@HystrixProperty(name =
            "execution.isolation.thread.timeoutInMilliseconds", value = "1000")})
    public String paymentInfo_TimeOut(@PathVariable("id") int id) {
        return paymentHystrixService.paymentInfo_TimeOut(id);
    }
    
    @SuppressWarnings("unused")
    private String timeOutHandler(int id) {
        return "I'm order80, the service provider system busy or server callapse, id:" + id;
    }
    
  4. 测试

    request:
    http://localhost/consumer/payment/timeout/4
    
    response
    I'm order80, the service provider system busy or server callapse, id:4
    
7.2.3 全局服务降级
每个业务方法都对应一个fallback方法,导致代码膨胀
服务降级方法和业务代码混合在一起,导致代码混乱
全局服务降级解决两个问题:	
1. 代码膨胀
2. 代码混乱

解决致代码膨胀

  1. 业务类

    com.chris.springcloud.controller.OrderHystrixController
    在类上配置默认服务降级的fallback方法
    需要支持服务降级的方法上仍需要配置@HystrixCommand()

    
    @RestController
    @Slf4j
    @RequestMapping("/consumer/payment")
    @DefaultProperties(defaultFallback = "paymentGlobalFallBack")
    public class OrderHystrixController {
        @Resource
        private PaymentHystrixService paymentHystrixService;
        
        @GetMapping("/ok/{id}")
        public String paymentInfo_Ok(@PathVariable("id") int id) {
            return paymentHystrixService.paymentInfo_Ok(id);
        }
    
        @GetMapping("/timeout2/{id}")
        @HystrixCommand()
        public String paymentInfo_TimeOut2(@PathVariable("id") int id) {
            return paymentHystrixService.paymentInfo_TimeOut(id);
        }
    
        @SuppressWarnings("unused")
        public String paymentGlobalFallBack() {
            return "system is busy , pls try later!";
        }
    }
    
  2. 测试

    request:
    http://localhost/consumer/payment/timeout2/4
    
    response:
    system is busy , pls try later!
    

解决代码混乱

  1. 实现PaymentHystrixService接口

    @Component
    public class PaymentFallBackService implements PaymentHystrixService {
        @Override
        public String paymentInfo_Ok(int id) {
            return "PaymentFallBackService fallback-paymentInfo_Ok, the provider collapsed, try it later.";
        }
    
        @Override
        public String paymentInfo_TimeOut(int id) {
            return "PaymentFallBackService fallback-paymentInfo_TimeOut, the provider collLapsed, try it later.";
        }
    }
    
  2. 配置FeignClient,使用支持服务降级的fallback实现类

    @Component
    //配置FeignClient,使用支持服务降级的fallback实现类
    @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallBackService.class, path = "/api/payment/hystrix")
    public interface PaymentHystrixService {
        @GetMapping("/ok/{id}")
        public String paymentInfo_Ok(@PathVariable("id") int id);
    
        @GetMapping("/timeout/{id}")
        public String paymentInfo_TimeOut(@PathVariable("id") int id);
    }
    
  3. 异常处理

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'com.chris.springcloud.service.PaymentHystrixService' method
    com.chris.springcloud.service.PaymentHystrixService#paymentInfo_TimeOut(int)
    to {GET /api/payment/hystrix/timeout/{id}}: There is already 'paymentFallBackService' bean method

    原因:PaymentFallBackService实现了接口PaymentHystrixService,且因为接口有共用map路径**@RequestMapping("/api/payment/hystrix")**,所以spring在实例化Bean时发现一同一URL下有两个相同的方法,不知道调用哪个

    @Component
    public class PaymentFallBackService implements PaymentHystrixService
    

    解决办法

    1. 将/api/payment/hystrix内嵌到每个方法的URL中

    2. 使用@FeignClient的path参数

      @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallBackService.class, path = "/api/payment/hystrix")
      
  4. 测试

    停用PaymentHystrixMain8001服务

    request:
    http://localhost/consumer/payment/ok/4
    response:
    PaymentFallBackService fallback-paymentInfo_Ok, the provider collapsed, try it later.
    
7.6 如何处理服务熔断
7.6.1 Hystrix实现服务熔断

SpringCloud框架通过集成的Hystrix实现服务熔断

Hystrix会监控服务间的调用状况,当失败超过设定的阈值时默认为5秒内20次调用失败,就会启动熔断机制

熔断机制注解为@HystrixCommand

7.6.2 Hystrix熔断如何工作

How it Works

https://github.com/Netflix/Hystrix/wiki/How-it-Works

martinfowler

https://martinfowler.com/bliki/CircuitBreaker.html

7.6.3 服务熔断实现
  1. 修改业务类

    com/chris/springcloud/service/PaymentService.java

    /**
     * 模拟服务熔断
     * 配置中的属性在抽象类HystrixCommandProperties中定义
     */
    @HystrixCommand(fallbackMethod = "paymentCircuitBreakerFallBack", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //是否开启断路器
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"), //请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "20000"), //trip circut before retry 的时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")}) //失败率达到多少后启动熔断
    public String paymentCircuitBreaker(int id) {
        if (id < 0) {
            throw new RuntimeException("id 不能为负数");
        }
        String serialNumber = IdUtil.simpleUUID();
        return Thread.currentThread().getName() + "\t 调用成功,流水号: " + serialNumber;
    }
    
    @SuppressWarnings("unused")
    private String paymentCircuitBreakerFallBack(int id) {
        return "id 不能为负数, id:" + id;
    }
    

    com/chris/springcloud/controller/PaymentController.java:39

    /**
     * 模拟服务熔断
     */
    @GetMapping("/circuit/{id}")
    public String paymentCircuitBreaker(@PathVariable("id") int id) {
        String result = paymentService.paymentCircuitBreaker(id);
        log.info("paymentCircuitBreaker, result: " + result);
        return result;
    }
    

  1. 测试

    1. 使用Jmeter多次连续访问此连接后

      http://localhost:8001/api/payment/hystrix/circuit/-10

    2. 再使用postman 调用此连接

      http://localhost:8001/api/payment/hystrix/circuit/10

      会发现即使是大于0的正数,仍然走的是服务降级后的fallback方法

      id 不能为负数, id:10
      
    3. 等Jmeter访问过后,再使用postman 调用此连接

      http://localhost:8001/api/payment/hystrix/circuit/10

      求得出正确响应

      hystrix-PaymentService-10	 调用成功,流水号: fdea7e0aead64adbb1fbb5bb046b2b3c
      
  2. 总结

    先启用		  enabled
    时间窗口 	  sleepWindowInMilliseconds
    达到请求数阈值 requestVolumeThreshold
    错误百分比阈值 errorThresholdPercentage
    
7.7 图形化DashBoard搭建
7.7.1 准实时调用监控

Hystrix 会持续记录通过Hystrix 发起的请求信息包括请求数,成功和失败数等并以Hystrix Dashboard 图形化的结果展示给用户

7.7.2 搭建监控
  1. 建module

    cloud-consumer-hystrix-dashboard9001
    
  2. 改pom

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.chris.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${common.api.version}</version>
        </dependency>
        <!--hystrix-dashboard-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
    </dependencies>
    
  3. 建yml

    server:
      port: 9001
      tomcat:
        uri-encoding: UTF-8
    
  4. 主启动

    com.chris.springcloud.HystirxDashboardMain9001

    @SpringBootApplication
    @EnableHystrixDashboard
    public class HystirxDashboardMain9001 {
        public static void main(String[] args) {
            SpringApplication.run(HystirxDashboardMain9001.class, args);
        }
    }
    
  5. 测试
    http://localhost:9001/hystrix

7.7.3 监控具体的微服务
  1. 确保pom中有web和actuator两个依赖包

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  2. 在启动类里面添加如下方法

    com.chris.springcloud.PaymentHystrixMain8001

    	/**
         * 为解决hystrix dashboard
         * Unable to connect to Command Metric Stream.
         * 此配置是为了服务监控而配置,与服务容错本身无关,SpringClou要·d升级后的坑
         * ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
         * 只要在自己的项目里配置上下面的servlet就可以了
         */
        @Bean
        @SuppressWarnings("unchecked")
        public ServletRegistrationBean getServlet() {
            HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
            ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
            registrationBean.setLoadOnStartup(1);
            registrationBean.addUrlMappings("/hystrix.stream");
            registrationBean.setName("HystrixMetricsStreamServlet");
            return registrationBean;
        }
    
    
  3. 测试

    http://localhost:8001/api/hystrix.stream

    使用Jmeter分别对下面这个请求进行并发访问

    http://localhost:8001/api/payment/hystrix/circuit/-10
    http://localhost:8001/api/payment/hystrix/circuit/10

8 服务网关

8.1 SpringCloud GateWay
8.1.1 官网

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

8.1.2 是什么

SpringCloud全家桶里面最重要的东西就是网关

SpringCloud Gateway是原zuul1.x的替代产品

提供一种简单有效的方式对API进行路由并提供强大的过滤链功能,如熔断,限流,重试等

SpringCloud Gateway基于Spring WebFlux实现,而Spring WebFlux基层使用高性能的Reactor模式的通信框架Netty
速度是Zuul的1.6倍

8.1.3 能干什么
  1. 反向代理
  2. 鉴权
  3. 熔断
  4. 日志监控
  5. 流量控制

8.1.3 Spring WebFlux

传统的web框架, 如struts2, SpringMvc等都是基于Servlet API并在servlet容器上运行的

在Servlet3.1之后出现了异步非阻塞支持,WebFlux是一个典型的异步非阻塞框架,它的核心是基于Reactor的相关API实现的

可以运行在如Netty,Undertow及支持Servlet3.1的容器上。

8.1.4 三大核心
  1. Route

    路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由

  2. Predicate

    参考的是Java8的java.util.function.Predicate

    开发人员可以匹配HTTP请求中的所有内容例如消息头和请求参数,如果请求与断言相匹配则进行路由

  3. Filter

    Filter是的是Spring框架中的GateWayFilter的实例,使用过虑器,可以在请求被路由前或路由后对请求进行修改

  4. 总结

    客户端向SpringCloud GateWay发出请求,然后由GateWay Handler Mapping中找到请求相匹配的路由,将其发送到Gateway Web Handler, 再通过指定的过滤器链将请求发送到实现的服务执行逻辑,然后返回。

    过滤前可以进行参数校验,流量监控,日志输出,协议转换等

    过滤后可以做响应内容和响应头的修改,流量监控,日志输出等

8.1.5 通过YML配置网关
  1. 建module

    cloud-gateway-gateway9527

  2. 改pom

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    
        <!-- SpringCloud GateWay-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    
        <!--
        eureka client
        网关作为一种微服务也在注册到服务注册中心
        -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
    
  3. 建yml

   server:
     port: 9527
   
   spring:
     application:
       name: cloud-gateway
     cloud:
       gateway:
         routes:
             # 路由的ID,没有固定规则但要求唯一,简易配合服务名
           - id: payment_8001_routh1
             # 匹配提供服务的路由地址
             uri: http://localhost:8001
             predicates:
               // 断言,路径相匹配的进行路由
               - Path=/api/payment/get/**
   
             #路由的ID,没有固定规则但要求唯一,简易配合服务名
           - id: payment_8001_routh2
             #匹配提供服务的路由地址
             uri: http://localhost:8001
             predicates:
                 # 断言,路径相匹配的进行路由
               - Path=/api/payment/lb/**
   eureka:
     client:
       #表示是否将自己注册到eureka-server,默认为true
       register-with-eureka: true
       #是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
       fetch-registry: true
       service-url:
         defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
     instance:
       instance-id: cloud-gateway-9527
       prefer-ip-address: true
8.1.6 通过配置类配置网关
  1. 建配置类

    通过RouteLocatorBuilder类创建路由

    package com.chris.springcloud.config;
    
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class GateWayConfig {
    
        /**
         * 当访问地址http://localhost:9527/guonei时会自动转发到https//news.baidu.com/guonei
         */
        @Bean
        public RouteLocator customRouteLocator_guoji(RouteLocatorBuilder routeLocatorBuilder) {
            RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
            routes.route("guoji_news", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
            return routes.build();
        }
    
        /**
         * 当访问地址http://localhost:9527/mil 时会自动转发到https//news.baidu.com/mil
         */
        @Bean
        public RouteLocator customRouteLocator_mil(RouteLocatorBuilder routeLocatorBuilder) {
            RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
            routes.route("guoji_news", r -> r.path("/mil").uri("http://news.baidu.com/mil")).build();
            return routes.build();
        }
    }
    
    
8.1.7 动态路由配置
  1. 改yml

    spring:
      application:
        name: cloud-gateway
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从服务注册中心动态创建路由的功能,利用微服务名称进行路由
          routes:
            # 路由的ID,没有固定规则但要求唯一,简易配合服务名
            - id: payment_8001_routh1
              # 需要注意的是uri的协议为lb,表示启用gateway的负载均衡功能
              # lb://serviceName是spring cloud gateway在微服务中自动创建的负载均衡uri
              uri: lb://cloud-payment-service
              predicates:
                # 断言,路径相匹配的进行路由
                - Path=/api/payment/get/**
            - id: payment_8001_routh2
              uri: lb://cloud-payment-service
              predicates:
                - Path=/api/payment/lb/**
    
8.1.8 Predicates

​ https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories

  1. spring gateway 启动日志

    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [After]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Before]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Between]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Cookie]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Header]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Host]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Method]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Path]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Query]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [ReadBodyPredicateFactory]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [RemoteAddr]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Weight]
    [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [CloudFoundryRouteService]
    
  2. 配置yml

    predicates:
      # 断言,路径相匹配的进行路由
      - Path=/api/payment/lb/**
      - After=2020-09-11T13:40:01.365+08:00[Asia/Shanghai]
      - Cookie=username,zzyy     #请求要还有cookie并且带有username=zzyy的键值对
      - Header=X-Request-Id,\d+  #请求头要有X-Request-Id属性并且值为整数的正则表达式
      #- Host=**.chris.com
      - Method=GET
      - Query=id, \d+ #要有参数名id并且值还要啥整数才能路由
    
  3. 测试

    curl http://localhost:9527/api/payment/lb --cookie "username=zzyy" 
    curl http://localhost:9527/api/payment/lb --cookie "username=zzyy" -H "X-Request-Id:5"
    curl http://localhost:9527/api/payment/lb --cookie "username=zzyy" -H "X-Request-Id:5,Host:www.chris.com"
    curl http://localhost:9527/api/payment/lb?id=15 --cookie "username=zzyy" -H "X-Request-Id:5"
    
8.1.9 Filter
  1. 生命周期

    1. pro
    2. post
    
  2. 种类

    1. 单一的GateWayFilter
    2. 全局的GlobalFilter
    
  3. 自定义全局过虑器

     @Component
     @Slf4j
     public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    
     @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
         log.info("************** come in MyLogGateWayFilter :" + new Date());
            String uname = exchange.getRequest().getQueryParams().getFirst("uname");
         if (StrUtil.isEmpty(uname)) {
                log.info("************** illegal uname :" + new Date());
                exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
                return exchange.getResponse().setComplete();
            }
            return chain.filter(exchange);
        }
    
        /**
         * 加载过虑器的顺序
         * 一般数字或小,优先级越高
         * 全局都是0,放在第一位加载
         */
        @Override
        public int getOrder() {
            return 0;
        }
    }
    

9. 分布式配置中心

https://docs.spring.io/spring-cloud-config/docs/2.2.5.RELEASE/reference/html/

微服务意味着将单体应用中的业务拆分一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。

由于每个服务需要配置信息才能运行,所以一套集中的动态的配置管理是必不可少的。

9.1 是什么

SpringCloud提供了ConfigServer来解决这个问题

Config为微服务提供了集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置

SpringCloud Config 分为服务端和客户端

ConfigServer 称为分布式配置中心,是一独立微服务应用,用来连接配置服务器,并为客户端提供获取配置信息,加密解密等访问接口

配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和查看配置信息内容

客户端就是一个个微服务,通过指定的配置中心来管理应用资源,以及与业务相关的配置内容。并在启动时从配置中心获取和加载配置信息。

9.2 能干什么
  1. 集中配置管理

  2. 不同的环境不同的配置,分环境部署例如dev/test/prod/beta/release

  3. 动态化更新配置,服务不需要重启就可感知到配置的变化并加载新的配置

  4. 将配置以rest接口形式暴露

9.3 怎么玩
9.3.1 服务端
  1. 建module

    cloud-config-center-3344

  2. 改pom

    <!--config server-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
    <!--eureka client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  3. 写yam

    server:
      port: 3344
      tomcat:
        uri-encoding: utf-8
    
    spring:
      application:
        name: cloud-config-center
      cloud:
        config:
          server:
            git:
              uri: https://github.com/ChrisLi716/springcloud-config.git  #git仓库名称
              search-paths:
                - springcloud-config
    
          label: master  #读取分支
    
    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
      instance:
        instance-id: configcenter3344
        prefer-ip-address: true
        # Eureka客户端向服务端发送心跳的时间间隔,默认为30秒
        lease-renewal-interval-in-seconds: 1
        # Eureka服务端收到客户端最后一次心跳后等待的时间上限,超时将注销服务,默认为90秒
        lease-expiration-duration-in-seconds: 2
    
  4. 启动类

    @SpringBootApplication
    @EnableConfigServer
    public class ConfigCenterMain3344 {
        public static void main(String[] args) {
            SpringApplication.run(ConfigCenterMain3344.class, args);
        }
    }
    
  5. 测试

    在hosts文件中配置 127.0.0.1 config-3344.com

    http://config-3344.com:3344/master/config-dev.yml

    结果:

    config:
      info: master branch,springcloud-config/config-dev.yml version=1
    
9.3.2 客户端
  1. 建module

    cloud-config-client-3355

  2. 改pom

    <!--config client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <!--eureka client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  3. 写yml

    application.yml是用户级的资源配置文件

    bootstrap.yml是系统级的资源配置文件,优先级更高,更先加载。

    SpringCloud会创建一个BootStrap Context作为Spring应用的Application Context的父上下文,初始化时BootStrap Context负责从外部源加载配置信息,这两个上下文共享一个从外部获取的Environment。

    BootStrap的优先级更高,默认情况下不会被本地配置覆盖

    server:
      port: 3355
    spring:
      application:
        name: clound-config-client
      cloud:
        config:
          label: master  #分支名称
          name: config   #配置文件名称
          profile: dev   #环境名称
          uri: http://localhost:3344 #配置中心地址
    
    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
      instance:
        instance-id: configcenter3344
        prefer-ip-address: true
        # Eureka客户端向服务端发送心跳的时间间隔,默认为30秒
        lease-renewal-interval-in-seconds: 1
        # Eureka服务端收到客户端最后一次心跳后等待的时间上限,超时将注销服务,默认为90秒
        lease-expiration-duration-in-seconds: 2
    
9.3.3 客户端动态刷新配置
  1. 引入actuator图形化监控模块

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  2. 修改yml暴露监控端点

    # 暴露监控端点
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
  3. 业务类中添加@RefreshScope注解

    @RestController
    @Slf4j
    @RefreshScope
    public class ConfigClientController {
    
        @Value("${config.info}")
        private String configInfo;
    
        @GetMapping("/configInfos")
        public String getConfigInfo() {
            return configInfo;
        }
    }
    
  4. 修改完github上中的配置信息后发post请求刷新客户端

    curl -X POST http://localhost:3355/actuator/refresh
    
9.4 配置读取规则
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
9.4.1 /{label}/{application}-{profile}.yml
  1. 读取master分支的dev配置文件
    http://config-3344.com:3344/master/config-dev.yml

  2. 读取dev分支的config-dev配置文件
    http://config-3344.com:3344/dev/config-dev.yml

9.4.2 /{application}/{profile}[/{label}]
  1. 读取master分支的config-dev配置文件
    http://config-3344.com:3344/config/dev.yml/master

10. SpringCloud Bus消息总线

10.1 是什么
10.1.1 总线是什么

在微服务架构系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统所有的微服务实现来订阅,由于该主题中产生的消息会被所有的实例消费,所以称它为消息总线。

在总线上的各个实例,都可以方便地广播一些需要其他连接在该主题上的实例都知道的消息。

10.1.2 Bus是什么

Bus是对Config的加强,可以实现分布式的自动刷新配置功能

支持两种消息代理,RabbitMQ和Kafka

10.1.3 基本原理

ConfigClient实例都监听MQ中同一个topic(默认是springCloudBus), 当一个服务刷新数据时,它会将这个信息放入到Topic中,这样其它监听同一Topic的服务就能得到通知,然后去更新自身的配置

10.2 能干什么

动态刷新全局广播

动态刷新定点通知

消息更新推给configserver配置中心,再由配置中心广播给其它微服务节点

消息更新推给configClient,再由A去传播其它的微服务节点

10.3 怎么玩
10.3.1 安装RabbitMQ
10.3.2 创建新的module
  1. 建module

    cloud-config-client-3366

  2. 改pom

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--config client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
    
  3. 建YML

    bootstrap.yml

    # 暴露监控端点
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
10.3.3 通过configClient刷新所有客户端

利用消息总线触发一个客户端/bus/refresh,而刷新所有的客户端的配置

不建议使用这一种

  1. 破坏了微服务的责任单一性,因为微服务本向即是业务模块又承担了配置刷新的职责

  2. 破坏了微服务各个节点的对等性,例如订单模块有三个集群节点,其中一个有配置刷新功能而其它两个没有配置刷新功能

10.3.4 通过configServer刷新所有客户端

利用消息总线触发一个服务端/bus/refresh,而刷新所有的客户端的配置

  1. 修改配置服务端configServer

    cloud-config-center-3344

    pom

    <!--添加消息总线RabbitMQ支持-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    </dependency>
    

    application.yml

      #rabbitmq相关配置
      rabbitmq:
        host: master
        port: 5672
        username: chris
        password: 123456
    
    # 暴露bus刷新配置监控端点
    management:
      endpoints:
        web:
          exposure:
            include: "bus-refresh"
    
  2. 修改配置客户端configClient

    cloud-config-client-3355

    cloud-config-client-3366

    bootstrap.yml

    #rabbitmq相关配置
    rabbitmq:
      host: master
      port: 5672
      username: chris
      password: 123456
    #暴露监控端点
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    

    pom

    <!--添加消息总线RabbitMQ支持-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    </dependency>
    
  3. 测试

    http://config-3344.com:3344/master/config-test.yml
    http://localhost:3355/configInfos
    http://localhost:3366/configInfos

    动态刷新全局广播

    curl -X POST http://localhost:3344/actuator/bus-refresh

10.3.5 动态刷新定点通知

在github中修改了配置信息后,只刷新微服务3355不刷新微服务3366

  1. 在github上修改对应的配置文件

  2. 发送post请求刷新对应的微服务3355

    命令:curl -X POST http://config-3344.com:3344/actuator/bus-refresh/application-name:port

    curl -X POST http://config-3344.com:3344/actuator/bus-refresh/cloud-config-client:3355
    

11 消息驱动 Stream

11.1 官网
11.1.1 大纲

https://spring.io/projects/spring-cloud-stream#overview

11.1.2 API

https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/3.0.1.RELEASE/reference/html/

11.1.3 中文指导手册

https://m.wang1314.com/doc/webapp/topic/20971999.html

11.2 是什么

Spring Cloud Stream是一个构建消息驱动服务的框架

应用程序通过inputs或outputs来与Spring Cloud Stream中的binder对象交互

input 对应于消息者,output 对应于生产者

通过配置来绑定binding(绑定),而Spring Cloud Stream的binder对象负责与消息中间件交互

Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置,引用 了,发布-订阅,消费组,分区三个核心概念

目前Spring Cloud Stream只支持 RabbitMQ 和 Kafka

11.3 能干什么

屏蔽底层消息中间件的差异,降低切换,开发和维护成本,统一消息编程模型

不需要关注具体MQ的实现细节,只需要用一种适配绑定的方式,自动的在各MQ之间进行切换

11.4 怎么玩
11.4.1 Stream 标准流程

binder 可以很方便的连接消息中间件
channel 通道,是Queue队列的一种抽象,在消息中间件中是实现消息存储和转发的媒介
Source和Sink可以理解为消息的输出和输入,从Stream生产消息就是输出,消费消息就是输入

11.4.2 使用到的注解
middleWare消息中间件,目前只支持rabbitMQ和kafka
@Input 标识输入通道,通过输入通道接收消息进入应用程序
@Output标识输出通道,生产的消息通过输出通道离开应用程序
@StreamListener,监听队列,用于消费者的队列的消息接收
@EnableBinding 指定信道channel和exchange绑定在一起

11.4.3 消息生产者驱动实现
  1. 建module

    cloud-stream-rabbitmq-provider8801

  2. 改pom

    <dependencies>
        <!--boot web actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--stream rabbitmq-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <!-- 一般通用配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
    </dependencies></dependencies>
    
  3. 建yml

    server:
      port: 8801
      tomcat:
        uri-encoding: UTF-8
    spring:
      application:
        name: cloud-stream-provider
      rabbitmq:
        host: master
        port: 5672
        username: chris
        password: 123456
      cloud:
        stream:
          binders: #在此处配置要绑定的rabbitmq的服务信息
            defaultRabbit: #定义的名称,用于binding整合
              type: rabbit #消息组件类型
          bindings: #服务的整合处理
            output: #一个通道的名称
              destination: studyExchange #要使用的Exchange的名称
              content-type: application/json #设置消息类型,文本设置为 text/plain]
              binder: defaultRabbit
    
    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
      instance:
        instance-id: stream-provider8801
        prefer-ip-address: true
        # Eureka客户端向服务端发送心跳的时间间隔,默认为30秒
        lease-renewal-interval-in-seconds: 1
        # Eureka服务端收到客户端最后一次心跳后等待的时间上限,超时将注销服务,默认为90秒
        lease-expiration-duration-in-seconds: 2
    
  4. 启动类

    @SpringBootApplication
    @EnableEurekaClient
    public class StreamMQMain8801 {
        public static void main(String[] args) {
            SpringApplication.run(StreamMQMain8801.class, args);
        }
    }
    
  5. 业务类

    public interface IMessageProvider {
        String send();
    }
    
    import cn.hutool.core.lang.UUID;
    import com.chris.springcloud.service.IMessageProvider;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cloud.stream.annotation.EnableBinding;
    import org.springframework.cloud.stream.messaging.Source;
    import org.springframework.messaging.MessageChannel;
    import org.springframework.messaging.support.MessageBuilder;
    
    import javax.annotation.Resource;
    
    //定义消息的推送信道
    @EnableBinding(Source.class)
    @Slf4j
    public class MessageProviderImpl implements IMessageProvider {
    
        //消息生产信道
        @Resource
        private MessageChannel output;
    
        @Override
        public String send() {
            String uuid = UUID.randomUUID().toString();
            output.send(MessageBuilder.withPayload(uuid).build());
            log.info("uuid:" + uuid);
            return uuid;
        }
    }
    
    @RestController
    public class SendMsgController {
    
        @Resource
        private IMessageProvider messageProvider;
    
        @GetMapping("/sendMsg")
        public String sendMessage(){
            return messageProvider.send();
        }
    
    }
    
  6. 测试

    http://localhost:8801/sendMsg

11.4.4 消息消费者驱动实现
  1. 建module

    cloud-stream-rabbitmq-consumer8802

  2. 改pom

    <dependencies>
        <!--boot web actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--stream rabbitmq-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <!--一般通用配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
    </dependencies>
    
  3. 建yml

    server:
      port: 8802
      tomcat:
        uri-encoding: UTF-8
    
    
    spring:
      application:
        name: cloud-stream-provider
      rabbitmq:
        host: master
        port: 5672
        username: chris
        password: 123456
      cloud:
        stream:
          binders: #在此处配置要绑定的rabbitmq的服务信息
            defaultRabbit: #定义的名称,用于binding整合
              type: rabbit #消息组件类型
          bindings: #服务的整合处理
            input: #一个通道的名称
              destination: studyExchange #要使用的Exchange的名称
              content-type: application/json #设置消息类型,文本设置为 text/plain]
              binder: defaultRabbit
    
    eureka:
      client:
        # 表示是否将自己注册到eureka-server,默认为true
        register-with-eureka: true
        # 是否从eureka-server抓取自己的注册信息,默认为true,单节点无所谓,集群必需设置为true以配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
      instance:
        instance-id: stream-consumer8802
        prefer-ip-address: true
        # Eureka客户端向服务端发送心跳的时间间隔,默认为30秒
        lease-renewal-interval-in-seconds: 1
        # Eureka服务端收到客户端最后一次心跳后等待的时间上限,超时将注销服务,默认为90秒
        lease-expiration-duration-in-seconds: 2
    
  4. 主启动

    @SpringBootApplication
    @EnableEurekaClient
    public class StreamMQMain8802 {
        public static void main(String[] args) {
            SpringApplication.run(StreamMQMain8802.class, args);
        }
    }
    
  5. 业务类

    @Component
    @EnableBinding(Sink.class)
    @Slf4j
    public class ConsumMsgListener {
        @Value("${server.port}")
        private String serverPort;
    
        //监听队列,用于消费者的队列的消息接收
        @StreamListener(Sink.INPUT)
        public void input(Message<String> message) {
            log.info("消费者1号,接收到的消息------>" + message.getPayload() + ", port: " + serverPort);
        }
    }
    
11.4.5 分组

订单服务做集群部署

如果一个订单被两个服务获取到,就会造成数据错误,甚至重复扣款

分组解决两个问题

  1. 消息重复消息问题

    处于同一个分组的多个消费者是竞争关系,能够保证消息被其中一个消费者只消费一次。

    但不同组是可以重复消费

  2. 消息持久化

    未分组的微服务在重启后无法正常消费那些未被消费的消息

    而有分组的微服务重启后可以正常消费那些未被消费的消息

  1. 不同分组

    group: Group-Consumer8803

    spring:
      application:
        name: cloud-stream-provider
      rabbitmq:
        host: master
        port: 5672
        username: chris
        password: 123456
      cloud:
        stream:
          binders: #在此处配置要绑定的rabbitmq的服务信息
            defaultRabbit: #定义的名称,用于binding整合
              type: rabbit #消息组件类型
          bindings: #服务的整合处理
            input: #一个通道的名称
              destination: studyExchange #要使用的Exchange的名称
              content-type: application/json #设置消息类型,文本设置为 text/plain]
              binder: defaultRabbit
              group: Group-Consumer8803
    

  2. 相同分组

    将cloud-stream-rabbitmq-consumer8802和cloud-stream-rabbitmq-consumer8803的分组改为相同名称

    group: Group-Consumer-A

    消息只会被相同分组中的微服务消费一次

    spring:
      application:
        name: cloud-stream-provider
      rabbitmq:
        host: master
        port: 5672
        username: chris
        password: 123456
      cloud:
        stream:
          binders: #在此处配置要绑定的rabbitmq的服务信息
            defaultRabbit: #定义的名称,用于binding整合
              type: rabbit #消息组件类型
          bindings: #服务的整合处理
            input: #一个通道的名称
              destination: studyExchange #要使用的Exchange的名称
              content-type: application/json #设置消息类型,文本设置为 text/plain]
              binder: defaultRabbit
              group: Group-Consumer-A
    

12 服务链路跟踪 Sleuth

12.1 是什么

在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的服务节点调用来协同产生最后的请求结果,这是形成了一个复杂的分步式调用链路,链路中任何一个节点出现延时或错误都会引起整个请求最后的失败

Sleuth 用于分步式请求链路跟踪并且兼容支持zipkin

12.2 官网

https://github.com/spring-cloud/spring-cloud-sleuth

12.3 能干什么

Sleuth 负责请求链路的数据收集

Zipkin 负责数据展示

12.4 怎么玩
12.4.1 zipkin安装

SpringCloud从F版起就不需要自己构建Zipkin Server了,只需要调用jar包即可

https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/

下载zipkin-server-2.12.9-exec.jar

切换到下载目录下

java -jar zipkin-server-2.12.9-exec.jar
http://127.0.0.1:9411/

一个链路通过一个traceId唯一标识,span标识发起的请求信息,各span通过parentId来关联

span:表示调用链路来源, 通俗的说span就是一次请求信息

整个链路依赖关系如下

12.4.2 服务提供者引入Sleuth

向服务提供者8001引入链路跟踪

  1. 改pom

    <!--引入Sleuth和Zipkin-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>
    
  2. 改yml

    zipkin:
      base-url: http://localhost:9411 #链路跟踪数据的展示地址
    sleuth:
      sampler:
        probability: 1 #采样率,介于0到1之间,1表示全部采样,一样用0.5表示一半采样
    
  3. 业务类

    com.chris.springcloud.payment.controller.PaymentController

    @GetMapping("/zipkin")
    public String invokeZipkin() {
        return "Hi, test sleuth and zipkin! port:" + serverPort;
    }
    
12.4.3 服务消费者引入Sleuth

向服务消费者80引入链路跟踪

  1. 改pom

    <!--引入Sleuth和Zipkin-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>
    
  2. 改yml

    zipkin:
      base-url: http://localhost:9411 #链路跟踪数据的展示地址
    sleuth:
      sampler:
        probability: 1 #采样率,介于0到1之间,1表示全部采样,一样用0.5表一半采样
    
  3. 业务类

    com.springcloud.order.controller.OrderController

    @GetMapping("/payment/zipkin")
    public String testPaymentZipkin() {
        return restTemplate.getForObject(PAYMENT_URL + "/api/payment/zipkin", String.class);
    }
    
12.4.4 测试

http://localhost/consumer/payment/zipkin

http://127.0.0.1:9411/zipkin/

13 Spring Cloud Alibaba

13.1 是什么
13.1.1 官网

https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md

https://github.com/alibaba/spring-cloud-alibaba

https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html

https://spring.io/projects/spring-cloud-alibaba#overview

13.2 能干什么
  1. 服务限流和降级:

    默认支持Servlet, Feign, RestTemplate,Dubbo和RocketMQ限流降级功能的接入

  2. 服务注册与发现:

    适配SpringCloud服务注册与发现标准,默认集成了Ribbon的支持。

  3. 分布式配置管理:

    支持分布式系统中的外部化配置,配置更新时自动刷新。

  4. 消息驱动:

    基于Stream为微服务应用构建消息驱动能力

  5. 阿里云对象存储:

    阿里云提供海量,安全,低成本,高可用的云存储服务,支持在任何时间,任何地点,通过任何应用存储和访问任何类型的数据。

  6. 分布式任务调度:

    提供秒级,精准高可用的的 [基于Cron表达式] 任务调度服务.

  7. 分布式事务:

    使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。

13.3 服务注册和配置中心 Nacos
13.1.1 是什么

Naming Configuration Services

是服务注册中心和分布式配置中心的组合,相当于Eureak+Config+Bus

13.3.2 能干什么

替代Eureka作为服务注册中心

替代Config作为分布式配置中心

替代Bus作为服务总线

13.3.3 去哪下

官网: http://nacos.io

https://nacos.io/zh-cn/index.html

https://github.com/alibaba/Nacos

下载地址:

https://github.com/alibaba/nacos/releases/tag/

13.3.4 安装
  1. 下载

    nacos-server-1.3.2.tar.gz

  2. 配置

    cd /opt

    tar -zxvf nacos-server-1.3.2.tar.gz

    cd nacos/conf/

    vi application.poperties

    ### If use MySQL as datasource:
     spring.datasource.platform=mysql
     
    ### Count of DB:
    db.num=1
    db.url.0=jdbc:mysql://localhost:3306/nacos?useSSL=false&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=UTC
    db.user=root
    db.password=65536
    

    新建naocs数据库并在nacos中执行SQL

    SQL位置在./conf/nacos-mysql.sql

  3. 启动

    在nacos的bin目录下执行

    ./startup.sh  -m standalone
    
  4. 查看

    http://master:8848/nacos/index.html

    用户名和密码为:nacos

13.3.5 基于Nacos的服务提供者
  1. 建module

    cloudalibaba-provider-payment9001

  2. 改pom

    <!--springcloud alibaba nacos-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
  3. 写yml

    server:
      port: 9001
      tomcat:
        uri-encoding: UTF-8
      servlet:
        context-path: /api
    
    spring:
      application:
        name: nacos-payment-provider
      cloud:
        nacos:
          discovery:
            server-addr: master:8848  #配置Nacos作为服务注册中心地址
            
    management:
      endpoints:
        web:
          exposure:
            include: '*'  #监控所有
    
  4. 主启动

    @SpringBootApplication
    @EnableDiscoveryClient
    public class PaymentMain9001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain9001.class, args);
        }
    }
    

  1. 业务类

    @RestController
    @Slf4j
    @RequestMapping("/payment")
    public class PaymentController {
    
        @Value("${server.port}")
        private String serverPort;
    
        @GetMapping("/nacos/{id}")
        public String getPayment(@PathVariable("id") Integer id) {
            return "Nacos registry, server port:" + serverPort + ", id:" + id;
        }
    }
    
13.3.6 基于Nacos的服务消费者
  1. 建module

    cloudalibaba-consumer-nacos-order83

  2. 改pom

    <!--springcloud alibaba nacos-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
  3. 写yml

    server:
      port: 83
      tomcat:
        uri-encoding: UTF-8
    
    spring:
      application:
        name: nacos-order-consumer
      cloud:
        nacos:
          discovery:
            server-addr: master:8848  #配置Nacos地址
    
    #消费者将要去访问的微服务名称(成功注册到nacos的服务提供者)
    service-url:
      nacos-user-service: http://nacos-payment-provider/api
    
  4. 主启动

    @SpringBootApplication
    @EnableDiscoveryClient
    public class OrderNacosMain83 {
        public static void main(String[] args) {
            SpringApplication.run(OrderNacosMain83.class, args);
        }
    }
    
  5. 配置类

    nacos-discovery 集成ribbon实现负载均衡和服务调用

    @Configuration
    public class ApplicationContextConfig {
        @Bean
        @LoadBalanced
        public RestTemplate getRestTemplate() {
            return new RestTemplate();
        }
    }
    
  6. 业务类

    @RestController
    @Slf4j
    @RequestMapping("/consumer")
    public class OrderNacosController {
    
        @Value("${service-url.nacos-user-service}")
        private String PAYMENT_SERVICE_NAME;
    
        @Resource
        private RestTemplate restTemplate;
    
        @GetMapping("payment/nacos/{id}")
        public String getPaymentInfo(@PathVariable("id") Long id) {
            return restTemplate.getForObject(PAYMENT_SERVICE_NAME + "/payment/nacos/" + id, String.class);
        }
    }
    
  7. 测试

    http://localhost:83/consumer/payment/nacos/45

13.3.7 Nacos支持AP和CP的切换

如果不需要存储服务级别的信息则可以选择AP模式

如果需要在服务级别上编辑或存储配置信息,需要选择CP模式

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switchs?entry=serverModl&value=CP'
13.3.8 Nacos支持服务发现时的负载均衡

Nacos的负载均衡是指在服务发现时进行负载均衡,正常情况下在进行服务发现时会根据服务名称从Nacos拉取所有的服务实例到客户本地进程中,但Nacos提供了一个功能就是在拉取服务时可以根据随机策略只拉取到所有实例中的某一个,这就是Nacos中的负载均衡。
这样在消费者本地存储的服务实例就会比较少,可能就存了选择出的那唯一一个.

它根Ribbon中的负载均衡不冲突,Ribbon是在消息者本地调用服务时的负载均衡,可以理解为Ribbon中的负载均衡是发生在Nacos的负载均衡之后。

%5Btoc%5D%0A%0Aspringcloud%20%2B%20springcloud%20alibaba%0A%0A%23%23%23%23%201.%20%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84%E6%A6%82%E8%BF%B0%0A%0A%23%23%23%23%23%201.1%20%E4%BB%80%E4%B9%88%E6%98%AF%E5%BE%AE%E6%9C%8D%E5%8A%A1%0A%0A%E6%98%AF%E4%B8%80%E7%A7%8D%E6%9E%B6%E6%9E%84%EF%BC%8C%E5%B0%86%E5%8D%95%E4%B8%80%E5%BA%94%E7%94%A8%E5%88%86%E6%88%90%E4%B8%80%E7%BB%84%E5%B0%8F%E7%9A%84%E6%9C%8D%E5%8A%A1%EF%BC%8C%E6%9C%8D%E5%8A%A1%E4%B9%8B%E9%97%B4%E9%80%9A%E8%BF%87%E8%BD%BB%E9%87%8F%E7%BA%A7%E7%9A%84%E6%9C%BA%E5%88%B6%E7%9B%B8%E4%BA%92%E8%B0%83%E7%94%A8%EF%BC%8C%E9%80%9A%E5%B8%B8%E6%98%AF%E5%9F%BA%E4%BA%8Ehttp%E5%8D%8F%E8%AE%AE%E7%9A%84restful%20api%E3%80%82%0A%E6%AF%8F%E4%B8%AA%E6%9C%8D%E5%8A%A1%E8%BF%90%E8%A1%8C%E5%9C%A8%E7%8B%AC%E7%AB%8B%E7%9A%84%E8%BF%9B%E7%A8%8B%E4%B8%AD%EF%BC%8C%E5%B9%B6%E4%B8%94%E8%83%BD%E5%A4%9F%E8%A2%AB%E7%8B%AC%E7%AB%8B%E7%9A%84%E9%83%A8%E7%BD%B2%0A%0A%60%60%60%0A1.%20small%20services%0A2.%20lightweigt%20mechanisms%0A3.%20own%20process%20%E7%8B%AC%E7%AB%8B%E8%BF%9B%E7%A8%8B%0A4.%20independency%20deployable%0A%60%60%60%0A%0A%23%23%23%23%202%20SpringCloud%0A%0A%E5%88%86%E6%AD%A5%E5%BC%8F%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84%E7%9A%84%E4%B8%80%E7%AB%99%E5%BC%8F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%EF%BC%8C%E6%98%AF%E5%A4%9A%E7%A7%8D%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84%E8%90%BD%E5%9C%B0%E6%8A%80%E6%9C%AF%E7%9A%84%E9%9B%86%E5%90%88%E4%BD%93%EF%BC%8C%E4%BF%97%E7%A7%B0%E5%BE%AE%E6%9C%8D%E5%8A%A1**%E5%85%A8%E5%AE%B6%E6%A1%B6**%0A%0A!%5B3092e2167f850e1996768181397265d2.png%5D(en-resource%3A%2F%2Fdatabase%2F909%3A1)%0A%0A%0A%0A%0A%60%60%60%0A%E6%9C%8D%E5%8A%A1%E7%BD%91%E5%85%B3%20%20%3E%20%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E5%8F%91%E4%B8%8E%E5%8F%91%E7%8E%B0%20%3E%20%20%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%20%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%202.1%20SpringBoot%202.x%20%0A%0Agit%E6%BA%90%E7%A0%81%E5%9C%B0%E5%9D%80%20%0A%0A%20https%3A%2F%2Fgithub.com%2Fspring-projects%2Fspring-boot%2Freleases%0A%0A%20SpringBoot2.0%20%E6%96%B0%E7%89%B9%E6%80%A7%0A%0Ahttps%3A%2F%2Fgithub.com%2Fspring-projects%2Fspring-boot%2Fwiki%2FSpring-Boot-2.0-Releases%20%0A%0A%0A%0A%23%23%23%23%23%202.2%20SpringCloud%20H%0A%0Agit%E6%BA%90%E7%A0%81%E5%9C%B0%E5%9D%80%20%0A%0A%20https%3A%2F%2Fgithub.com%2Fspring-projects%2Fspring-cloud%2Fwiki%0A%0Ahttps%3A%2F%2Fprojects.spring.io%2Fspring-cloud%0A%0A%0A%0A%23%23%23%23%23%202.3%20%E5%85%BC%E5%AE%B9%E6%80%A7%E5%85%B3%E7%B3%BB%0A%0Ahttps%3A%2F%2Fspring.io%2Fprojects%2Fspring-cloud%23overview%0A%0Ahttps%3A%2F%2Fstart.spring.io%2Factuator%2Finfo%0A%0Ahttps%3A%2F%2Ftool.lu%2F%0A%0A%0A%0A%60%60%60%0A%7B%0A%20%20%22git%22%3A%20%7B%0A%20%20%20%20%22branch%22%3A%20%22ee9d426af8dd722b791e1c5f0c612d2bf95a8682%22%2C%0A%20%20%20%20%22commit%22%3A%20%7B%0A%20%20%20%20%20%20%22id%22%3A%20%22ee9d426%22%2C%0A%20%20%20%20%20%20%22time%22%3A%20%222020-08-16T20%3A32%3A04Z%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22build%22%3A%20%7B%0A%20%20%20%20%22version%22%3A%20%220.0.1-SNAPSHOT%22%2C%0A%20%20%20%20%22artifact%22%3A%20%22start-site%22%2C%0A%20%20%20%20%22versions%22%3A%20%7B%0A%20%20%20%20%20%20%22spring-boot%22%3A%20%222.3.1.RELEASE%22%2C%0A%20%20%20%20%20%20%22initializr%22%3A%20%220.9.1-SNAPSHOT%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22name%22%3A%20%22start.spring.io%20website%22%2C%0A%20%20%20%20%22time%22%3A%20%222020-08-16T20%3A33%3A29.306Z%22%2C%0A%20%20%20%20%22group%22%3A%20%22io.spring.start%22%0A%20%20%7D%2C%0A%20%20%22bom-ranges%22%3A%20%7B%0A%20%20%20%20%22azure%22%3A%20%7B%0A%20%20%20%20%20%20%222.0.10%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RELEASE%20and%20%3C2.1.0.RELEASE%22%2C%0A%20%20%20%20%20%20%222.1.10%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.RELEASE%20and%20%3C2.2.0.M1%22%2C%0A%20%20%20%20%20%20%222.2.4%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.M1%20and%20%3C2.3.0.M1%22%2C%0A%20%20%20%20%20%20%222.3.1%22%3A%20%22Spring%20Boot%20%3E%3D2.3.0.M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22codecentric-spring-boot-admin%22%3A%20%7B%0A%20%20%20%20%20%20%222.0.6%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.M1%20and%20%3C2.1.0.M1%22%2C%0A%20%20%20%20%20%20%222.1.6%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.M1%20and%20%3C2.2.0.M1%22%2C%0A%20%20%20%20%20%20%222.2.4%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.M1%20and%20%3C2.3.0.M1%22%2C%0A%20%20%20%20%20%20%222.3.0%22%3A%20%22Spring%20Boot%20%3E%3D2.3.0.M1%20and%20%3C2.4.0-M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22solace-spring-boot%22%3A%20%7B%0A%20%20%20%20%20%20%221.0.0%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.RELEASE%20and%20%3C2.3.0.M1%22%2C%0A%20%20%20%20%20%20%221.1.0%22%3A%20%22Spring%20Boot%20%3E%3D2.3.0.M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22solace-spring-cloud%22%3A%20%7B%0A%20%20%20%20%20%20%221.0.0%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.RELEASE%20and%20%3C2.3.0.M1%22%2C%0A%20%20%20%20%20%20%221.1.1%22%3A%20%22Spring%20Boot%20%3E%3D2.3.0.M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22spring-cloud%22%3A%20%7B%0A%20%20%20%20%20%20%22Finchley.M2%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.M3%20and%20%3C2.0.0.M5%22%2C%0A%20%20%20%20%20%20%22Finchley.M3%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.M5%20and%20%3C%3D2.0.0.M5%22%2C%0A%20%20%20%20%20%20%22Finchley.M4%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.M6%20and%20%3C%3D2.0.0.M6%22%2C%0A%20%20%20%20%20%20%22Finchley.M5%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.M7%20and%20%3C%3D2.0.0.M7%22%2C%0A%20%20%20%20%20%20%22Finchley.M6%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RC1%20and%20%3C%3D2.0.0.RC1%22%2C%0A%20%20%20%20%20%20%22Finchley.M7%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RC2%20and%20%3C%3D2.0.0.RC2%22%2C%0A%20%20%20%20%20%20%22Finchley.M9%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RELEASE%20and%20%3C%3D2.0.0.RELEASE%22%2C%0A%20%20%20%20%20%20%22Finchley.RC1%22%3A%20%22Spring%20Boot%20%3E%3D2.0.1.RELEASE%20and%20%3C2.0.2.RELEASE%22%2C%0A%20%20%20%20%20%20%22Finchley.RC2%22%3A%20%22Spring%20Boot%20%3E%3D2.0.2.RELEASE%20and%20%3C2.0.3.RELEASE%22%2C%0A%20%20%20%20%20%20%22Finchley.SR4%22%3A%20%22Spring%20Boot%20%3E%3D2.0.3.RELEASE%20and%20%3C2.0.999.BUILD-SNAPSHOT%22%2C%0A%20%20%20%20%20%20%22Finchley.BUILD-SNAPSHOT%22%3A%20%22Spring%20Boot%20%3E%3D2.0.999.BUILD-SNAPSHOT%20and%20%3C2.1.0.M3%22%2C%0A%20%20%20%20%20%20%22Greenwich.M1%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.M3%20and%20%3C2.1.0.RELEASE%22%2C%0A%20%20%20%20%20%20%22Greenwich.SR6%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.RELEASE%20and%20%3C2.1.17.BUILD-SNAPSHOT%22%2C%0A%20%20%20%20%20%20%22Greenwich.BUILD-SNAPSHOT%22%3A%20%22Spring%20Boot%20%3E%3D2.1.17.BUILD-SNAPSHOT%20and%20%3C2.2.0.M4%22%2C%0A%20%20%20%20%20%20%22Hoxton.SR7%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.M4%20and%20%3C2.3.4.BUILD-SNAPSHOT%22%2C%0A%20%20%20%20%20%20%22Hoxton.BUILD-SNAPSHOT%22%3A%20%22Spring%20Boot%20%3E%3D2.3.4.BUILD-SNAPSHOT%20and%20%3C2.4.0.M1%22%2C%0A%20%20%20%20%20%20%222020.0.0-SNAPSHOT%22%3A%20%22Spring%20Boot%20%3E%3D2.4.0.M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22spring-cloud-alibaba%22%3A%20%7B%0A%20%20%20%20%20%20%222.2.1.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.RELEASE%20and%20%3C2.3.0.M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22spring-cloud-services%22%3A%20%7B%0A%20%20%20%20%20%20%222.0.3.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RELEASE%20and%20%3C2.1.0.RELEASE%22%2C%0A%20%20%20%20%20%20%222.1.7.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.RELEASE%20and%20%3C2.2.0.RELEASE%22%2C%0A%20%20%20%20%20%20%222.2.3.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.RELEASE%20and%20%3C2.3.0.M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22spring-statemachine%22%3A%20%7B%0A%20%20%20%20%20%20%222.0.0.M4%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RC1%20and%20%3C%3D2.0.0.RC1%22%2C%0A%20%20%20%20%20%20%222.0.0.M5%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RC2%20and%20%3C%3D2.0.0.RC2%22%2C%0A%20%20%20%20%20%20%222.0.1.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RELEASE%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22vaadin%22%3A%20%7B%0A%20%20%20%20%20%20%2210.0.17%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.M1%20and%20%3C2.1.0.M1%22%2C%0A%20%20%20%20%20%20%2214.3.3%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.M1%20and%20%3C2.4.0-M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22wavefront%22%3A%20%7B%0A%20%20%20%20%20%20%222.0.0%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.RELEASE%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22dependency-ranges%22%3A%20%7B%0A%20%20%20%20%22okta%22%3A%20%7B%0A%20%20%20%20%20%20%221.2.1%22%3A%20%22Spring%20Boot%20%3E%3D2.1.2.RELEASE%20and%20%3C2.2.0.M1%22%2C%0A%20%20%20%20%20%20%221.4.0%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.M1%20and%20%3C2.4.0-M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22mybatis%22%3A%20%7B%0A%20%20%20%20%20%20%222.0.1%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RELEASE%20and%20%3C2.1.0.RELEASE%22%2C%0A%20%20%20%20%20%20%222.1.3%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.RELEASE%20and%20%3C2.4.0-M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22geode%22%3A%20%7B%0A%20%20%20%20%20%20%221.2.9.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.M5%20and%20%3C2.3.0.M1%22%2C%0A%20%20%20%20%20%20%221.3.2.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.3.0.M1%20and%20%3C2.4.0-M1%22%2C%0A%20%20%20%20%20%20%221.4.0-M1%22%3A%20%22Spring%20Boot%20%3E%3D2.4.0-M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22camel%22%3A%20%7B%0A%20%20%20%20%20%20%222.22.4%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.M1%20and%20%3C2.1.0.M1%22%2C%0A%20%20%20%20%20%20%222.25.2%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.M1%20and%20%3C2.2.0.M1%22%2C%0A%20%20%20%20%20%20%223.3.0%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.M1%20and%20%3C2.3.0.M1%22%2C%0A%20%20%20%20%20%20%223.4.3%22%3A%20%22Spring%20Boot%20%3E%3D2.3.0.M1%20and%20%3C2.4.0-M1%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22open-service-broker%22%3A%20%7B%0A%20%20%20%20%20%20%222.1.3.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.0.0.RELEASE%20and%20%3C2.1.0.M1%22%2C%0A%20%20%20%20%20%20%223.0.4.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.1.0.M1%20and%20%3C2.2.0.M1%22%2C%0A%20%20%20%20%20%20%223.1.1.RELEASE%22%3A%20%22Spring%20Boot%20%3E%3D2.2.0.M1%20and%20%3C2.4.0-M1%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60%0A%20%22Hoxton.BUILD-SNAPSHOT%22%3A%20%22Spring%20Boot%20%3E%3D2.3.4.BUILD-SNAPSHOT%20and%20%3C2.4.0.M1%22%2C%0A%60%60%60%0A%0A%0A%0Ahttps%3A%2F%2Fdocs.spring.io%2Fspring-cloud%2Fdocs%2FHoxton.SR7%2Freference%2Fhtml%2F%0A%0A!%5Bed33c9a60e12c26cea7cdb9c68faa999.png%5D(en-resource%3A%2F%2Fdatabase%2F910%3A1)%0A%0A%0A%23%23%23%23%203%20%E7%BB%84%E4%BB%B6%E7%9A%84%E5%81%9C%E6%9B%B4%E5%8D%87%E7%BA%A7%E5%92%8C%E6%9B%BF%E6%8D%A2%0A%0A%E6%9C%8D%E5%8A%A1%E5%BC%80%E5%8F%91%E3%80%80%09%09%09%09%20%20%20%20%09SpringBoot%0A%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0%09%09%09%09%20Eureka%20%5B%E5%B7%B2%E5%81%9C%E6%AD%A2%E6%9B%B4%E6%96%B0%5D%20%2C%20ZooKeeper%2C%20Consul%2C%20**Alibaba%20Nacos**%0A%E6%9C%8D%E5%8A%A1%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E4%B8%8E%E8%B0%83%E7%94%A8%20%09%20%20%20%20%20Ribbon%5B%E8%B6%8B%E4%BA%8E%E5%81%9C%E6%AD%A2%E6%9B%B4%E6%96%B0%5D%2CLoadBanance%2C%20Feigh%5B%E8%B6%8B%E4%BA%8E%E5%81%9C%E6%AD%A2%E6%9B%B4%E6%96%B0%5D%2C%20OpenFeign%0A%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%20%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%20%09%09%09Hystrix%5B%E8%B6%8B%E4%BA%8E%E5%81%9C%E6%AD%A2%E6%9B%B4%E6%96%B0%5D%2C%20Resilience4J%2C%20Alibaba%20Sentinel%0A%E6%9C%8D%E5%8A%A1%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%0A%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E7%AE%A1%E7%90%86%20%09%09%09%09%20%20%20%20%20Springcloud%20config%2C%20**Alibaba%20Nacos**%0A%E6%9C%8D%E5%8A%A1%E7%BD%91%E5%85%B3%09%09%09%09%20%20%20%20%20%20%20%20%20%20%20%20%20%20Zuul%20%5B%E5%81%9C%E6%AD%A2%E6%9B%B4%E6%96%B0%5D%2C%20Spring%20Gateway%0A%E6%9C%8D%E5%8A%A1%E6%80%BB%E7%BA%BF%20%09%09%09%09%20%20%20%20%20%20%20%20%20%20%20%20%20Spring%20Bus%2C%20**Alibaba%20Nacos**%0A%E6%9C%8D%E5%8A%A1%E7%9B%91%E6%8E%A7%0A%E5%85%A8%E9%93%BE%E8%B7%AF%E8%BF%BD%E8%B8%AA%0A%E8%87%AA%E5%8A%A8%E5%8C%96%E6%9E%84%E5%BB%BA%E9%83%A8%E7%BD%B2%0A%E6%9C%8D%E5%8A%A1%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E6%93%8D%E4%BD%9C%0A%0A%0A%0A%23%23%23%23%23%203.1%20SpringCloud%E6%96%87%E6%A1%A3%0A%0Ahttps%3A%2F%2Fdocs.spring.io%2Fspring-cloud%2Fdocs%2FHoxton.SR7%2Freference%2Fhtml%2F%23features%0A%0Ahttps%3A%2F%2Fwww.bookstack.cn%2Fread%2Fspring-cloud-docs%2Fdocs-index.md%0A%0A%0A%0A%23%23%23%23%204%20%E7%BC%96%E7%A0%81%E6%9E%84%E5%BB%BA%0A%0A%23%23%23%23%23%204.1%20%E5%88%9B%E5%BB%BA%E7%88%B6%E5%B7%A5%E7%A8%8B%0A%0Aidea%20%3E%20new%20%3E%20project%0A%0A!%5B40330a539d34149ffde61a5d67021431.png%5D(en-resource%3A%2F%2Fdatabase%2F913%3A1)%0A!%5Bfc0097e41257de5236afd2da9368041a.png%5D(en-resource%3A%2F%2Fdatabase%2F923%3A1)%0A!%5Be9df598013b91396a9ff73b9133a05a2.png%5D(en-resource%3A%2F%2Fdatabase%2F922%3A1)%0A!%5Be39fc0c8b655fcfd7159caeb57ccdc5c.png%5D(en-resource%3A%2F%2Fdatabase%2F921%3A1)%0A!%5B86610eb4342176a367cbb9b36b098b29.png%5D(en-resource%3A%2F%2Fdatabase%2F916%3A1)%0A%0A%0A%0A%0A%23%23%23%23%23%204.2%20%E5%88%9B%E5%BB%BA%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%A8%A1%E5%9D%97%0A%0A%60%60%60%0A1.%E5%BB%BAmodule%EF%BC%9A%20idea%20%3E%20new%20%3E%20module%0A2.%E6%94%B9pom%0A3.%E5%86%99YML%0A4.%E5%90%AF%E5%8A%A8%E7%B1%BB%0A5.%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%60%60%60%0A%0A%23%23%23%23%23%204.3%20%E7%83%AD%E9%83%A8%E7%BD%B2%0A%0A1.%20%E6%B7%BB%E5%8A%A0DEV%E5%88%B0pom.xml%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-devtools%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E6%B7%BB%E5%8A%A0%E5%88%B0%E7%88%B6%E5%B7%A5%E7%A8%8B%E7%9A%84pom.xml%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cbuild%3E%0A%20%20%20%20%20%20%20%3Cplugins%3E%0A%20%20%20%20%20%20%20%20%20%3Cplugin%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-maven-plugin%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cconfiguration%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfork%3Etrue%3C%2Ffork%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3CaddResources%3Etrue%3C%2FaddResources%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fconfiguration%3E%0A%20%20%20%20%20%20%20%20%20%3C%2Fplugin%3E%0A%20%20%20%20%20%20%20%3C%2Fplugins%3E%0A%20%20%20%20%20%3C%2Fbuild%3E%0A%20%20%20%60%60%60%0A%0A3.%20idea%E8%AE%BE%E7%BD%AE%E6%89%93%E5%BC%80%E8%87%AA%E5%8A%A8%E6%9E%84%E5%BB%BA%0A%0A%20%20%20%20!%5B993b718dd78602370e1ac9ae2aa8f4df.png%5D(en-resource%3A%2F%2Fdatabase%2F918%3A1)%0A%0A%0A4.%20%E6%9B%B4%E6%96%B0%E8%AE%BE%E7%BD%AE%0A%09ctrl%2Balt%2Bshift%2B%2F%0A%09%E6%9E%84%E9%80%89%E8%BF%99%E4%B8%A4%E9%A1%B9%0A%09compiler.automake.allow.when.app.running%0A%09actionSystem.assertFocusAccessFromEdt%0A%0A%20%20%20%20!%5Bddb571aeec6768f23d38820ed14cd83e.png%5D(en-resource%3A%2F%2Fdatabase%2F938%3A1)%0A%20%20%20%20%0A%23%23%23%23%23%204.4%20RestTemplate%0A%0A%3E%20%E6%98%AFSpring%E6%8F%90%E4%BE%9B%E7%9A%84%E7%94%A8%E4%BA%8E%E8%AE%BF%E9%97%AERest%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%AE%A2%E6%88%B7%E6%A8%A1%E6%9D%BF%E5%B7%A5%E5%85%B7%E7%B1%BB%2C%E6%8F%90%E4%BE%9B%E4%BA%86%E5%A4%9A%E7%A7%8D%E4%BE%BF%E6%8D%B7%E8%AE%BF%E9%97%AE%E8%BF%9C%E7%A8%8Bhttp%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%96%B9%E6%B3%95%0A%0A%23%23%23%23%23%204.5%20%E9%85%8D%E7%BD%AERunDashboard%0A%0A%3E%20%E5%B7%A5%E7%A8%8B%E7%9B%AE%E5%BD%95%20%E4%B8%8B%E7%9A%84.idea%E6%96%87%E4%BB%B6%E5%A4%B9%0A%3E%0A%3E%20%E8%BF%BD%E5%8A%A0%E4%B8%8B%E9%9D%A2%E5%86%85%E5%AE%B9%E5%88%B0worksapce.xml%E4%B8%AD%0A%0A%60%60%60java%0A%3Ccomponent%20name%3D%22RunDashboard%22%3E%0A%20%20%20%20%3Coption%20name%3D%22configurationTypes%22%3E%0A%20%20%20%20%20%20%3Cset%3E%0A%20%20%20%20%20%20%20%20%3Coption%20value%3D%22SpringBootApplicationConfigurationType%22%20%2F%3E%0A%20%20%20%20%20%20%3C%2Fset%3E%0A%20%20%20%20%3C%2Foption%3E%0A%20%3C%2Fcomponent%3E%0A%60%60%60%0A!%5Baee0dd9dabe50b8d9b2a66fae302ea83.png%5D(en-resource%3A%2F%2Fdatabase%2F919%3A1)%0A%0A%0A%23%23%23%23%23%204.6%20%E5%B7%A5%E7%A8%8B%E9%87%8D%E6%9E%84%0A%0A1.%20%E6%96%B0%E5%BB%BAmodule%20%20**cloud-api-commons**%0A%0A2.%20%E6%8F%90%E5%8F%96%E5%85%B6%E5%AE%83module%20%E9%87%8C%E9%9D%A2%E7%9A%84entities%E6%94%BE%E5%88%B0**cloud-api-commons**%20%E9%87%8C%E9%9D%A2%E7%9A%84%20com.chris.springcloud.entities%0A%0A3.%20%E5%88%A0%E9%99%A4%E5%85%B6%E5%AE%83module%E9%87%8C%E9%9D%A2%E7%9A%84entities%0A%0A4.%20%E5%9C%A8%20%E4%B8%AD%E6%9E%84%E5%BB%BA%E5%85%B1%E7%94%A8%E5%B7%A5%E7%A8%8B%E5%B9%B6%E6%94%BE%E5%88%B0%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E4%B8%AD%20%0A%0A%20%20%20%60%60%60java%0A%20%20%20cd%20cloud-api-commons%0A%20%20%20mvn%20clean%20install%20-Dmaven.test.skip%3Dtrue%0A%20%20%20%60%60%60%0A%0A5.%20%E5%9C%A8%E5%85%B6%E5%AE%83module%E9%87%8C%E9%9D%A2%E5%8A%A0%E5%85%A5%E4%BE%9D%E8%B5%96%0A%0A%20%20%20%60%60%60java%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.chris.springcloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Ecloud-api-commons%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3Cversion%3E%24%7Bcommon.api.version%7D%3C%2Fversion%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A6.%20%E8%BF%9B%E5%85%A5%E9%A1%B9%E7%9B%AE%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE%0A%0A%20%20%20%60%60%60java%0A%20%20%20cd%20cloud2020%0A%20%20%20mvn%20clean%20package%20-Dmaven.test.skip%3Dtrue%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%204.7%20idea%E6%97%A0%E6%B3%95%E8%AF%86%E5%88%ABApplication.yml%0A%3E%20ctrl%2Bshift%2Balt%2Bs%0A%3E%20%E9%80%89%E4%B8%AD%E5%AF%B9%E5%BA%94%E7%9A%84%E9%A1%B9%E7%9B%AE%EF%BC%8C%E5%8F%B3%E5%87%BB%E9%80%89%E6%8B%A9%60Add%60%0A%3E%20%E9%80%89%E6%8B%A9%60Spring%60%0A%0A!%5B872e6386dfaf73d4182f0cad5178eae1.png%5D(en-resource%3A%2F%2Fdatabase%2F952%3A1)%0A%0A%3E%20%E9%80%89%E4%B8%ADSpring%2C%20%E9%80%89%E6%8B%A9%20%60%2B%60%E5%8F%B7%0A%3E%20%E8%BF%9B%E5%85%A5%E4%B9%8B%E5%90%8E%E5%86%8D%E9%80%89%E6%8B%A9%20%60%2B%60%20%E5%8F%B7%EF%BC%8C%E5%B9%B6%E9%80%89%E6%8B%A9%20%60Other%20Files%60%0A%3E%20%E9%80%89%E4%B8%AD%E9%9C%80%E8%A6%81%E6%B7%BB%E5%8A%A0%E7%9A%84%20%60Application.yml%60%20%E6%96%87%E4%BB%B6%0A!%5B575284c06e2ca0426a37a70cb918fe1d.png%5D(en-resource%3A%2F%2Fdatabase%2F953%3A1)%0A!%5Bb2c4aef83dceda21da1dbe5db2859b96.png%5D(en-resource%3A%2F%2Fdatabase%2F954%3A1)%0A!%5B6646739273ccd7a0ef7203d6f85f284e.png%5D(en-resource%3A%2F%2Fdatabase%2F955%3A1)%0A%0A%0A%23%23%23%23%205%20%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A%0A%23%23%23%23%23%205.1%20%E6%9C%8D%E5%8A%A1%E5%88%B6%E7%90%86%0A%0A%3E%20%E5%AE%9E%E7%8E%B0%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0%EF%BC%8C%E7%AE%A1%E7%90%86%E6%9C%8D%E5%8A%A1%E4%B9%8B%E9%97%B4%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%EF%BC%8C%E8%B0%83%E7%94%A8%EF%BC%8C%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%8F%8A%E5%AE%B9%E9%94%99%E7%AD%89%0A%0A%23%23%23%23%23%205.2%20Eureka%0A%0A%3E%201.%20CS%E6%9E%B6%E6%9E%84%0A%3E2.%20Eureke%20Server%20%E4%BD%9C%E4%B8%BA%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E5%8A%9F%E8%83%BD%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%AE%83%E6%98%AF%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A%3E%203.%20%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E5%85%B6%E5%AE%83%E6%9C%8D%E5%8A%A1%E4%BD%BF%E7%94%A8Eureke%20Client%E8%BF%9E%E6%8E%A5%E5%88%B0Eureke%20Server%E5%B9%B6%E7%BB%B4%E6%8C%81%E5%BF%83%E8%B7%B3%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%B0%B1%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87Eureke%20Server%E6%9D%A5%E7%9B%91%E6%8E%A7%E7%B3%BB%E7%BB%9F%E4%B8%AD%E5%90%84%E4%B8%AA%E6%9C%8D%E5%8A%A1%E6%98%AF%E5%90%A6%E8%BF%90%E8%A1%8C%E6%AD%A3%E5%B8%B8%0A%3E4.%20Eureke%20Client%E9%80%9A%E8%BF%87%E8%BD%AE%E8%AF%A2%EF%BC%88round-robin%EF%BC%89%E9%BB%98%E8%AE%A4%E6%AF%8F30%E7%A7%92%E5%90%91Eureke%20Server%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%EF%BC%8C%E5%A6%82%E6%9E%9CEureke%20Server%E5%9C%A8%E5%A4%9A%E4%B8%AA%E5%BF%83%E8%B7%B3%E5%91%A8%E6%9C%9F%E5%86%85(%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92)%20%E6%B2%A1%E6%9C%89%E6%94%B6%E5%88%B0%E6%9F%90%E4%B8%AA%E7%BB%93%E7%82%B9%E7%9A%84%E5%BF%83%E8%B7%B3%EF%BC%8C%E4%BC%9A%E5%B0%86%E8%BF%99%E4%B8%AA%E6%9C%8D%E5%8A%A1%E8%8A%82%E7%82%B9%E4%BB%8E%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E5%88%97%E8%A1%A8%E4%B8%AD%E7%A7%BB%E9%99%A4.%0A%0A!%5B4714c749cb5aeab117135d739b26c8ec.png%5D(en-resource%3A%2F%2Fdatabase%2F914%3A1)%0A%0A%0A%0A%23%23%23%23%23%23%205.2.1%20IDEA%E7%94%9F%E6%88%90Eureka%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A%0A1.%20%E5%BB%BAmodule%20**cloud-eureka-server7001**%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%20%E5%BC%95%E5%85%A5%E6%9C%80%E6%96%B0%E7%9A%84eureka%20server--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-server%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BA%20yml%0A%0A%20%20%20%60%60%60%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%207001%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20eureka%3A%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20hostname%3A%20localhost%20%23eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84%E5%AE%9E%E4%BE%8B%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20false%20%E8%A1%A8%E7%A4%BA%E4%B8%8D%E5%90%91%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%B3%A8%E5%86%8C%E8%87%AA%E5%B7%B1%0A%20%20%20%20%20%20%20register-with-eureka%3A%20false%0A%20%20%20%20%20%20%20%23%20false%20%E8%A1%A8%E7%A4%BA%E8%87%AA%E5%B7%B1%E5%B0%B1%E6%98%AF%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%88%91%E7%9A%84%E8%81%8C%E8%B4%A3%E5%B0%B1%E6%98%AF%E7%BB%B4%E6%8A%A4%E6%9C%8D%E5%8A%A1%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%B9%B6%E4%B8%8D%E9%9C%80%E8%A6%81%E5%8E%BB%E6%A3%80%E7%B4%A2%E6%9C%8D%E5%8A%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20false%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20%23%20%E8%AE%BE%E7%BD%AE%E4%B8%8E%E4%BA%A4%E4%BA%92%E7%9A%84%E5%9C%B0%E5%9D%80%EF%BC%8C%E6%9F%A5%E8%AF%A2%E6%9C%8D%E5%8A%A1%E5%92%8C%E6%B3%A8%E5%86%8C%E6%9C%8D%E5%8A%A1%E9%83%BD%E9%9C%80%E8%A6%81%E8%BF%99%E4%BE%9D%E8%B5%96%E8%BF%99%E4%B8%AA%E5%9C%B0%E5%9D%80%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2F%24%7Beureka.instance.hostname%7D%3A%24%7Bserver.port%7D%2Feureka%2F%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%3E%20%40EnableEurekaServer%20%E6%BF%80%E6%B4%BB%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E7%94%A8%E4%BA%8E%E7%AE%A1%E7%90%86%E6%9C%8D%E5%8A%A1%E7%9A%84%E9%85%8D%E7%BD%AE%EF%BC%8C%E7%99%BB%E8%AE%B0%E5%92%8C%E6%B3%A8%E5%86%8C%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableEurekaServer%0A%20%20%20public%20class%20EurekaMain%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(EurekaMain.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%E8%AE%BF%E9%97%AE%20http%3A%2F%2Flocalhost%3A7001%2F%0A%20%20%20%20!%5B21f5802416f5f706e0a1ea3682f1cbdd.png%5D(en-resource%3A%2F%2Fdatabase%2F911%3A1)%0A%20%20%20%20%0A%20%20%20%0A%0A%23%23%23%23%23%23%205.2.2%20%E6%B3%A8%E5%86%8C%E6%9C%8D%E5%8A%A1%E5%88%B0Eureka%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A%0A1.%20%E6%94%B9pom.xml%0A%0A%20%20%20%E5%9C%A8%E5%85%B7%E4%BD%93%E7%9A%84%E6%9C%8D%E5%8A%A1module%E7%9A%84pom.xml%E9%87%8C%E9%9D%A2%E5%BC%95%E5%85%A5eureka-client%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--eureka%20client--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E6%94%B9YML%0A%0A%20%20%20%60%60%60%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20%23%20%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Flocalhost%3A7001%2Feureak%0A%20%20%20%60%60%60%0A%0A3.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%3E%20%40EnableEurekaClient%20%20%E6%BF%80%E6%B4%BB%E9%9C%80%E8%A6%81%E6%B3%A8%E5%86%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%9C%AC%E8%BA%AB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableEurekaClient%0A%20%20%20public%20class%20PaymentMain%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(PaymentMain.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A4.%20%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E6%88%90%E5%8A%9F%E5%90%8E%E6%95%88%E6%9E%9C%0A%09!%5Bc44f1bf526eec967f31ae8dc35a0904c.png%5D(en-resource%3A%2F%2Fdatabase%2F920%3A1)%0A%20%20%20%20%0A%0A%0A%0A%23%23%23%23%23%23%205.2.3%20Eureka%E9%9B%86%E7%BE%A4%0A%0A%E7%9B%B8%E4%BA%92%E6%B3%A8%E5%86%8C%EF%BC%8C%E7%9B%B8%E4%BA%92%E7%9B%91%E5%90%AC%0A%0A1.%20%E5%BB%BA%20module%20**cloud-eureka-server7002**%0A%0A2.%20%E6%94%B9pom.xml%0A%0A3.%20%E5%BB%BAyml%EF%BC%8C%E5%90%8C%E7%90%86%E4%BF%AE%E6%94%B9**cloud-eureka-server7001**%E4%B8%AD%E7%9A%84yml%0A%0A%20%20%20%60%60%60%0A%20%20%20eureka%3A%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20hostname%3A%20eureka7002.com%20%23eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84%E5%AE%9E%E4%BE%8B%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20false%20%E8%A1%A8%E7%A4%BA%E4%B8%8D%E5%90%91%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%B3%A8%E5%86%8C%E8%87%AA%E5%B7%B1%0A%20%20%20%20%20%20%20register-with-eureka%3A%20false%0A%20%20%20%20%20%20%20%23%20false%20%E8%A1%A8%E7%A4%BA%E8%87%AA%E5%B7%B1%E5%B0%B1%E6%98%AF%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%88%91%E7%9A%84%E8%81%8C%E8%B4%A3%E5%B0%B1%E6%98%AF%E7%BB%B4%E6%8A%A4%E6%9C%8D%E5%8A%A1%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%B9%B6%E4%B8%8D%E9%9C%80%E8%A6%81%E5%8E%BB%E6%A3%80%E7%B4%A2%E6%9C%8D%E5%8A%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20false%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20%23%20%E8%AE%BE%E7%BD%AE%E4%B8%8EEureka%20Serve%E4%BA%A4%E4%BA%92%E7%9A%84%E5%9C%B0%E5%9D%80%EF%BC%8C%E6%9F%A5%E8%AF%A2%E6%9C%8D%E5%8A%A1%E5%92%8C%E6%B3%A8%E5%86%8C%E6%9C%8D%E5%8A%A1%E9%83%BD%E9%9C%80%E8%A6%81%E8%BF%99%E4%BE%9D%E8%B5%96%E8%BF%99%E4%B8%AA%E5%9C%B0%E5%9D%80%0A%20%20%20%20%20%20%20%20%20%23%20%E7%9B%B8%E4%BA%92%E6%B3%A8%E5%86%8C%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2F%0A%20%20%20%60%60%60%0A%0A4.%20%E6%94%B9%E6%98%A0%E5%B0%84%0A%0A%20%20%20%E8%BF%9B%E5%85%A5%20C%3A%5CWindows%5CSystem32%5Cdrivers%5Cetc%0A%0A%20%20%20%E4%BF%AE%E6%94%B9hosts%20%E6%B7%BB%E5%8A%A0%E5%A6%82%E4%B8%8B%E5%86%85%E5%AE%B9%0A%0A%20%20%20%60%60%60%0A%20%20%20%23%23%23%23%23%23%23%23%20SpringCloud%202020%20%23%23%23%23%23%23%23%23%23%23%23%0A%20%20%20127.0.0.1%20%20eureka7001.com%0A%20%20%20127.0.0.1%20%20eureka7002.com%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%205.%20%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E6%88%90%E5%8A%9F%E5%90%8E%E6%95%88%E6%9E%9C%0A%20%20%20%20%0A%20%20%20%20%60%60%60%0A%20%20%20%20%20http%3A%2F%2Feureka7001.com%3A7001%2F%0A%20%20%20%20%20http%3A%2F%2Feureka7002.com%3A7002%2F%0A%20%20%20%20%60%60%60%0A%20%20%20%0A%20%20%20%20%20!%5B3b8778b9e31208c0bc87905a800561bc.png%5D(en-resource%3A%2F%2Fdatabase%2F912%3A1)%0A%20%20%20%20%0A%0A%20%0A%0A%23%23%23%23%23%23%205.2.4%20%20%E5%B0%86%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E5%88%B0Eureka%E9%9B%86%E7%BE%A4%0A%0A1.%20%E4%BF%AE%E6%94%B9%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85**cloud-provider-payment8001**%E7%9A%84yml%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%60%60%60%0A%20%20%20%0A2.%20%E4%BF%AE%E6%94%B9%E6%9C%8D%E5%8A%A1%E6%B6%88%E6%81%AF%E8%80%85**cloud-consumer-order80**%E7%9A%84yml%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B3%A8%E5%86%8C%E6%88%90%E5%8A%9F%E5%90%8E%E7%9A%84%E6%95%88%E6%9E%9C%20%0A%09%0A%20%20%20%20!%5B8a02bc27ce5849ce94b783588ca038de.png%5D(en-resource%3A%2F%2Fdatabase%2F917%3A1)%0A%20%20%20%20%0A%0A%23%23%23%23%23%23%205.2.5%20%20%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E9%9B%86%E7%BE%A4%E9%85%8D%E7%BD%AE%0A%0A1.%20%E5%BB%BAmodule%20%20**cloud-provider-payment8002**%0A%0A2.%20%E6%94%B9pom.xml%0A%0A3.%20%E5%BB%BAyml%0A%0A%20%20%20%E5%92%8C%20**cloud-provider-payment8001**%E7%9A%84yml%E4%B8%80%E6%A0%B7%EF%BC%8C%20%E5%8F%AA%E6%98%AF%E7%AB%AF%E5%8F%A3%E5%8F%B7%E9%9C%80%E8%A6%81%E6%94%B9%E4%B8%BA8002%0A%0A%20%20%20%60%60%60%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%208002%0A%20%20%20%20%20servlet%3A%0A%20%20%20%20%20%20%20context-path%3A%20%2Fapi%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20%60%60%60%0A%0A4.%20%E5%90%AF%E5%8A%A8%E7%B1%BB%0A%0A%09%60%60%60java%0A%09%40SpringBootApplication%0A%09%40EnableEurekaClient%0A%09public%20class%20PaymentMain8002%20%7B%0A%09%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09%20%20%20%20%20%20%20%20SpringApplication.run(PaymentMain8002.class%2C%20args)%3B%0A%09%20%20%20%20%7D%0A%09%7D%0A%09%60%60%60%0A%09%0A5.%20%E5%B0%86%E6%95%B4%E4%B8%AA**cloud-provider-payment8001**%E7%9A%84%E4%B8%9A%E5%8A%A1%E4%BB%A3%E7%A0%81copy%E5%88%B0**cloud-provider-payment8002**%0A%0A6.%20%E5%90%AF%E5%8A%A8%E6%88%90%E5%8A%9F%E5%90%8E%E7%9A%84%E6%95%88%E6%9E%9C%0A%09%0A%20%20%20%20!%5B5333bcd3c88a98d56ef1596ea96f1d03.png%5D(en-resource%3A%2F%2Fdatabase%2F915%3A1)%0A%20%20%20%20%0A%0A%0A%0A7.%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%0A%20%20%20%E4%BF%AE%E6%94%B9%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85**cloud-consumer-order80**%20%3E%20**PAYMENT_URL**%3E%20**PAYMENT_URL**%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F%2F%20%E9%9B%86%E7%BE%A4%E7%89%88%E6%9C%AC%20CLOUD-PAYMENT-SERVICE%E6%98%AF%E5%9C%A8Eureka%E4%B8%AD%E6%B3%A8%E5%86%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%0A%20%20%20public%20static%20final%20String%20PAYMENT_URL%20%3D%20%22http%3A%2F%2FCLOUD-PAYMENT-SERVICE%22%3B%0A%20%20%20%60%60%60%0A%20%20%20%60%60%60%0A%09%22org.springframework.web.client.ResourceAccessException%3A%20I%2FO%20error%20on%20GET%20request%20for%20%5C%22http%3A%2F%2FCLOUD-PAYMENT-SERVICE%2Fapi%2Fpayment%2Fget%2F4%5C%22%3A%20CLOUD-PAYMENT-SERVICE%3B%20nested%20exception%20is%20java.net.UnknownHostException%3A%20CLOUD-PAYMENT-SERVICE%5Cr%5Cn%5Ctat%20org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java%3A751)%5Cr%5Cn%5Ctat%20org.springframework.web.client.RestTemplate.execute(RestTemplate.java%3A677)%5Cr%5Cn%5Ctat%20org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java%3A318)%5Cr%5Cn%5Ctat%20com.springcloud.order.controller.OrderController.getPayment(OrderController.java%3A41)%5Cr%5Cn%5Ctat%20sun.reflect.NativeMethodAccessorImpl.invoke0(Native%20Method)%5Cr%5Cn%5Ctat%20sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java%3A62)%5Cr%5Cn%5Ctat%20sun.%0A%20%20%20%60%60%60%0A%20%20%20%0A%20%20%20%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%20**%40LoadBalanced**%20%E6%B3%A8%E8%A7%A3%E8%B5%8B%E4%BA%88RestTemplate%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E8%83%BD%E5%8A%9B%0A%20%20%20%0A%20%20%20%60%60%60java%0A%20%20%20%20%20%20%40Configuration%0A%20%20%20%20%20%20public%20class%20ApplicationContextConfig%20%7B%0A%20%20%20%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20%20%20%20%40LoadBalanced%0A%20%20%20%20%20%20%20%20%20%20public%20RestTemplate%20getRestTemplate()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20RestTemplate()%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.2.6%20%E4%BF%AE%E6%94%B9%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%E5%92%8C%E6%98%BE%E7%A4%BA%0A%0A1.%20%E4%BF%AE%E6%94%B9%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84yml%E6%96%87%E4%BB%B6%0A%0A%20%20%20%3E%20%E5%A2%9E%E5%8A%A0%0A%20%20%20%3E%0A%20%20%20%3E%20instance-id%3A%20payment8001%0A%20%20%20%3E%0A%20%20%20%3E%20prefer-ip-address%3A%20true%0A%20%20%20%60%60%60%0A%20%20%20eureka%3A%0A%20%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20instance-id%3A%20payment8002%0A%20%20%20%20%20%20%20prefer-ip-address%3A%20true%0A%20%20%20%60%60%60%0A%0A2.%20%E4%BF%AE%E6%94%B9%E6%88%90%E5%8A%9F%E5%90%8E%E7%9A%84%E6%95%88%E6%9E%9C%0A%09%0A%09%3E%20%E9%BC%A0%E6%A0%87%E6%94%BE%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%E4%B8%8A%E5%B7%A6%E4%B8%8B%E8%84%9A%E4%BC%9A%E6%9C%89IP%E6%98%BE%E7%A4%BA%0A%0A%09!%5Bimage.png%5D(data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAABFEAAAFjCAYAAAD1k5SmAAAgAElEQVR4AeydB5gdxZWo%2F5vD5JyTRjmjHFBCEjkaeOCA42J7ndf7bC943zrgCDY4rnEEAyZLCJRzQAnlLJRzmBlNDndu6n5f9Z0eeq6uhAAhhDjNJ6qrTp1Tp%2F7urqlbXV1la2xs1JFDCAgBISAEhIAQEAJCQAgIASEgBISAEBACQiAhgdTUVCPdnlAqiUJACAgBISAEhIAQEAJCQAgIASEgBISAEBACXQjIIEoXHBIRAkJACAgBISAEhIAQEAJCQAgIASEgBIRAYgIyiJKYi6QKASEgBISAEBACQkAICAEhIASEgBAQAkKgCwEZROmCQyJCQAgIASEgBISAEBACQkAICAEhIASEgBBITEAGURJzkVQhIASEgBAQAkJACAgBISAEhIAQEAJCQAh0ISCDKF1wSEQICAEhIASEgBAQAkJACAgBISAEhIAQEAKJCcggSmIukioEhIAQEAJCQAgIASEgBISAEBACQkAICIEuBGQQpQsOiQgBISAEhIAQEAJCQAgIASEgBISAEBACQiAxAWfi5I5UXScSCREKhdF0cDhdeDxu7DbbedUuRKhFwoQjYTQceL0e3rvFCyn17DxaNGzULxKNYrc7cXs8OB2xsSUtGiEcVnW3GekO%2B4V5%2BW71zvZOUoSAEBACQkAICAEhIASEgBAQAkJACAiBy4XAOQdRdF0j0FLPrjcW8sqMOew91UJ%2BRV%2Bm3HgbY4cPJDP5vQ2mhEMBFv%2Fli7ywaRCP%2FO0Bct2XGolOKNDK8X1bmDXtBVZvO4o7O5%2BJU%2B9g0rhRlOaloUdCLH%2FqUZ7Z3soff%2FUTUjyOC3JSi4RY9s9H%2BdeOd6Z3QcYlkxAQAkJACAgBISAEhIAQEAJCQAgIASHwgRBIPIii62jhNt54%2Bvv8ZtZBoroNNQnj8M71%2FP3NrWyeejff%2F8rH0Ww2bDY7doe9cyaJpkXRNB2b3R6bsaLrRLUoug52hwO73Q66RjjUTmtzM03NrQSDISJOJw57hx1Vvq6hRTV0bDicjs7ZL2pwR9M0dN2Gw2EjGo3G8ijdDttKL6rpHXp2Ek2c0bUIVbtm8z8%2FeoL6UNQou%2FX4IV558jcsWzWBX%2F3qO6SE2mlpaaa5uZX2YAif043D4TDqqus6uhY1ylEFOOyqbjZURSOqbi1NNLcECIY69Ox2I7%2Ba0WM386Kya0Qi0U42aq6LSlP1UhztDsVFcb6wWTAfyF0khQoBISAEhIAQEAJCQAgIASEgBISAEPgIEHA88MADP4yvp45Oe82bPPTIS9iv%2Bhh%2FfOyX3P%2B5T3PHbTczqHc3ho2%2FlmRbKy%2F960kON7roWV5gDLKogYVA9V7%2B%2FI9nafIVU57jp63%2BJAumPce8xaupi7goLyqAaJAdS2bw6tJNnGkOUFt1iFMNYfr1KDcGKKKRELWHtzLthed4feMu9KRcCrNSsNltRMPt7Fs1jRdm7qNH%2FyK2zH%2BJGfNfp9WdR0luCtH2ZjYums4rsxdytMFBt4pCXGqAxToGoQZ2ws0s%2BPOP2FpXzHce%2FRPf%2Bdr9%2FJ%2B772TMsP4MGjqGiiw%2FJ9c%2Fy%2FNz11NT30TNqeNsOx5mcP8K1HyUSDjIgU3LeWX6NFZu2IEtrZDCrGTQIxxb9wzPz9tATV0j1YZehMH9ywnUH%2Ba5Z56jPbWM4myVVyMabmLOM39iQ10mfcuzsesa7S31rJr7EjPnLeZQbZSy8lI8aqDKWof4iyZxISAEhIAQEAJCQAgIASEgBISAEBACQuB9IeDxeAy7iWeiGCI1lKITbWuivqmZ3NRsvCkZDBw10ZgVEWoNEDy4mdmb6hk%2BeiBFfgd6NMT212fz%2BqrNDL3hHhpObOOx%2F3mAdUfbDYvzFsxl0c3f4UefG87J%2FbvYezKExileX1RNPWncdeNEtHAra2f9nUf%2BPINAVIvpvTqTifd9ja%2FdMxVnJMjJPetYOB%2FCtfOZv3KPMStlyZLFHLrvq6QceI0nF24nqoNt7jyWbPgUv%2Fzup8nwxVVVV1M%2BQIu001DbQKgiC6%2FXT0Xf4VRgQ4%2B0UXd0E%2FuOVxOOwoolC0nqn8rn7pkEbbVMe%2FzHPDNvGxE1tcRmZ%2BHsWdzxjZ%2Fz2cmV1B1JpDeeQONp1qxcjrvPdYzulW%2FMWomG29i6ahG1gaHcPbEHocYTPP3w95m%2B7qhyD2zzWbr0Nh7%2B2VfJ8sfVwaAj%2FxMCQkAICAEhIASEgBAQAkJACAgBISAELgWBhL%2FK1acjnqxefOMzg3n4X4v57pcWk5RTyrU33Mmk8cMozs%2FC6U3hhlsnsPiRGcxYe4p%2Fn1hIKFDPqmULSc2eQo%2B8JI4sfZ03QwU89Odf0L8wmbrDOzjoHUxKkotJn%2Fk2gabP8dymwTz25H9TlOzFaYty5vBSnnl2Gd3HfYL%2F%2BOq9pNtbWPT0Yzzz6lOsHTaIMSU%2B1MKtUf0ANVlf4Jnpj6HX7uQH33%2BIWf%2F8HWWDr%2BOvL%2FyMtGg1f%2F75f7NmxzL2V9%2FOsLLMzk%2BOjM9v3MmM%2F%2BSXWfjDP%2FH4D7%2FCP%2FypXHX1zdx80yR6lhfic3npc8tP%2BcLpX%2FL0tlYe%2F80vyEj24bHb0bzJ9O0zjp%2Fe%2FD16FqcSaj7JIw8%2BwKqVi%2Fj0lD70vfVnfOH0L3h6R4A%2FP%2FYL0pO9hl6r%2BgRIfdcUGx7puL6xNCM1GqHu4DoWvRnm0z%2F%2FB7f1y6ftzEHWH%2FWR5pWNlC7FAyFlCAEhIASEgBAQAkJACAgBISAEhIAQOBeBhIMoqHVIXB4G3vo%2F%2FOqqw%2BzbsYVVq5Yw%2F8U%2FMvtlL8Ou%2FQz%2F9wvXk9JzMkO7zWfb7GdoGfktmnfMY9VhN9c%2F%2BCky%2FG6as7LQ22r5x6MPMWDUZK695mpGF7iMXXCcTidOpwOH043fn4TLpb7yaWXL7LlU5%2FXnkc%2FfSpI9Qlh3MfzGu1i74Mes2naUkcU9sdkduNwl3H%2FfreSkuQi5enD9gDyeXu%2FnM9%2F6N4qzfRD1cfOtU1jzuyU0tgXPqr%2Bykd39Gn7%2BaG%2F27dnOhtdfZ9WqV9i0bDr5%2FSfyo%2F%2F3ddKcLmJ%2BuvD6%2FHjdCpda8ySEL9PLjGd%2Fy1MNrUQjYepq22hNDxrrszhdSk%2F9i%2BD1%2BTr1znIiPsFmJyk9i1S9lQV%2Fe4QTg0YxeepkJo%2FK71wTJl5F4kJACAgBISAEhIAQEAJCQAgIASEgBITApSFwjkEU9aWJjtPtpaR7H4oqejD2ultpqjnCP3%2F%2BE9YuW8bpz1xHgT%2BV0cMGs%2FrlrWw6XsfBOavwlAzm9iFZxgBJ8dBb%2BMF%2F%2BFmxagtbFjzLstdeYOSNn%2Bbf77uBRAWrhVprDrcTOriGb395o7HOisKgtiEORu3kVjcYfqnFbB3OfJKT3Gq8B4fDicejBmX8pCe7jAEH3e4kJcXfOftEzfSIX1LEZneRWVDOiPxShoyeyqdba1n23GP8Zf4y5u38PHf3jtcAPRrm%2BOYZ%2FPz3r9Fz1FSG9fAagyh7WxvYeQHXTNd0olH1oZTyR0eLBomGY5NT1MBOcskovv%2FDb7NoxUq2bZjHLxbPoGL0LXzvq%2FeRnRz7BusCipEsQkAICAEhIASEgBAQAkJACAgBISAEhMBFJpBoLMMYqGhvrGLBs38ladidDOpRQpLHgScpg5zkZKjXiAAOt5c%2Bw0aT%2Ftxi%2FvrCDPxvHqb3NXeQ4Xagdr9pPlODM38w99x%2FNXe2nmHan37J2lUzqf%2FYVHJcNuwOF9FIE41NLfg9Om6Xk%2BL%2BqbDfRXpOPilel7GYqh6NEHEmUVyUYZmRcfYAxzthEw02s33Zy%2BwN92TMsN5kpvhwuJIpKMjGxgFjxxybzYXTZiMaaqe%2BqRV3WMfmdLJn9Yu0hgdz89130z3dTaCpilPrFncWrz6Hcii9YIC65jZcYQ2HL8WoL1qY%2Fdt3Uje0GK8twtF1S9hVpVFgDBZFCTfW0Ogq5PaPf5nb7mplxQu%2F47kNqzjecKcMonQSlhMhIASEgBAQAkJACAgBISAEhIAQEAKXnkDCQRT1yUqg7iiz566hat56%2FH4%2FLrWdcDhEc2uAPuOvpdhpN7Yr9ub25Y7x%2Bfx21ku4%2FZl84rqJxpa8kfZ2Xn3mV8xZfxq%2F34ta0aOlqZns7veQluTEobkprBhEZNlqfvCNf8PryeHffvIwA277IsM2%2Fw97G9tojTiMGRt2m42U3EK%2BeO1VOG2t752S2p0n1MKaWa8y%2F2CQl31J%2BDwuY60Vte2yv3wkdwxKwWmPUFCagz5%2FIw9844v4PG6mfukH9O8%2BnOiKN%2Fjpf3wZn9tBOBSgsaERZ9%2BBhm9qW%2BLCsmz0BZt44Ov3G3rXfuVn3No9n%2FwkL1vm%2F41vrH0Jlx0CvgJysmNVUjNuVk57gr%2FN32h8PuRQ8tZmUvN6kpvif%2B%2F1FgtCQAgIASEgBISAEBACQkAICAEhIASEwLsmkHC1UvW5TGa3Efz6b7%2Fj%2FnuvpyDZRs2ZM7Q7M7jx09%2Fi%2F37jLlwOtdGvDZfHS59xt5HkdpA%2F7GOMLPMas0VcniTu%2FsJ3%2BeydU0jSmqmpb6XvhHt48AcfJ9XtwOXx0XvSp7lnygACDWdw5xST5dRIy%2BnBl7%2Fz31w7tBst9VVUNwQo6T%2BRL37rO%2BQkO42dgex2Bw67xXWbDbtaXyVuG2D1eUwsLW7Wis2GO6WAz%2F%2Fs73znq59hQHkWTXU11LVGGDT5Xn7y4H%2BS5nUZnzP1mXA3X7hjApHGOrTkUrrnptN98lf4%2FB3jcYWaqW%2BN0G%2F8HXz6xgG4nA6MRWvVorSG3nhDL5pcSmWWD296IV%2F7zn8wYVAxLQ2NeIuH8L3v3k9hkssYeHK6PUz85Jf5xmfvIjdZ50xNHXn9ruE%2FH%2FwB%2Banud32RRVEICAEhIASEgBAQAkJACAgBISAEhIAQeO8EbI2NjWp5joSHWhdF1zXUhjLqXH2mYrPbY2uOaBrBpjrCTi8nt8zmwYef4p7%2F%2BgN3jS7v%2FOTmLf3YCiBqcMaw0TGmYdjWOtYHUbYNeawsTdOMLYDVoIRVT9lUDqnNj98aSNEx8mPmjVVH17TY2iOGjbiBFJVF2emwZ0Iw62jmjtWhY1cdNVijBm8sXIySlP3YnBlsdnWusnTsuqPsd%2BgZ6YZPSqY0lT2b4bth12YzbHf6pXJ0%2BK5COYSAEBACQkAICAEhIASEgBAQAkJACAiBS08gNTXVKPQcn%2FPEHIr9gFczTs4%2BQq21PPfQ95i%2B8yjYnfgz%2BjCqf6nxo9%2FMfT59lccYHElgXuk5jJkupqW3QmMwQcnfSuoYjOiaYti3289aTLarmq1zwKdLuiUSq0PcAIYxsHF2eRa1zsEPa5o6V4NQcda61lUNlpxVv3grEhcCQkAICAEhIASEgBAQAkJACAgBISAELjWB8w6inM8ZhzuJQddOYH31LMgbzle%2FeT%2FFKY6zBgjOZ0NkQkAICAEhIASEgBAQAkJACAgBISAEhIAQ%2BLAQOO%2FnPOethK4TDgUJRzXUQqput7tzS%2BLz6olQCAgBISAEhIAQEAJCQAgIASEgBISAEBACHyICF%2FQ5z3nrY4stKus6byYRCgEhIASEgBAQAkJACAgBISAEhIAQEAJC4MogYNni5sqokNRCCAgBISAEhIAQEAJCQAgIASEgBISAEBAC7wcBGUR5P6iKTSEgBISAEBACQkAICAEhIASEgBAQAkLgiiMggyhX3CWVCgkBISAEhIAQEAJCQAgIASEgBISAEBAC7wcBGUR5P6iKTSEgBISAEBACQkAICAEhIASEgBAQAkLgiiMggyhX3CWVCgkBISAEhIAQEAJCQAgIASEgBISAEBAC7wcBGUR5P6iKTSEgBISAEBACQkAICAEhIASEgBAQAkLgiiMggyhX3CWVCgkBISAEhIAQEAJCQAgIASEgBISAEBAC7wcBZyKjmqYRjUTQEwklTQgIASEgBISAEBAC75KAzWbD6XSiwvdy6LpONBpF9VnkEAJCQAgIASEgBITAxSTgcDiw2%2B0J%2BytnDaKoTkk4HGbtmtXoCTomqtOj8qjDPLeGKLmmnSUz8tvtXWRdKmmzobpTpm2rfWWTjjJNHbNMq6wzzfRNZdb1C%2FKli%2B5F8NO0p0LDjQ5fVHA%2B2VnyDp4q3XoYds8hU%2FlsdrtR93PxNFkn9EUZiOMWS9KV853XIqFu3HUyfFF%2BdthUgTqsuueSdWQ8ty8xU532zKi1ziqtS1lx%2FimZOpROonxmmmnbGreem%2BWYtsz81lDlN%2BXn0%2B0i6%2BCdSFddY%2FMZ7aJzjutv%2BpLo3lAyw4YKOzJamRhJCXwxbZphIj%2Fjda3Xxywz0fNt6pl1tJZh%2BJag%2Fp0cErQnpr71Hu5MizvptNORHh83s5vpZmimq9BMM8O3S7PqWs%2Bt%2BlYb8edd4h3XymqnU65OznG%2Fm2zMMs3Q0H0P7aLZ3pj%2BdNq1%2BNmZZmHX6bPF33Olxdu22jNlVl0zLVE%2BM80MzbxWfSVTh%2FV%2BTiiPZTLyWv9n2D6PTF0L671v9cV89s00qy%2BmzCzLKjOvr5KdpXseX%2BLbaKvteJlp18yTqCzVKRk5ajROl8vww5r3nZyrAZSNG9YTaGvrUh%2Fzmpi%2BdIYJ2gyzvHO1i4a8oz1R50bbo66N%2BbfE0i6eTxava71Opn%2BJfDmfzMyvQiOfCjsS384XlS1RHcz0znLP8YwaZVp4dhT7VmDReyuxq59m%2BWZZZh2s7ZNV17h%2FO%2Bpo6p4lj2srlNxq15q%2Fs9wE9Ugk60wzr%2F%2F5%2Fs50FGTqWMs1z%2BNl8XEznxla5eZ5fKjyXmiaadeqY6aZNhTzd9V%2BK0OWa9FpT%2FkX97fkfDLTHyN8h75Y7Zp2zDQVqsO4jyz36lnyWCZT3QhN3fg22sxkyN9j%2B32WH2Z701HI28mtviR8Viz3iZlXhabdRGlGvUxmlgxmukqKL8u0Z4aGWgdvU0%2FpmHLz3lD5OtM6nrdEMtMNJVP3W3z5ZnnnaxfPJzPvYWWni59mG2Dxs9MXy71l1iGRzExToZlPheqwlvV2%2BUz5hepa88f%2F%2FVayTjsqcq77ztJmWn03%2BCd4Ts0yE7UnVpnJ23odDfvv0pdE94zprzJpPe%2F0I%2B6k34CBZGZmovot8YetsbHRYBgvcLvd8UkSFwJCQAgIASEgBITAeyYQCoXesw1lQPoqFwWjGBECQkAICAEhIATiCEQikbNmu6amphq5zpqJolLVyIyauiKHEBACQkAICAEhIAQuVwKqv6L%2BySEEhIAQEAJCQAgIgUtFQEZKLhVpKUcICAEhIASEgBAQAkJACAgBISAEhIAQ%2BFATkEGUD%2FXlE%2BeFgBAQAkJACAgBISAEhIAQEAJCQAgIgUtFIOHnPNbCdS1KoKmavYdPY7fFVqdNySymrCjTXOPLmr3LuRZt58zxarJLS7HLbNsubCQiBISAEBACQkAIXDwCRn%2BluY6Tp6oIhHX8KekUFRXhdV3a90VqUbzWuuPYUwvxuRydi71evJqKJSHw0SKgh1s5fuw4DS3teFKyKS7Mxe9xEmyq5vCxKjR3KmWlhXhcdupOHqOmvpmo3UdFtzJ8bgfRcIBjhw%2FRrnvIKyolM9mD3fLDRItGqD99hJO1rfgzCynJz8Bh02lvrOLQ8Rrs3lRKSktI8jixm58P6hotZ05zvKaWsGYnp7gb2SkeiLZTffwIZ1oiZBeWkJvm5cDefQTDETS1P4PdgSe7mB75abQ31bD%2FSDM9%2BlYYbUVT1R6O14TQdB0tGiWtpA8lmV4cdrWYtUY03M7RAwdILu5NTrIT9CjNdVUcPVGDMymL4qI8knzujjZHJ9Leyomjh2kM2ckvKiErPRkiIU4eOUhDQCO3pJysFB9OR%2BI2UrVl0WAzRw4doU1zUlxaTorfhR5u58ihg7RrTrLySsjNTAItQu3Jo1Q1BEjPLyU%2FMxmnXafh9FFO1rbgy8inODcTl9spbeJH6%2FG9Ymub%2BKmxVFePhjm1cx7%2F3NZCVnY2mVk5ZKT7jW0F1TbIkXCYSCRqrCQcjca2GVQPuqZFiYQ1ktLTO2RRzMVZYrIwYaNB0Y3Vf9Uq%2B8pWuGMBF%2FXgqgYkEomlRaMR4zwSjZWlyjDyKxtabEXmzvzhsJGmGsVgezuhUJhogp2GLNWUUyEgBITARSWgftCFQ0GCwSCRqGZ0gCLhUKzd62izVBsaDoUIR6Ko9qpdtVcd7ddFdUaMCYErnIDqEwSba%2FjpD35LTdRPVlYWaakpxo8M1TdQK%2BjH%2BiaaseuR0Q9RfRjj2Yv1T1QfRm2XrPoqapdC1bdQuwVY%2ByeqL6H6I6GgerZDsf6Hsm087yHag0GjH2P3pGDr6McYz7nRV4oYtkzbZj9HxVWZcRshXOFXTKonBC6cgG5zkpqRRU52FoHdr%2FDq6v1Eg%2FU8%2FsAjNNtTCRxcym%2Fn7CEYiuJPTSMzK4tU7SgvLdxAMBhg8%2FSH2dvsxtd%2BmMcffZ529dx3bKth%2FJ6o28K%2Fpr1BZnoyW5%2F6DluO1BGqPcDDP3sRV3IGgf0LeWzWDqKmknrmAVdSKllZ2aT7bTz53d9Q1drOvtUzeHl7Kxnpbp576jlqQxpZOblkpgdZP3MrqWkZZPkdRBv28JMHH%2BDJ%2F3mSmtYwmq7hSsojKzuTjIwM6re%2Fzo7G9o4%2Bg4YWaWfWLx7k0d%2F8glWHA4YvkaY9PPH483jSMwkfWcjLszYY%2FY1YuxZhy%2FyXWX7SSaYvwL%2Bee57WYJjqFb9lxf42UlxtPPXQbzjTHIztoNlxOYx2qaOPomsRVjz3TzbVech0N%2FL4C%2FNoa29n86u%2F5EjQQ6qrmZf%2F8CjBUISGba%2FwzKJ9pKd6efWXj7DrdBvNJ3fw3Sc34k3NYPNrz7ChOub3hV95ySkELl8CjgceeOCH8e6pRdqcztgkFV0Lo0ZGt0e7c%2BvQclJSkvF6HATqD7BrzxFenzOdNXtq6durnLVL1pNRUYwzEmTf0um0ZJRwbOUqsrqVs2D9Jqo2L%2BSAvZICVx1zXn6Ghau2k1HWj0yfzqbNKwkc3spz0%2BcTTi%2BlKN3F5hfnsPf4ZmYuXE96cSkbXn2a5Tuq6d6nEmc0xOqZTzNtwRt41YisDzZs3Ez9ya0898JraFmV5Gin%2BONPfsSCN7bjzOtJWU6KjH7GX2yJCwEh8L4QCDVV8fSvf8wL89fQmlRGZa6Duc%2F%2BjXlr95DVrTdprijbl0%2FnuZfnsPt4lFLvEX7%2Bo1%2Bzbt8Jug8aSIq8rXlfrosYvTwIqEGDi3Govorqs6hByL3L%2F0H5jf%2FO8O75pKWl4vd5QGtk49I3yK8oh2gr6zbvIDc7la0vzWPv4Y1sP%2B0iemgO%2B7dvYU9jGgUpIeY%2B9wTz1%2Bwlp6I7Ge4wzy%2FaRdPeJcxY8AZZ3fvhOr2BX%2F3kYVZsP0DFwKtI8zgJNx7nH7%2F8IdMXvUE4vZK0lp0EU4pp2bOMbceqmfXCi9S5cwgfWc0z0xaQ02MAGT4HNfvX8fSTz7OvwUX3ikLc53gjfDFYiQ0h8GElYLM78fr8JCUnkZ7jZteKk%2BSlV7Mt%2FwZuHlJEQWkJNdP%2FQsbgceRkpJGckkJyei7ztu5kQHo7T61I5u7bRpJf1A133QrCJYNJdztiMzyi7ax%2F5vfkTPkcAyoLqRxYybK1x%2BiWY2fT%2FjbGjR9CUvgUm474GDuoCIfdbvyWMH4rudwkJSeTmpYJR%2F4XrXQ8O7Zu4o4bryU3K5vC8HZeO5XP2N75JHnDHN0dYNC4gaSnJuHwpjN26jXUzdlM91uuJsXrwu3xkZycgt%2FewJzZm7j1holEq7ewZFMdFWX5VIwYT6%2BUBhrSB9Iz203zvpXscA9h3KBu5Jb2Yd3mRfQsL%2Bbpp1dQ2SuZ9et2cct1E8jKKcR%2FfB2bg5nM%2BN1u7vnqrRQWFFGaXsXutizKc9OMLwaMAaXmI6xbW01eURpatIZV209wx42TyMguRHtjOlVZfQmf2EJaz%2FGU5ySxb%2Bsmeg8fxfS%2FrWXSfbdSXpDDwJ4RFq9tJFq1mXF33UVlTiYVeQ4en36I0VeV4nW%2B7Tv8D%2ButKn5fYQTUSxQ1sGg9PB6PEb2guzgaauf05sXMeGU6M2fN4s2qFppqj7NgxWEm3PlZxhc1M%2BfNelLqV7FkRy2tjWeYud2OmwZ2LltBW3uIDYuXkjv6HsYWRHj58ecoGv9xPn%2Fv9Sz81YMcqAuwZ91SjqSP5jOfv5c96%2BbR0NrMrjnz8Pa6kU9N6cEvfvwnel57D5O6tfDXpQepWfu%2FNBZM4uufu52jM%2F7Aoep69m5ZwX7685Wv3M%2FCV%2BYRSi9m8pgy7vj8lxnfp0AGUKx3gJwLASHwvhJwJ2Vy7ZgSrr7rc9wyvJBd035BzrhP88U7x7L6X49TU3eUNYda%2BexXv839H59AdsVIKgYP4Utf%2BQJFSV5pr97XqyPGrzQCqvNfdWIreWley249OpFQLTvX70JNlI1Gmti%2B%2BwDB9iZ2zp6Pp%2Be13Di2mN0rF%2BMZfAfXDCli8%2BKXKb%2F%2BM3zx4%2BNZPWcarYEWls15CW%2B%2FG%2Fn0LcN45PeLCOcMpM%2BQAXzpm1%2BjLM1rTO93p%2BRxw9hCpn7yfq4fUkLNvvXUtrZzat9mtp9w85kv3s%2F%2BV%2F%2FBdq0fX%2F3srTz2%2FCqaqncwff5ePvXlrzE28xCvzt9FbD7vlXZ1pD5C4CIQ0DWaTr3Jk399jbyxA4i2avQuVT%2F%2B7dicSeSXNxuzwNSUrlBLDdP%2F%2BmsGlvTGFo0Q6FnW8cPdRkZyIS0RLTaVxJhFplF3rIScDJ%2FhpN1bRIhWbJ50%2Bhc18NSff88zSw4ytHcOtgR%2FmbVwgC0Ln2Ve233kp9vwOly4HQ5sNjtpubkcb2jtMtOjk4Tdhc%2BrXlh3Xe9A0yLsX7kUxv0f4xOflJLh3DBpAG6XGkjydFlKIaVyOLmn1rBg1qvMfvVFdu1pIOTN4v4v3kSyK4Q7qAZ9YgPNmQUuGmrr2d%2BzLz633diF1Z%2BVR6Al3NHuaBzfNJfZr73CnNdmMGveAqoba0jWC3GqgSObndzSCK3tUbJK%2BrHkpSf44x%2F%2FSVSA2%2FkAACAASURBVLBoKDZ0Tubnk%2B5Xdm04cwrxNLfSrAUp8zpibWRyJrnH6s%2FaLraTh5wIgQ8ZgbddE0XVx%2BHykDdoFLfc1MuonsNpo6bFw6DRw8nwOwmnJ9PUrNN78mQ2PDWX2kle%2BowdRpor9pmNGq11VPSnZ46fQH0Te32V3FKYhlvzMqZvFafqAzhyKhjXK5toewsum50gNhyOciqK0%2FGcTsLv6ktOmp9QRg51p5vYumE10%2FbvZK4T7ElZVEY1nFkVjBtUgIMo7oYQAdUwGdsfntVGfcguk7grBITAh5WA%2Bnxa15pZ98o21i39Dm67hje3Gzd78hiRF%2BCH3%2F065WPu5St3j5T26sN6kcXvD5yA6uDn5fflTEuA0gxv3B%2F9znn7sU9mdHA4yynLT8NuD%2BFN8lORmwZ6A7vWr2D97A04XS5cBf241QaO4hH0Lk7DWZeMfrSecMdbKZtd%2FaTq%2BgNI9XeMJRMseXoN7IOa3JvrKqJ3j0K8vlZob6fp%2BF5WvrGITVuX43K46D%2Bp4gPnKA4IgcuRgB4Nsu%2BNOfzuuTf42oP%2FRbfsJBr2b%2BdYVQCtWxI2rZ2GU06KgPrDa%2Fn1I88w%2Bds%2FY2xZEqHTrdiOVhGMangddpoDtXgdsOjxXzJv91GSh9%2FL%2BIzD1DeFIM%2BHFq7Fobk4sW0Zgd538u%2F3ZGDXG3jl0UcIDPgCj%2Fz376i2lfH1n32Lomgr0x5%2FmBP5N%2FP9b47EZWslHA0SNt5eO2ltqCU7qa%2FRSnR9l30uyrqx7snCg63c%2B7lSHI7YWpTW3NYWx5FUzMfuvx9d0wmHA9SFppPiVAM4Nux2NyHHKaKaepNuo7k2iD8jmcI962mPaKRqGsGmBly%2BCmJv1O0UDb6OzIJMAq0hrr1mBC5HFQF9BxFNM9Y3aazScWScZPq0IF%2F68VdJ9zjYs%2FBlNtZHSD92huaQRq5PR2usJej14NMdnApH6eZW67M0U5Xtx2a%2FoPf31irLuRC4LAlc0CCKsbZIIEBzU7PRyfcl%2B40OihptVP%2BMQRKHA3dabypylzNtfjWf%2BOrNODgdeyOkxjKM6W823P4khgS3sG7XYAZlBpm%2FpZJP3ZHESUdspFIzRjtj3ZJYZ0SV4TBGTN8qy8OgiRM51q0%2FN43viS85DQcRdhkL36qHU4st%2FGS347TbqGls4XCkifKKirjuzmV5TcQpISAErgQCNjsOl5PWphYO7qxl9J0DySq4l9E9c%2FAlpxqLXfYcdw8PDL6WpX9%2FiLrASOzhMFWnqmjPzaY4yS%2Ft1ZVwH0gdLgkB1U%2FoPuYefvebp%2FB97l6Kk2H7spfIHHE7rvRWqmtraFj%2FEofr841%2BjFocUg2CqLfA5sCH3ZlMv6FjKa64icFFyXg8XpJsYaP%2FEctjR03kV7oOHapOniKSnUFxarLRx1EDL60trezbtRtdjaQYAyox%2B6oou91ufAqgHmxlL7msH6P77OeG%2B%2B4j2ePBlySfHF%2BSm0UK%2BdARaN63lJc3tPH1b3%2BVDGeUYDBMRulg6v%2F8Zw6UfQnHidfZXnAPV%2Ftqef7p1dz1tW%2BTnxIkEHThyargptQZbD%2FYlx7OEyzfaePLN3jo9cX%2FZJKmGYOewZNhnlm0jN7pI9j88u%2FpPv57pAWDbFq4nPHl1xA5tZldoQpuc3XjP3%2F5WGyQVmtn3qO%2FJ2nCJ%2FhUrzwCgTbsPh89CtJ5df0RbuqfzOwNbdzxmWJjtkxUaaln36Cvo0ejtLU20trWQnNLK5leOx6njeoNT5NUMoJ0j8toJ9RaasaCtOqzxXA7TU3NtKQ20RZ043PZO9ZnCrBvxbMUVN6Ex6Eb66u5HDkU59pZsruKcUXtLD%2Fq5q5JlQy6exprNx9idJnOzBk7uelbUzs3%2F7A7nPiyB3L9XXrsc0i9kCxqeX3XSYZlN7CqvQ%2Bf7pHDQd%2BLHKueiDM5xObdu7l6%2FMcom%2BpizoJNZEzoxry%2FLaf3fV%2Bnu%2B7iJ8%2B8znfvHsr2RWuYfOfHSXI5PnT3nzgsBBIReNs1UdQT73D5iZzay7GjRzl69AjNQT8lhZn4k9NIT%2FHg9CSTmppOTpqHtIxU9IKr6V%2BeicPuIjkzh%2BySYnxeFyXZGTgcTioGDaThwFb2n2xhyic%2BSXG6B7fLTXZ2rtHQ%2BJOTycnOITnFR26PYtxOF1k52ZSVZuB0ukhKy6Rn71H42o6wc99h6ts0Y0Vqv89PTlYmLrud9JQUCkpzSMst5dD2LXhzu5ObIT9KEt0EkiYEhMDFJ6B%2BJLmyu1F%2FcDtaRg%2F6j5lC27Gd7Dt0nHZcFOWls3%2FbenYdOEnByHvpXZZNYbqDnbsOU1JRSbKsiXLxL4pYvGwIXOw1UdTz5vCmMGRQCYd3bmbP4dPkDb6O7vmZlBZksH7DDlJ6j2dQZSF52Vn4Uvzkdlf9CztudxIZRZW4nA7yynrSuG8T%2Bw6foN2RTGlBFh5PEpVFsf5Hbno6ZZXZFGX52LZ1H8XdepDSsWOHJ7c7J3ZtxpHdg9KSAtKyCkjx%2BkjLLSLN68CflEJuaR5%2BlwOPx0%2F3igp6d89j68atnDxTT3JmIZlqdw85hIAQ6EIgFGiipaWZ6lMnOXH8GCFXJsUFBQwdVsSuzZupcxZz53VX4bOHaalt4HRttZGvJuyhsiifor6DObFjHYfrHUy89Uaykj24nE5j%2FUen04EzpZR8bz3rt%2B4jdeAdDOtVSGpuGX0zW9m8dSf10Uxu%2BdhNpCWp3ysuQ0%2B9sm2KBmmoO03VyRMcO3qSgoruFJd3x129k617TzJkwhS65aRhd6iXw3Y8%2FiQy8zONGSZEGlm7aBW2PmqGfSsFlWX4ndDWGKC8%2FxDSk1zGgEu44RA7j7SRn5PMsQ2r2N%2FixdZwAm9hb7L9AbYtXcbOg0dwlY9n9KAy3FobK1bupbi8kJLyCtoObWLn0UZGT5pKYWYKGT1H0H58O7uPNDDs1jspyfLHBnc7iNscbnx%2Bd%2BdL8opeFdS8uYHdJ1qZev015KRn0n9oX%2FZt28jBE3X0uvo2uuelkVbSl4zwcTbvOkiPqbczsDSLlKwCBiadYfPWXaT3GcuY7rm4ZceyLve2RC5vAudbE8XW2Nh41gwz1RkxF025vKsm3gkBISAEhIAQEAIfNgLt7e0XxWXVV1F9FjmEgBAQAkJACAgBIXAxCYRCahe%2BrquVpaamGkXIh2kXk7TYEgJCQAgIASEgBISAEBACQkAICAEhIASuWAIyiHLFXlqpmBAQAkJACAgBISAEhIAQEAJCQAgIASFwMQnIIMrFpCm2hIAQEAJCQAgIASEgBISAEBACQkAICIErloAMolyxl1YqJgSEgBAQAkJACAgBISAEhIAQEAJCQAhcTAJnbXGs62qv8TBtra2oc%2FNQZ9al26xx67nKb41bzy%2BWzPTJDM0yzNBMt5b3TmWmjUR655JZ81rPrX5Yz808ZvheZPE%2BmTbN8L3Yttqw2jHLtIZmXjO8GDLTRrxNa9x6rvJb49bzSyEz%2FTVDs3wzNNOtvrxTmWkjXs8at55by4o%2Fj4%2BbevGhNV%2B8TMXVodqIRDKz7bgQWYepTjsqbuolkplpZhif10xXoSkzw4shM23E27TGredWP%2BLP4%2BPvVs%2F0yQzj7Zjp1vIS5THTzPBC9cx88XrWuPXc6kf8eaK4af9CZfFlWfXeqcwsO5HeO5El0jfTzNC093b%2BmvkS6Z1LZs1rPbeWFX8eH3%2B3enaHo2NXjLO6IKa7FxSqVfNbW1sJBoPSP4kj9m6vjakXH1qv%2FTuVma7F65nx92LbasNqxyzTGpp5zfBiyEwb8Tatceu5ym%2BNW88vhcz01wzN8s3QTLf68k5lpo14PWvcem4tK%2F48Pm7qxYfWfPEyFVeH9E86QFym9%2BBb3r11Fn8t35K89RyZeS5UZuaL17PGrecqvzVuPY%2BXmbbNMD6vmW7VS5THTDNDq555%2Fn7KEtk208zQ9OPt6mLmS6R3Lpk1r%2FXcWlb8eXz83eqZPpmhw%2BnA5VK7VZ097yRhD0atdL906RLQddR%2F6lCbc6njfHElM%2FMlymumxedRcVPXGhoFxv3PyKsGd8xfZR1y04Zy11yp3%2FRVZUlUpko385hys3yrrMvT01FeZxBXnmnH0Nd1w5f4MuJlXXQ6GJo6neVYTlT%2Bc8mtsni7ysS50i7EnsUFw47SMcuzhmY%2BU26Nx%2FtwLpnpj%2BmvEbewVnrx9k1biWTxeRPFld65yrPmV%2BeJ7jNT93zlm3asoVmuNc3kqWTWozPdwsLwpyNTvA8q2dQ5n8xQj29xzqX7Hu5rVY7V3w63DZ7xz3Sn7%2Bd43g1bHb6Ydqy2zfqaaSYHM681bj035So00xOFZj5lX8kTHfEyqy8qf8K45dqaeczyzbbILM%2B0Hx%2BaviS0%2Fy7vc6svVvumb%2FGhmUeF55NZ5ea5Ck3frWlm%2BoXU36qv9BIeFtYmQzOfeolg%2FVtilqnkpuwsHUubaNrpEnaUl9C3OFl8eeoW65Jm3AxvsTXLUXmsfiUqy5rHzGuGpp3zxRPJlJ7pn5KfL646I1Ovu94s6l2H6vosXrSQcDh03vKs%2Fr6db8qQNb81bqZbQ6vzBte49vEs%2BTnYqGTzfjPL7NQ9h8ws7xzNT5fnzrRl%2Bm6WYV4za9y8vxPqJGiPzXzW0PCto67WdHVulmn1RaWruHlY85g6pvx8MlPfqmP6Yg3NfFYfzPP4sDNvR90Tla%2FyxPtnpiUqN5HMLPfdlBdfdnzcWl6nfUt7ZfXR1DXzmfU1bZjpZmjqqriZ12rDTDP0Ezwfptx631n1jXIS9E%2FiyzP8sNjvtBv3N1rZNvKeJ90o0%2FyfpWxTzyxb%2BWw%2Bf%2FGyt9S7tocq3dRLpGPW3SozbXWWG1cHs05mPmvctBeva81rylRo9c2Ix7VZZpryL9FhLTtR3rPk53muTF%2BUHSsPs2yzbmb8fOWZ5VpDq13TvhkqmfWwppvlmeWrfGaaOremn0tmtWctxzw35YnsWtPM%2FJ31svRdlMxMN84t96up1xla7vPONPPEIjPLttpV2ax17sxjubam%2FHwyszgVqnxmGfGhmc9Mt5bfaT%2FB823aPVd%2Bq1ydq2PEqNFkZmZ2xLoGCbc47ppFYkJACAgBISAEhIAQEAJCQAgIASEgBISAEPjoEpAtjj%2B6115qLgSEgBAQAkJACAgBISAEhIAQEAJCQAi8CwJnf%2BDzLoyIihAQAkJACAgBISAEhIAQEAJCQAgIASEgBK50AjKIcqVfYamfEBACQkAICAEhIASEgBAQAkJACAgBIXBRCCRcWNZqWdeiBFrqOVVdh44Djz%2BF3Nxs3E77OZYUsmrLuRAQAkJACGiaRqitHs2djs%2FlwGZZj03XNaLhACeOnSIpq4CMVD8OuyVDPD49SrCtlhMNXiqKUqUdjucj8Y8kAfUcRdpbCdm8%2BDxO7OgEA82E7T6Sve5zMlF6WjhAQztkJPsSrsB%2FTmURCAEhcGkI6LrxW%2BRMbSN4ksnLycJl16itPk1zawCHN4WcnGy8bmfH30SdltoaapuaidpcZObkkep3Y9PC1FWfpjEQJTM3nxS%2F9%2Fx%2Fby9N7aQUISAEPoQE3nYmiq5FqN23hCfWncbpsNFyYiNP%2FO0VIpGoZR31WM1VZyQUCqNpsZWoLzaPaDRCJBJ53%2BxfbH%2FFnhAQAkJAEdC0CCdXPcnO001dVjA3ZNEo1RtfYkd1m7Eeud06wpIAn2pnWw6%2Bwcz1B1CD3MFQuMt29AlUJEkIXPEEdE2jft8yXj9Qb%2FQR1LNRt%2B6fbDp85qy%2BioKhadFYf0JtrmG3Y7Orwc3zDF5e8QSlgkLg8iUQbjvOrOdfpDkY5uiq51mw8RBR49mNbZfecHAd%2F1x%2BmGA42lkJtQuYw%2BlEb61m%2Bv%2B%2BQm1zgDeXvcTsrdWgNfPUCwtoCgZ5n36ydPohJ0JACFyZBN52JgrqLY2u4c7Ip6y8nGhhAZHmmUzfVc9NOTUsX7uNlqiX4ROnkBc%2BxJP%2FmE5yZR%2Buue56Iid2sHHbQUgvZ8qkUaT5HMaGReFgkJqju1iz6U1svhwmXDMeZ%2BspVq9aQ6u7kPHjR5JCM%2FP3NlDQsJvDzS6mXj%2BZ4MHXeXLmOsp7DeSWGyZzZt9GNuw8QmaPEYzpX0zz8Z0cCXg4saeBqbdfjd9xZV40qZUQEAKXPwH1Iy4UbGLtsiVUt7rJDrbg0zSCzTVsW7uSg%2FUaIydMJi1ynOkL3iCcB9mpmdS%2FuYLNB8%2BQUtyPscP7Ej25mZasQRSnuqk%2BtBs9pwx7VCMcDnJyyywee%2FVNRl09gdsnj8CVYB%2F7y5%2BUeCgELg4BLRImpGlqr0Ww6URUPBSiavcOTkTaObJzD6kVQxg3uILa3Yv506wd9L1qBLeM68P%2BKjuDsttYt6eBlhO7iaR2Z3Cljw0btpPZZxxj%2B%2BQTbq3nDfU8h1MYOWEcJdkpnG%2FS2MWplVgRAh91Ajon188h2u9aKspLqCz9OM%2B%2FPIvw0AoycwrIsulk%2BYLM%2B9UWAldnsnXTIYYNH4I%2FI9v4Fw5kUpn1NA3Nk9h0OsQtdwwk1WNn3JZ5rDkwhql9PNgdMoD6Ub%2FLpP5C4J0SeNuZKFaDNpsdh9tDQXEB6w%2BeIeovYMSYcYzqX8zvfv0qwaQi0nKSmXj99eT4nGQV92LshAlclXaIJWv2qs3H1esfAnW7mLnkTUZPvYmp14whxRFk8WvTyBs0jqGlUebPXUKguY6ZzzxJUveRXFUY4vdz9%2BPM6UNSto%2BpE8eitR7ltTVHGTF2LL7jc9lysJqqg5tZuL6KydcPw%2FuOamatpZwLASEgBN47gWi4jTVPPIxWNJSJY%2FpxbP8JY%2BbI%2BnmvcCipD%2BNG9mH%2BqwsJJZcwfmA%2BY665ngHdssjtNZwJEyeSWr2IaetOcObN5ZxsDBizWU7t3sTxlmDszboOqaWDac%2BrYOrogeo3oxxCQAjEEVCDmWcObGbhjiATr72RlBPLeXldNd6S4Wh5xUwefRWh5pOs2n2K9jMHeW3RKgaMm0L6ydd4YsF%2BrpkykYNP%2FYnDDUE2L3kJvXIkowZks2jma4SiWsJZLnEuSFQICIH3SKCuto7S%2FBycTid2RzJhj41IVDdmlLXVn2b1kqWU3jkSnz2FwYP6GqXpuk4o0MSedQtZ03Ij6clR%2FG43XrcLu91JTkk2p5ta0NRvEzmEgBAQAu%2BQwNvPRLEa1HW0aISWlnryk4uI1u7k73%2F6F3tONxIJ9SBgux2P10%2BSz4OdCIfXz%2BHvL86jqS1En5tL0fXeoEdoOrCNnKGTyc9Iw6ZHCLUdZMeiN5i9aivqFVJ63wncOK4nrhF30a8sl7pQFk1b6rC5cvD5%2FXjcbrQ3V7N26QJ2vDGPSNjGNZ%2BfzBCHi6HjxpCc5LV6LedCQAgIgUtOINpaz6zd%2FfjOZwtJd2qMGlJOrRZh955trJ29koXYsHt6Mf7um%2FD5k3CkpuK06%2Bxa9jx%2Fn7WWQChKzxvGoqep8Wcd9bmCFlUzA2MdPvUJgsvtweNLwu9x43DIyPElv8hS4GVFwGa3odYf0tV%2FxowUHfXyx2ZLZ9TYwaSn%2B%2Bk%2FZgR7n98P%2FQfh9Xnx%2B3xE242uBzo28vuOJjMliVBxCkXegaRmZNOtrJZgsInt615nzfSVOJ0uyOvDxzQdjzHr5bLCIM4IgSuOgNfj4GRLC5rmx6br2MMBY92jUNNRHv7ZHxj9if%2Fgtr75eDwubLiMBzocbOeF3z1EffltfOULQ%2FE6gwRC7USjUXS7nbbmOpLSnPIZ3xV3t0iFhMClIfD2gyjmN8J6bGps86ntzFl6gns%2FM5rX%2F%2FA8U%2F%2F9If6Nw%2Fzyx%2FONxZwcNjutgQAtrYfZdjTEQ4%2F%2BkZotM5h7IjZVzmZz4C%2FtQ92idTQNKCTVCXZnNv2njuFTd3yRsgwvNi1Ka93Rtxo2mw2braMzpNmNQRxX4VDG35DLp%2B69Fr%2FTjhZu58CaDbLI4qW5b6QUISAE3oaAw5fKtRVvsv9YHYNzdTZtO0pFPweVPQZTevvNTOmTawx8qE8QDhttHLSf2MwrB8v4%2BWP3sXfBEyyL2kjJK%2BLNmgDBpEa2bN5L%2F2E3GW2jWr9B%2FUC0R6JUnTxFbkkRHvmc522uioivVALqeUgp6s%2BOZ1cxqtvN%2BIMnmL0qypQvZxA81sjOzXsYlT%2BAPes2oA%2BaisPhwBbRqa2uwutQ%2FQu1NooN4z8jQmcfJLZmip9eQ8dx1RfvZUhpOmrtIrt8y3Ol3k5Sr8uKgI2yYVNYPWsxLeW307RjJt7UQdjaTvDQ7%2Bdy3zcfpFteOi71IkG9cFDzw%2FR2Zj30U4o%2B9hU%2B1rcIn9uJFnVQ7ImwfHcVU3p5Wbo7nes%2BmYVTnuPL6mqLM0Lgw0LA8cADD%2Fzw7ZzVwmEOr1vKpk2bOdbs5aa7P0Z%2Bqp%2BcUg9vLFvGyUgGw3r2oKJfCdneMAsXrCa%2Fcgi59joWrNhISt8x9CrKIzcrxVi8zZOUR56%2FhTkzZ7H9YDUl3frSq1sBK2dPZ%2FX67bS7UynOzSBsc9OvIBWHw0bUkUqfknTSwg0sW3%2BAnleNpsRxilmz5rJt3ymyi0tIcdvwZBaRLYuhvN0lFbkQEALvMwG700PJVVexf%2FVc1u48Rd%2BRgyko7km%2FPt2p2jCfRSvWcLzBQVl5Hk49iCezgvSsHDKad7B03XYKeg2itLw7lT0HcmLtq2w%2BHmbEuOHk5ReS5neje7MpL8gg88wW1h8J0atnGW6ZjfI%2BX1Uxf7kSUAOKTn8GQ0p0Fs%2BbzfZjrdz4mfsoSnFTe%2BAIkQwXGxbORS8fz21jKvG4nGQ07Wf17jP07tsTny%2BV4kwfEWc65fmpuOwOfBll5Kd60IPtpJcNpLKyG3uWvcaSleupandSWZJnDKZcrkzELyFwpRBwJeVRlBpm7uz51Hh7ceOU4TjCzZw8socDu7axadNG9lV56FbuYu3KTRQV5rL32DGOHt7Nlk0b2fHmYcp69KJXn15Ub5zPorW7GXfz7VTkpsjuPFfKTSL1EAKXiIDH4zFKsjU2Nr7Nx4DqEx6NqJoaC9jtDmMLQDUzpHNquXojo96K2m3oapqcepdjs6F2kVAzz43ptPZYHsOI%2BixITU3XNfXqB4fdAXqUaMcS2WpF7Zi%2BKi9mh445JkpPHerNEFpMR50b5XfMmlG6cggBISAEPmgCxvap6vMCox1Ub67Vatda7JODjrYx1sbFZtqpzxnVriGd7WbHDBUtGlUNqfHP3L1H5VHNoJqaDHajrZS274O%2B4lL%2BB01AfcZj9FeMfokdPRpmz8L5nOl%2FDaPz3didjlh%2FwdihJ%2FZ5nOpzqD6GTb3BtvQfYs%2BYLfZpkJHe0XfRdKMPYsxm%2BaArLOULgY8IAeOTVvX31GbDoX4nEPv7Z%2F3ENfb3Mfb3VP0tNXcLVX8bjd8vttjOXOrnhvFbo8PORwShVFMICIGLQCA1NdWwcgGDKBehNDEhBISAEBACQkAICIFLTED98Aq2NBPxJJPkVtsYX2IHpDghIASEgBAQAkLgiiFgDqK8%2FZooV0yVpSJCQAgIASEgBITAR4mAmqnqTU37KFVZ6ioEhIAQEAJCQAi8zwRkO4f3GbCYFwJCQAgIASEgBISAEBACQkAICAEhIASuDAIyiHJlXEephRAQAkJACAgBISAEhIAQEAJCQAgIASHwPhOQz3neZ8BiXggIASEgBISAELj4BHS1nWnHv%2FdiXS2Tcq4V9s8lM5dWidcz05U%2FVpk1%2FUJl8TqmXqL0j7pM1V8OISAEhIAQuHAC6m9Uor8n5t%2BudyIzdVTpVj1r%2BoXK4nVMvUTpF17bd5cztih14jknMojy7piKlhAQAkJACAgBIfABElA7Uz33r2cIBAIYW1rF%2B6J6cufqdZkyc6XZ2JZYhgWVpKvtO0yZadfIoyIdXURTR4WdyeeSKaNxzsTbj1mJ5XsnMtOuqWPGTXsq3ZpmjVvPjTp0%2BG%2FqKj3TrpkWH5q2rflMvXiZGTdtvF35Zr53Epplq4uvkFv9UnYMuTqxcDHz6GrnJbUrZEc%2BI9tbTOLdtbplyMz7xlrPjl3WOpM6T2K%2BddqMS1dOdPpiLeidniewa5gwC1ahOsx88ekx6Vv3pcpn6piyc4WmTSU37VrPzTQztNoxyzBtmHFrHuv5%2BfxKJDPtWv2x2jPLM%2FNZ4%2BrcTDf1rbqJyjPlVj1T18x%2FLll8PhU385p%2BWe3Hp51LZpZr2lO3QlwzZaga9oyHybT01v1gpJxb1gWVtTyrnlmXt6x3NLMdnLsYiT26XZ5ti10jq%2FkcWu0ZeVSC5X436pWApWnP9Cu%2BfMPMW%2B2CtRjjuph2uwg6yomXWctQ%2Bc24qZuobCUz7Vjzm2mmrpLFp5kyMzT1zXxWnUQyU0%2BFSsfMY8at8gRZrOJ4dUPWWf67aL9jBmLX2PTLrNeF%2BGLeNxbdG268icKiItRufPGH7M4TT0TiQkAICAEhIASEwOVPQNdxulzGbJTL31nxUAh8CAl0%2FqBJ4PuHRZbA9S5JV0o9ulRKIkJACFwMAuplTfwhu%2FPEE5G4EBACQkAICAEh8OEhYLMZb4fUdFs5hIAQEAJCQAgIASFwMQmoT4Y1TUtoMvFHPgmzSqIQEAJCQAgIASEgBISAEBACQkAICAEhIAQ%2BugRkEOWje%2B2l5kJACAgBISAEhIAQODcB89vwc%2BcQiRD4wAnIbfqBXwJxQAh85AjIIMpH7pJLhYWAEBACQkAIXFkEjCm3kTCRiHb5rZHSMR1YU4vWXeCh65oxhVi7VL8OdZ1IJEIk2nXaciTYRFNTgPP6rmtEoxHCkbO%2FHb%2FA6ko2IXB%2BArpGJBwiFAqddY%2BiazQ3NxIOR85vQ6RCQAgIgYtIQAZRLiJMMSUEhIAQEAJCQAhcegK6FqV6%2Byzm7qwmGn1rsCL2PXPUGJBQ4xHm983RqEbnAIUa5IhGiWqxARgzj%2FoOOn4Mo4vM2EjhLR0li%2F2LDYCoMmL5Q1Tv20RTIBSTa0quo6swavoW01WDERHlSyTAr45p3wAAIABJREFUiUN7jYENtV2GymvaU3StfnTWw8TeOWhj%2Bh%2BzreoTq5MBosOmKl8HLcyqRdM41RYwOBj%2B6Trtu2fy6uqDhIzBqfiBndi34tFIiCOLHmP1vtMJN%2FYw3ZJQCLxbAtFwC7OffpQVq1ZT29Ju3MdqwUfjeYuGWDzzeU4H2o1nWt3j5rOsHmDjOet4tt9t%2BaInBISAEIgnIFscxxORuBAQAkJACAgBIfDhIqB%2BLKnZEGpwwvRc1wjUHmXN2k20e4u4ZvwwXOEzrF65nprmIJVDxjGgLJv22gMsWbEJ3V%2FA6ImjSNUbeWPlapptmVw9YQypHkdsU0xdJ9R00tBv9%2Bcz%2FuphtOxbCcWjyfJG2L9%2BDbkDR1B3aCdNdfUcanIx8uoxFKQ60cLNxiDI8cP7CQVq2BcpYlhqExu37aHN5mfE2HGkRWv41xOP48y%2FivFTpmAPtRk1ibQ3snXdao7Uagy5ejIlmU5OHtuLPdDClr2nKOg3iqsq8zt3smxvrmHtqlU0O3IYOWYEWa4gqw7Vk1Kzi%2BOtbkZfPZZ0d4jtK5ez%2F0yAsoHjGVKZhh4Nc3r%2FJrYcrSW35xCG9SoxfqQqJ%2FRoOwe2r2Pn0UYqB4%2BhX3kuerSN9SuWUtPmJLW5jWhx11ks5mWQUAi8JwK6xr61y9my5zg9U2oJNx9n2crd1LbrDLp6Kt0y7LFteXWN1qq9rFy7jYArg8mTx5Okt7B5zVpOBRzGM5aX7jc3uH1PLomyEBACQkBmosg9IASEgBAQAkJACFxxBELtbfzrH7MoGDqFobn1PLXyAJo7k7GTr%2BfG66fyxj9fYm9dHUue%2BDl9xlzHdVPGkGYLsPJPP8TffRTDyzV%2B%2Fb%2BLCakZJUA4UMOLP3%2BY3IHj6J9%2Bht89v5WUDBcvP%2FsqG1bM5B87nNhoY%2F4r03H3nsBNY7sx7bmXqW9tZvvcf3KitoXNS15g2ZkCJvUtJrOkL5NvvI0pI8p4du5Kokn5lKXVMPH6mylO19m4fD5trS0s%2FtsfOJk8gOsnDuH5n%2FyMw3VtbFv4HDOPpzFu0hg2Ln2RlpB6K68mlARYOetFMq%2BazNWVNma%2BOIv2lnqeeuwXRIqGMqgowsOz9hDGz8Dx13P7Lddy8F8PsuN0gHDjaTaeyWHS5GuoXzuDpYebYrN1dI0T21bw8pFMJk0Zz44lr3CssYWVf%2FkvmrIHMWFUH%2FZuP9w54HLF3UhSoQ%2BWgM1Ot%2BEjGNC3Fzdefz0FBZVMuO5GbrlmKE9873HOBMKo4btIsIVpj84id9A13HztRFJcNpY%2B%2FTdqswczbkgRT738Ok3t8snPB3sxpXQhcOUQkJkoV861lJoIASEgBISAEBACHQQikTr2H1nLtp%2B%2BicsWoaHyVu4Z4GDus8%2Bwbt8pWuvr6VX%2FKa6afDN%2FfOS%2FSek5ns%2Ff1Jen1zXhP%2FgjvC6IRosIRabgdkCw7hTzjjWy5uf%2FD69TJ%2Boei3b3nYzNX88%2FFnv5f%2F91M15HG%2FkV5VRm%2BXDbi%2BkbhcPN6lMh3RiQ0NO7MXVIAS47VL%2B5mqdfeJXjZ5qpS7mKwG1gt9twOh2oN1zqk5pIOMwGrZIv9MrF63MwdchxDpxuRMsq555RJXhcNpKdTpo1jWQcaNEqtsxfzZGVOw07ek537tWHwoiP078ojeDpbBqOHac1UMCCF%2F%2FG67tOUVdVRVpdM86UAm4cWYzX62bk6L78dPNxhpepT380Du7exME1M%2Fif5W4irVFyxt7MjLW9%2Bf5nc%2FE5dSZd3YsjstW0PHvvEwG73Y7D6cRhh2jjQZ748z%2FYX93E6bqjNLR83hhAtDt9XHNnd%2F7y2x8yt2wU3%2Fi3W1mz7xBVWx9int1OW2s59fdOJu198lHMCgEh8NEiIIMoH63rLbUVAkJACAgBIXDlEbCpKumEAi20NHtxOp3oUR8F3UYz4eabyEtx401O49DC%2F6W9z518%2B1Yb03%2F3W9Q3MDl9JvPN7wxjy7wnWH5sIFcX5dLrc1%2BmMjsZtzcJn8swjjslk775JVx3%2F%2BcoTPXh8SVjbz7AxlPZTB3ayguvH%2BCT43Opr67iZG0T2fYGDqJxk9%2FOGRvGZwQ2ux2n3WEMTMyYv43x932TrMAhfv%2FKXkPucvtpaa6luqVdrYRi%2FHDsoZ1iz9EaPFmwcV82Y6ckccThQP2wtNts2GxvTSq22TPoOaoPkyZ9ioJUL26PB7utBZvT2ZlfkarbOp0DqaP55reKWfKXB42ZNnqgiW17q0jtns627fsZ1nMgtqjdsJ9X1IsBt1zLrYML8bjcpKZ4aKo8xr4j1XiydLbtOkFq2ZV3W0mNLh8C6inU9QgbX3ycwvFf4IacVv7wvYdiDtps2O0OcgZM5pslV7Fj8QzW14apKKpk5Lhb6JefgsfjI9UTe5Yvn1qJJ0JACHxYCTgeeOCBH35YnRe%2FhYAQEAJCQAgIgY8uATVYYuuYAaHbIiybMY116zewceNmPN3GMrW%2Fn8UzX2Pdljex5fVkUM9idi2dyeZDQQb360NJ3x7Ub5nDy3OW05I2kFsnD%2BGqqweyas401mzaRbstlx7lOTjUjzSXn2FDilg0%2FRXWbX8TLakC57ElFI%2B7m6v69qR9%2FaukVPaj%2BsA2Go%2FuY%2B6aQ1xz5%2B2UZvjRAjWkVwxT3xyQV1SCz2Ejx93IglkLqHGV0b1bCf0qCshKS%2BfFF2aT2WMQmZ4oxd360Htgd7YvepnFa95k9L1foV9hMoFAA3kF3XA67ATa28kvLsPrsGN3uCkoKWX5ay%2ByZsNOgv4sehZncbINhpdlY7dpxhomI0cMpmrdHNYdaGTY0O7kVQzGaw%2BSHDzKjBkL8fW5hpsHl%2BJ0aoTtOfQd2AvnoWXMXryKw1Uheg3qR79Rg9my4GVe33SUyoHdyC3uR06qT9ac%2BOg%2Bju9jzaO0NrWQX9Kd%2FNJ8ls%2BeyZG2ZP4%2Fe%2BcBZUWRNeCv08sMOWcBI4KSQQQxAIqJYFYwo6LLyrqu2TXuGjEnTJgwIaggIiAiSRHJCEjOcRgmvtjd%2F6nuNzAg4O%2B6iri3z5l53a%2FSra9u3aq6Xa%2B7VcMGNGxxDLqTomqtWqz5Ziwff%2F4l20OH0KNtU5oeVZ9FEz9l0rezyLOrcliTGpiyY%2Bo3bCfJWgj8uQiUPsC6bK2CwaB3qeXn5%2B98BlvZCHIuBISAEBACQkAICIE%2FMgE1mSl1ohx4OV3SyVxGDx%2FOaef1xzL83ScHXi6RQAgIASEgBISAEPilBNRr1dUbv8oeOTk53uWuPaBlQ%2BVcCAgBISAEhIAQEAJC4BcQ0NDNGG2P7%2Bo9u0F%2BOPAL0ElUISAEhIAQEAIHEQF5JspB1FgiqhAQAkJACAgBIfDHJWAYIWrWbfjHFVAkEwJCQAgIASEgBH41AdmJ8qsRSgZCQAgIASEgBISAEBACQkAICAEhIASEwP8CAXGi%2FC%2B0stRRCAgBISAEhIAQEAJCQAgIASEgBISAEPjVBOTnPL8aoWQgBISAEBACQkAI%2FN4E1MPe4vE46XT69y5ayhMCQkAICAEhIAT%2B5AR0XccwDNTnnoc4UfYkItdCQAgIASEgBITAH5%2BA6%2FLcs0%2Fv1Yniuv6LB%2Ff25p79hZWt9L7ilX6v4u6Zf2nYnt%2BXzVedl8bbVx77Sq%2FSlYaVPd8z%2F9IyVNy9xSv9rvRzf%2Bn3FrZn%2Fuq6VK6y8VX%2B%2BwvbW5q9pd9bHqV57yvs5%2FJW6Urz2FvcsmHqfG9xfi6P0nCVdm95lH5X%2Bqni73moMHXsr%2FyfC%2Fu5PMqWuTdZSr8r%2Fdwzfun1vuQoDd9b%2Bp8LU2nUsS%2BGpel%2F7vP%2FU%2Fb%2B4qj8y4aXPf%2B5sFLZVBp17I3T%2FsJK06vPfcXb1%2Fdl0%2F7c%2Bf7yUGGlcpc9L5VpX2F7llk2bdnzsvHU9%2BoozfP%2FG%2Fb%2FifffzHtvMpbWqfRzT5lK67S38L3F3Vu80u9KP8umKz3fX5iKUxquPtVRKtfPhXmRy6Qvvd7bZ2neKqxs%2Fur658L2jL%2B%2F%2FPcWtzR%2FFabO9xanrBx7C1fpzjn3fGrXqbO34pFXHO8Vi3wpBISAEBACQkAICAEhIASEgBAQAkJACAgBn4C84lg0QQgIASEgBISAEBACQkAICAEhIASEgBAQAr%2BAwE9%2F4PMLEktUISAEhIAQEAJCQAgIASEgBISAEBACQkAI%2FK8QECfK%2F0pLSz2FgBAQAkJACAgBISAEhIAQEAJCQAgIgV9FQB4s%2B6vwSWIhIASEgBAQAkLgQBNwXQc7naK4uATHBd20CIZCBC0LTTsA0rkOqWQaw7LQDZ3%2FRAQ7k8YBdN3E0PeRg%2Bti23E25brUrBZBz1bWsTPYjoNmWJj7SnsAsEiRQuA%2FJWBnUiQTCVJpB8MKEo2GEdX%2BT2lKOiEgBH4tAdmJ8msJSnohIASEgBAQAkLggBJwHZe8peN4Y%2BQEvv32W775ejxvvTqGvPjv9%2Fpj5chxbJuMbeOSYuydQ9gYd8i%2B%2FOAX84lvXcrNnywjo7xC%2Bzwc4uvn8dQnszznUWm0TCrB0%2B%2BMpSij3DByCIGDm4CTSTN36hjGfTWNGTO%2BZcX6vAPjHD24MYr0QkAI%2FBcJyE6U%2FyJMyUoICAEhIASEgBA4EARc7GSa%2Bscez8lNq%2BGkCvjm5UFsyjuBGCWsWLqcuBvikEMbE9GSLF5fTMzexo6ERr0mh1IxpJG%2FZR1rNmwjULEODWpVIn%2F7ZipVrY0W38SGgiC1q%2BWQzFtJPFibdO5qNuTFiVSpz6H1KmNokCneypi3hqEd1YkOrQ4lUZxg27oVbCkupkr9Q6lZPsC2bRshWUxJpA41gwlWr1pLUovRuHE9QpbL%2BmU%2FkluSoXKdRpRPp0jE06xYNI8EQRo1aUzM0sjf6stplqtKwzrVcWyHVDqN42Qo2L6JlWu2QCBCQX7xzzhgDkQ7SZlC4JcTSG6bw9wVIc46ux3hUBArEPiPdnf98pIlhRAQAkJg7wRkJ8reuci3QkAICAEhIASEwEFEwMUloxwPiTj5m1cyfnMXKkc1po8cxkq3IpVYw0ejJ1OSt44nHriZZSVRyqdW8cA735FK5PHOiLHkVKnCjunPMH3xBuZM%2BppViSRrJg%2FhxZFfU1Kyg6%2BHPMLGdXMYPXIB1WvUpHrFMGoXjDpsN0j%2BujRVatchrLm49mJmLs6lZiWLof8YwubCBFPef4kJGwNUDcPHr77NVqsy5dNLGD5pHluXfMnr32%2Bnes1aVIwFcRyH9PgXyLcqE9g%2Bk2cmrCJVsoK3PvqaKrXrYi8fxZgZy7GzW13sdBHDho8mWqse5YoXkru98CBqPRFVCOybwNbls9iq5fLQHQP5x12DWbQhf7edV%2FtOKSFCQAgIgd%2BGgOxE%2BW24Sq5CQAgIASEgBITA70bABddm3eI5zCyKkSrcilajNoZWwqLF37JpyUZm6Q4bAvXo3r4mgaP70vaI2oR2FJEcupDi9uv58Yel5G5ej%2BamqBXdTLdDK%2FPZ96sJfluDo2vZLN%2BwmvGxi7itxiFUCU3l5ZeX0vHsfpzQNAxo3vNPwpEY0Vg5QgEXwzqSrie2opKVR2NjIcUlGbQGR3HWsfUJsZ0VW5aw9P1XPEKbYofR7ZhWVN80jFdf%2FpbuF1xKo6BBqPtAmjesQSbYmC2frWF7zo%2FUadGNKpWqUKHDuYz6%2BGuOr1Ed9Zuh1IoJ5NQ7jjqVKuLGTqbmrC9%2BN%2FpSkBD4LQloOOjR2tzy8AuEMjt4a8RHNL74ckKGJj%2Fr%2BS3BS95CQAjsk4A4UfaJRgKEgBAQAkJACAiBg4OAWkyZ1G%2FamuOaVkOz88k8dAtb8u%2Bj1qHHcFLXq2hUJYSmaSRyl6Opfbilz2rVwKjYkObtcujdsws5YQtwSResJv%2B%2B9%2BDEM7io%2BjyGfj6DLqddQPmKFTjrmpvoUbiBwTe9y%2BGDB1Ir5j881iCNXbyDdaFyZQooS1DzytW1MDUbteSUnudTu2LUXwhqGv0H3Uk8dxVPfTaJOsc1Ai1UNjGxOo3J%2B34d6WY1Kdq0iKrlKvkPndU0zGqNSM5aQzzTBPLWUVyU2C2tXAiBg5VAlYYtiS3Z4DkLMyV5xNMarrcDq7QTH6w1E7mFgBA4WAkYt9566z8PVuFFbiEgBISAEBACQkAIKALq5yx2pCa1KoTQdJ3kjsVUaNKJIxvV4tNXnuSDT8exWavCkXXLs3iDS4eja2LpGXLXORzTuSXlE4t5ecirfDFtAVUbHE6NKtWorC%2FhkGOPo26tGuQtX0nXjq0wUlv44MUnGTZ6Mof2voi2jSp7jgxN06kQ28Kbb42iRtM2BDdupGbbo4mZOiW5y6jWvAMlRVtpUK8RphmgcQ2LD4Y8x8djviIvVJt6wW28%2BuwTfDxuFh27nkXDyhZLi4Ic17AiJglW7gjSrlVrcgrnMeSVt1iaqMaFPboQs9Ksyg%2FQtnlTqmtrePGF11hWVIFy1avS%2BogGBOQVJtJBDnICZrQGtUPbGPLCi0xbVkjvcy%2BgarmgvJ3nIG9XEV8IHIwEgsGgJ7aWn5%2B%2Fv8e%2BH4x1E5mFgBAQAkJACAiB%2FyUCrovjOrho6JraFaKu%2FemNuledTqe8ZygYpuUtvNSOFLX9Q4WpB7Oq1xB7rwW2HVxNwzD81wo7jg2agY7jpVfpVN52xibjOKj8TPUKY5Wfet2wY2PbNrphobkqX8Pb1aJEUXfOvTcQa7r3KmLXsclkMl6%2Bum5gGBp2Rr2aGEzv1cyqNmqHjZJS5e1i6LvkRNcxDRNNy4YZOu7OtwNpGLrh1av0tcf%2FS%2Bogdf3zEVD903%2FzlYZpWvt%2B7fefr%2BpSIyEgBP5ABHJycjxpxInyB2oUEUUICAEhIASEgBAQAkJACAgBISAEhIAQ%2BOMRKHWiyNt5%2FnhtIxIJASEgBISAEBACQkAICAEhIASEgBAQAn9AAuJE%2BQM2iogkBISAEBACQkAICAEhIASEgBAQAkJACPzxCIgT5Y%2FXJiKREBACQkAICAEhIASEgBAQAkJACAgBIfAHJCBOlD9go4hIQkAICAEhIASEgBAQAkJACAgBISAEhMAfj4D5xxNJJBICQkAICAEhIASEwP4JqLfg3H%2FP3SQSiZ9E9N%2BEo95q89Njf2E%2Fjb37N%2FtLu7%2Bw3XMpfVPPLvnKpi17rtKVvS57vmfYnmX8mus9y%2Fk1eZVNu2e%2BZa%2FLnqs0e17vL5%2ByYXue7y%2BfPeP%2BkuvfKt%2F9ybBnmWWvy56rPPa83l%2B%2Bv1XY%2FmT4T8N%2BTtZfku%2F%2B4v43yymb1%2F7K3F9Y2TzU%2BS%2BJu2fa%2FV3vme%2Be1%2FtL%2B98K21%2BZ%2Bwv7ufL3l3Z%2FYXvmu2fcstdlz1W6stdlz%2FcM27OMn7veM6%2By8fcXVjbe3s73l3bPsLLXZc9Vvntely1rf2Fl4%2F1cPnvG%2FSXX%2F18ZrriqPw0POQTDe9Pe7iXI23l25yFXQkAICAEhIASEwEFAQE2C1MRGOVPkEAJCQAgIASEgBITAf5NAqbNF03bd9Ch9O4%2FsRPlvkpa8hIAQEAJCQAgIgd%2BFgJrUWJZFIBD4XcqTQoSAEBACQkAICIH%2FHQKpVArHcfZaYXkmyl6xyJdCQAgIASEgBISAEBACQkAICAEhIASEgBDYnYA4UXbnIVdCQAgIASEgBISAEPiPCKitv6V3rdz%2FKIdfl8h1HO%2B36L8uF0ktBISAEBACQkAI7I%2BAOFH2R0fChIAQEAJCQAgIgYOAgHJe2GQyGe8ZKeo5KcqZ4f6engzXwU7ksnj%2BajLpFIXJ9G%2Fj0HBdL9%2B91W3rkrmsKczg7C3wIGhFEVEI7I2Ack6qPl3avx3n9%2BzYe5NIvhMCQuB%2FnYA8E%2BV%2FXQOk%2FkJACAgBISAEDnICjp1hy%2FwRPDVyJbUrhzF0Az3cmHMvOIkK4d9nqmOnk8z44HU2NOlD1VUT%2BXTNoVzSqR6WZfxX6dqpXOZNW0zTju1%2Fkrdl5fH2G59w9ZVnEg1Z%2F9VyJTMhcKAI2IkNvPHAE8Sr1cGwAhzWpgedW9ZD7gQfqBaRcoWAEPh9ZhbCWQgIASEgBISAEBACvxUBF9wMtDjtQno0q4buxPnmpRtYn9uOWFWT9atXU%2ByGqV%2B%2FDkE9w8bcEvTUDgoSLrUbNKRcQKdo%2B0Y2bt1BIKcaNaqUJ168g1hOZUjmk58wqZATIl28jaSRg124hQ1bC4lUrk39GhUxDZ10OsnE3Jpc1qs6bFiM60C6JI%2B1W7YST0HV2vWonBMivn0Dqzdu98qpXt7kh4lvkFvxeI5tfhS1KkbVyyEp2pZLcSbOjh3FlKtcnWA6n835SeoecghhLUr9Iw%2FDttPk5udBvJDcQhXWiFjdttSNDKYg3Z1IyGLX%2BwR%2BK%2FCSrxD47Qlktq8lU%2FMkLunX2ddrTRcHym%2BPXUoQAkJgPwTEibsfOBIkBISAEBACQkAIHBwEXNchGS%2BmsKCALWuXMn59ByrFDL4b%2FT6L42GiiWV8%2FMV0SnJXc%2Fedt7FoawZ32w%2F8692ZJOK5fPDxFxjBEBunvMSsHzcyfexY1sSTrJ%2FyLI8Pm0C8pICpz9%2FJmtULGDnsW3IqViInGkbXlatC%2FZyogOr1q1GhzM4TwwqRU74i5UIuL78xhq15axj6wIdYsYrkxKIELZOSTd%2BjhSLEQqVvGXKY%2Fd6rvDVxJQHL4OWn72X8wjys1FpenLCEVHIDn7%2F8FoniIl5%2B4gFmrEsSzGzi8U%2Fn4qDToFIjVhY7yC8eDg69FSl%2FnkB88xrmrZjAHX8fxJ0Pv8KyLcWi3z%2BPTWIIASHwGxKQnSi%2FIVzJWggIASEgBISAEPi9CLisWzSbmUU5pAq2EDm8GaZbzLwF00iuL2GVbrM0UY6TWlTGPeQsjj2iHrGCBNveWEBJm7UsXryGRMloNBfC4S10aVieL2avJTA5SqOaSVZuWMmoTG9ur16THHMKn3w6muadzqB9LIhu6qitJ7FIGF0r3f%2FhkirczPdfT2Pl5u3kzd3Gxl4daXQYjPn0Y5q0OJETW9SjfNQkXKUaOeFdP7%2Bx05Xp3LklVctlMJJHcGzrQ6nn5rJ09loc2ySdSpNRz305oiudmzUgnIqwftR3pNwjMQ2XvMTvxVzKEQK%2FPYFoow5cc2Vr6taqTHLHEkZ8NpoGl55HwNBkt9Vvj19KEAJCYC8ExImyFyjylRAQAkJACAgBIXAwEdDQdJND23TklGbVcFN5cN9NbC16iIq1GnJYpx5UjliEYjlY8fXoloFlGGiavwjTYzVoeKhF91NaEAoGiUTCBDPl2fzvT3Hbn0i%2F6nN5f8L3dOx5DuXKRTm176XkbV7Fy%2F9%2Bm0bP%2FJVapo6mBdi4NZe07YBypGguMz8YQXGLMzithcuHyz7ENWJ0uvBSmm%2FfyqhXR%2FPjoZd7cqdTJWzfXkilSuU86LpuYhg6hq6jGyaWaaBn9Gy%2Bmi%2B3%2BkmDaWGaBlrad9yot%2FMUxFPUqajiHEztJ7IKgX0TMGM1aNIw7T1cNqWed4TjR1bPlxU93zc4CRECQuA3IyBOlN8MrWQsBISAEBACQkAI%2FB4ENF3DKleZSlrA2wmiBSLUbJJDwAzT%2FdQzeebhe1m2A1r2vIrLjq9BLBT1HRThGIdVq0ioRiva13%2BfR%2B65hVS0HlcPvJEW9etzasti0q3qU7V8DuUnv0vX%2BmHMzGbeeOIxvl2dT4uzB1E1oFZxGoaZQ2jpKlYWZqgfqULlnCCHH9%2BcJ5%2B5n69qd6Bl7YZUDBYxZsgTjJm%2FloYdL6ZJzCJ9XF9uf%2BCfrLvkTi7oXA7l1gmVCxK0fAdKjVpViRg6mmuQEw1gmDGq1KqOFbAIhy2%2FHlaQKhVzcDJ5rFy3gWNNU54Z8XsonpTxuxBIbprHcy%2B9xcJVW6h6aBeuuep8LF0chb8LfClECAiBvRLQ8vPz5T1he0UjXwoBISAEhIAQEAJ%2FZALBYNDblfFHkNG1U2ybP5rPljWgb59jD8ANcpeVXw1lut2e3p0aEyzzbJY%2FAh%2BRQQgIASEgBITAwUQglUrhONmdb1nBc3JyvDNxohxMLSmyCgEhIASEgBAQAjsJ%2FJGcKJ5QrnpNkAv6AXpuv5rseT8lkt847FQSORECQkAICAEh8B8Q2J8TRX7O8x8AlSRCQAgIASEgBISAEPgJgQPtwDhQzpufgJAvhIAQEAJCQAj8eQkcoFslf16gUjMhIASEgBAQAkJACAgBISAEhIAQEAJC4M9JQJwof852lVoJASEgBISAEBACQkAICAEhIASEgBAQAv9lAuJE%2BS8DleyEgBAQAkJACAgBISAEhIAQEAJCQAgIgT8nAXkmyp%2BzXaVWQkAICAEhIAT%2B9ASSyeQf5u08f3rYUkEhIASEgBAQAv9DBFz1oPh9HOJE2QcY%2BVoICAEhIASEgBD44xPY3yTnjy%2B9SCgEhIAQEAJCQAgcbATk5zwHW4uJvEJACAgBISAEhIAQEAJCQAgIASEgBITAASEgTpQDgl0KFQJCQAgIASEgBISAEBACQkAICAEhIAQONgLiRDnYWkzkFQJCQAgIASEgBISAEBACQkAICAEhIAQOCAFxohwQ7FKoEBACQkAICAEhIASEgBAQAkJACAgBIXCwERAnysHWYiKvEBACQkAICAEhIASEgBAQAkJACAgBIXBACIgT5YBgl0KFgBAQAkJACAgBISAEhIAQEAJCQAgIgYONgDhRDrYWE3mFgBAQAkJACAgBISAEhIAQEAJCQAgIgQNCQJwoBwS7FCoEhIAQEAJCQAgIASEgBISAEBACQkAIHGwExIlysLWYyCsEhIAQEAJCQAgIASEgBISAEBACQkAIHBAC4kQ5INilUCEgBISAEBACQkAICAEhIASEgBAQAkLgYCMgTpSDrcVEXiEgBISAEBACQkAICAEhIASEgBAQAkLggBAQJ8oBwS6FCgEhIASEgBAQAkJACAgBISAEhIAQEAIHGwFxohxsLSbyCgEhIASEgBAQAkJACAgBISAEhIAQEAIHhIA4UQ4IdilUCAgBISAEhIAQEAJCQAgIASEgBISAEDjYCIjUooUuAAAgAElEQVQT5WBrMZFXCAgBISAEhIAQEAJCQAgIASEgBISAEDggBMSJckCwS6FCQAgIASHw5yXgQjqBvnkjetL581ZTaiYEhIAQEAJCQAgIgf9BAnt3orgO%2Btp5RC9oT6x1a%2F%2BvbTuiXS4hsHo75oyRRE85ldCMlWiO62NzbLS89YT%2FejHRe99DLyzC%2FP4zYu3a%2BOlbtSLWug3RKx%2FC3JxLYNgDxNqovNsQO6kP0UdeJLA%2BH2wHnAxa4XaCn75KtFtnYm3aEB1wF8EFa9FKijEWTCB2XFtiXp6tibVpR3TgE5ibcgmMeZbo1Q9i7kiBEs21MVbPIPLvwZjFGbAzaAVbCA57mljbNn7avz1KcP4qgsMfIDLs2111SpZgTRlO5I7X0XNXEbnhNgKbSvx8Va1V%2BNdvEGvb2pdFydO2PdF%2FDcPcsoHQk7cR%2BnHHTrXSinIJPzKQ0OQlqPPQswN3pet8PtEn3sDamI%2BWSmCs%2BIpot%2BN2has6%2FuV%2BrK15BN%2B9k8io%2Bb6c6QTmoklEHhyMGbfB9SfvwXcfJHr36%2BhFqZ3l7zyxU1hfvky0%2B3kE52%2FcVR%2FXxVg7l%2BgFJxF57Sv0dHbyn0lhzvqY6IC%2FEMhNeGVoJTsIvXAv4W83omVVQIsXEPzwMcJvTkHzkrpgpwmMeMxnrfic1JPI029iFcTBdTAWfEmsQ7tdban49bkVMz%2BzUy6tOJ%2FwIw8QmrEeLV5E%2BM4LiTw7Gj2V8auUimNNeYfoU%2BPQbbwy9U0rCD%2F8D093Ysd3I%2FrMMMztca%2F99a0bCD93H7GObYi1P5no429ibi8BpcuJAoKv3%2BG3qdLNdr2JPjLE181MGmPlVKK9T%2FR1uk1bojfcRvjLeWipNErO0KPX7mozVd8OpxKesBQtnUYrzCU44iVf71spnX6Q4NzlhJ67aXcdUunaHUfk7a8JTBlG5OkR6JnShZiLvmom0f63YG0r8hl5%2FWUzkWtuILgsz9cBRcZ10EoKCEz6kGi3rMzn%2F53QtyvRCwsJjHuN6GvfZNtqp3aohJ5uBya8QPSWxzGL0tly0hiLviL6j8EYyTT61h%2BIXNKNyGuT0JLZtnAdSBQReuI6olfdhpUXR9%2F8A5EHHsXKTaAVbSZy%2FhlERn6Pls6mSZQQ%2BOApIp8sQVNiZFIYq%2BYT%2BUc%2Fn3PX04kMHY1RkPDbyKubjbFhAZG7bscqSPmy9OtH%2BOtlaGmlBC5aSR6hJ68nNGMdpFPoaxbuyrPLaUSffZfQJ8%2F7uqnsnOKuPtt1IHr3MPSUi5a%2FlvA%2FryMyZv6uNrDTWNPfINb3RgIbs3rj2uhblhG5%2FBoCW9V3DtqOrQTff5Jotw7E2rYleuujBJZvRfWT0HO3Ze1P1j526ETk4wXo8WKsGZ8TPaOTr7tnn0d49PdodraTlTaTatuiLYQfvJrIsOnoGVVnvIW7Nfq5rI4pe3QG0QeeJLh0C1oqhb5pAZHLu%2B%2Bqq6pvz0sIbCz021i1fSpO6LHrCE9Y5NtjlW%2ByhOCwx4l8sgAtkyT05F922fYL%2BhF5%2FVPM4oQvA6CVbCf06C0Ef9iQ1Z0M5rQ3if7zRYxiZZtV%2B%2Bwg9OwDhKetxfr%2BfSKPvu%2FplV%2BPJNb094n%2B6yP0dAZrwmvE2mfthGonZSduewO9JE7omRuJ3jsUoyhbvp3GXPIF0YfewUhkdSydIPDxEz%2FtZ8quDh5JYPZYonc8h1Fq81wbc%2FZoog%2B8h1EYx1j2DbH2bcr0bcXtb4S%2BGkX0lkcxS7J9RI2d6%2BYTvfA6QhNHEjn7LMITVmLNH0X01Kz8ym7cfB%2Bh6T%2F4uprMJzyw7642U%2FU7sRehWdvQlD1Xh5PBXPAJ0f6DCKzYnm0r0HN%2FJPLPvxPYWuTpHAnVr98kemInT5ej191DcNlmtKIigq%2Fc7uu3yr9U1zt0JDLsm5%2FqVyZO4JPBfhu3aUOsU2ei9z9FYNkmz5bp25YQOf80X0dL5wjnDyKwbjvmfCXn334q5z3%2FILCtyO9TN16we9rTzic0Zy6RJ17G3JH062ynCD17M5H3p6OlbHBs9K3LiF57BdY2NQ4rO1VE8L1%2FEb3%2FHQzVBt7hYk17h8hD76HHy4x%2FKn68kOAbjxBr15aYaoeBDxL8ocwYmM1BlWWs%2B57IwP4El%2BTttDta4UbCd5ybbavWxM6%2BmsiQEZi5RaDGhxWTiPbovEtPFJsb1HxEjZu%2BTdbzVhMZdCWBTarNSvu1GnvyCd%2FVf1fbqLSdT%2Ff6h15STGDCe8ROzNqLi%2FsTmvwDWjyOsfYHIoP6%2BenatiXywnDMHcUYyyYS7dFplyyqzW%2F4F%2Ba2PIIfPbqrL3Q%2Bgej9TxNYrto2219U%2FZd8TbRDdp61U2faEOt%2FH4GlS4kMurpMHVy0vLVEbnkAa11RKUX0jXO9uobmb96lY06K4Nt3E%2F3Hk5jbi%2F12VOX9%2BDXRvzzit6PC4mSwlM04ISuD0kNPjtZE734Da%2Fl3RO59GjNvVxsbi74gevezmIVFGEu%2BJHpGdg6r5pCD7iY0eT5aPAmpBMGXb9m9z7U9ichHs9BLSrBmjiF6brbc3pcR%2Fuwb9MJ8gm%2FdQ%2FjD6VA6HNspgq89QvirZWhqjFZzpUVfE73Cn7fGzr6c8FcL0UuSXv9U9jfa%2F76s%2FmYxKZuxcQHR8zr48nQ7l%2BhDz%2Fv9Nlmq0zuR%2BifpJNa4V4he%2FzBmoW9PlYIZa74nevrphKYv9%2BVRsVU%2FeuB2QjNWoxUXEHpmILHWygZ0JHrjLYQ%2F%2Fw69KDuOlSnGWDWZ6ONDMfPj%2FrfKBs0ZTfTWF9ETaYzlU4n2OX43fY32%2FCtWXjHW2JeIXnkrgc35vo6r8Wrbj0Qvuw1zc6E%2FPpYUEBz1MtHTs%2FPcgf8kOH81Wv4WQk8N3L1tWrcjPFbNszKeHTB%2BGEu0e5nxoFQvrnwYa8UPRO75J4Etirnfv%2FR184heewfWph3o%2BauJXNdj9%2FxPOm13O%2BBkCD11qzcGavFizxZGB9znzWf8PF2MZdOI%2FPURTDUPSycJjH%2BH6HHtibVqTbTPQMKjviR6dvfdba6Ss%2BcVBJfnQyaDOfszor1v8Oyit%2FZR85b8dUQu6knkw2%2FQ1Hjk9YU0wTceJzImO2Y4GYy1ao50sV%2BPU88m8s44jG35mD986fdbr41b%2BXau372YWwvQt60mfO9f%2FDSqTzz2OtbW0rG%2FTOM7NtbU94hedS%2FWpvyd441WsJLIBadn0x9HbMBNhD%2BZilGc9OxfcMg%2FiB7Xbpdtb9OWyNvTdtkVVb9NC4n2Op%2FQpIVoar2njkwxoaceJDR7vf%2BdGsPnf0n0UtUn2hDr05%2FwpIXeutL6aiix9m19rspGKqZqrn7P6xglWfuFi%2FXNB0Q7ZXVLrT3vf4bA8m2QUePIQiKXn57tB9l535kXE9isxs8XiDw%2Fyi9rxttELx1EYG3hzrmQvmkhkRtvIbBxhz%2BPSZcQHDOUaPcu2TH3DkKzl6OVHXsUz8%2BeJdpR6Ud2%2FG3ViujjowiOeZHIw%2B9g7FC20B8jjB8mEr3%2BGa89g6%2FdSazUDvc%2Bn8jz72HmFaAlE4Sef4TwxKVo8QShp27YpdO9%2B%2FrrrI153trEXDDOb5dSnVA6esWDmFt3EPjgX%2F44r9YkVw4kPHwCRl4B7DnnzKqHtm0FkQF3Ya3Zgb55EdELbvZ1xOtrLlrxeiJ33EdgfQlaMk5g%2FDCiZ6k5cBtilw4iNH4SkZsv2rUmVG2o2rh9B0JTf%2FT7rDf2DySm%2BlNpuNfWXYiMmI9eXIK5YAqR63r5ac%2B9nPD4WWglZdYISl7FfdLrRNUa08unB9FHXsbakOfppL5hDtFzOu5aA7RuTbTnQKwNu9bt2Wrv88Pca4g3EVyA%2Fv0OnJ7n4VaOgmbgBkO4JphTx2EsnI%2F%2BzHtknv0bmXKmt0gxpw3Devtz3EM2Yl7aGW3eBLSSNPa554Ol%2FDUabrXaYCcxJ32HFm6CfeoxkCpCnzGC4Kgv4ZVnSFdKE3zpHqw3p%2BB07YVTI4q2fgnWgGvRnngaZ9kMtLU2zpV9cEOGL1vFhmCXYI77FGP0IkING1NyUx8c3UbfsBDj85noF6fQYvmE7xiIMTsXp%2BuZuOUs2LQM666HsfvWwRh8K8FD3yLRrArGhoUEHn0S7eir0bcvxZj0Ps5lg6B62KuLphZ7M6ehFVfHvvB4MHVflvq1oGQ75tdf4Da5Eu3QCl7f0BKFGBPm4%2BSsQ2tiYr7zGVqjU7BbNITkdvQvXyI4aTbaU3fAwq8xVhjY%2FfrgWgYYBm61xrh2CcbXw9GrH4l%2BSiO0RZMI3Xo37nEDcA0tO9FchPXMK2jbKxHo0YVEq3qge8tTf4FsxzHHfYS%2BcCHWsE9J33sljkprpzA%2FfQvjq8W4JRPR%2B3TEMVw0tcgd%2FBjGxLVwRE%2FSV3fKTmC3YA66DmvYUFK1Qhg%2FfIX12Hs4Azuqps4a%2FwzGxClogUOwux8LdgH62JcITdqE88ZfMRZOQCuI4%2FQ%2BFzca8PnFyuMarp%2BHIqfYzJ4IFTvDYfUxxs5Az%2F%2BRUMNGxLse6k9eF81FHxOEq0%2FEWD6N8M13oOn1sc%2FsBXoGbfZwglSCM2sSHPR39B3lsbv1Ai2BPvk5whOmk3z%2BX6RjhZgfjkOrdgT2cU3BLkT%2F5i2C42bAaw%2FDounoi1M4fc7GjRpoG1di3nQ54YFPkeheDWPqXLTGHbBb1PW6lmuGcMqH0Aq3EXz8TswvFuN0PQs3x4LNK7FufxD7onY4vaqgbVyM8cF47Iv741Yrh1MtijFvCsaMiuhXnonj9VYNLANtzWcEn22Gc1NvHLeY4NB7MH7IJWOpSJpv3It3EHjrMQJPjsA9rTdO9XKQvxnzlptxn3kcbc4M9Bnb0S5uh1vWnaoWK9tWErjtQfR1Flbn7mS6Hu47JFfMRZ85DSN5Dc6PUzDHzcFdOhir6zGkapUHWw1Qi7CGjEQraowxsBg3vQh95CT03pejRVdgzJoGS24j2OB1kkdXh0wJxtzJGOk6aD0aY3z7MaE7H0Yr3xT77D6QyUd%2F507CBQYlA7riePVzPJtgjP0e56o07prJmF%2BMw11cTOCDISTrlIdkAcbn49Eq9MWomUv42uvRco7E7nUOaBm01XOgcSvsc85D274O472PcTueiXN0fdwq1UCzMad%2BiPnqpzCuBKPZ0zi1Y56TzvxiKPr4xQTuqIk9%2BAbsqIm2fQ3Gt9NxtpWgs4nQg4MwvirGOe1UnPIB2LSUwEOv4N5zHsbE99EadsduXg8MHQwTp3oAY8ZHhG59ErdtD5yOUcjE0WfMRzv5WL9%2FlxpstWCbPwHz%2BVFQJRfzuNdI1SmHlk5hjv8KTa%2BB3asTOCXoi8YR6DsR7dXnsPMXYkzdhHtOH5ycoK%2Bjsaq4Sm%2B8Put6ThJj1GzQV6MdfyiuMrFKjrlTMLQGaKdUw5j0LVq9ttjH1oGiLehvP0joy3nEn7sZO2p5nV%2FbPBfji%2B9IH3o6jlqUvzYEfWoQq08f7CPKe841861PcZpejPHjVIwZAfTkmdhBy1tA6Qvnog8vQbvhNMyJE9HsSthnd4Kg0nHdbyO3CGP8FIz5Ywk1OIz4ea1wdAd99Wz00WvQruoDqpq6gVu1EU7vPlC4EfPN93FO7YvToCpuvaroK6agfzcPPXU1thqrXBd98Rz04evRL%2B0GS6ehb96G3fcq3LA%2FbLqxHJyIhTnjHYJDmmJfdwokthN86SH07WHS1Q7DbVLRm3wZM8ei55bHPusECGhoaxZjXX8l%2Bj2vkWifwZg1CY69AKdhZd9WB0K4Uc0bN7xGUmPmhA%2FRP%2FuSYKoczjN3kIlYaDvWYIyejdMngRZNExzyANbL43HO7I1TPoi2fCaBiy5Gv%2Fvf2HWb4%2FTJQdu8AGPYHJyLeuHUrIRTt1zW1pYqF2ipIszPX0GreCR259be2Kov%2FoLg5V%2BhPf8cTnI2xrxNuGeejVMx7KcP1cQ1HMwJH6B%2FNpFgJgfnqVuzcq725HT7JLCDyzEnzMU98RycWuX8sSRUAdc00L78AKvZCWS6NEIrWoc5%2FGO0SD5G9%2BZkwgbGd5%2Bhz1jjp1FttP4HAve9jFZcEavzcdgd63u6py%2BcjPFtHD19Bk444A9GmRJCTwzA%2Bnw7TvezcSMBKNiGvmoLHFFzV%2BXVmXLMD30K46MJGCXHkn76SpygiZa3CXPEAty23XAOrwUFW9HfvJvQzKUkHrgGfcHX6Ks1nD69cSOmNwa61Q736razf21fjzHme9xLS6BqxLfX6n%2FxJozvxqEd1Rv7yGq%2BHhhBnLCDqeYG93%2BAc8KZuJWCULIDfeEKtCYhQoP6o3EUzjnngptGW7UcvTADCyajrzZwevfCjVj%2BsFD1cM8mGF%2B8jla5KfbxLcCJoy8aQ%2FDyyWgvPEvysCqgabjh8jh9zkVLxTE%2BeBtqtMfueATk1IeidRhjZuJeFs%2FWAbSCNehTR2H0uYx0nRg4aaz3h2AM%2FwJjwxGkXxiAXSHo69ZbIzDmFxEsXxv7r2fgBnW0tQswvv0UPTkAO%2BT3Mad8LZyzzkPLXYv50oe4PS%2FEblgVt1FltE2LMD76Ev3iS6Gi38bGivnos%2BejFZ%2BPMX8S%2BnoTp9fZ3nxC2%2Fgj1sCr0e8cQuKkKhhTvkGr0RK7fcOsDQ54umwsGEXwhkehQzecluUgWYy%2BdDF6%2B0YYX89ED9dG69ne75tOMcbsyei5zdFa18b8%2BnVCdz2P2%2B4MnN4VIHcl5l8uRL%2F2fuJ9T0HbuhR98hvo2%2FpDJdVv1Fit7NU89Nl5OOdfhBvW0BZ%2FQaDPh%2Bh3PUjyjFY4ag6483DRirYSePwljHn5BE4%2BA%2Ft0Zac19B%2BnoS%2Bahz7oTtyhT5JsUtVrX%2BP7KVCzG9ohAYwxs9BqHYPd4VAo2Ij5z%2F4YHc8ncfsAMhXUXF8V5KIv%2Fwb9sxXo5%2FWEnLDvBFoxE33qAvRUX%2FQfpvi6ftpZuLEQaDpurAquqWGN%2BRz9i1kEzNrY%2F7ocW9mivLXoM4ZjbBuAEygi%2BORNmCPX43TvinN8CLatxnrsRbj9AszhE9Ead8Ru3tCXR60%2FKkVBV3NscCOVcE49F60oH%2BP5V6DNadgtG%2BFWrYFWuBpjxETcngOhshqLQN%2B6An2eaqdrcQIrMcYuw%2B1zPo6qr5obh8rhhP3x0EugnHpTZ0GiLdqxlTGHj8L4fDHBnAbYd56LE7LQNizC%2BH40Rt5F6N%2B8R%2FC2t3HO6okTC0BJPvrijTjdTkfLL0T75mOMVTWwe7bGrVALN6KjpUuwXnoeY%2FIctI8uInNxC5ywhb71R4yFs9Dm3E6w4VCSzWvikkSfNxU9Ug%2Ft%2BEMwFowk9Ld%2FQ%2BPjcHqe4zkh9JFPEiz%2FEHbReIwdJWQuvAAsy2Pmlq8CmQJC9%2FTHWFPdnwORQdu2FqPAIV3Fq%2FXOf1piK9aQZ9EnbSZwYlcy57TBNXWMTXMx5m7EPa0HTuUI2vb1mP%2B6EWPuzZQM6o752Qz0Kkdht26SHac1nGo5uFp2guk6mEu%2FQZ83Df32B3HefJZUvRxIF2LM%2BBSt%2FAmkDq%2BMNe4FgvcN9edjvaKQuxxzYF%2F06%2B4n3awGtrJLiVyMN9%2FBbXs2zhF1cBs0wC1d56gbwtM%2BRNei2GecBkEX%2FduPCH4zH%2FftwbByDsb3ebjde%2BBUivmMQhX9Os79Ev2Hehi9W2OOHYrx%2BWx0o7o%2Fz4uF0JQuzfwOfWsRWkWN4JM3Y70xBadbb5xqYbS1izD7Xw1Dh5E4vOrOPm5O%2BRad2jhntcQNWd4Y5tauhFMxgTVuMKEKVYirdWThckKD7kQ7uj9QjDFtBlq1ZtitG%2FtroZFPeDduE4Ovwpg1Ea3wCLQWORhTZqHVa%2BOvPZIF6J%2B9SmjSNBKD70Ob%2Bzl6URq7T69dOlFZjddgTvgGLdwY%2B%2BRmEN%2BG8cythEcdT%2FK%2B20jXrpy1B6WqoZx869FnfoSx4TJvLasvHIue9xe0KuVwNbxxW%2F%2FiC4yeV8K8dwnc8TGcdArOcTEo3oGxagt2sw5QvQXazE%2FQld%2Bkx8m45WM45WN%2BQZqOU6ctdp%2F6aKqtPh6P2%2FsKnOrlcSqHMMe%2FQuDhYdD8eJze7WH7Ssy%2F9ydyxb3E%2B56AUy47J1H9%2BEu1IaAi9pnHg55Cn%2FAWwdlLcJ%2B8A23ZDPTFav3ZEzcU9GyBm1MFV81B%2F5%2BHP1LtLbJtQ6Q89sVXkGxc1Tc0yoC5aYxUGjQLZn2C%2BcOFZFrXRkuVYI0YAxVywFU7PpSHUYOqdUgPuN6bAHnXqlMXbAXdwj2mO%2FFBF3qDrb50GpE%2BN2EuWItbfj7WO3Oxn3yPxPGH4Sq3f6IYoyiJGwli%2FuhCsCGpa24gU87wDatpQOEmbxFHlXpow54k2PoYEp3q%2BbLYjrfDw5zzAcb0DaSff5PkMXXwtlGouy%2BqvnYJ4c%2BmYf37KeyH%2B2M%2B%2Bzia1YbktafiJud5g4Q%2FwGSBKc%2Bb0po6bUhd%2FxdsS%2FM7o6mjb1rs57nzTpMal9TODLXTJvvnGjgnXUD80naeY8lYMpnQwH9i%2FphHRsWpcjjpq68nrZxUir1abBVtAbWrIVmMMW8CgbtvheYDSF53rl9%2BKoU1%2Fl20RF3cRoWYH03CaHbhzkmJJ7lre3eFtFAUpn2JteFCknXCaEWbMMdPgspqMaxkVPJm0DbPxphbgNuqOfp7r2P2aU26SpRUz6sxP72UwNPv4fZvS%2BCRwdD6UpKnNvewePVVd5xtF%2FfwE0hedxGuW4I5pQrBm8eil1zvM6pYjfSV13h5egOaYfqTzlK9VLsbvPZRu1PUn4abo2PcfzfWkc%2BRrmL68mZsNHXH%2Bd2X0IzGJJ9%2FlHTVHOWOhJS6W6URePMu9E1RUq89Q6p%2BRU%2F3tO3nEOl3CdZ7X5Hp2ww0E6ftmSQGnYXrpNBXdyFy2Y2Yi7ZjZ1yo0pj0tTeSrmxCSSGhuwZgDP8S%2FYQ%2B%2FmL4hJ7E%2B7X3jY9avGk21vShmBOXkHloCInjGvv9KZkA3fQcZF6%2FmjuO8OjpZC6%2FllQjtfgqIbhM1V151%2F07KgqJU%2F0IkjcNJHTTQwSPqk%2B62jqspydiP%2FQ%2B6drZSZCdwVgxjcDrn%2BHcP5R4j2O8yQ0pdZdXh1QJwUwGUqW31Ephq90MKYy5k9A2V8I9PIwxYgxG58bYlpvVXXU3yPXuSGNEPKNvTV9J%2BuxmuOkE1vg30DKKu4rnoCkdUn9Kp211Z005grZg3f84mRfuxg6qfFX%2Fs727sYGXXoS6vYg%2Fdh22MoZ2Gi0%2B0BsQPQeKElXhUPHV3b9SWYI5oK8i8PC72Pf1w%2FbKVnew1e6AH9DWZci8%2BHeSR9fynQYqG8OAk8FYM4%2FwhMk4Z11C%2FMxjfP1NFxEaMR4at4Yt32NNX0ymV0tcVXgqg1upEtqctwl9fgLxM5p5k2FPJsfG%2FOpDjKlx0i%2B%2FQvKoGqCclJk0qA0j6U0E1CKlUx%2BSfdvimGrk0b0BPPjcExBsQvLG68hULe%2F3eeV89pzQpW3kev3fGjMaaneA4gWYX84jfVF7XwYVv1FHEoNuxNUc9A3zCF99Keb363EaOhCuSuby60nWDPoD%2FE%2F6m7uT6069U7ZLtZ%2FadqY%2BMXC69CJ%2BaQdwkpjffkTousGYWwdgR8vjBmJkunYn9MZ3GIXdcJ1c9Fmb0VJgTF%2BE1vBYzymjRRqQaVoZbbnt3c3zbFvaALWzK5325VBlq502tVqSvPZanKiSO2sPM7meiG6F8uj%2Fvg3ryNdINa3m2y6lGyqtOgyLdLseZFp3Rdu8hOgno7HPu4JEh4aqQbBGT%2FbaR%2B3W0QKqjqr8TJaDn48bzSF95bWk1SLWs8cGZBJw1TkE77%2BVYLvGOGtGYo5eT%2BbZoTjhFVCuNek2NdA%2FtaHuUaQH3EBGTbILthG%2B5xqMz6eitW7lOY%2BdM%2FqS6NLQd5Ypu2Eqx1ap89sfM7ScarjzPiP4zsnY%2FRR7f0zRMhmMH6dgDZuI%2FcDrxLse6etc4WZCj12D%2BeoHZF66h3gXDWPBCMIjt5Hpdz3JIyrhqrqUTj53qpjipsExJ5H86%2BWeY0rLXUbkkoswZ68idWgGjGqkL7mGVCPV1xVj01%2BwqV2pSs7ZowgOOxG77y45PXug%2BjrlcC64hvjRFfyyVdpUMfph5TEmf4%2FWqQHGovFoG1y00GLMzXHsWibmtBlwVA%2FsckF%2Fd87UUWDUwG2Ywfz4M%2FT2%2FT3Hv2dPlByl7a988uk45idzcE%2B7hcS1p%2BHEwl7Z3gS%2FFLOqh1rUFmzw%2BhQt28A3r2FtOo9k3fK%2B7hsBnDP7Eu9xtO9QndGQ0FVjMLf2w1XjZuXDSF95HenKSk8B08JVY7eXtzLgasdCdnzdZdazfRfPuZc4o5HfLso%2B2QlCH06F%2Bm1JDroeWy1oVb66jr5yAtqKOPbDN5Bod4jnYPcDbSxVjpLlqgG7yUJim9%2B2LbuSvPES%2F0bJth%2BJXHQRxtw1aE0qe7bIqduM%2BMCmHrfI9xPQWp5J4oZTPYeHvmK63ydVf1HzQeVo9fqrb%2FNVp1ROIfOLGXBMW5j%2FJtbyc7CPrevVU%2B0scqtVQR%2FxFKGTWpNoXh2tdJwvbTPdxD7yROKHdcLYMB9j6Oc4va4m3qmu54g0v3vH2%2FmhHMde2couezZW7chVfIGqh5C6fiCZqAHxHdk%2B9zVax7M8U%2Ba2O53E9V38%2BYbqB2QIDH0WrfLhJAcNJF055vcj3fB2qardA2rXgSoTR%2FPsVGmZWsEGAkPexj3lJkr%2B0cd3XGUSWO1fIHj30wQ6tCSttuiq8VyNTWr6WKoUqs7hCmSuvo5U1RgkdhAc9iDWE49iHzOE1CEVfP1R%2F71daWPRtzi4retgvDEU%2FeR7sJXTTtVf9eXk91jPDyNz%2FzXYpm87PFvh2W4d5%2FiexAd28%2Byc0XMcoYEPExx3CnbP5jvHGjVmo3aYpjM%2BXzV2q7mnYqAkV7peqTbpK%2Fv78yxPJ03PkRpQu0HLVUD7%2BnmCE1sT73Gs3yZe3W2M78dhfryKzCMvkjiuCQSULU1540F%2B%2FMIAACAASURBVKOWvwLLNXFOPIfEBe18e6jsvWn6fULdK6zfivj1x6IVbyb65nu4J5xL4rKOuBEDY%2BVET05%2FLEn77aR0M8vd6396FPuia0g2zPFvUu60t6WYs2OO6qeqnmkbt1JVtNFPEDy1A4k2df1%2BrGyZsr3T50DtE0lc199fCKr%2BrtpB6VQmTfDJReiB5iSv749dIeKtaYyl4zBmr8Ht3grtlWcxejyNo%2BYwSk7XwQ1vxbp%2FMJmX78GO%2BfMYZde0ZCGBl15Fa3Qe8cHXYceUI1bZFF8W6zMHt2JN0v2vJRMN%2BTLoOtr2uejz1mP%2F7X4SJx2Gq5zLiquScTf752LMHYsx38U9rg762yMxTz6adNWoP3%2FTa5Duey2pw6tAOk5wyE1YH3%2BKfsPJXvs5bbqTGNAdN6wWomqu5ztySsmqdsEOQ%2BE8AoNfIfPgdd48xWsXtau6aAPWkPdxT%2F87JX89E1c5t%2BwEgVZPE7h3MNr7b5IYeDKUbCQ6fgzOGRf681t1c8Xrw6qk7Dyl7uGk%2B%2FcnEwtidD6EcP8XMEpsbKXD0epkLr6aZOOso8DTAU3NbNDU3NJrW2VDq8LMtwiNP4V4tyO9OYXmzVczGPPHYL05G3vwOyTaNfYX35kkxrbtOGodtRNstr8c0oHENVfgqPFLHaZypmTQLl1K8Ml%2FEqz3MIwfjF6uGYm%2Fn4kT9dctbpvTSPzlVNyAhjFvFOELb8dc28vrm6X6ouY6bueexC%2FvCJaGMWc04WsfxdyQj%2BONBbVJ97%2BGjNIXxckbW1T%2FcHCbdSX%2Bl3MhoMaU7whd%2Fw%2BCw2diX3Myjuqbu%2BmHsie2P59XdkvlXWqzPfSqrmo%2Bn8Kc9Cla61NJXNeXTLUKXh%2F25DRNNNcm8OY6ApkUqf7XkalRwXe2eXMRk9SZ53vlmLNGEp64kMwlV5NsWhMSW4n0GQYnX0v8L2fi5ES8eFbLZwjeczdWl49IHVbLG8OUGnhtVTs7dwyZmM2qEHroY8%2Bf4HEpV42MsmEVon6aUlvgt9DP%2Ft%2B3E0UlVY6LMSMI16ziAXcatyLVXN2x0XErtcZtvAVj9FT0ZmfB9h89D6VzwWloXyzwC1YDWd5WAh%2BOwAqrRgthtz%2BZtLeuVQumIrQdO3DdFObi%2BRCO4lQPY3w3G%2Bq1JtnxcBwtTWDJQvSCNG64EpkGVXxjnF5OYOSHWKqjmkHs9l1IK50NBHE7XYBdYTTmYw9iNX8S12tg9TOXOMaXn8Dx55NuWX%2FXxMZSdzHU%2BBkkefvthPv1IzRoBaxcTvqFf3uLe31LDAKV%2FbtLZTVKKdOyBQSGD%2Fd3ogQjpDt18dZKfqb7%2Ba%2F4FBd4DNQdZ3P2dLR4PZxaMVjiwPqVWCM%2BxFR3kawgdovjSFVVSmujrZxG8IYx0GAAJTf3w1Z3A1VnTJRgDvsa5%2FS%2Fkm63neAdb2L264F9ROXdBVELp7Zn45ZMx%2FxiHqlLWmDOG4e%2BsQr2%2Ba3QZ6he43rOseAnr0HjHqRu60zgstuw5qz1diY41ZuQeOYBwuddT2heAygKknzkQuyc0O5lqa2cC2YR%2BiiMm9yIPuJV6PwXnJip5l5QuANr5MeYFUJghXBadiHZpGJ2grF7Vl5vNoM4V9yM9uldBJ76COcfPf1IiqfatTJ3Ps4Fr5Gu7nuWvUBlyFMFGDMX4nYbQLpeJdyAUn8Tt3IDMqcfjfXdVAy7qadfagsnO3agOWnMOd9CYW2cOuVwlQNPTaIK8r0%2BoX7mZazaAC3UjiE1YGbQZ0wgHN3oLYDcKnVJH3ckxpQv4OhTSHdoki1XFZ31uioBM86uxYzadaQGYc%2B%2FUdZ6ZVmYITJtzyZz3kTMf9%2BBUWEDnH4niR5NfUeJiuZk0BfOgApNSPU4Fid7Z09NRNShObu2QGdz9T9UWyXysMaOgVOvJ3khBAd8gLXmMpyGagfW7odb9XCcM2qjvz8K46TDcFIbsYaMwbn4KrQPR%2B0eWV2pQTsQwv77rej%2FvI%2FQsK7EL2zqx1OLlx3LMZbkkRl8MXb5CPr29VjLN%2FqL9kaH%2FzS%2FMt%2B4VY%2FCvusCjDvuJ%2FB5MxIn1tgZ6tZqjFu%2BCPOKfujXXkPmhA6k6tcAtWtC17Ls1YRCsTc8fsaaaRizcrH%2F9SJMuAlj7BiMU5uTKXVSt%2B5Guq2Fdd9ArEPfzX6v%2BmfGuyvgNu1B6rDquKGsfVE6qBDkq7Z10GZ9STCy3rMbbqQyqW4n4BzRErY9RmjAndj9ziLdpo3vTFEOrFK7o3YKbZqPMX4Rzm1v4cy9BfOLkRg9W2KrDqX6QTru21Zs9MVz0daXx25YGZelULAd85P30dUOQ93AadKSZItGu3RnJ7X9nCibmoijFRfjkkbLz%2FVslLpb5R2GRabpibjb78ZYnourz0CLH459bkW0zydinNkE8%2BtZuId0IhOzsFTdNq0g8OG7WNFodnficnDrZIVwYdscQiNG%2BndxAuXIdD7Zt%2FmGhXvOANxFgwk89QrOo4P2Lriuqw3v2UmjmuCqHX46rnKEK2uTuwHrw2GYoRC4KfQp6udMalBRh4uyCdbIEZg5ATADvp1qXJH06VdgfjcB6283QXIBTt%2BnvUWha9XCHtzB2%2BUVVM6QVAKU3bAtz2mnr1iB26NJ1uFsY3w9htD2mr5MNRqT7NwCp6xzQ%2Bnm0aeQ6RbCfOxGgsd%2FRsY3Ev5iaO5kqH406VOa4qoJpapWhZqk%2Bg3C6PsAxvpi0keVz9bfnzy7ikG2ybIV3fWh2jjp65H6naS5YDpaXghbjcHaMshsxBrzEUYNNaBrOE07kDxMOUVM3GbdyJxsYj4xiODxo8konSx7ODvQxw0n%2FGMlz046dZuSatOITPeOmM99iRk%2FDePzj6FLH%2BzCKZiTl5LuXg597gKcq%2B%2FGDeho%2BauxPv0ELn6IVINZBJ4ah7W1H8nqZe4ol5ap7l6bYewTq2K%2Bcx%2Fh%2FJVkzuhO%2BshG3qKnrC9DOW3N6e%2BiFTcl%2FehfMW%2B8CGvcItJ92%2Fi5qQl0SRFaXh6oXZ2Tv4VG9f3dZorZ%2BlVYIz%2FErKAWN2C3PZHkIVX9xXipPPv6VA7faWMJJZXjVe0%2BbUiqQ1PsFi0xh79KaJCBfV530i2Owa5UDqfiobjVLMzb%2F0rksktId%2BxMpq66k%2BYZAn8O4cni7561251Iqlp20qv6r6qDatu5U9Dyo7j11YIiO%2BaoTyWDk%2B0zqv%2Boa6WTKkqiBGP0h4QX%2BLuntM2L0IqUg0yNPw7W9PfQtzQk%2FdzfMe%2B5CnPcTPSmtbLjuo579gCcgs8xr7sPc8SDu0%2FES%2FmUyuA5obKLUiWD8kAoGTLrsEZ9gFGtnJdCm%2F2dN48rTa4WsFq%2B2rptej9l1Jcuwz3pWlCOazXWzfmK0PA8MA3cnGqku7THProdDL6X4EV%2Fx7zuXNLtjyVTRTkxlNfDQVsxldB7WedfOh99xQaoa6NvnIe%2BPEr636fjlMsuXi2TdKdzsGqpnTerSDfbKdneT0on8OWrkuzVH%2FODSzDnrCB1SIud8bWSXKy3X4DOV5A6oxyBG57AWvc3nEZZR0v5SqTvGIB162BCHTpRcpqyobtpuGcDfCetSeaYrmS6f4L1yZfopx6FXTofViVuWo018gPMyuX8mxnfLfazKs1ux2asj5WuK7ti4Bx9HEm1i0o58lv2wm65FfP2fxM4%2FDkyanexOtTPuGfO8pwOqRYNvRuj3velc5MStYMrhf7d54QCG%2FzxOVKLVNcO2Gq3sjqyeuEtBNX5Tt1UNl6VkYvx%2BXuEFyr7gjdfVjc%2B%2FEONXcUYnw0nVKM8WCZu3aYk2x7h7TbLRtr9Q9m0E%2Fth15yLedWdmGOf9J0rKpauYx9TH%2FPdN4nc7pDpdTrpY5t6%2FdOzw2o%2B4TlU1DxD9R91E6sY68MX0eqeRPLmXgR7X4Y1fw2ZKv4cx7UsnJtvR7%2FrDkLvn0XJBUf4%2FUPdlCxYhb5YzUsuwC4X851ASg6FxvbndVrBNgLDR2Kp3XZqfdT6BFLV6%2BE0qopx7%2FWE11xG5oQupBvUwPGcMGWq66Sw3v0I99hupK5uTmDALZizLiZ9ylF%2BJLXbragALd%2BC4s0YM9dCjZOyY5WLPnMK4Y8S%2FhhUriqpLp34P%2FbOAkyOKmvYb1n39LhlZjJxIRBChAR320DwYAsssEiCuwYJ7h5kcQjO4hosyCKLLe6WBIgnk8xMxrqrq%2Bp%2Fzq2ezESX5fv2Z%2FPt6edJuqZL7r1vXTn33HPOzYrFv2mw8ggLEv0IztoD5%2FQJpHbeidbhycXls6d%2FhP1zGf5V2xIW5MfzKlwyW%2B6Od9PjON%2FMIBpYhSVcjRIottTvUKB0KsvsaSQeexovP8J%2B%2FH4QC3OZi0rfUT8f97nHsY21hUXYfzjpEbKo0ukji1vrbI%2B%2FnoN3xmF4qz9BYNzF48m588E70G04aVGgpFzcH77GWdgKTiF%2BZYf8GT8xgm8%2BIe%2FxJ4hkIcjLx99mJH5ZkszuR%2BLM%2FB5vzF5QNYL0%2FeeSLSskisSVKjfnaG4iytpYC%2BeZRaF4%2FtIpr3JdazNWQz2RHeJ%2B%2FCYUFBKWxfMxq34uiceewsuXtPMI1tucTLd4jGpvT1EiSbDa%2BmQP2orE3S9h77cFYXlnK7hO6f2zQytBdv2tcMbfQ97Js8juvyv%2BumsSlBQbJbjIYmaek1PoGLm78zPNuxXRP1ZImrbjODjzv8aqS5LdaRPCkqJY8YGLv%2B3uJMWla0od9KvO1Ztc1zfn41h2tFuwH7kPuu9oLGSN6LOoDvepR3AKis04EA7eiPSa3U1b7ZydFR2vXInS1Ig9%2BRWQya2TwO7RiD%2FwT3EjKC4nu9c6eHe%2FjDd7K6yX74bVxQzVxZ2cG4Rlsr9gDvbzT5nMyTPI1uBv19eYy9ovXknBu7caUy5rfjPhmOvw%2B1fiveUTOSK8yorQVBInH4D98Vyi0mrsGx4glOe2zcR%2B%2FtnYTcjNw4pqyW7bw6zokZdP%2BsgLSR0%2BlsQFD%2BDvmMuPdEBtrZBMLj2kxHxcj6D7CDLHHkHyhJsJx99GZoQ8M0uULCLKq8hpVzvhDLOw6BOc56QjB5JFULUGYf%2F2a9pHm%2Fa%2F2%2FsS0XSnccSf%2F%2B4CY%2F5ntYQE424g0z0f95sQWr%2FHfmFSPOAnU1h%2BMf4Og%2BLOe%2FJzMHgwfPUq3g%2F7E67Tg8j3cX%2BcjP2thX%2FBxmTL6kik7sZ99m0yA3Za0h1AKmhxFcG6I3CeuRNn94F49z9OtOEOBJXTsGVgEuuBuim4d75FeMq9%2BL17Ye%2FUHffBp3E26k%2B2KI9s783wDxhJ4tp%2F4N%2F9ML64dORwxyXOCR5z38eeJD6EaVgYwM%2Ff5OK1RNBQhy3lEaVGMg9rQQn023rFwr2s4lcPIH36paSOuYjkwB4EslogH7Gyycr7EvPS%2BKf2%2F2VV0pL3VVhIJOVb%2FLGRVWZZ%2FUYsTbJt2PefR8Gz14DfgjWvnvCkG8n0yMf9LsT66W0Su29Hwo5g3mzotxXpsX8g8uYZKw4%2BfBtn0ffx08sGEA7sh5VOG438kukuzsC%2FfBAVlJE%2B8Fzsdw%2FEbliXtrP2JBRLqPaPmUjLsr%2B9VFnbL1jBtygAvn4L5815ZG8aRbZ%2FBm%2F1ibgPvkLmlFHL3pQoINxiJ%2BzJl%2BN9shtZ6z2sBTVktl6LxOPPLXu9%2BcUi7LsR2csPJ3n2eST6XBavqEtT8ZshkwdiWpdN4z55Hd55D5i4LdG%2BFxFc8mcC486xnEfLyuUamxIcPZLENZeQqD1rsewYdB1K6x33kHjicdw7LyV5eSuJQcNJ33YnmW6xAN7xxLhtJh74C%2FRdF39ILVHJgaSOuwbvswPJDs8pJBNFBDvti%2FPhuySuvg2O3Cj3CLG%2BEku%2BnCDd8eCOoyDAEveYhm9jATBVjDt8PTKb7k3r7d1IPPIIzlmH4QTFRCOPpPXKw2NrMnnFEgfpxb8iVhyZDboS9DkI96nxeB8fQTC83Ai79tu3k%2F%2BHJ80KjjV3IeHup5FeswvW12JFMx9r8ks4qVgIsdeqJ7NWLyI3J6BKLiUdGZSX%2BHT6O%2FSx7zqbgifFbD8D81sIx15KtrowNwmzoKgbYT8X9433sDKPw%2Faj8XfMI%2Fn2fbgzRmF%2F%2FwvhGHEZzNXbWdOwJ70Yr0rKRHX6j0AnJYqYwj%2F3TLzansiHwjXwt5R3ZxGV1dJ25o2kjjiB5K2DyKy91KR9iXIs5w9pL3WzsZ97Ied6GsEv30OwTnyxEVCasF9%2BDmSCartYdYVYvUcSFpTTdvIE8rfbGWutP5Heb%2FPYNFTmaXJ3TrDlkxfI2%2Bkt4ybGggWw1g607S3uFFPi1cd3X8GZWhQr8moH4qw3lLBwqVXCRIrsdodgffg%2B3rjriE5bNzepkffaFPcxnRUvgjYhQlMG0itQnC4Hh%2FlJ%2Bv%2FHJ5B6ZaLpE625dYQHXEhmcA32D%2BLyMh%2Fr1RdwCkVpYWHPdcj23SbudiWf2x%2BE9dEHeOOuJzp1RKf6JCtVTVhvvIRTEitm7f4zyQ4%2FgmDNLYjansH76ifsl6YTnHQWQYNH4slJeFXdsBtXI71%2BD8PVe%2FdZ7GlV%2BOcMwi%2Foilf0KN6j75M5fOPllEhWRPNpO%2F0BEkOfwnv4Ebx9b8Kr6Utw5tW07LrO4vHGrp%2BOd%2BVjRNudht%2BzN9F%2Bo0hcfzPO9oMJpR5kWnDPGkvB5SnjtmvVp8n%2B5Rn80iSeWBq0%2FYj98vNxPcHGohq%2F56aERhGwnKx1%2Fklkmw9ewZkVW%2FdEtatjD18Lf%2FujiSrWIPHwg7hH7Y%2BXX0VwwBm0HrczrX%2B5meRjj%2BBOHE%2FeuVmidUeTvmZ8vFJo8vICJEU4sbGsGvxRA%2BKx%2FZErSb10m%2BlPrHl1hIdcRmZQdYdJfOd8LX0sHMRV8O1XsT7LWdy0zINFokQROase7%2FL7YIuj8Xv2IDpwVxIXPYi755b4tfHDZFEss9dx5H06huSdT%2BMPb5%2FkLp3Yiv6WyYXUwRdxZKFJPtO%2FgtTg%2BFja9DdvktxxFEkJljZvDqw5ivSewwkT8Qqs9em7OMFPpg%2BmqAfRWiNIj9iD1ok1JB5%2BAOe0sTheMdFOh9J2%2Bh%2FjBSxxO3omG%2FdzYRvWtAVEm8qCkx8rkkUJu1j4ELlQ5GcPWtqM9UmcuV%2Fxv5NP5CZjaxDpSHJ9sv3dezh%2Fz5K9fAP8NUtx17gS7%2F438E%2FbPu4LxMp79ZFkTv6exCXjSAy7KbZ8WlGSIgvl5YPEcFi620xPw578IshipfD86Xuw%2BnY8SeT7FyfH523HuI%2BlV9sxttBOFpEZ%2FSfsDw8hcc1fiI4QS0m5VcbHLJEZH1cwQRNLwM%2FexambGnNOlhIOXYugd8WvU0ZK%2F%2FK3l3FkQU%2F6w7pp0Dm%2BTNiE%2FcYrWMbNzSLqPgV7UL8VK1GEkVdE5tDxOK9tT%2FKOx8muE8cHjMTKcedTiLqsReKhJ3GP2Q8vUUVwyNm0Hr0DYadhNQYXmRiL7gs%2FEe57BNkea%2BBuXYPzxEs46%2FaJEYn7Urd1yVx%2FAsmjTyQ58JZcrDeZFqXBTxKl8lYg20XQWIf94rPxyr%2FtYDWX4u%2B3GW1X3krisUfwHr2c5JXnk1hjc%2FwJV5Fes2Zxu7frvsL54DvCE04j270b7qAy3CefxtlCXLpF%2FviGxMGj8cTlYUEdVunqZO7fL2fdG8K0D7AnzTQKWBKluKutTXb1siXfm%2B2SHbIjwelfkzh1LN6tV%2BWUUtK%2FZuLF8GSuXzHQpB2liGTclXbUUQNXfjTnp3jMlsWdGfOguBK7KYz7cX8u9t9ewZLxy7Kw11hAZsjBuTra6bFOkuzeR%2BC8%2BxqJCffj79U9bieix5X4So64w1pYTT%2BROGMs9rs%2FYdke1r2v0LrFgLj%2ByuOkzxRroBda4vmw9At91iU7rIrIyyc7ZDhu3svQsx9hVWH8PqQ9ypjw10vIf%2BVmMxdl1nyiAy7G71GB7cj4kvvIIuQNp1Jwf8q4FVuNLuFZN%2BLXlMhSMdTPi1nIwonrYbWV4e%2BRWxhof4Z8y%2Fwqv8hY3sWx%2BNo7n84XmYbc%2BYclj81pC3%2B7E4iKB5F4%2FK%2B4R%2B%2BHl19BcNA42k7YkyCxotWbJR%2B1zF9%2BG1aYT5QQF9XFpY%2FlJhkGlo6LIv3N%2FB%2BwJ4nVqg3zZAH8a5zWbCziNi6I%2BzBxaXekD4vI9Nu9Qzm5TAaW%2FGHlSpTqHmRuuJX0gOqcABRrxMxw5eYRDNsa54nn8P76EtZzbxMcdTtB8mUWP9RNEA0YRut9D%2BbceeIXZC2cC4kU4UaHkDl9lFlFs5%2B%2FB%2B%2Fpe3D%2FvAFhz2qsurdx6n0yNWvS9MKX2DO%2BI3%2FsEfFgIM8t3YrWifeSLc69CNE218%2BMSydWFl1Wo%2B3Eg0kdeTmetWlc6cW%2FeOBwuOsD3IUHkGk3t13MRBqqS7D6WlBcSji4N6E0PjHbTBYSDR0Wx%2B1YfD1GoxetexAt948jWNxZRthzviXKt7AWLOq4WswVxfRJBll5%2BWJRsd9pZHZZ22im3Qduxnl%2BEu7ojWNN4%2Brb0zbxOvzi3EBjyjgLvATRzofTdvGfcK87Hu%2Fc8YTXXolflcW7bQJW3VcktlmLhDRaJ0FU8CzuIdvGZugduYFkimCz7XAfO4Ok%2BN19Mp%2FgipFE399hrpIAt%2B57k7Bm1OEcuwOFx5rxj6jyF9wv9iIrpvCieFp3baLqOYQDOzrijmRkNcsj3PZYWq46gFAs4X%2F6nIJt%2F4j33uHGqpleq9N260R8idkheZZuoVPb6HhWx5FoJYMhm5E55AUSt16INbwnWL3BKyHsUos9%2BS3sbQcQFLQ3VIvIySOsrcV5%2FzXsgzciEDM1UaxIfIm%2FfUJUu09sTSJxTHbel8yBW8dBTh%2B5CffFZ3APGGk031HVOmSvHkdQYsPsb0iePwHvtW%2FIblMO%2BUWEx15I88HtE2px42gh2X8tuONr3LltBN0LOgryW4%2BM%2F3EF4YA%2BWD%2BvSVZWxzt%2FZOWkth%2FMeh%2F352ayq8VCeedLlndsLJmefhRr6td42w7CtHXRg%2F18H%2B5Bmy7nFpuo%2B2CCoUW4jz%2BJlfcx7HA4YXX%2Bkh3c0nc6SfxN9sTZ%2BnXcyy4n6rUIqi2i0u5E1Y3Yb30Cg7YmfdjVZA64gMRjZ5B4P7fKufSzOv%2BdLCQz%2Blic98fgXXw1zA9ioUTa9WrDaD11bTjhTLyPXyN5xFF4L8kK87qdnxCb%2FzXOxHnyC6yf3iS1xr1xvcwrwHn4eexhokiWj0VY1p22Uy8kdcgRJG6cFwd7thzCPpU4z%2F8dp3EfEzcjd0PHl5ckPPQCWg7aCFnoNZ%2FcgJBdb1vkn3VOHYnn7iFx9k14P%2F2RYIBYAIC1aB7u0%2B9gfTCFvAG940ZpeTj3PYW95n5x3zF8NOlzDwI7wp78MN5fJ%2BHN3pfAcqBa4hPcS1u3nMVY54FIFBKyqldmYTfFgdOMVCFCbXMrVOeUkyLkbbAL%2Fqi1iFIpov4DyfbttlgQk%2FJEyXyymw8jef19uC1fEVx4HtkBDl7tDXgP3QuL%2BpFep39HWx%2F%2BB9ruugi%2FJN8EkE7ccyGJm3JBDWXVYq19aLl7HGH7aqS82fS8HDvxoV2LzNE7kjznEhLN67FkoJ%2F4shX%2BL4LF6iNou%2Fde%2FEKJyeKTfOgyEpfnxhRZQayoJX37vWQq2hnkOikxvRY%2F9x5lsMaQOCbM8vqvNTfDH3%2BYqQ%2FWD2%2FjXX0nifdn0yp6GlkZOn0CrX%2Fo35HtJd5LLuci4BR1oe30i8jfeU%2B8O2fGyl%2FbJewzFKZNwp3ZQra3WLmJItzH%2BWgyVtSX0FiMrJDAsidkHB25J5lDdzUuifabE009cmePJpQgSoXDyEy4m3T%2FXN8i%2BfUXxeP%2FEvncC%2B%2BuGZ0mMTKe9iR76URah5XG%2FUSurJbbi2BwFe7td8H8YrJDVyNoWkjiijNx76wgWm1LshL%2FImjFe%2Fx5rCn%2FILHRIOMeZ6zI5t6Ms58olpYj5EmeCqtJ7zmW9B5jcOZMIXnxqTj334W7%2FdpkjfVGGMc1mTYH65ojKLg29yLdPLz3vyW9VmiUMcHh4%2FG37G%2BU7N5143Gen4yzlQjMDgwYSdvtV%2BNX5ixilvcel6Ud%2F%2BIlCE66lpbRUg9k7OoYC%2F0tRuNvviv2ZXUk7rwQ74mH8A7ajnSfobSeNASOPxv3q7fIO%2FpEvBc%2FIVthwYBtabv9qiXyIi4Q4noVjdqHzCE7mlVL%2B%2FXb8R59FvfgXQjEzWl59bdznqVM%2BV3wL7%2BVtjXjOBj2T2%2BT%2F6cTjdBvT3sPW4IQf3gyBbedHL%2BPVCHe5I%2Fw9x8aT1Qsi7DHYNLnnEneEVfh%2FTKgQ5neOa0VHtuQP5z0hIk5l7KIxLNXkrwlZwktC0V9R%2BBfdiZhysGa9i7eVbfjvT%2BT7FZiXe0RHjKO5hO2zrkPd7DOrr8N2fW2xrq4icST15K4bBLe3qPAThBueSTN1x5m4gmQWUj%2BSftjey5hVS%2Bi5HScf0zFqh0Y94UysZn1Jdb8VoK%2BNUTWwhWWZokTYYgjcZjmWvj9u3W8jzCN9%2BIzWHN%2Bwfvj5njyHqSuv38dzv4b56q9RZTIJ7v7MTiv7U3i1OtgQVM8cVwikfgPq3EGzsefEm0wMmfB1OmiPlsYt%2BhM92KzqJF46iLyrvm8Iz%2F91yZ9%2Bw1kqtst9qTjz8bWdTKWlNbQNm48qQNPIXH7ojgwLDZhrxrcJ%2F6OO3csgSzSLl3f3CKCAy%2BmZf%2BNYs6SpV%2FdjkTh0Zvs5XfRulapmbwbl4Cjr8kVzIKCGvyrbqetXymRyIG%2F5iP1taIPbVddTuqgS3F%2F6W3ceiXvssjqb7En%2FuZ7Yi%2BaR%2BIuUWxdi7f7xqR7dXLFknTEuvnvT2BNnY59%2Bl4UnpF7h4WtuH%2FeFb807ruMcmaz%2FXF2mIR7yQSi5HwQQ%2BnCrkQ1LdhvfYw1dJvcSnynAohs2HMN2ibegy9WJu2LFHJJqj9tR4yj7fDTcH%2F4gORpJ%2BL%2B9Q0yZ%2Bwex%2FqKsnhP3mgUg%2B6YURhbaWlHVR7eFJHXpf%2FrRfb87%2F1fcwAAIABJREFUc8j2KTfxxRLnnIP72N9Jn%2FIHM38K9zmRlmN2WBw7bIXvzU2S2esE3OdGk7jmXpjdINNdohpxZZwWuxbWrh6%2Ff2lH07%2FAqs8S9KrK1a9OZV7R4fCtaL3mfLJlBca9MH%2FMKBKTviQ9wIfqtchccxNtObkqfoS4LC9dGS2ighraLrqB1B%2FH4KaHQlvGtO%2Bwfw94aDJOQxt%2BTX%2Ban3gfe95U8iUOqLiCdf6IDLHpwbRcezhhu7xu0opMwObk5XcQHXAEPP8QySvuJxx%2FAKEI4MJ%2F2A5kdl%2FfLC5GfdfAX60HUdiwZLsRuXPfk8nsNhScCOfhK3GfeBBnZ3EXtoj6DKbtzon4RQWxMkH6Db9jM4D2rIqlm%2Fu3N2GdnYy3wJKJiAVOzt1M6pUs0MgcqlkC68dzN6t1EbR6Zi4lMSH9rXbF33o09iVzSTx6Cd6Eh3D33uE3z4PCyt5EBdNxvv0FVhfLXZnHgf3Ll1iZiKhHeaykWlwg28iOzXefalx47bpvSf3pQLw3f8CvjaDb6mYx1a8Qq5Z4TrhsHWh%2F2LLfi%2FUdy54Sc81W7GnTcMSkSF625xFVtkcgsolKehBsOJjEleOIKoaQ3WQNon9M7niUaK5bFuH88EMcAFbOpMSiQxZFHOjWE3%2FIsNg%2FsKgN76FTsGdlyKy%2FM9HdT5IceyrWuIPJludhf%2FcPrEUtsVZZnptZgP3j9ziyUie9mDw31anS2g7Z9XfDP%2BpDEhc9TtR9E6M08LcbizdxLxLHXwBH7UlQGOFM%2FQp3aivpIw4iECKmDS3VkCKPcLMNiJa2FJYV08a52D%2F8AK6oJm0oKiMsqCJYb0O8884h2Ws8frlL4vmJWK02wdpiMtYaa866r44%2FZCgRAWFRI3mHXYMzvZFAzEabpYw%2F4BTKirGUsSAuo2StW3eCihqCYy%2FDPvRQkuddh3XMJjivzsf%2F67u0bdrTTK7sGR%2BROuo4vNe%2Fwx89eIn2IFpdmXhkN%2B6BN%2BYgoo3%2FTHZILfaP0qmH0Dgb97kXiY6eSPOp2xrh3mqYTWrsgbjPvo69Xq8lFy6WQra4IkhZ6mZhf%2Fctdls9zlfvxu4rYu4sQZBbm7CnTsGpzwVaS%2BQTdhefthU9MH6yxF3I7H06znsH4z79N6LBfc1glv3jTiRPu4686%2FLIbDuC0G7Fk0BWZRvi77oH7pjxpC7vSnq3zYjsFrzJ9%2BN%2B1Ezm9h0JxW1CJojVfeO6GWVxqg7C3fN03OmNZMX0v6SEYM0hZCpdrEFr4Lz8LI4EBN58yziuwszpON%2F%2FEHcq0nFW1pDdel%2FcRw8mccxZcNKfyVa4ON9%2FivfdItKHHUg2tYKyRgHMn4Hz9pvxCr0oR3qtTtCtfDHe5R44HsHa2xAMvwdvv8PhguPxexSYQLiJd74iu%2Bc%2BsbJgwTSct940oVkiJ4GVbMX94GeCq5%2BjZa%2Fhpr5IBOvUnkeReOsH%2FMJObSyXcFRQjr%2FPLjgHXoDj9iH7%2BChC57PlZqvzj3Jf%2BoTzsb%2FcF%2BfVeUT7ikVQL%2Fydtydx4zjyU2eTXn81SNfjfDwF7JzbT%2BeHLHOcmygdfQr5ex%2BGNSdjlCgS88R79VOyQ4bFA8PCBqx5FpGshC%2BN3s8YU3QrM4K2D27G7ypxWTJ4L9xE8tpJePP36EhVAmD1XJvM0XuTd8r1YIlZs4u%2Fw764Dx1J3llXYB28kwms50z7Au9bh%2FQ%2BI8xEgznTcb77DssEpLagvBr767%2FhTg%2FwB%2FYlsrKwYCFYOa27pJrN4H38FPbcXmTefoF031jx6L52G3nnT8KbuYvYBJi%2BOTtkqLHysGts3EmTcX6cR1AmLm8tWFN%2FxGkRxZv060nCrrVE4vJl%2Bvk8srtvQvLGieQN6YY%2FoBzn%2FSdxXltEcNfa8eRA6vXaG5IZtXGssZd%2Br7MFhORV6uDwzYjqb8Fq7Up2UDeiYpdgo2HYlz8Be44j6CIdak45Ju%2FBCBWykCkTms4vRvrDeWYssWRVVNLLKyQ0w1Fuwuwm8UdKsLUv8G55gqjvbh3v6VcdtafZ%2Ft3pJhEUZAVkyg84C3IrZNJPda0xriXxlZ3z2%2Bne9sOicoK1huAX52H174nz9mScNz%2FGGi6TxwBr1s8430cxX5nkVnUjLFpKOSrPErP5mkFkLjqK5JFXYjkSnNglWGcU4ZCH8A49kejcI8iWJnA%2BfY3keQ8SHnkF2RoZeJdSLphdpaaReP0rsqO2jeO1tBdDhPHK7mQHDzXjotWnBHfS7jjfzSGsFh%2F8JhPE1Alz1kduHlGXwo7mJPnsOpjMRUeQPOpqLFfGpNwnaMP65UecArFclAWFBFF1DWEij%2Bxma%2BMecjn84XSCmiKizEDC2macDxaQvewCo3R0pr6L89lMsvf%2BjdZN%2B5k6ZE99l%2Fw%2FHkfik1mEIsDWz8d%2B7x3cvETsoldeTeLdV4hq18TvUYnV1mhcSclfLRd3QXahqsd7%2FmnY7ESarzmcUGJpBG2kzt4N5%2FnncfptGbu49BuAP2QIURQSHrU3qePfwq6PY0WZoJJTfsRZkFspSxYSdq3qmKyJK4qU%2F5P3ceuL4%2BclS6Emjntgzf4J53vRAcqijgclpTifiKCeIjOwb2zJtLDeWDhYdT%2BSmvwN2f6rEZYVYc2dC2JwJC5x8q4lwKXkZWEiHo9SxUTF8UQhquwZv1vPwup9Iu5zu%2BP8OBerb1lOgdP%2Bslb2bS2zGm5lW0g8eRcMO4yWm04gkAlDtpXkDcfgvfgw7u45twDJoe2RXWdH%2FL2fI3HDyyaGycpSW%2F65Tu11iT5DOJTEba7AhYF9saXNvfsZ1qZbxDLOnJlmrDbCs5HdShFlkDslxB80gMgLQRbCxOUjZZwO4yy091XtbUUU6pWDyO64EYmz9yfPvhZ%2FtUqsOd%2BQvGIc1qAD8Uf0hl%2B%2BNn24%2FfH7OHNLYkuBonJs2X1KYrtM%2FRH35zTOt%2B%2BTuOgvRHuOwx9UvbjYsruP%2B8o%2FCK56hlaJQSZFb5hG%2Fg674b39FX5ZbjcfmfAXdyV9ziXk77Y%2F1jyJN5Jr%2B9LXzJ2B8%2BVnWHNmkrzjEux5PcjssSnhMqvDiwuYGyc7%2FS25am3GnjYVp0FiscVjSdS1S0csIsshWG0TMsftSPLkm3M%2BJzbZTXfBu%2B0ZEmdfCEfsY%2BIh2D9%2FTuKLVvwdhhhFgzXvF5zvv4vbgUwCK2tygWDbF8YWY1nBQa5eLF0n5GqJs%2FbzVJwo5w4g%2FW11V0IJkLvSj0V2re3x938O75pnsIprzSJc4rWncOqS%2BGv0IiKDtbAOZDHOuIwv%2BUC7%2FpfY6vvoG2g5esfcpg7N5B%2B4J%2B6kN8nu1j7HwsQWazv7BvL33g3ng1lEa0REqRqyO%2B9A4qrTyS%2FzSY%2FoG%2Fdb770Dw3YiDCRmWlssU4srsfQjiRRRYUhy0msEvQcQVJVjzZmN1ZKBIoklFytyJFC5d%2FUbhGfdS%2Bve68cBdFvnkX%2FYPrgPvUmwawBWMcGAtfAHVhEFA7F2eZbEC29gZ7eK3ZTnz8L54fvY7VbYF1cSSHy3peUDSbKwK20TriS12yHY05uIQmlHg8luO4LEuWPIs6%2FA71OGNfsrkpefhTXiEPyh4h2wVD1cEnHHX83S%2F%2F2A46Wxp36N%2Fd1CotE5C2GRg6QOWPVxrDc7QdSta04Z0PGI9qOg23Ayx%2B1GcvwdWLbECXXJbvJHvKrHSB5xFtaJB5CtLjJBoq36RcuWV2SIxvk4U37AMgtBERSUQzSb5EUTYK2xtB69H9bWvUgdcQV56wyndZvaeOF2rXXxt9sudsuXsktftdRQbgbe7n3xBw81rlQu%2B%2BK%2BdR3O%2FKZYv5FpNXXCFQsmeRfJAqLyWPkpAdOdb7%2BChvkkH7kJ%2Bx8%2B%2Fk07EpiNW6S9pPE%2B%2FMxY2DrvvIaVWY2wsoywKo%2BwSx7eLXcSHrIbYaKNxM0XYa0%2BgqBnAYnX7sZJ98TvKQvsGahbhJWf1%2BFu3A73X%2FiOSvoR%2FGEI7g0Xksfx%2BANrsRZOJXnZ%2BbDanvj9a5ZULIpyRwLmTvkR22%2FB%2Fv597J8zhGKlJtUo04b901ScBfkxFwnqX1OTC0j%2FzzO2fCWKCE%2BllSaSrTvuKFzRzsjqZDKP7DX3mASiQtHOFeKP3A33rjfgwOPJVhdgl9QQFUgcgCRRWTXUzyJxyAHxSpEMmtU9ydxwHVFZBVGRaIljJYikF9WmjIlO0HUNWm%2B4m7yLjyVx%2BEEkxMwmkoj3R%2BGP6IP1SRdI%2FUTysAPixiT5LR5C5qaziSoriKyyeGBPFpPZ81ScN2RbMOmAk4R5A2i9%2BVbyzr%2BQ5KFi7iaCSjHBsWfFnZk07PxiopICIhFgc23Vav4B55abCNfenGx%2Fsz5PJBYhFZUw92nyDvp7TFsm4AO2p%2B36U8jsNw6r7VK8Y8fiSTnzqshefRuZNWtMgNioezGRCW4nJtvxqnZUVRCbslV1JWp5lMRhOXZSxm4jyFx7NlF1L6LS2Pc8rOhB2zUXk3fSqXgvJaFya3zxzzNmihFh7RCym29gYjSwqyhRpLxJouou0Fhqyurvsh%2FuM98S7L1HHJ%2BgtJSo0sVunoU9qwL%2FkpGL%2FSYjryv%2BkbuRuP8bHDGsSQr7Cqgsze2U1LnSSVqyK0YVvPEIqUOejAOfRSnCE68mPbwHTlN3E%2FAtcfQYErLyJtfn5ZN56GkyNbmdCxKFcXnF79YrgPIyyJfgSE68snjKOOzvjoeB%2FY2pv7%2FlQUQ3VJI87WryHgpMZxbZXcnePJrs4LVovTOPvGPPJu%2FZ28xKPVE5%2Fs0Pkl6nm4mpEtUWYxUX5bS1DmFpLbIri7g7yEAedZkVTziNb3aSqEdXoqk2kQioJQXYD19K%2FjO5yY%2FrER54GS0HDKft6r%2BQd%2BF5JA77Mwkxrw5ShEedSWjM0kLjZkSRKBlzmjwnSdCrH96MiSSO%2B3hxXQ93PYnWc%2FYjlPx0KSFqrVxGkJVONizpRtsFd5B3zXi8E8bgyYpLaBPudiRhWQlWj94w9wHyjnkjfmkS3HGrzYmKN8DfcR0iCUom%2FWfPoWTHbIH7wedYO5URlZQY001xr6NLqTErzQ7dmWDDp7CDdcisVkzUWERUUQYygcmvMccihBpG5X3ioGaOQ1jRm%2FRpx5M68goi0a47Lpn9x0FpJYkrzyZ1o0zsIygZgn%2FNdgTtuxSYNl9uBgHxRV2cF1lNlgllvw1Iy%2BTttImEXUuJvAz2e4%2BSd8OE2Gw%2FDIj2PoW2kWuYjtMEWRY3LwlkG2Vw3n6V6JCTyPYqi5UEkUzudsV77EWcH5sIu4j7nJgWO4j%2Fsj9qDM7n3%2BI%2B%2B63xhw%2Bq16P1ntvJO%2BNokkc8aeqqBOMOTryaqKCAqLo79iOXkPeU9DFxOwn3G092cAvOzZfgNubmu0ExwfniSlYcXyduNO%2B9TrTLaPwBlYsnZsGGOxCu%2FjjO1EbCqjLIlsUTRxlrZceEXhLTKQ%2FKRPm2APe4g3CN8gaiom5kb55ImwQIlf5OzJP3OAs7fQ3eecfhGk1%2FNcElV9O6tqwCtZh%2BlrJSM7mI%2B%2FDO7T53bNuE1WsS7Lw5zvQNyFbmE3ngb7Y97r3vEWy%2FBYHkQUL1VnYhKg3jPMvtwlX6oR4S7EtMm7vApNfIG%2FNebHpv%2BpVNaLtPFPjlIH624rrmlJE%2B9FSc1z%2FG6tsP2oWA9uwJ67w8otIyosJkrt1IWmVQKruCtbvPiDVOOVFtJo5pIxHbrYDEUQfH%2FZTkuqCYzF0Pk%2BldiqwaRrWlUB7noz058y11VcpXFtcV028lJf5XLXY2jyghbaUK%2B7pTSP2lXZGVIDj9Tlp36B%2FnUUz0u1SaYMaxH7FLZouxOHt%2FhPt2I2FFirC4jNYLbiHvsrNJHCn5lAiMKcITrqRt361z7iQhUXE5Ue%2FyeGc6qXpT3sG94QlYb6tYiSJlk75FdtKTnZvM%2BC%2F1qIKoqta4XUZlNUTFC%2FBOOxRPzssn2Qv%2FluuXzKdjk9nyMJw%2FfoT7TrPJZ0Q5UZWPc87h5LdPMrwKgmvvpnV4OcGwkUQ97yfaYxsjNEZ5NWQP2QX7tjqyGw8y%2FYHz%2BRtEg3Yjs1E%2FIvGbl2WI%2FuuR3X1NnI9%2FIBgwCBa8R%2BL44%2BL6IvVp%2BJ8I15yLe%2B3NeLKKJgsFXUeQuex4gpzC3hYf%2F2%2BaCU7%2FE6GsTJnrUmTGHkfeSc9iZ0YRST8hQehyliKR9AVi1ZrwjCKIpsdIHHkgCSPbQNR1PdLGGiReDImKuxB1dXEuH0fKTCxE8VuOf9t1RBU12LeeRurunAJGxo9jriMoqMO55ibyW2WlTGIe1ZC96gr8igR5L08k76o5cTnTPtGoY0nvNBTri8%2Bg6cml8rI%2BmRvPJOrSDSrEgkRku%2FZ329X0dcu4nEpbKyk37cOsasuENlUE5aVEElPKCPVAXjFRUTWR04r73nSCoy4hkB0bpM8OE%2Fh7HYz7%2Bk049RB2K8XKrYhGrrhfX4LzzSzsGb1zAnbnSZK02QKifmVEZcmOSXVJNVF5BeR2y5IqKDtmRfLcfJE%2Fy6F8UexmIIt2Xj5RdS0054OXIiorxX5hAqk3blrcB0e7nIm%2FaRvO3ZfhzpUHirIwQXDmFWR6lpGsLgYvZz0lCYosJX2PtPu8PNJHjcfKvxL3nGNwpX7IOPOHo2k7cX%2ByxUns0p4mX%2B7Fp%2BMabmLJuQXZcZuKbwDesYfimeCwpYSnTaBt9CbxRMY0MHCmfAKl6%2BGPHEQoijKpxnmrkT1oU9xvv8H6QwVRYbe4z5JYHX3XJ33BISTPfNj0oZH0fYVF2M9cR%2F5kz7j4RRvsSvq8I%2BOg9IsnuiKP1hBVN%2BTkEVFwO0QFpUSlsquHWOZVEDVMwztybNwHSL0o64V%2F3x1EEo%2BuUZRE4jrg4O96HO6HH%2BO8mDG7cAS1NbTcdw%2BpM44kcexrJGSMCULCIy4hlH64awL7vktIPRK7Whh55tBLaTlgkw5LPWEi%2FVTvIiIJemrasMxLpJ%2Bq7KibYt0gi6zCS5QkiSLID3BOP5yU6e8torxigsvvoHV9sWjOlbWkDCpLiMT9v6oolkHNWO2SHnMu9te%2F4HxbTlhUgNUyF%2BfCG%2BOxUhZWC2oJLr6erMTqkZhrIitVVRpXUWv6NKzGavxdNo2Dwsozozz8vUeSeO4L7LydobgnmB1GZBOFHmROP4q8YyYQ9eth5lYyt5CNPxKXn0VK6rYEB%2B25Of7IUsLGKqKmOSTG5MYAKb9s8HH9JVgfPkfy6mtiecT3iYbtTfrPGxOawPViQf89SLD3kcOIRAZ2baJEV7K7bIr35N9h%2Fz%2FE713GTsPOJepWSSRetbLILgHeX7qF1Gt3xUoEmdeMOoHmM%2FeI05S8lHQxQXrb5dygdgMyJ%2BxL8pIXCXt2NbzTp1yEVXwR7hlH5pj6RNsfS%2Btx%2B5JtX1iQ9IqLiWQxdnG9zTUUSbeyO9GU10geOlaiXptNFKKdz6BtuwEwczpROBv31MNxRf6Wpp7flezd9xvrqUj6FtmNtryGqCW3MYBt4%2B96LM4%2FvsN9b55R6IklcuvN95E67ygSJxyeG3Ndot2Px19b6lL7BFLkiTL47mnyxryQm%2FdCtMZeBJvNxSpZl%2FSZ%2BxDI7jTr70HmzB9JTLgVZ%2BPzwczHKo2cuYSsJX2PnBP5R%2Fo2qa8ic5s%2B3SEqqzJzdHGND0uqYeGLJMaOybGyiLr2I3PrjUTFZTDpflJjHjZWrdEam5C57TQyA3I7xBk4Id6EC3C%2BnWFiuoXjribbrYgoWULrg%2FeROuVYkkdNihVQQ3cgfdlRxjo%2BETTjXDkOd5GYs0vg40L8K6%2BPA53LOxM5rLRl2TAZudco%2FCIxHiiqye0AJn1ugraTridZcSHexSfjygAmIRy2OoS2Mw4kKOtUH0QGlYC2v7way44meHVIdPBptG3a31jck56Dd4TM0WM5JqrohX%2Bb7PC5nAWs9nx1%2BrYaGhqW1mfFIDItOAtkL%2FPcyrNUBtmGs6ICWhqxgyRBaSp2d1gwn6ikymzPZcm5poCwvMgEN7QXLDJa6cWJyOphcQpLArO5hXGUfVGp%2BWmcBQuJSrvE0YDFH7utGXvmbCw%2FIqroQlguQq5ldtmx63IBd0xhxEqj0ExeZBthS5Qi7Q0t62M3LsSS%2FFbkJgny7KZGnDmzISsa7loC2ebKbA8rPnltOHUNhCJkiJBnhBYfZ%2BEiwsryuPOQdNvzuLDTPuuiISwoIhQljGgeRSM8dxZWWxhruovz4%2FslAOmCuVBUZbS9ZqKYTuM0NpuOIYzSOHUibeTelvDPKzCRiK2WhbkytmvS0tgN9VhOHviypVhJh7lbrqzmfZXldm6RwJSLFmJZhQSFCbPC6syaS9i1u1mJsJqasMVlOOViNywi7NKlo8xiVdLagt3iE4oQJX2E1JX6NqOZNB1rpwom7CSwm90U%2B4%2BaTkVcuUrjqOiWWKEIPzETlI%2Fwk6CNVRWxsCS%2F%2BRlTPlJlxh3ImTvXCJtx1OjYh9Kur8PKq4xXvaQ%2BZdLmvdtz62JBp2u3eKcXya88TzTUc%2BYZ4U60jkGpbHMWm7%2FLs8SX0wSHEy1m6Jv92kXoioI0dnM2rotyvZgZNizAooBQtq2TgFvNsgNO7iMCaGk5oQT4knfR2owzc4ZsCGI66KBSFEPSeGWlO409ZyFhrQgp8bOtdAu2tENZXTCPlAG5nEAUHBL%2Fpakhbotlshrcnminb0lT6uCsGVitPhR3IaiKA%2B6Ku5a9QFw22vMqij7Z9cImrCjt4C%2FvcFEDdtYjTIbYi9KEXSqIsq25915qVmTthXVYsqWctKUcs1A6dQly29BsFDey05YjsRWqq2NtsfA17a3OKF1liz%2BjNhet%2BcL52HWNRjgPqysJ8%2BPdNExu2%2B9b2EhYWUkUtC1ZByXP6VZMva7tkduqW565AKuhCfKLCWtrCJM5Ran0P3ULzWRBVuPsxvngiUVZTskhiZp6uBAKy8zKj%2FhlBiW5LRKFs%2FR9C7OE3aS9xLvxSP12Zs0GX3Z16kpQXkwkLjaL6rGa0h2rHlLvpZ7IeC4BG%2BfPg7ZszKSybLGyRIRye9ECY50iwtvidx742PULjXWGCSobJgna64Sck5XrAkk7xJZgkn57xyLCT5KwXNLopFMXvukWnLp5WA2t8SpgmUyIZAeWALtuPhSW5%2FquTvVt6UPh0rzIKAtM8Gupo%2Ba5jUaR3v6%2BrdZ67BaLoCynhJDVUlnlbI4IuhTH9byxOTb3lzSEVzLfbE9ombxUmPHH9KOyzfaCOVhOaTxGmclue8bECiCLM2seYVV1PMGTaPyyjan0YSJ8S7uW9tjchN0SEpYVEAUZnPkLY3et3KMiCYJdkVOySUDQutmQkrYuPoudGqOMA1K%2BVifuZ0T4DLLYElQ8TBEUuXG9lPbZ%2FhGLs%2FKKDr5Sn8WqIC3PiAVzY0a7aAH2otAoztrfjfTPzqwZufpTRSgK7nb%2FYXmv2TacBc1x%2Fy1KLGl%2F9U1mbDeTasnD8uqZbBc4f74RusyuT1LfZAW9%2FSPuqbKylW1efj7FF72LLHBEOLJS29YpBoa4nZZL%2Fy71K2vqvwjb5m95FyILNPmE0geLDCA825xY6MwpKyTPVtNCbOmLvQBbVgNlxwr5yPgprpYp1wQFtyUmTSQuj7UEhTIBy61ui7wg50rKc8ptuVmYZXDqFpnx125oICqR%2BiZCVmwSLcEEQ6m7spub9KntcpPcbuppSaywkL%2Fl3UtfKeWXuiFPkbpUUoiYQi87fogSOB5b7Pnz48lAl1pCCTwoOj%2Fpx%2BfPz%2FVrpQRi9SLbMWfTi%2FPSXhvFxU5kE2OFY%2BWbCaDJwOJ3W04osQ7abzDFD83zkS2PZRwTVOICO0fakKz6iXJI%2BkeR4RqN%2FGJ2YCytjlfizURCGGZx6haYdk%2F9HMiv6GgrwqRxAVabRyCuIUu0WWHm48ybgyjvFu8WkcngLGyK63FOuS7yn73IJ5Q2ErRhN2YIKsvj9ihj9aIGrChpApSa%2FrqhJeYv5ZQ%2Bpagk7kdELpG%2Br9knKq8mlMm07LoocpO02fa%2BVSy5JHCtuJ%2B0uxlKe5o7e%2FH7CGsqCcWFW7hJOeVdSf8rbVHYJFNmS07TL4u1iIzHefG7MVttGn6SQcx7k%2B2rA9kF08irud9bFmCnPUIvNLHmworyXN%2BWk8%2FmNpjJr0yW7aYGrEU5N0lxAZA2JeOgvMfOH9kBsjFjWJq%2BxYypzdgL07Elg%2FAV2SQXaNOURaybu1SYdmiRH%2B8kJe1T7m1aiNMIgcinEkRW2qukMXNm3BeU18TBWIWz5NHIjO0ZiuUe07e2t3c5Je907kworIy3KJZ%2BV%2BrZ%2FDqi8sp4a2ipm7JN94JFhGXSXxO%2FA9mZUN6BfMQSpbQsro%2Ftz5UxOBlvY283LcCK8uP%2BW57XLvelHTPXkT7NaqzHmSdx8TBbLUsdNP2uGUsasH3P8LBEhmzPS6etVKVN2k1Zkwe7sSkeH9vjv%2FltZseXqCg3vkgeZFyXOF7zG80kOqypjneykaC88xbGZWuX7aR%2FkTZBrv7VN5r4jWGNzNvycv1fri%2Bbu4iwqjy3O1xcVqutCbs%2BY8ZbI8uJ%2FC5jivRf0uYaAqMwFbnavLf2XUml7oo1WEluRxip3DLPqW%2BJZej2dptpwZ7fYBSMocig7f2qWMsYea2MsFrGQ4kvJIWPxyhnrsw9y3LjZO73%2BGycr4VNHWOAjE8SiFSsc0Q%2BFStf2X3KfHILWZUVZgMKO%2BMSFuVDZhF2m00g41pO3rcW1cdzXJGR5f0ZBk3YM2Zhdh0rq8ilI20%2Blye5RuTDhuaOgMSSrij3PNm5MmEWqo3CWeqL4dFidviR%2B%2FAKO%2FrKXI5NHZRx1JNxzcOW4P7J9j5a2oH0x%2FWExlghwJ4v88lOu4LJPKykyIQbsOubc21BDChKMO%2BgU%2F9i2u%2BihliWzSshEPlfdk2S4hnZpNHMp6zAMzLU4oDA2Qx2Y6PpS8VCMqqsjvsTI4%2BI3rgxlrGKJUByJ%2FmzvYxna6GoAAAgAElEQVTybeYHslDUvhmIpJnTGcyfHYfMkLGpukvcByzRP%2BRkB%2BmnZBdPuVXaQnFBHLdOPA3m1cXjdXtfIPNP6RPbN4TonJdOx8XFsRvz8pUonS7UQyWgBJSAElACSkAJKAEloASUgBJQAkpACfw3E2hXoqxA9SNo4pUDs5Ij2kwxdRHt8WLNWm7%2FdNE0ijlZuxJQTBFl9addqyPnxU1AtIcSvbz9d0nCPDPeYvS%2F%2BWVo2ZWAElACSkAJKAEloASUgBJQAkpACSiB%2F3wCy1ei5Exl3K%2F%2Bjnfz%2FVj1rURdBhOOPYDM4G6LXTgSkybiNA4gvd82sb%2B1RBT%2F%2BTOSZ10ZB7ESxYr4ig8eRWbsFni3XIn96YzYhFFMJ8u7kT3zHDK1Jgb0fz4tzaESUAJKQAkoASWgBJSAElACSkAJKAEl8F9LIOcI3Ln8EgMii%2Fe3iaRGj8VpsrGqq7CzP%2BE%2BNNnE5xErFXvG5yTOuxZ3wgQSP8o2vvF9zodP4bz%2FD%2BySSqyaWvPPbl6AM%2F1zvLuewE6WYVV3xarpilVSYuJLdE5dj5WAElACSkAJKAEloASUgBJQAkpACSgBJfCfSGBZSxSxQgl83DffhYF%2FovXaUwiKc%2Fv6ituOIwFdWvHeeBwrUwvV83Aeeh3rrJ1FjRIrUyq6kjnrfDI1Esgo3lfa%2FvlN8KoITriQtjWL4x0HjKvPUsGszB36nxJQAkpACSgBJaAElIASUAJKQAkoASWgBP6zCCyrRDExTlyCwX1w77%2Bf1MkNBHvtib%2FeMLKydVAUYc%2BfgnfvS0Rjzidb9A7egxNxj90WvzBn2NK4AO%2Fpp3HLZT%2FofIL1Nok3mfHrcF56lNRXEmFftsZag%2FSGg5bcsuw%2Fi4%2FmRgkoASWgBJSAElACSkAJKAEloASUgBJQAobAskoUiRDruPgjDwOvGu%2FFd3DPOBTX7Up4wIm0jt0G9%2F0XsGaBv1E%2Fso6De%2FezJN74gez2A4xXj9l669XniWQ7vEQ%2BVtAVf6ikl8Z662Xs4nwTpDbqNgVn3YFkl95aTV%2BOElACSkAJKAEloASUgBJQAkpACSgBJaAE%2FsMILEeJIv43FlFhF%2FwdDsbfel%2FsedPxnpiId9NZeFsPxHnmBbPvujt2H7xsGjJZrNvux9l8fFy8kkrSV1yHX12weOce%2B5c3wa0mO%2F562gYWg23HihTPNntXmz3mxQpGP0pACSgBJaAElIASUAJKQAkoASWgBJSAEvgPJLAcJYoEiA3xvn4Pp6mETJ8uRMkCom7lYGWwp76F82ojwa3P0DaomCgKcKa8T%2Bqw8XhfjiUQSxYvQVRQQFSY23UnmxHNjImXYqXbsFo9gyJyPaxUHvac73AX5pMe0hec5cS6%2FQ8Ep1lSAkpACSgBJaAElIASUAJKQAkoASWgBP67CCyrRJHosIGP%2FembeKf%2FBa9QrEZEsZIkPOUvRNMfgQ22JrNxX8KUB1FIkFiXYJ087He%2FJlitmChRtqQyRCxM8gqJ8ufiHDmaAnHfkS2O8ysJL7ie8G%2Fn4X7VlWDiNWTzVYny31UFtbRKQAkoASWgBJSAElACSkAJKAEloARWDQJWQ0NDvKnOMvmNsFqbcWbMwEpHRF27ky0rwGptxE67BKUFsXGJ3BeF2E0LsOwiQieLU58mqCojsju550QRTsNCLD%2FsSMl2CEtKiPxm7LRNUNLpmR1X6ZESUAJKQAkoASWgBJSAElACSkAJKAEloAR%2BNwLFxcUm7ZUoUUQ5EsX%2F2mOVyLf81v535%2By3%2F97%2B3flc%2B7GcW%2Fqzsmcufa3%2BrQSUgBJQAkpACSgBJaAElIASUAJKQAkogf%2FPBNqVKMu683TOiCg4llaYLP13%2B%2FXtv7d%2Ft%2F%2Fe%2BXtF51b0e%2Bd79VgJKAEloASUgBJQAkpACSgBJaAElIASUAK%2FIwENQPI7wteklYASUAJKQAkoASWgBJSAElACSkAJKIFVh4AqUVadd6U5VQJKQAkoASWgBJSAElACSkAJKAEloAR%2BRwKqRPkd4WvSSkAJKAEloASUgBJQAkpACSgBJaAElMCqQ0CVKKvOu9KcKgEloASUgBJQAkpACSgBJaAElIASUAK%2FIwFVovyO8DVpJaAElIASUAJKQAkoASWgBJSAElACSmDVIaBKlFXnXWlOlYASUAJKQAkoASWgBJSAElACSkAJKIHfkYAqUX5H%2BJq0ElACSkAJKAEloASUgBJQAkpACSgBJbDqEFAlyqrzrjSnSkAJKAEloASUgBJQAkpACSgBJaAElMDvSMBdUdpRFJBJpwmCkMhcZGFZNq7n4bkulrXknVEUEQZZMpkMERaO6%2BG6Lo691IXmtojA98n4PmEUEcUJYNuOeb7rOthLJ7Bkcv%2FiXxGZloV89%2BX3uN0HsXpNAemG2Xzy2XfUDlqH7uUFLDeb%2F2IqerkSUAJKQAkoASWgBJSAElACSkAJKAEl8H%2BXwAqUKBFR4PPBXX%2FmhlcyhCGI1sTOK2X4hpuzww7b069bBUnPwbIsolAULi3M%2BOId7n7gAb6Z3kTXgevzxz33ZMhq3cjP81hClRJFpBd%2ByyXHnMu3ftbQFT2K55UwZKOt2XX0DvTrVo7n%2FC8ZykQhbQt%2F5L5LL6XooGs4Y4d8Zn3zBhNueJRhe5%2FJyaOH%2Fd99w1oyJaAElIASUAJKQAkoASWgBJSAElACSuB%2FhcDylSgRRomyqLGehnofrFhZwqJFvPbUPfzthadYe4t9OeXo3ShOOvjpJj645zwuf%2BJjsmGs%2BGh85wUu%2B%2Bxdhm%2B%2BH2ccPxp3CS1KSCbdyqKGeur9ELE8ic1dmnj9mbv5x98ns%2Fe4K9l97erFypcoDI3VipRaLGLsTqYjYRjIr4uBiFWMKHcs2879GhGFEXKdOYdF7VpbM378mlT27NfJCkWuEcsYozUy93e2iJF7JR%2BRZFbyIGl0spgx1jhG4yR57Jz%2B4qzpgRJQAkpACSgBJaAElIASUAJKQAkoASWwihJYvhJlcWEcSrusy7k3ncfqJS5BNs2MHz7l6Qfu4vnX7uPBIWswZquBtCyYyR0vfEPZ4NFcOv4wagpdmhbM4rNPPiG1%2BuZLKVAWPxw3L5%2Fy3cfz0Nj1zI9Bppkv33qca294iLcemczOw%2F5EQnQjUURr%2FXT%2B%2FtY7zG2x6bvGCNYd0id2FYoCGqZ%2FwuvvTWHoZtuSqPucNz6aQmntGmyy8ToUJzuUK%2B0pi9VL0NrA519%2Bw5rlPagsyTfKljAImDf1U9758GtawiSrDd%2BItVerxRWFjXFXauGbD97m0%2B9mkijryjobbESvqqLFihq%2FeQH%2FeOcNps1tpkufoWy03loULKk9as%2BCfisBJaAElIASUAJKQAkoASWgBJSAElACqxiBf6JE6VQaS%2BKcJOk%2BYAQHH1dG3ZHH8sZ9k9hxowEUhiF%2BFGJ7FlHWJ7ISFFbUsuFWtUtYanR62nIPHS%2Bf3kO2ZED3B5nS8iXZbIRnZ5n20UtccMG1zGzxTbwVL5Gi%2F3aHc%2F5hO1DshTTM%2BJQnHnyKuXUzef6Jp2jNhia%2ByiODNuOCc06jW8nSxYxomz%2BNRx5%2BjD36rseaXYtJtzTwyUt3cNktz9GcFUsTC%2B%2B%2Bu9nsTydz7J4bE7XO5%2B4LT%2BGpj2YYixjLcnjg4TU45pyL2LxfEX7TXG658GSe%2F2gmYQRuMp9n192NK845hMT%2FklfScqHpj0pACSgBJaAElIASUAJKQAkoASWgBJTA%2FxcCS2sXVp6oxEWxHZJFtfxhZH%2B%2BevlT5jZAl4puHLTValwz6WmOHfs6xdV92XbUbmy52VDKC%2FNwnWWtQZaXUBj4pFt%2BYc4ci7zefbEJaG34gTuvvQm%2FagRnH38ovYrhi9cf4rbHbueJQQPYf4u%2Bxk0nnc7w6ns%2FcfiFNzK4ayFT336QKya%2BwsWX%2FpVLztt7meTEZScIAuPmk8208fOnk7jyrlep3XAPjtxvJ0oSAR%2B%2F%2FABzi4vwHIcwWUyXdXbmogNH0LU0ybwf3%2BaWvzzAcw%2B8wUZnbMf8L55j8hdw4AU3sHGPEprnTeHb%2BqoVWuEskyH9QQkoASWgBJSAElACSkAJKAEloASUgBL4jybwrylRpChWHJPEMUFfQ7JBhJcsZONDLqBixAd8%2FuUXfPbJxzx6x8U89ddKNtpufw7dZ0sSy1GkBH6Gpnce5Iq6yQaSuAvN%2FOFzZvgl7LLjSBwCfn7vaT5q6cKp5xzL6pUpo1gZsvlubP63d3jtoy%2FYb%2FM%2B5l43kcfOY45im%2BF9cKyIyp2P4PD6Ru568w1mLtiZrit5DX5mER%2B%2B%2FDRB6UacfuIYuhYlsKKQqgNONfFX5DjIZulTkeSdFx6hKZ0l09ZCS2Rht9QZ65i8whLyWcS7zz1G2%2BDhbLjRemwzsHSZXYxWkg09pQSUgBJQAkpACSgBJaAElIASUAJKQAn8BxP4l5UoEjw13bKATz7%2BDidvPbqUyHbHtlGkDNlwawatuymj02nm%2F%2FQpd914M69Pfpw9R29KdYG3DAbZ1cef%2FjlvznaIgizpTJZEZT9G%2F%2FkQ%2FrhhN6www7xZ8wiap3P1iWNwbPGLibdSzgYhXvEcWnJPdVyXbjVdEOWORYSXSFLdtYYgmE46m%2B0cd3Y5%2BciyqLEFu6IPZYWJeHtly8GzHZOe39bE989M4PLHvmfgkNXJ92yTl%2Fags5btUDxge0461ue519%2Fl9Sfu4LlH7mHtHf7MifuPIumqP88y0PUHJaAElIASUAJKQAkoASWgBJSAElACqxiBf6JEiYwFhp9Jk26TnW1C%2FHQLX7z6KJOmeAzZdxTd8i3SrfW8eudtdNv%2Bz%2FStKcbzEpTV9GeN3rV88XkTbbkda5ZmYzseqW1P4o79hhlFyYRTzuDb0GXNwYPM9sZRZNOlugwrzBJGCfObOAY5jig4PEpKChbvrOOn07z7zkcMrl6PpIOJcfLB%2B%2B%2BTyi%2BmsjAfq3np1Dv%2BdtxCeg%2FoRTDpET75diuG9RILkohMWyvZ0CVpLeSpR9%2BneJ19Of6oXUi4Fovqfuami05jvuzVE0VkW5roNnwkx647kramhTw%2F8Vomvfos8%2F44ku6qROmArUdKQAkoASWgBJSAElACSkAJKAEloARWUQL%2FVInS1vItN194prG%2BiMIszfXzmT5zHsV9tmLsqGG4Vsj8Wd9x38uv0Dj5PXp270ZB0iHT3MDM2XPpOmhPqlKJ5eKxXZe8gmIqKiuhvJSjzj2NM8%2B9kluuvYluF59E95RDjw3%2FxJYvfsF3baWUFibjHXnE1sROcMiRe5FvxVYe2Uwr7z19Cz%2B%2B8yiFCZtFdTOYPi9i11MvoKo4QetKlCheMsXaI%2F9M9aTxXH7mcfTuUYtnBdTXzSV%2F9ZGce%2FSO9O7q8Pc3H%2BbMme%2BS70LD3F%2BYMT9Nn6Egbkkv3nIpD3w0k9qaKhJ2REPdXErLB1Ai2zfrRwkoASWgBJSAElACSkAJKAEloASUgBJY5Qn8Ez8Tcd2p4%2BtPP%2BTDD%2F%2FBp9%2F8RFBQy84HnchVV51Gj7IUtpugss8IbrrxMnbddDCZ%2BVP55OOP%2Bakuy3qjDuCMM%2FYn9Wu2%2BbVdagasx4mH7Ej48xtcevVE0qFNXllPxpx0OiN6FzL9%2B8%2F55LMvWZhNsdkuY%2BnXJd6aWN5CfmEx%2B4w5jNUrI7767DMWUMW%2Bx53GgZv1WG48ls5vTspQ3nMoF1xxOhutVsaPX3%2FMV1Pn0GfESI4esxclReWMPvN8thxYwbSvPuGrqXPpufb2rL%2F2aiZIjOsl2O7QY9hz8yEsmj2FL778lkS3YRx6zIkU6dY8nVHrsRJQAkpACSgBJaAElIASUAJKQAkogVWWgNXQ0BAtN%2FfiuuP7Zjtf5Aor3mHHtm2zQ498536CKCLstNtNfLmF7Tg4ttNx3eKEJK5JQBBGSDwR1wSplfAjEUGQNb%2FLLkCO60gcWyR2SjYICGXvYEDSdhwX27Yg9JnyzkTOmzCZA8%2B7iU36F5rrJE6L3G%2FyaeKodE7PWpx%2BnEe7owzZILeFcbwTkYmxIsmEcXBZyYJlWR1bN1s2rlibyHmTx9Dgai%2B7yePicuuBElACSkAJKAEloASUgBJQAkpACSgBJbCqESguLjZZXrE7jwSLTSR%2FXblk62NLFBa%2F1nVFFCwuy1xuWTiux9JPEUVLHOR15dkRxYXEY1n2s2x6y6TfXobE0qnHT5Oy2Ss4Z66wbVwT%2BHbZ1PUXJaAElIASUAJKQAkoASWgBJSAElACSmDVJ%2FBP3HlWgQJaFslUAalUXodFyyqQbc2iElACSkAJKAEloASUgBJQAkpACSgBJbBqEVixO88qU46QdGsrIQ4Sm8TTnXBWmTenGVUCSkAJKAEloASUgBJQAkpACSgBJbAqEPjn7jyrQilMHm1jibLKZFczqgSUgBJQAkpACSgBJaAElIASUAJKQAmskgRWfXeeVRK7ZloJKAEloASUgBJQAkpACSgBJaAElIASWNUIqBJlVXtjml8loASUgBJQAkpACSgBJaAElIASUAJK4HchoEqU3wW7JqoElIASUAJKQAkoASWgBJSAElACSkAJrGoEVImyqr0xza8SUAJKQAkoASWgBJSAElACSkAJKAEl8LsQUCXK74JdE1UCSkAJKAEloASUgBJQAkpACSgBJaAEVjUCqkRZ1d6Y5lcJKAEloASUgBJQAkpACSgBJaAElIAS%2BF0IqBLld8GuiSoBJaAElIASUAJKQAkoASWgBJSAElACqxoBVaKsam9M86sElIASUAJKQAkoASWgBJSAElACSkAJ%2FC4E3OWlGoYhLS0tpFKpZU5blmV%2Bi6JoueeW9%2FsyFy7nB3nuiu79reeWk8zin%2F4dz1z88H%2FxYGV5%2BRcf9asuX1F6K%2FpdHvpbz%2F2qDC3nopWlt5zL%2F8c%2F%2FSel91vzsrL7fuu5lYH9rc9c2X0rS29l5%2F4dz%2Fyt6f3WvKzsvt967t9RhpXlZWXprezcv%2BOZ%2FynpraxsKzu3svz%2F1nP%2Fv9P7rfn8n9y3sjL%2B1nO%2FNT8rS%2B%2B3PnNF90la8lmRHLWi%2B37r7ytL739S7hXd%2B%2B9Ib0VpCZPfem5lPH%2FrM1d238rSW9m5f8czf2t6vzUvK7vvt577d5RhZXlZWXorO%2FfveOaqkt5vLfvK7vut51bG7P%2FyuZXx%2Bq3lXtkzV3buf5Ke3LuyMVP0IfJxXdeMCUuntVwlimQ2mUxSWlq69PX6txJQAkpACSgBJaAElIASUAJKQAkoASWgBP5PEgiCgMbGxhWWbblKlM5Xi0JFP0pACSgBJaAElIASUAJKQAkoASWgBJSAEvhvJ6AxUf7ba4CWXwkoASWgBJSAElACSkAJKAEloASUgBL4VQRUifKrMOlFSkAJKAEloASUgBJQAkpACSgBJaAElMB%2FOwFVovy31wAtvxJQAkpACSgBJaAElIASUAJKQAkoASXwqwioEuVXYdKLlIASUAJKQAkoASWgBJSAElACSkAJKIH%2FdgKqRPlvrwFafiWgBJSAElACSkAJKAEloASUgBJQAkrgVxH4p7vz%2FKqn%2FA8u%2Bn%2FsnQd4HcXVsN%2B9e4t6L5Z7lXu33DEGbGx6C5AECHwJyUfoSSCJIRAICZBACAFCSegQQu%2FFYINxrxLukm1ZtuUuW7LVb939n9mrldbylTHY%2FJ9jn30ee2fnzJw5887u1d1zZ86YRoTaynWYyX1JidOItReQYfjZXbGcPZEwJhq6K46clIFkxcPuveuoDAfJSOpFXnIKphmirnor5Q0VJMZ1p0tGFpFwPTsry6iONOJxt6N7Vhe8eqyWjqAjUlUICAEhIASEgBAQAkJACAgBISAEhIAQOK4J%2FJ%2FPRDHMCFs2v0XZfhPM2Kw1zUtGRj96ZA2kc2oPAluWUGEE2Fv6LtPLKuiY1I7Zi%2F9B8Z4aGmq28PiCGaQn92bXhrf4YksjmnK6ZPSga0Y%2BKdVrmLmuGNNso7HYJkiuEBACQkAICAEhIASEgBAQAkJACAgBIXCCEziimSjhcCO7dyxl7s5CEuLHMqnvcKorF1Gpj6ZvhkFVxVLKjf7010tYVdXAznA9U3pPpHzzFyzbv4V2GZMZ07UrhhHGMELU1VezYOseJnZKY9b6j6kM19I16yLGdOuMz5uC1whh1mxieb2HS706n23by4RRF5LsCzO152BmbV%2BFN24X4wq%2BT15SEik9xvDC8o8Z0%2FFCEr1JeCIBXB2HUrV8NSZ9rVkvqg9Vu1cye8cCIq4sJuRfSKpRxZLSD9gR8TKk87n0ykxiS%2FGLVLo6sKl%2BG%2Fl559FY9TFbI%2BlM6ncu2fGeE%2Fw2ku4LASEgBISAEBACQkAICAEhIASEgBA4%2Fgl8%2B5koZgR%2F3Sa%2BLFvP2F4Xka99xcItZVTtX8P26ojlGNm%2Ffx2le2sJVRazvM5kYv5p1Oxbwbx9Pk7qeS7x1bMp3t%2BIYYaprFzJhwteoWNmO0xvKqPzz2FS74vZsvE1yupMa5JKOBxg%2FbZCOnQ9G68G%2B8ghO96FS3fjTstF99cQbPTTMcWHS3PhSUghK7yHUNhA1a2t3sLsRc%2FQs%2FPA6LIhM0KwdhMzy4oZl%2F8Tzh14IdlxGotXvkFqu4s4q%2FdprFv3DpvrGtixbRYNcf05vdMwphf9lbScMzgpxc07a0ramkBz%2FN890kMhIASEgBAQAkJACAgBISAEhIAQEAInEIFvPxPFNAlXrGbt%2FtlsXrIE5Y3p0aGAdm7TWiqjlulETAPDBM3lJr9DP5K9bqp3FlK2Zzkv7HfjIo6haWFyzAjzS58jMX4UU5LjCNdv45Olz1EW2U1tfRW9636FmRghEKxibbXGxQMzcZlh4o197A%2BbJOoRjLpqwp543G43e%2Fwhuvq8RPyN7HclYZpBKrcu4sU1nzJ11O%2Fon5WCpkKiGAahvSUkZBeQm5KMC4NIqJK9fpPxuRlgxNM1LUB5pYFPd9M9pxuJhp8cXw86pmfgIZdQZYPlRJEIKyfQUyNdFQJCQAgIASEgBISAEBACQkAICIETksC3d6JoLtx5wxmwo56poy8nxetC00y2btpE2d7NjM%2BNZ%2B3OtWjZU9E0V1PAWJ2EjuPp1jiAi0dMINHjwoiEWVMVx5kjfkeeOZu3ixZSkFqKO%2FcaftlD55XZd1t1TSNIefHLZLa%2FFK%2FuwTBMxrXTmbu6iAv6dGfOhiV07XM1ub5M3l38Ib0mXMjmzYtp1%2BUsXPUlfF6%2BiytOvoOsxHhU8JVoTBQNPXcIjUUzqOiQT06ihuZKIifBTdHOegam7Wd9ZRxjurvZVmb3QfVTBcBVbhPNSp%2BQd450WggIASEgBISAEBACQkAICAEhIASEwAlGQJ82bdpdsfpsGAbx8fFtOwk0DbcnmXYJLgq3fU5p5TbifR3pkNWT%2BIYFrKuupXf7k8jLaE9GYjzehFxS4nzExWWSxXYKdy6gfF8V6SmdSfDEkZreg9y0DiSaNWRmDiboX0hpdYABeWPpkNOBOD1Co5FEr%2FZ9ife4cLlcpGT2J86%2FmuV719G1y4UMbJeFz5dOn%2FgAS3fOwZM2hlO6dcAM1bAnvI2t%2B9dQtreYqkAyWa5almzfSsesHnRNTWL59hmUVe0mLbk7vfLy2b3nc9ZXVzGk11l0SkrApceTmp6Pz%2BMmwZtBTkYObt2Dz5dGXkpSk5MoFknJEwJCQAgIASEgBISAEBACQkAICAEhIAT%2BGwgoX0ggELB8DmoChX34fD4rqVVXVx%2B0TY2apREOh8nIyGjbiWJVj87osGZ1qNkZ1owTE8M0rFka1kwNu0Vr9oa6iMrV5jgtMzpMq669Y040AooyK2qwim8SnT2ispzbILe0Zc0NsTpoLyeK6nRpWLNOlG5Lr1VfzSpp0q%2BaULKoQZYd1jXRPkT1WkWiLCw9lhmqmHU4wdrdlbMQEAJCQAgIASEgBISAEBACQkAICAEh8N9FQPlCampq0HX9AH9ISkqK1ZFvv5zHqh5dzuJwzliOD5emH4KShiVvceg0O0tsZ4TTTdKiSLXVchVNNek6IDtqk%2B4oazlrHNd23eZqlgOo%2BarJUXNgH5rbdjhxmvMcVSUpBISAEBACQkAICAEhIASEgBAQAkJACByfBL797jzHJw%2FplRAQAkJACAgBISAEhIAQEAJCQAgIASEgBGISECdKTCySKQSEgBAQAkJACAgBISAEhIAQEAJCQAgIgQMJiBPlQB5yJQSEgBAQAkJACAgBISAEhIAQEAJCQAgIgZgExIkSE4tkCgEhIASEgBAQAkJACAgBISAEhIAQEAJC4EAC4kQ5kIdcCQEhIASEgBAQAkJACAgBISAEhIAQEAJCICYBcaLExCKZQkAICAEhIASEgBAQAkJACAgBISAEhIAQOJBAm1scG4ZBJBI5YF%2FkA6vKlRAQAkJACAgBISAEhIAQEAJCQAgIASEgBI4fAsoXcqijTSeKpmlUV1cfqq7IhIAQEAJCQAgIASEgBISAEBACQkAICAEhcFwR0HW9zQklMZ0oyoHi9XqPKwjSGSEgBISAEBACQkAICAEhIASEgBAQAkJACBwJAYmJciT0pK4QEAJCQAgIASEgBISAEBACQkAICAEhcMIQECfKCTPU0lEhIASEgBAQAkJACAgBISAEhIAQEAJC4EgIiBPlSOhJXSEgBISAEBACQkAICAEhIASEgBAQAkLghCEgTpQTZqilo0JACAgBISAEhIAQEAJCQAgIASEgBITAkRAQJ8qR0JO6QkAICAEhIASEgBAQAkJACAgBISAEhMAJQ0CcKCfMUEtHhYAQEAJCQAgIASEgBISAEBACQkAICIEjISBOlCOhJ3WFgBAQAkJACAgBISAEhIAQEAJCQAgIgROGgDhRTpihlo4KASEgBISAEBACQkAICAEhIASEgBAQAkdCQJwoR0JP6goBISAEhIAQEAJCQAgIASEgBISAEBACJwwBcaKcMEMtHRUCQkAICAEhIASEgBAQAkJACAgBISAEjoSAOFGOhJ7UFQJCQAgIASEgBISAEBACQoqyH%2FsAACAASURBVEAICAEhIAROGALiRDlhhlo6KgSEgBAQAkJACAgBISAEhIAQEAJCQAgcCQH3kVSWuscBAdMkHAkTCobQvXF43C60Y6hbkXCQYCiCS3fj9XqOKdv%2Bf2EyTYNwKEQwFCYuPgHddSyN0JFRMI0IwWCQcMQkLj7%2BuOrbkZGR2kJACAgBISAEhIAQEAJCQAgciwT0adOm3RXLMDMSpHz5xyxdvY%2FMju2Jcx%2FZi5tpmgT2bWPGrHn4fVlkp8SjHZnKWGZL3iEIGJEQmxbPY1Hpbjp0ysPjcqFe0BsqNnL7nXfTkNGfvh3T0I6hgWmoLOP%2B237NqoZMRvXvStv%2BAxMjHGbt%2FFkUbquma%2Fvc%2F6MXcpNwsIG1n35GYa2bHrlHzlM9i6ULX%2BfWOx6h28hTyUv1UrunjDlzFmMm55CeFIeGiXJIrFk8i%2BLNjeS1z8LdNqzmu8QwwuxYPZcvFxRSUlJCcfFa1peUUFJSzIbSMlLadSbJ5%2F7OnlUjFGTBMw9z9%2BuzOXvyybh1%2BVBoHhxJCAEhIASEgBAQAkJACAgBIXDMEPD5fJYtsWeimOqFNMDaGf%2FgxeXD6FwwnDTfka78ManftZ6nnnic067tQt%2BOGYd4IT5mOB1HhpioWR0r33uV5%2FdkMHzMUOLdOmAQ8jeyrXwr%2B%2BqDYMKxM93DxKXH0y4ri7Ts9EPbZqr%2BBVjw5gt8rA9iwvAB1qya%2F4sBDAdrmPfk43w65momDeqK6zCcGYeyUw1JYnou6RnZpCZ4USCqylfwwj9f5pxbetGjXSqYJmY4yLwPX2RF%2FRgGD%2B%2BNz%2F31z6wRCVM651Uef6cEzeXCZTvQNBfuuGQy%2B48mN8WH9h3dFNZMlICfhsZGIqbqqRxCQAgIASEgBISAEBACQkAICIFjl0BsJ0oMe03DIBIJEzE0dB0ikYh6b8Pl0tHdOror%2BsKmXorCYVXOAFzouo6uu8CIEAqHMQyDUDBgTeHH47Z%2BeTaN6JKSSETVwXqZ03W3VU9Ty01CQQwtusxE2WGYJpp6yfN4HLMNTIyIbaOBaWq4dB23W8flcqH0GKZBRNmm2tFUP1QbSq5%2B%2FVa%2F5BuEQlEb0ZpsV%2FXtF0sHFzWzRr2AhhUHw1RGo7tVf6KzOyw%2BaHjcnuiv%2BKZJKBRqblfNHIhEQkQMF8qXoUyyOCm9ip3VXwMD1QcXiq7SqcbAUO25VL0mRpqGYShZBMPUULhVP00UA2WTjqZF%2Bx6OGKgZKQF%2FgJDuovUEI6UnHIqgKXZWPc16QVczFoJhw%2BqPS29Z8hPlECIcUfZr1j2hXsZ1l3LQNDFqskXlK5ud9S2GYWV3dEytsVBj7HLj9ejEpbbjp7ffh%2BZS46RMsfsRsbw9Kt%2Fun7pPwoYa5yCBgB%2BvW42xGj%2BssW25L6NcrHvTpWw2CAdDmMqJYFmt8Cu9mjW24bAaJ3VvRu%2BpaL0WB8WBfQDFuC13gDVO6jlAt%2FqnZv205Gm43fY9bVpLrExNw%2BVy077vKfz1bxPxeD0YEdXP6L0QDgYIBIJ43HqLm0M9M%2BEQgUC4%2BRl1e9wx72P7lnZ7unPdH6%2Bjo9dt6VH3ju720LF9ioJnLSVSTKI8FTOTiHouUc%2Bh23q%2BrPvPUI4vl3UvqufTpannIXpvKrnFULF1u9FaOZcsZk22W89D8%2BeKelYi1j0dfdRcVn11j8V4NO0uyVkICAEhIASEgBAQAkJACAgBIXDUCRy2EyXor2PVv3%2FCH97vy213jeWtJ59jzZa9tMsfyXmX%2F4xzRnVDw6C%2BYiNPP%2FUEcxevxO9Kom%2FBafzwx1fSN3k7D%2F7iXhrCET566Ca%2BfCaTi6Y9zY9GZxKu28V7%2F36aD75YxK6qRjI79%2BP0877PZeeORyfMV289zn0frOCW677PrDdeZcHqclI69%2BWCK6%2FlexP6WS%2BHygFSs6OEN55%2FgRlLi9hXZ9K5%2FwjO%2Bf7VnDWmJ7oZZt%2F2Yl565l98uWgNQT2ZAaNP4bKrrmJgpzTLyeOv2cKzDz3A50vXEdBTGDZuMt%2B%2F7If075LR8oLaNASRYCNfffEWr7%2FzAatKK%2FAk5zBy0vlc%2FZNLSIvU8NJjd7GsIpm%2FP%2FAn4hVlI0jJJw%2Fyx%2F%2Bs4rcPvUD%2F9AArXrySez4czO13jeGTl95nwOW3cGpOBffdeA%2Fxl9%2FH8OoP%2BHCzj0fuuBGvFqF0yae8%2FOqbLFtTTlxGe0addgFXX3UhmfFuAvX7%2BfDvV%2FHK0tO55efJvPTCW2yuDNBrxESu%2BPHVDOmYyPbP7ueJJWusHlx13rlk553Pw8%2F%2BL2pug32Earfw0PU3srHz93nwrh%2BS4dMtZ1Hlmre4YdpLjLnlSa6b2LF5qYhyyOxe8BzX%2FGUR%2F%2FunX7Dpg%2BepyxvPr646H8IB5rzzDG%2B%2B%2FxkbK%2BrJ7TKASedfyg%2FOHIPXcrgYVG4q5F9PPc3CFWWkdOzD6eddSMOzD%2FHZ6B%2Fzxq8voKGijN%2F89g56TLqOmy8bb%2Bn88tUn%2Bc8HM9i2P0iH%2FBGcfcnlnFHQhZUvXsabK2uBzVx8wefkjLuap%2B68lCSXWkpWyvNPPMEXC1dTb8TRb%2BRJfO%2ByKxmV345w0M%2BHt9%2FMi5Fu%2FOXSvrz82scM%2FN6vuXBMN4K1O3n1X4%2FyyewiqgNueg0dy0WXXcmEgZ2jzhkzwtYVX%2FD8S6%2BwdE05Ce16MeXss1Ev%2BwcfJqGGSt747VW8ZZ7Lcw%2F%2FlFSPjr9uH%2F%2B4%2BzrmbE7i%2FmefoH%2BqF7WEZ9WHD%2FLAf9Zx458eJG3bZ%2Fzmb29w15P%2FplPVHH555xPUNwZ59q5reTWpB3967XEGNA2kEQmwduZzvPrmdMr2Buk2eALX3XQd%2FdqntOlI0d0pdOvdl%2FxEtTTIPjTLSRHy7%2BX5aVcxO%2BVynvjdxaR4dGum2rx%2F3szfV%2Bby5N9vI50A7%2F%2F9D7xf7uKuH4%2FnsX%2B%2BRsHPHuTioTmE9pXx2nPPMH1OIfsaXeQPH8vFV%2FyEcf062A1Fz5Zj0s9nz%2F6Rp6Zv4OyfTeOKyYNw%2Bfcx553neOOjOWzeXUNiux6ccvYPuOKiU0mLU846OYSAEBACQkAICAEhIASEgBAQAv9%2FCLT8nH4Y7alfzAONpbzy0mt4sroxqH8%2B9dtW8Pqzj7CvMYQR8vPlW08zd%2FluegwcwdABvdFrd9CoZqR4U%2BjVvxcer48O%2BYMZUVBApwyf9YJeOv8tPl%2B%2Bm449B1Oglg4Ze3j%2F5WdZsaeh2apA9W5eefJV9nmyGTRkAO7K9bz80N9ZvidkzSSordjEP%2F5yDx8t20SXPsMYPWo4CQ1bef%2FNV9hb00DN7nU88afbmLW2mj5DCxg6oDt7Vs3kT9P%2BSkllAyF%2FDfMfm8bMdfX0HTqKYQN7EdizgcrAwatbIsF6SqY%2FxYOP%2FpvdkUwKRo9mUM9c1i%2F8mDfmbyYS8wW6uSvNCfULvb9hPc%2F86xkCie3IaYoTEwr42THrST5YuI0unTqjmxF2Fc%2Fgob89yea6BEaMHkPfzhkUfvQ0t%2F35NWr8YUuncmj4G1bz0keLyOrWn4H5nShfMYdnX3mPgKmTmNuLbukpeJNzGDFmDEOHdiOuVQwKT1IHzrpoNPUb3qeodF90lkY4wMy3PifSbigXjY4Va8QkHKji46fuZ12Vh07tc4kE6il578888vwnaFk9GTVyBNnefXz49P088cEqIiqgaM12%2FvnQfRSWB%2Bg%2FdATdcuNY8NEzlPqDzYycCSMcon7blzz9ymckdOzPyILh5Mb72VNRZc2aSO88jA6pCXiVg2n0aIb27oBbOfaqtvDXX97EjJV76T5wBMMG92H%2F%2BgU8eP%2FfWbPXH23CNPFvK%2BIfD75CMKkDuenxNFbv5Jk7r%2BHN%2BVvo3HcoI4b1J7R9OY%2Fe8wDzt9Va9%2B7%2BzXO4%2F56%2FsGJbhAFDC%2BiZG8%2FcD15gZcw%2BaOjeZE65ZAqRsi8o3hGw4pgE9hWzcf0ewvXbeGP2dmsWS8hfxcIvFuLtPpWe7ROaMSgHhy81l375XUiIi6dr3yGMHDXEcsY0dYQ95cv510erSevUh4H5Hdi6%2FAv%2B%2FPiH1IejM72alTkSkVAVKxctYP68uSyYP4%2BFCxZSWLgFNXfksA8jTN32Eu6%2B52U82T1ol%2BrDX72dp%2B6%2BnQ8Wb6Jjn2GMLBhMsHwpf733AVZWNLQ4m9QMlGAjc%2F9zP099tI6JP%2FwFl08ahFcz2FWykNdml5LRtT%2BjxoymU1IjX7z%2BD2YWbabtHh221VJQCAgBISAEhIAQEAJCQAgIASFw2AQOeyaK0qiWHri9jUy9%2BjFO6ZlgvSgvfPMJnvyglM2NAQYnwY7tpejeAfzommvomJGEz%2BvF6%2FWiEc%2F5P72Ej6b9jaHnXM01UwfgVUtlMOl%2B8pXcNaSOiKGW1ISpLy%2Fk139%2BjpVbAgzLjv687nYncdK1t3POkE6YYT%2BVX73MDfd%2BTFHZXgakpFLy6WMs3%2B7hqnseZUp%2BsjVLQO1o4nL5cGlBij76hJX1edz72AP0SIu3Zp5UbV%2FL3Xffz7w5xXQ5rR2rVzXi6ziK%2F7nuCsuh4fF4LNsPpGlSX7WTp96ZT87Yi%2FjjzZcR51ZLFtQSCgNfQjzhhv0HVjnElaZXMeCMe7l6ygB8Ho3aHVvQXG4qd5r8%2BckH6JoRh9G4l%2FeeeptIr6k8fNvVJHnVTIAwxTOf4d5XZ1K25wx6p0WXQXnj93H9b5%2BhZ6aXcGMVb%2FzxN3yyqowKNDoO%2BR5n5C%2FhhT2p3HDb7eQmxKFrBk5rXbqXzgUXkvr2VyxasISTek0i2FjF7OLNDJx4ETlex7KR5n5pmFojkexLuefWC0j2umjYvY4%2FvrKUkT%2B6jZvOH2bNXAk11vD%2Bk3%2Fh8y9ewz%2FlDnYu%2BjdLd2Vw%2FYMPMa59HJoZYV%2F5Kq795e%2BbNTsTinH9xuVUh%2BP4waU%2FZXx%2BDj6fF6%2FHi9ut0fnUWxn72fV84urHr6fdRFJCHGY4QGnRTAr3%2B%2FjNg39jcOcUXBjU7C3mr7f%2Fkbc%2BXcm0iwdGl5nUB%2Bj1y4f58UkdrZlL5YUfMrPM5IY%2FPcCEXtm4NJO66l088odbmP7KPEbefDIzn3mVXfH9uOuhP5CfFgdGmD0bFnHjb%2F%2FsmNHR0gtd95A26CLyUj5k2ZIShuX0Zsui99gV6UT%2Ffn7W%2FPtjas66lkj5KmZtj%2BeCX48nxa2zt0UFCe0H8tPLz%2BJ3f3yJ035wDd8b29Na0kQ4ZC1G8qT7uOsPf6RDRgIh%2F34%2Bvu%2FHvLyqiB0Nl5KferBTUKkOh8p59v4%2FNcdvcek%2BUjMu4V%2F%2FvgqPo%2B1DJdUSoFBQ5%2BS7H%2BWHg9PxuDU2LnyfZTsj%2FHTaQ5zcPxdNLQ2q28R9N9%2FKax8U8bsfDLGWi4X89az79FH%2B9vJCJlx5B9ecW0CctURJI2%2FAadz3pwKCas0YJvV7yvj9Hx9i27Y9mGaP2B06lKEiEwJCQAgIASEgBISAEBACQkAIfEsC38iJouJ0uN39GdQ7jTiPC0M36NQlC40N0dgLbi%2BTLvwZax9%2BirtvuZHM3PZ07z2YH%2F3kcnITPdaLnoqRoGIlqFghLi0a1HTuG0%2Fz%2FrwVVNX5rSVBDfV1gG7FybD7pSck0b9zDvHxcRghjZTeQ0k1P0KFqlDLF0oLa3H1GMJpvdOJ90W75fPFWdUD9Q2UlG8lULuH1x77a3QHELVbUEMNVbUBdlaUo%2Fv68b3f%2FISNj7zC7TcvJCOvPd36juOyH5xHh3TnEgfwN1TQGIgwtmAMSYkJtJrMQaRlPYRtvuPcMk1FxXXxeAZwxqmDiPO5cRGxXrxdbjddL7iantmJljOorrGeVTX7aaxdwyMP3G%2B1p%2BJ4NO7bQaC2jk17G8hPVbsd6bg9E%2BmUl0yciouiJdN3QDzTt6g2m%2BJ5uKIxNtR2wSpejAXQYZ0ql5yZx%2BQ%2Babw5bw7rzh2Dd8ET7GhI59Ip46yYLwcUb7rQ3emcfdk5pCbEoRlBqqu209jYyPYl7%2FJgySfWMhI1U6Zq%2B1b2RbKoCYcoXbIV8rowMi%2BeuDif5URJycljrEtjQYxGVHyX9ILLOKtgI%2F9%2B4Ne8nZJJp87dOePSKxndJy8a40b1T%2FfgUY4VXScYCLNjYzGNjS7ef%2FERPtWjIVJDgQa2N0TIWl%2BGYQ60XsTdnYZx6dgOxHm9hANBdm4pobHRzxf%2FeYrF3mi0lHDIz5a9ERITVxAOj6dobxWd%2B08iPz2ReJ8HzAhZXXszwa0zN0YfVFwYT1wqw9rlUbhmMQ0nZ%2FDJFzvJG3USlxS4ue%2BpD9m88zLqCovwpGUxqke6FePGqUrF%2BlExiKzYLG7VV4%2FlnGiKKERa6gDS05KJi%2FOgk8yg4X0xVqsYRmY0Zk2M%2B9Pt7cxlN%2F2Q9vE%2By6mh4rB4vB2tpV4td2xTwJg2Ir6o%2Bzm5c08uGpRp3c%2FKgVWxfjU1DQYzX3%2BSJXFuFXkIMxKivCFCakkpwcggK%2BZKeGcJ9%2F1zHQ0R07pvrAdBM1GzskrmvMbTb8xmX32j1XKwsQ5%2FyGXFuTnANickSQsBISAEhIAQEAJCQAgIASEgBL4DAt%2FIiaLevdSLugpcqg71OupSL6UqcKeV4yK710ju%2FNtgylYuYd7C%2BRR9%2BR73xPfhkZ%2BOsYKqqnLRlzkVQDVMwL%2Bdt9%2F9mOypv%2BKO743GTYjKdV9yy%2F0vRhtp%2Bl%2FTXdav5JYNqm0VoNSWuXTScj0Y67ZSureeQXkq9kP0BSyiXgNNE49LI1BXTeGyJbitILjqhdJE9%2FhwuSLW7I%2FU7hP4w5%2BHs371EubPX8ySL15FT87kF5dPOsBR4vEmoLtMdmzaTDDUhziPbi3L8AdCeK1tj6KBN%2F3%2BgBWoNk7XUb%2B0b9%2B8NRqEtrlnil8qSfFRhva7qQqEm56eaTlQVFH1cqpm7FTuLKVmb3lTXAvFz8Qbn2EFk42qVHrcLeNjBXK1sNukomNlqMC70f7bbTabBLh9yUw472w%2BvvM53n53Lv4ZK0kdcgkFXRPa3P7YpSeSkqyC6EZHSAUcVkGGN61dzjY1o8Bxj8TntrMCBWd1SiaypIQ3Zq%2FivFG98JoBNiyZw9xQhJiRLlQwYF8qP7zlz0zZWsLC%2BfNYPH8h%2F3jUQ%2F7ff0Fa0z2p4uMoJ5PVR%2BWOc7swIvtYWbi0%2BR6yxt4dR57e8hruSkokXgUhtpwM0aC0ambU6q%2BWRIMcN927LreHVE%2FY6mtufBxFe%2FawPxDG63FHY%2BvUVbOjrTVdVgBiH6dO6cunz66icHMfNtQGGF8wku59TeIjb7F41Toaly8ns%2BOZ0SVeqBkmBx4WT6uP9ljacuUkUw5KqxPW4LvdajZXo10g5tntzmDYSSe3iokSLaoWi6lAyOGKSuqDYZLcbkJBP1u31WGaOS36NA217ZdPRZ5Wh6bYuzEi1axdvsxy2imrFHvlJM3Uo8F6VVFd89J59Ln0M1cwffprzB4zmEm9s6xZK289%2BxZ1A67kz9dMIl43qd6%2BltvueiDahvwvBISAEBACQkAICAEhIASEgBD4%2F0jgGzlRDmmX2q0jWMPrf7uT2h6TmDyiD6dO8lFRXMLuQMR6V%2FcmJOExI6xZvJj1Pb0E9tTRrbdGOAj7d2yhsrIXruA%2BPnnvE9src8gmbaHuiWfUBWfxzp3%2F4q933ME1111D%2BxQXpUun8%2BFyD3f%2B7koGD%2B7LR4W7OefyH9MjN81yNIQaG%2FHr6Qwd3JNI%2FS6e%2BO1viT%2Fph0wuGMzkKSmUlG62dt%2Bx24meNRLSOnJS11ze%2FeRp%2FqoF%2Bf5pg4jU7ObdN94i%2F7I7ObO7TofkZPaXr%2BGJt%2BZw0ZjO7Fo9i2e%2B2ILpTT5AXdOr7gF5rS%2B8Samclp9HXUovvn%2FBeWSnRpc4Nezbj7fDQAb3zMIM1rSudtC1cnBkdvRhrNnK7GUlDE2tR8%2FqbzkfnIWVgyqp00kM6PYfZr71GLrHzaVTx0UdDM6CbaTVLi7pud3onZmMNuBszjllMAleNeslTHV1I50HDiXb5yV9ykX0%2FOQPvP%2FYnXz8pNoVxrB2lWkrqIwRDrJ5%2Bt94amUal543mdETTye0ayWf7woTVBskaS4yE%2BOIlJYyb80mupp7SOgyiG4Dx5D4TglnXXU9g7plWc6piL%2BRBlIZMjS%2F2Vnl7I56%2Be%2FUdwSp8bM5%2BQfXMaxnHh61i1IgSH1YZ9CwQdYMkHPPLmDuw9P5%2FX3JXHfFVOLCNXz%2B5hOsj7ThCFJ7Vrl0Oo45h25P38Krz71CQzie4YN7k5TWwFmdXLz%2B%2FnOkb65nzO8mRblZy3Sc1ml4E5LRXWGKi75iY1aQbY05nNQ%2FKZZPzFmxzXQk0sCOLZtx%2B6IOGOXoUDN%2FUrPzSPYk0L5DIsE5n%2FD6%2B704u6ALu9d%2BzPQ1OzFzu7epUy1L6zhkAhnvrGXURT9heK88a1lXxF9PbTiBYSMGkqCHrZ2oPJ36cfet%2F0NcaBNbb%2Fo1b%2F7jnwy591ckhoI0BE2qt21iZ0UFqXqA%2Be%2B%2BQF1jNA5Qm42LQAgIASEgBISAEBACQkAICAEh8B0QaNuJouKfuN3R7YE19YKqZk1EtwRutsPafjW67an1y3jEIC01gXdefpTpLxjW7I60Dn245wcjUK%2FIcdk9uHxcLk%2FPeoVbF79Bdrf%2B%2FPne33HauF68MOt1bp7%2FmtVGdpeutFdta9GlF%2FbyheiVNTUjusWxVUa9g3lI6X4KN%2Fysgrsf%2Bg9%2F%2FM11llz3pHLGz%2B8g0eej19jvcfXOXTz82P2ErK1TNNy%2BJCb%2F5HeM9Hgwwzo9eyTw3IsP8fHzhjXjJjlvBGedPu6gl2xfYgbn3XQb%2Bx%2F6PR%2B%2F%2BRjz3oi%2BcGb2GsX3ctzoXi%2Bjpp7OJzOXMuv5e%2FjyRRcZXYfxv5eM5pmP1jXPdLD6ZU%2FraYJqbQ%2FcvO1yNFMt%2F5j8v79h%2B1%2Fv4tE%2F3xndDlgtC0ntyg13DcfjcRMONS3vaNpq2h4jawvqpq2K1fgNmHIGuZ8%2BwHN338zLCalM%2BdFv%2BEFBYtNY2y4dDV98AuNGD2fmqs9wezty0qBuLbMbbOVNMz9UG9FthqMC5USJS%2B%2FMb%2B%2Bdxh3T7uW%2B2a9Fl5Hobtr1nci04aOtWRue3KFMu%2F8e3nvlBaYvKiEuuysTz5xKzfNPMq9pJoU1C6eJh5pdEpfTl4rCp7lr7nvWFs7KMXfhjeeQq7bwNWDMhafx5l3%2F4uHf%2FhxfUjrfu%2FFeLh41mVsvW8kDzz3IW2G1oESNfTwTLv0Vo0b7cJnB6HbYhj0LBVxuL%2B16jeHu68%2Fmjkce4cOwmvGhWTOXhp%2F1M0aMGWnFYeky%2Fip%2BtnEvj731Pr9Z%2Bi66x0v73qM5ybuLxWoraBupk5masZHUjYHDO%2FHG3HLSJvyc7tlxuNE57YqpvHrn2%2BzvNJozh2RaW3gb6jlo2l44OtPHRVq7PvTPjmP2B0%2Bx7BMfKR3PYOgjP7WWNKmZTHZAFuu5tbYUVrOBmmY8OW1p2gbbCK%2Fh%2Fht%2B3ixRZXV3PBff9ihXjOvMsLOuJ2nBfUx%2F9j6mv%2BAmPm0wF43vztubVIwcpVd9PrR8FliKNJ28%2FJO48Yo1PPDMo3wQaNqWWncz8vybGTXWg1rgo%2B5Lt8%2BH1%2BclPqk3l191Ib977EOemlnCLVN6cNb5I%2FnLS9O57cZPrOcyNaszHl9c9LOp2WJJCAEhIASEgBAQAkJACAgBISAEvnsCWnV1dct6hub2TFT8ii2FH7B2Ty5jJo0l1RViT%2FFnLCrLYtJ5o0nSNCsI7L5ta5n%2F1XYKTp9Eu3iPFe9g9%2Ba1FK0sxYxPZ0DBGLpkxjdrDvnrWLloLltrNfoPH0vPvGSMYD1rls1nw85aMjvm0797OsWLCkkvmMKAdl52lyxnyaZKxk2YSGaS11omEvRX8MXHC%2BgwdgoD8pIsR4cRCbNvx0YKi1ZQryXTb0gBvTqpZTHRN9lIOMDuslUUrSoj5Emkx4AC%2BnXNbtquV%2FU5zM7SlXy1tgwjPpuC0aNolxZvv48298FKmGq72mpKVhWxflsl6Xn51u4tyfHKXaTCPESoq9zKooVLaXBnMXrcaLSK5SxZV8nIiVPJ9EWoWDudRWU5TFY8XWq9i0GgdjeLZi3CN%2BBURvdIdbRpWjsIla76irWbK%2FAmZTNkZIEVvFd1T%2B1sUlb0Kev2dGfKOYOisSzU9sMlX7KszMf4qeNIU8uOTIOqrcUsKCzGl9ObscP74g5U8dmseXQdOpGBndOtF2IzHKRi9adcc8eTdDv%2FHh74ybCYS2xUP%2Bt3rGbG0l0UTD6NDknR%2FivDVVvBml0ULi1ix75GMjr0ZNjgAaQltoQqjUTMpmCmphVPpH7vZu66%2Bga0c3%2FFff9zKpHG%2FcyZu4D0LkMY1rejNVvFv287S5cWUtkAXfqPYlDPds1bLiuGuzeuYInaMrlzf0YOzSfeWs4Ttsb%2BqzWl%2BM04egwYTr8eeXhcagVOmI1zZ1GsZXDGuKF4VKyYpkP1r2rbOgqXr6U2rNOpzzAG5Xcmzt3iHTEifrasWsKKsgqScnowfEhPtsyYwZb2AzmnoGdzsFZbp3U2DbatWcqy9dvpPGwiQ9Q22maEUKCSzz%2F%2BHHdeX04ZNciKQWPd19vXM6dwPWMnn0VOolo2ZRKs28PSRYvZG4hn9MmnkBNvsGLhTPaG2zN%2B%2FEAr4LF6jqvLFvHl6jAnn3ky6T7XAfez0r191ZcsXr%2FXWh6mnCHR5TZYsWV6j55E%2F46p1nKe2p0bWFy0loA3gzHjx9CwbjZFexKZdOoo4swwG79aRFmdzqSJ41rGw3oWwuwpX8eKVSVUBzS6DRhp7RrkdWmoHZfKVyxlRWWIM06bYG19HQlWU%2FT5THaF0xh32snW7JPSFYtYs3kPyXk9GdK3G18tXURmt6EM7d3%2BICfnAZzlQggIASEgBISAEBACQkAICAEhcBQIpKSkWFracKIoWTTmhhX5xJoREo2hoX7F11z2nBC1m476ZT%2B6lML%2B1T0ak8JaX2HNCLHzLa12LA6rTvQXbDVNwbDiOzTpscJPRme%2FWC91KsZF6zZMR1PLRQAAIABJREFUw4qJ6lK2NDfQZI9qQ%2F3CfoDMequ3XhANFZNB%2FXJu%2FTLf8jKs7FAvkEqudNr%2F2uKtytr%2F1IyJFi7RGi1xOaJt2S%2BnVlnVR8vO6K46thXROlZnm50%2Fdvt2W5Yey%2F6WmQ62TI2X6neTBdaLsUpbbTZlt4zPgfUt1ipI76K32VKfycaFH%2FDZGj9%2F%2BOdjDEiPBum1bXGebZtj8YrapWZxNNnQdO%2BoOpFANf956B62pg1jdN8OEKpjxawP%2BWLlDq6%2F759MHtgu6pByjIdqt1mn6mvrMbRe2qPtqbdr24Fm1TOMaLDig8beca8339stPbT6Z93nMe4pq1i0vrLL5qzSB45Fiz47ZY2DNTYt97CqZxhqJpTzfrLvs9b3isqPxhWJttvUD%2FvebbJNPaOqlJqhYt8Ztg3qrOywnglnZlPaqtP0fNkc1LOjxtp6Xux7S31eWH0%2B0Maomib77c8Kl6tlXOxnSOmx7Wt6BlVd654CS3eUr2rbalpJHfd6DOMlSwgIASEgBISAEBACQkAICAEhcJQI2E6UtpfzHPSC0uRUOMAAp0OlRdD8MtSS1ZyK9aIddWi0%2FPpvOW6aazherpx5KkCns4oli21Pc7Wml7%2BDqtkFvk5ul2s6x%2ByLo4z9Qm1nWS%2Be9kXTEojWL7Wt6zQXt18omx1GTknTy%2BZBstgvmbHGx7Yt0rib1x55jWW1jWieOPpPuobeKb4DG2t19fU2H0xcueFcejwpiS4KP3mZBe%2BF1dQHfHHJjLrqPk7p3675Rdu2zW42yv1gnc1y%2B2Xczmg6W0ulWuVFL2Nzsota%2FWu7uZgv861ttnU5z22Ng9p158Cj6dlrdbMczCFWP6LPRGuNTv1tc3GWanKCORWp56W5yIEOq%2BZsK9Fkv7OuXaDpmWvRY93ozWNvF3M6w1TeQbe6XVDOQkAICAEhIASEgBAQAkJACAiB75DAIWaifIetiupjloBa%2FlFXtYt1G7agJ2fTq1cPkuJalugcTcPVzAa1XW3FjnK27aoi4vKQ26EbXdpn41VRXOUQAkJACAgBISAEhIAQEAJCQAgIASFwDBCwZ6KIE%2BUYGAwxQQgIASEgBISAEBACQkAICAEhIASEgBA4dgnYThTXsWuiWCYEhIAQEAJCQAgIASEgBISAEBACQkAICIFjh4A4UY6dsRBLhIAQEAJCQAgIASEgBISAEBACQkAICIFjmIA4UY7hwRHThIAQEAJCQAgIASEgBISAEBACQkAICIFjh4A4UY6dsRBLhIAQEAJCQAgIASEgBISAEBACQkAICIFjmIA4UY7hwRHThIAQEAJCQAgIASEgBISAEBACQkAICIFjh4A4UY6dsRBLhIAQEAJCQAgIASEgBISAEBACQkAICIFjmIA4UY7hwRHThIAQEAJCQAgIASEgBISAEBACQkAICIFjh4C7tSmmaWIYBqFQCDABrencuqS6%2FiYyZ1lnurUep0yl1aHsUMd3IWtS3axfJWL122mL0w7brkPVi2W%2F1aDjv9Y6HaKD%2Bm3rU2Wc9ZzpI5G11bYzv7X%2B1rJvc93afluHyleHs99NWVb%2Fj4bM2Xbr9o6WzGl%2Fa51tyex%2B2me7nn2289XZzrPPhyuzy8WqF0vWupzz2pm269rnI5XFqm%2Fn2We7LXW28%2ByzU2anW8uc1860U1%2BstMqzx9BZT6WPhqxJjXVqrfNoyWz7nfq%2BbdrJQOlwXjvTh5K17qez3tGSOfvXWmdbMqcdtv3Osk6OdtnD1e3U49Rt67T1fZcyuy27Dfva2XZrmbp2Hq3LHq7MWc5Of1td36Ses6wzrWxwXrdOK3ksPqrc0ZA1qbFOTp1OO5TwSGSx7He2a%2Bu3yx1KFssuu97Rkjnbb63zcGXOcs70t9Gn6qjD7mfTpXU6WjKnXa11Hi2Z036nTmd%2FVPpwZLHK2Hn22anXzrPPTpmdPlxZ63LOa2fa1mufj1QWq76dZ5%2FtttTZzrPPTpmdbi1zXjvTTn2x0irPHl9nPZU%2BGrImNdaptc6jJbPtd%2Br7tmknA6XDee1MH0rWup%2FOekdL5uyfU6ezLdtGdVaM2pLZupwc7bJO3XY5%2B%2FxNZLY%2BVbd1vaMli2W%2Fbavz7GzPmW%2Fb5tTjlB9cz%2B32oOs6mmb3qaV8TCdKMBjgztunEYlEYlZS1ZWzJZbCI5Wp%2Bk69znac6dbtKJmzrrPs18m%2BbXvOelbjx%2Bh%2FrVnYdrfm4jT%2FWJI57fr%2FmXYycDJUNrQls%2FNVGcX5cOsdSqcta2vcnG0407Hq2TqU7EiO1u04dR2uzFlOpdVh2%2FdtZLF02Dpby1S%2B3cY3lVmGtqpv2304stZl7Gvn2bbNmfddpQ%2FV1reVKVtjcbX70FrmbOf%2FQtZ6%2FJx2fhuZXf9QZ2efW5drS%2BZk07rM0ZIpW%2Bw%2Bt9b5TWROHXb6cPupyrXun123rfzWdVqXc163Tqu6ykaVb6dtffZ1a5ktj1XvSGSqrjqcNjZlHbXToXQfrsxZTqXVYY%2FzdyFzdr51e99EZo%2BXbatd17bZPtv56mzn2Wen7LtKH6qtI5W1VV%2FlqyMWo28is3Woc%2Bt6rWX2ODjL2fUOV2aXi1XPKVNy%2B1DttSWzyxyNs7Od1mml37bBKVP5zmtn2ilT%2BU4dsWROua3HrhdL5tSh0sfKYdve2h67LzZHp%2FxoyZxtt9bZWua041Ayp53%2FF%2BlD2fZtZKqOOuz%2BO3WofOe1M304Mltv63rOut9WpnS0Plrr%2Btk119KjZy%2Fc7oNcJhyUoyoHA0HWlRRbTpTWyuVaCAgBISAEhIAQEAJCQAgIASEgBISAEBACxyuB6ur9GEYEDnaZIDFRjtdRl34JASEgBISAEBACQkAICAEhIASEgBAQAkeVgDhRjipOUSYEhIAQEAJCQAgIASEgBISAEBACQkAIHK8ExIlyvI6s9EsICAEhIASEgBAQAkJACAgBISAEhIAQOKoExIlyVHGKMiEgBISAEBACQkAICAEhIASEgBAQAkLgeCVwUGDZQ3VURd116W7cLo1QOIRhRKPxHqqOJVP1XB7SMtIxAvWYLjdhfwMN%2FmDzpltfp8Pl9pCQkIgW9lPX6KcpEPDXVRO5EBACJxAB9fmk6y5MI9IUGNuF2%2BtBMw3C4bD1meVy6ehu3QoIFYpEcOs6kUgYI2Ic9ufRCYRUhVtHV8x0F0YkTDhifG33XbqHhKQkXJEgEd1Hgh6mcl8NLX8yNHS3l%2BS0VIz6fdQ0hiyddj3dCGK44%2FGafhoNDx4zQF19I5EWBTFtcOnKTje6q2UrOjW2aqe5w%2F57FVOzZJ5YBDRrS0O3L46khDj89XUEgiEiRkS%2Be5xYN4L0VggIASEgBIRATALfwImiHCgeuo08myvPHcb8V%2F7OjNV7rS%2FFmuZS37PVHkYYhgFN18rponb7UdeetB787223EFn5Lp4%2Bk6hc8hr%2FenshZlNZ01AvMBqaS0PDtOqpa7U%2Fs4aBOyGDy2%2B6lZQdc3jomQ8wDqjXtK2SMqLJu2LZEbPLkikEhMBxSUDTSMnuxdXXXkX18vd5%2Fv1F4I7niptvp5trBy88%2BRRl%2B8N40rrwg6uvpndSFY89P5OLfngeGz59jhlF2y0nivrMin4eHZeUvnGnXC43nYefwVUXjGLpG4%2Fw0VcVzVtgWso09ZmtDs36O6DY%2BdLy%2BOmtt%2BLdOIM1%2BgjO6rybaX94gtpQtKT6mPbl9OXnv76Oxll%2F5%2FGPSghHIk31fk1c2Tx2Zo9lQHARReYQBmjFPPyPV9kfVi%2Bx6u9MBNMwMaxtKtWESuXQ1%2FDm9OEnV%2F%2BIzqleNJfLcqZUlRfy8BP%2FoSEQxmX9TTIsh4qSK2vsv1OmaWCayuEf%2FXtm%2FQ1Ral2aVU%2B1ofLEgf%2BNb6H%2Fugq620P3kWdw2flTaJcRT%2F3%2B3cx55zk%2BLdxMJKLun4j13UfdT9H7wkRTjkZX9F40IpHoZ4n1fajpubBu0aZ7yTSJKJkcQkAICAEhIASEwH8lgcN2oqgvnJ64BCadcy5DBuWS3nAuS8teJpiQy5C%2B3QiacaR6GlhRuJSacBpDhvYgHPaSnuRiw%2FKF7NZ9pKSk0eCOsLG8nMryClyeeLoOGEavvDT2bl3LytI99B0yirw0L3u2FLN6037OvvoWJnQ1mf7ZbHZu3UHV1m243HF06D2Ifp2y2FO%2BhuXrdtKuxyDaJ2n40jPx%2BveweHEhdcHDnCnzXzl0YrQQEAJOApruoc%2FE8xk5ZBChXChaupLimnQGDOhPj%2BR8Jq%2BYw3Mz19Ft0HhOGzuUhMhecnPXk99nIKGV2eT2yGZArw6Ea%2FeyfNEiKoPykqP4qs%2F9iWecweCBXemoXcyCdS%2FTZWBfKkoK2V0P3QYMw1tfgSe7Ox3T49lZWsSaHQE2lG4ncesu4gckkJSUiCcug%2BGjhpKTpLOlpIgtRjwpKRkkd%2BzPpCnd2FaylPV7%2FFa95G17yeqSRJLLw%2FbVZSR6y8kZeRa%2F%2Fv5ZbF0ynaXrthHYu4mv1u8ktX1PeuW6%2BGrlBiK1u1k8%2B3PKkn0kdRjEeVPGEd5ZhNftIaPrQPp1z6V6xwaKVpWR2W0wXdPBm9YOT2MFhcuWUx3W6T1sPF3TPZSXfMW6bVVkdurH0H6dMBuqWLxwKdX%2BkMxYcj54x11aw5fSmR9dfilJFUt5Y%2FpKPAnJNHja85Np15LPZt774GNW7YTBQ%2FLxhqpZurQQT6cxXP%2Bzy6ktnsWMeUX4UuIpXFyIntaJfl3TWLVqHd0GjqR7Tgr7d5aydHkJwYh8Rznubh%2FpkBAQAkJACJwQBA7biaKmySd1HMWwrsmsWbmSjr1G0r%2FzDPw9z%2BPGH08hVLePRi2ei85czgufbednP7kAX6SBuoBB%2FKVn89g%2F37V%2B9fPFJzN4wCAq%2FRuI9LuEn507nP3769DNBpYtLWXQyEG4XW7iPAYzPp7H6DGDyPE0cvqZ8fh92YQzK9mcOJabr5hEQ3UN8fFuln72KqH88zm1bzYNtdWYvnh6pt%2FD0x%2BsICI%2FG54QN7J0UgjEZ%2FTglLEDqFwzh3DeAMaPGcj6z7ZZs9OChs6gcRPJLNzFsLEjiTP8Bywtyeo6hNsvOZOEcC31%2Fjo6uXfwwheb5WXZpZPccSRDumWyYXURnXqMZujAYk6%2F%2BqfsmfUUL81t5Mc%2Fv4mE6q0kZecRMlykeM7nw9dfJn%2FkQLT4DaxVMzl0D2Mv%2Fjlnje6B5vaR6P4eL%2F%2F7E9zuOHpNupSs%2FX6SPBcw8%2F236DpqEFrCTvaqJTluL%2FlDChga344MvRtd87LInjCFrkPDZLq28ts7HuHky69lbMZ2Nq5%2FhKr6SormzyIutQPX3H4x9Zvn8tJrH9F5wlXc%2BMOJEGzAl5jCivcfY3%2BPizh9SEcaa2vQvB6GzXiJeQ0DueGCoVTXBol3n8%2B7L33I%2BB9cTpbeSEMgRGZ4J68v2HJYS5rkifxvJqBZy%2F0S09LQgo2Ul28ga%2BiFFPTpRmIkg9MnhxmR3J%2F8XB96YjpTTprP%2BnBXenbMxp9yKokdBtKjaw5%2F2XATesE5%2FPyc3nw0dxvnnjmMYH0docZ9VNx5Jxv3N1izqf6bSYntQkAICAEhIARORAKHGVhWw%2BNNZtSUs0gP7%2BDLGZ9R6c7m1AmDSXC7CFTv4rHf3cLtD7yAkTeYqUPaYYaqefWxP3D3vX%2BhOqErpwztYU2JVkt%2FlEMmMasXp04cwtpPHudXN%2FycG266hTc%2FfJvPl62nvraRiCeFwdnbWLRqO5WblvKXBx5nb6NBXGI7Tpo4lsrCN5n2y5t4e8kuhp5yJtlJXirWzecP0%2B5iQXmAvv364LGm2p6Iwyp9FgInGAFNp1v%2F0QzIdbF09qcUb6%2Bj%2F5hTSfLo1nLA8k3lJHceQkHf0QzvlcPW9asdThQTPS6ZFJ%2BHUN1eZr%2FzMu8s3ikOFMDtSWbE5Klkabv5cuZMdpvpnDY8gXWbKskffRpDp55Lnm8fH73xEtOXbqChrhYzLochA%2FrjVfFJ1LJL5T43DVZO%2FzfzVm6ioa4RV0I2A3vkQMTPV%2B89zK03X8%2FCrQajTppInNdt1VN3sPoIt5bbBKuY%2Bc50Guob%2BOCZh3j6jdn4cgczevgkRvfvzJYVi6gPhK0locrmSVfeREG7el58%2Bnk21ScyaepY9q%2F6kNt%2FdQvPzdrIiNPPpFOqj%2F1bCrn9tt8ya%2B1eug0ez%2BmTx0JjHUEVdyuxI6efNpr0pCTC9VXMf%2B9ffFy4XV56j%2FuPFpNAzWb%2B8fhTbIu040fX%2FZLf3%2F8Ig7w7WL%2B7gZ2rPuCRf%2F2bt15%2Fna17a6mtC9K%2Be2d2LvuQukAD8157lHfnlKLi87g9Gi6PWubjJi23PT6Pi33b1%2FLvpx5ga31ALVw%2B7mlKB4WAEBACQkAIHI8EDsuJon5FTM7uxOkFnQmYqZx76eWkYdJz5GTy8xKtL7lutwo%2BGF2Zrv5XX3zd1ppz3fpiq74qNH9dMNUaYfUFW8OtGdY6YrcvlYmX38rZw%2FNYuWIpexrUF2LdWjdsxSiw6Wsu0EzcbqxAhy5dXRrWr80Bfy01AT%2FhkGkFsrWryFkICIHjmIAKfOpNZszJY3AZGqO%2FdwNDOyaTkteXqUNyrU%2Be6rJiNtQkcebFF5AZ2kbh6r0HAKnZvppHn3iWTTVezrjiZq49dzieA0qciBcaKbldmTSsM7gzOefSK0gMNtBz1GSqSr%2FCk9OXCyb2pqK4kOzxV3BBQTsK5yxgb0MQTbeijUShaeDyJHDpTbdxUn4Sy5fMoyFo4HYpBxfW2aW5m%2BJZNf%2BVOAC4irOiAv8apjpH2LGxiNWVOmdeejFZ4S3MWbCSUMTA441jxNmXc%2BnYDsx4%2BVlKdjTgcbtxoaPpLlR8F7fbq%2F6EWH%2BQQn4VMDRAIBK2At26dQ0z3EBV1S5KV8znk4%2Fe5sl%2FvsCGag9Tf3QrV04daAVWP8A4uTjuCKgfe2q2LOfx%2B3%2FP3fc%2BQNGuAP0H9cWj%2FIFoJHcZxc9v%2FCkJtaUUrttOxNBwqRg9Vmw3EyMSAk0nLj6R1NQ0dJfJxk%2Bf4YW3v0DLGsj1v7mH4R2TmmLtHHf4pENCQAgIASEgBI57Aoe1nEfTdTJ7DifN3M%2FTf%2Fk9hVv2kdplDL%2F%2B1Y%2Fp1Q18ydn86JY7qScZdq1hTkklVwxL4pz%2FuYlx9RoJtVtZuHwDpw7xYwYaIeCndtc6Fu31cenEH3Nb7%2FPw6Aa7aw0r3knfwcPJjQuz1e%2Bn2l9NQt9%2BXH11Cl63SWP1dhataqDfhWfyi98UkJmTwdoF77C%2FwyQSgkFC4QiBQIBwSO32EPsL%2BXE%2FqtJBIXACEVAzHeLaD6ZPp0Tmv%2FkIL89YjSu5Mz%2B66RYKThpCMBSgbt8Gli7I4GfnDGX9l%2B%2Bxdk8mU4NBgiE%2F%2FmAQd1InLrloNK5wxNqBQ32GnPCfHpqLnN4jSdNqeP6v97KodC%2Fx7YZy1%2B%2BuJSP4KUVb6hjdSefjeUsID%2ByK5s1lwJixZMdrbPT7MYJBIsEQQS1IMBggGDLwpKfSb%2FhJ%2BMwwAb%2BfQNikx2n%2Fw20D68lK01n42VzyJrQHNTaqjnJwqPpakPr6fTRGNMae%2FyP0z95lxpzl3PqDMZTMfIs1OxtQ4SW8Of04fdI4fBoMP%2BvHDJwaoXrXRhYsKKL76afwq2mDScltx%2FLPn2dP%2B6kk%2BwLWrk2hYJDG%2FRXMXrafrqf3IzNDR3NlUNGlLyNHjCdBN4mgEQyFJbDscf%2FZouHydeGGO24izxtkf6OLzhkRViwrprFHR7p2Gc9lZ%2B%2FD63LhzenOqOSOmKFyGuprqPGbDJp8GQllW9jt17n0%2Bt8Qn5GH0biTnJHnMGZoBzRUcOQIgbDEXDrubyXpoBAQAkJACBy3BA7LiYIRoaJ4AS8%2FXcii4nL8EZNA2SJeeimO3r0H06l9OrPnLiESqWHBrJmQfyERw8%2BKxQuoqqtl8RefsakqRM0rzxDathrfmnrqt6ykvPJLyktPZni3dDatXMTq8hoKTp5MtquK9dv9hHYUsr62DE%2FDadYvPusrTSIVpRRv3cfubRsY2zebne8XMa9oE%2B17VZAV2U59wz4%2Bf%2FsFNoRLCZzwb0HH7X0rHRMCBxAI7i3l%2FVeeZu2ipVQ3hHA1buD1Z5%2BiX0Ydtb5N7N9QyE7%2FWp7ft4LSogXsN1J51bWRresKee1Fg%2Br1hQSXlTN%2BUDf2bVnJF%2FNWED6ghRPxwmRPyQJeeXYpS9ZsoS4YocG%2FhOeeS6R2YyHVqyso7eJm0fINNK55nEjVGWSbe5j%2BoZ%2F6XRsIZ22BXcXs0XdQs7SGJSUBJkw5hYTGCnYGdPaWFOEr3kaCodErP4eNhfMo2lhJj61%2B3BXrqEnazKrgZja7trDetZVtGyv5x7PJjOwWR8mmzVQHthLw92Ph3KUEwxHLZx6uKOG911%2BhuF2S2qzHmt1Su6uUxctK2LyhgBF9O1Gz42W%2BnL%2BK7PxqVuu7aWjws%2FCjN9kRX82y4u3sLTuFwb3aU7V5OfOWrSOzeBsjB%2FWkfsdaZs5ZQ1h2VTnOHwYTI7CFRx94kPETxtIpK575785h7koV96eYxjMmUFkyj7VvJzN%2BTH%2B2r3odV4LJsqJVrGl8kUlDclm14Eve%2FLyIKeN6saG4jLi4CIWFa9m2%2FRR6tk%2BmbMkMVuyok223j%2FM7SbonBISAEBACxy8Brbq6%2BgBXQyQSoa62lit%2BeAkqfahD98YzZPKVXHtufx657VZWVPrB5aZ9wSXc%2FtOTeeeRu5m5csehVIhMCAgBISAEhMA3IuCOS%2Bfc6%2B%2FhzNz13HXPk2yvDcoMkW9EUAoLASEgBISAEBACQkAIHIrA7%2F%2FwR4YMHYbX62sulpKSYqUPbyZKc7UDE0YowLqF7%2FJw%2BRyK9wejQiNC1apPefzvy9m%2BseLACnIlBISAEBACQuAICRjBGua99Tirw7vZURsSB8oR8pTqQkAICAEhIASEgBAQAodP4IicKKZpUL9vN6v37UYFf40eJoHGKtaurmoKFHj4xkhJISAEhIAQEAJfR8AwIuzZXMwea8WO%2Fbfn62qJXAgIASEgBISAEBACQkAIHDmBI3KiqOZbnCctxsTKa5FKSggIASEgBITAkRGQvzNHxk9qCwEhIASEgBAQAkJACHw7Aoe1xfG3Uy21hIAQEAJCQAgIASEgBISAEBACQkAICAEhcPwQECfK8TOW0hMhIASEgBAQAkJACAgBISAEhIAQEAJC4DskENOJolaYy1Tp75C6qBYCQkAICAEhIASEgBAQAkJACAgBISAEjk0Chwi7d1BMFA1waZq124E4Uo7N8RSrTiQC6ols6wk%2BlmRfNybHkq2HsuXr%2BiFyISAEhIAQEAInCoFD%2Fb38b5F93VgdL%2F34un6KXAgIgW9KQHOp%2BSbqM%2BLg42AnisuFz%2Bfj59fdQMSIoDVVNNt4kVNyp8x57Uyrpp26XJrLmu3irGuX0TQNwzSs8k65qt%2BW7OCuteTY7aocpc957cxrS6bK2HWc9rS00JJS5VqXsfPsc0vpFr0q75u079Sl0nb91rpb22LL7Tr2tbNtZ9rWa5e3ZbbeQ42jXVedW9trj2NbslgOPNWmak%2FdG%2Fbh1HsombOcM6302PVUfluH3e9YcptFa72tr1Vdu41YddqSOfPttG2Hrce%2Bts%2Bq3DeR2XrtOva1rU%2FlO%2FOc5dqS2XUPZYuzjEofjl6nHXYdZ56tw9b9bc62zbZeW2esfLtMa1va4mLriGWXrStWXVvWup5d1j7bcue1Ssc6vs4WZz27fZV3qOfefrZb63bWby2LZZudZ9dT184%2B2XI7X52dZWPlO%2FvjrG%2BnD2VXLJmzvVi22e3Z5exruz11bksWqz27nl3Hvo51bssep95DjaPSadvrrGO33ZZMjf%2B3%2Bfx2tqHadl63lVblDvX53ZYtlv4mO9vqh7P%2FKq0OZYd9fzdlNedb8qbvLnZZ5xg403Zdu2372j47%2B2vn2edYMpWnDluffW3Xad2289qZduqw68Zqz5bZZ7s9u32Vb9drLbOv7bpf175d7puc7bZb3992vjrb4%2Bi0x2mLM63atvtm64hlj60rVl1nPbucrdeWxcq3y8Rq75vk2bqdttl9svW0LhNLbtdvLbN1tD7bOlW%2BXdeZtvPss7O%2B3Yatw752lnGmVbm2ysSS2Xqd9jj12brscs5rlbbz7frOurHas%2BXOenZdu3xbstbl1LVd1rbLqb91Xlsyu11bX1ufmUqf%2FVkbS9ehZK3bcNpm17P7Yuu27Gn1LugsY9tp62rdhqpvy2ydqoz93Fv6HfeLrduuY%2Btz5ttpW59d1r62z3Zd%2B9p5jiWz9dr67Gu7nspvnadkscrbeXbdWO3ZMvts67brOuvEktn11Lm1bbYOZxmnPme%2BSseS2Xnf5vNb6Yx1T9l22bpb22Hbos7OPql0p06d0XU9VhW06urqmN%2BuPR5PzAqSKQSEgBAQAkJACAgBISAEhIAQEAJCQAgIgeOVQDgcPuiHoZSUFKu7B81EUbnKU9eW1%2BV4hST9EgJCQAgIASEgBISAEBACQkAICAEhIASEQCQSOciJYlOJGVjWFspZCAgBISAEhIAQEAJCQAgIASEgBISAEBACQiBKQJwocicIASEgBISAEBACQkAICAEhIASEgBAQAkLgMAiIE%2BUwIEkRISAEhIAQEAJCQAgIASEgBISAEBACQkAIxIyJ0hYWFXHfMCIYEQM0Fy7d1byfidoCqGVvE9Mqo3b3UbF3XS49WtY0iZgqwnM0QrLSZ6qdVtROPUqvEY1xq3TpSp%2FWotG2yTQMa9cgVVZz6bibbIgYBoYR3bVF1XPpOspDpNYyGabSq6G5NHSXjqaZ0fym9v4fe%2B8BJ0dx5n9%2FO0ze2Zyjcs4ZEYXIRiQDB7ax%2F4CNscH2OSc4Y4yNDcfhwwmDAwaTTRYIhDJIKOdVWIVdbc5x8kx3v5%2Fq2V5GywoLfC8GqRtWPV1Phef5VXV11VNPPZXkUfjsxcxbPCP8wggejpJLuO3tT2sYJn9JejI9SUnSAAAgAElEQVTMTCc8A%2FenEfyYpxSk8GNKKJ77ZRN4Cr%2FLIt%2FUdCKt4FvIIfgwn%2FvlE1gITBXF1oFZ7cK%2B2wgcEwFDJ57QTD9P4h0b6hL9kNmniH5NwjwBSryXZvz%2Bd1ESNEE8yS6rHxN9jvBbLvos0feKPszsv4xkfzREd32SIWWLe8IgIMY65rgh%2BT0Xcom2bn7jzXGQPnDelaKoKf2CeD%2BSf4qqIInxgq6T7DtEHim09wVLxNMR%2F4kyJUTfkxxj6UbSyV3%2FaMk8iUDEMMOTIy4zzMo%2BOY5KymOOtwbOdBAxJBRJSY59DDEWEUMf0QeKsgQPGpakJg8i%2FKgXXeSbHPm8Gy7CxPhFnLCY7CdEEnP82F%2BGLKlmmYZh5S%2FGRMlyzT7mqDzFOFEEyEk8DVEP7%2FIpfpv9t9kPCSSO3Ueb%2BSSlHCSHmeU%2F%2BUfwkYzyrqz%2FJMl7yMl6EOnfj8%2F3JPuXAvrLFCUeVXf%2FJFNzvJ5sE0fVjdkmkidgiLZybLT%2FSf422UbARsBG4BOOgPLDH%2F7wjsEyiI5WVQfpVwyDRDzKvvWv8PjTL7Fu43ZCsp9cn8aGN5eRM3IsLiXZnepags7anbz8zOO8vmI9h7sTjCwrwSHH2P%2FOq7SrxeT6XSRiIXYve5Iu73CCVW%2Fx5HOL2bRpMwfrO8kprsDvSX5oLf7EBzfU3cSaxU%2FxwuI32X6whbySCjI8Ek17V%2FL3pxezceNGtm3biZpdRkGGk6r1L%2FDMS8vYtHkzB1uilFWU4FYMjmxdzuP%2FeIVNGzewZcs2alp1hueEefJvf2ft%2Bg1s3rqDoJJNSUEW6sDEyUCL9LJ15Yv844VX2bxtH3F3NvmONp54JJlu08ZN7DrQSWGhl7f%2B8ShL315vylTbDaWFGWxf%2BgrBjHJTfqE4CjTtZuW6Q%2BitO2mW88n1Oehp3MdTf%2Fs7y1a%2BRU1TL3mlpfQeXMXfnxHybWDL5i3UBJyMGV6E8kE%2BihaQ9t1G4GRBQAwEY3088j%2F%2FTbRiJsXpzgEFZioEiXA3S%2F%2F8IAybQZZHouvwRp7f3c2k8jwS4Xae%2Bs2j5IyfSoZnUL%2BYmskJ%2BVsn0lfLP5buYuzIctAirHzhCYJZI8n3O4mG23hmyTrGjB6BY6CfPCGBsIU6iRDQ9QSHN73O3l4%2FZfl%2BJENj5%2BrXaCAXd9dOnnziBdZt2MD2nbvxFIwkN91l9itikSdQs5YX1zQzYVwpRryP5S89j5E%2F1uxXwrXreGFFE%2BPHlZnK2mNCaujsOPQC6%2BpWsbd1Jz3hdArSs1EknYZDT7Gs9m32tGxif%2BsuFE8F6Vova6ueZUvTemq6EhRlF0HXXuo1F5lOJ1qsh5UHDxHsWcfa2pXsadnInpYtHOzooCJ3FHKknfUHXmBz42a6gj4K0nOQ0akXZdW9zd6WzTT0xCjOLMGhJJUuJu%2BGzu7q3XgycnFaSh49RmPNCpYdWUpb0EVRRp6ZV1P9elZWv0ply27CxjAKvAY79z%2FKuob17G%2BtIprIIT893Yy7q3o33v48DT3BgdpNZKaXYsQ6WLv%2FGbY27UKThpHrcwv1Ed3Nm1nR0MmwnDxUaWhFueBXC7WwpHIXZfliPHrseEPVi67F2XN4K6qvEK%2F6wdIm8zOIh1tYXd9LRUbakN%2Bhocr9V8PEOHPz4Z3kZOZ9IJm1aDtv73%2BWbU2V6FIFuV4XxHrYXPU8G5q24XCWk%2BV2f2Ry%2FKs42OltBGwEbAQ%2BDAJDOZZ1uVxmVsf5JTCIhXupfO0B%2FveR5WSNnMrM0fnsXrOYfQcPsPTl5XSFE0neDJ326u3ceefvqI1kM2l8OUdWPcHPf%2FsCfaEA%2B1c9x%2F7GXnMtJB7pY%2F0ri9ld287%2BjW%2BzuSZGZlYmDbte567v%2F5TqrkiKvAahrmae%2Fs29vLq9jbHTp%2BNu2sKv7ryDQ2091Gxexq6aNnLz8vAZTfz3T37KpppW9qx6mSNByM70Uv3WM3zt9l%2FT0B1h34a32HokTm5%2BEYVFheTmZxBs2sXyd46QnV9IhiPCi7%2B9jZeEgsNcfRDWNXG2LX2EB17exvBp85g4KpfG2ib6Gnea6bLyCyksKqKoJB%2Btt4Hlr72DKzOP%2FGwv2577Dfc89hZ1%2B97mtVXbzdUpLR7lnecfZVNVI7tXv8yOgy00HVjPvXf9FzVGFrNPmU6kdRcrth7h8MY32X2knfzC4mQZeVn066xSMLJ%2F2gicrAgYREN99AVDdLS00NUbNFcNxQplqHE7B3ocDMtSifZ10dzURE8wmgKUQVdjFWu9syjJkOms2cJvn9nAir1N5sqxw53B2XMl1m87gNa%2FEpmS%2BIT%2Bqcej1K38O%2F6icmRibHn2XnYf2Mn%2B1pDZL6pKGpn1u1lf23dC42ALd3IhoCfi7Fm7mvVVTcl%2BRNfY8dYytuxvpGHvSlYfbiMrLx9Xoomffuc2djcF0HSDRCzCyufWUDx5ArIe5vXf%2F47N296mujuOjoKjcDqJ9ndoDscHrBqGRFYoDpr6mD3xRi6b9AXSw2%2Fz6q61JHSNhvo1jCn%2BPJdPuYUrpn6Rkb401u16jpz8K7l86le5aMJ8%2FLJEtH0H1YEOouFOVm98mKzMciaOuIzLJl9HSdce5g%2B%2FgcsmXoAj2sSj6%2F5CXv4iLp30WUpju3ll9yZCmkZ901pOH30Dl0%2B5mYnOHv6yeScRLWkJYvKta%2Byr30qPlhz%2FGXqc1rrXebFJ4eJJN1Ec3cLivfvo6dnDiqYgCybczKen3cCsomwgTFN7LxeOv5HLxl9GvG05L%2B49REKLs7fu3TyFQquueScJPca6dXeSkXspF4w8m707f0lTb5BA6xZerFrB%2BiPVxIT175CAJgP1WDeV7bVEhQX0B7x0PUZ14yY6I%2F1j3Q%2BYXlR4ItbO2roj%2FRbPHzSDDxdfklVmj5yGW%2FkgCwAx1q29g%2By8Szl%2FxJns3XUfjb29bNn7LH3es7lk3KVs3f08jcFI%2F%2Fj4w%2FFmp7IRsBGwEfgkI3BcvarQZEcC7Tz55Ho%2Be8cfOHVUjjBu5cyLdLrrdiJWX5IfLgM9HmLPmicpufBLfP2SGSiSxhlnnsXdP%2F4xm2tno2k6imUTaQjz1uSWF2E6XzT9bC6%2FegpSdBFbXn6Ax5Yf4PYrJ5vbcgwtTtfht6iMVnD7j79KhktGO%2FMMCv7yK55aVc1pmkTpyLksumQB8XCA2n0%2FoqkrDJKTyfMu4MrTRhBfdDGv3Xcry7ZeSK6ukzV2DmctnITH5cKhSERq9uAtm8CFl1yGHOoko6%2BKutauo%2Bq3r7WDhHc4kyZOoiDLjyob9FU14CwYyZkLz8XnUPG4XYSad%2BHwZXHOxZdS6NKp8IV4ZHM7068%2Bn%2FWPr6PlotlkyV0s3dHNxf85m46X3iAeDbN37SriU2%2Fmv764wOTpjDPOAS3MhmqDgvJpLFi4AIeq4k3zYxtSHlU19sNJi4DoSBKsePgX%2FPHNSiRZx5E5ke%2FffRvT8p3sXfsmmSPPRG3fx7fu%2BCUdfRE8%2BaP46S%2FvZnim00zbUVPNwtPOweVw4K6YzndvHcFtL%2B007dQl2UH6lLPpfGkPCW0iinryGDBrsV42vNbLvLuKUFUXM676PkVr%2F8TGfgs4RVWZNjufp7ZVc9aIabZp90n7Dp5ogie3kBgDW36tLSNipCNRPn4Ol15xAWqkndp136CuLcDEIr%2BpANiRPppbS7xIisr5t3ybold%2BTZf1vigqk%2FJcbKyOctkE9X23V5g7WMSGGMXFuDGfoX3L87RqM81tRtbWGnNLnQR9sTDl7gQJTcep9lvwGjqxWIAVm18ge%2FQtTM33JLcGG2LbjNjakVxDa6%2FbxLipNzIiOx1VlikdfSHVmx6ipmu8uY0mub1HISu9gt7DB4kb0%2FAMVHc%2FTimqi0C8k%2FKc01BlhZKyGezasYl4dimq7EPXIui6F1URm1mSo0aRv%2BL0M2PKIjpW%2FYLQsLtIaGH6Iu10Jhzm4lVIiwMKWR6VjlAHPVKQXr0Qt9NJmn8Gn%2FMVc88725P9j6FxZPs9dJbfwKR0J%2BvWPcCaUDV5GVdz7ZgKcwFPKGa6myt5Yvsf6CKHi6Z8jXEZGq%2Btf5UF868n0xXkzTV%2F5rT53yDSspEnKv9CnzSBHD3OmAHZxQ%2BDWKiNdZt%2Fw1uBVsYUfYFFk%2BYQO%2FAo73QbHExEuHHudezf9QiLW3dR6p1HhDEkEiEqdzzKyy1bGV%2F8NS6eMJGOw6%2FREOhgbSSHr59yiWnxg6GTiLTy%2FNt3s0%2FrYWrFd7lw5DAO73qM51o2UJ53PVdOm0%2F0wN9Y3w1VsR7mKy0UTrmdYr%2BHgzsewz%2FmClbvXMtFM8%2BA3kM8uvm39Mp%2B5o7%2BEacXS7zyzq%2BoDOucO%2F4HTC%2Fxs2rzY8yY%2BwUyPQo94Q56jT56jXycaozGAJw7sQBVlZmbE2BbUzuFo4RV1cnzTTyq%2Bu0HGwEbgZMageNSoogPhdh602CkUZSXiero%2F0jriZS9wOb3BEOP0dnSwbBxOTidDnO%2FrZ7wUOyWaO4M4ExGE1m%2B51IUBYfDiWzEySsexuGtRziwoYl3KmvJLBrDCL0Vb24hfrcThyr28hrk5eVQX99IPC1O5dpnuePQcuLBbig8lfkjM1gnPtCKisPhApeH0WPKWdnWRa5hcOTNB7l9owe328fpn%2FkmZ%2Ft1uveu4Bc%2F2YcW6qJJGsGPrxpGzZalrNlVR%2FaI2Zx68Re4Wn6en%2F3426Sl5zDros9wQZFB395l%2FPSHW03%2Bx577Ba6dphDurOPXP7sdtxSjriPOTT%2F6BfkFOuP8y1iysZoL0jYQH3Ya08rTWClJpl%2BYzq4QJePKcDkdA%2Ba%2BWjS5ar57zZP8eNcSHA4HF934IxbNHvYeDO0AG4GTEQEDg0gswbAzr%2BHWK%2Baw7qnfs3pzNZPOreDNdfXM%2BMokPFkqt3z1ZvYfPML29a%2Fz3OZGvnXOMGTDIGrEKEx3oMhicK%2BYfZxQUppDQ9MXSj59bBjwr3SyYKwnNHoYT7pP%2BJKSUFSH6YfKkl%2F4acjMLiayodPs0u2htIWMff%2BkI3CstiwWlQ6teY67Dr2NHAtQWziHG8qzkhNJw6CwIB2PKvwHSagOh%2Bm7zJpjCoVBekEGLe29gM8cDUXDYWKxOCgOPF5PyvbhJILivRM%2BKTLcboLCgsJIsHLffWyqduBQPJw3%2FiucNf0Kdu5fwsrgYXzpp7Jo4iloRpwtlU9TkpYFoQASniGVnIlogBy3y3y%2FzbJkhRxnL5GYDlonz227B4%2FDgUMr4coZl%2BIy4gSjAQxk3LLj6KGcpFBWfC6Htj7J4z19%2BKUiYkTxZM9lfmILK7f8mXYpwpyRNzE%2B511rkKSiJp1cV8L0pYIUoyvQiOJwoidixAwxPorRK%2BejxdvpDEfwewwi8Ti4hVJGjJesGpMpnfo9irQ4Oyr%2FgTHqi3xbjFsVJ1r3ARNzTQ%2FwzsENXHnqffiVEC9ufp2sCXPpTURIGGJhL0Yg0kg83sGy2mauPe1%2B3HovL216CgyNaKyXmGHglB3sO7gcz9hb%2BFaGl%2BpDz%2FLqoXLmRzpxFizihtIywg1LactayDcnX0%2BwfSO%2FOwjt1U%2BxX53Fl0%2B9lJaDz%2FNWXTajIp1QciFfyc1F16OEEgnTX16gdS2NjjP54sx5pPsy6WhdwwZ9Ntef%2Binaa5ew%2BPAoTol04ii4hBtLywi1rWFLUx05kpv1nX1cIUuEo930dR%2FkxcodfPq0e8lyO1Ekmcp136Zk%2BDeY74fdO35Oc%2BYdnDvnOtBjHFAKicfa6TTC%2BN3i%2BxrGqYjtO8lvgdeRTUL4uDEXRS3sP%2Blvvc2%2FjYCNgI3A8SNwXEoU8YETJu1j0wLsrKplWHoFmE7WLAetOol4nHhC6EYcFJWX8%2BqO%2FZw7pQyvohHsqqU24GRGcRYdPh%2F1re2Eo3nEwiG6QlAh9loCiUSCWDSC1tfBrh07mTz%2Bi6jyERIJjRhO%2FEXDiazcSn1niNIMlUSoiwPVdYyZuBBHy9uUjJnDVRfOItFXz1%2Bf20JbUHTwOgktQTQSJtTdwqpNdZRdk4fUJlF%2B7s1874rJpuWIWFwOV0s4C8Zz2dUXIofaeO2pF6hpCTBZNtASmrkq7coo5JyrbuL0C7vYve4VHnv%2BCRbcPA%2F%2FhHO44%2FvXDliiBBt3onizOO%2FK%2FyDXkWD9K0%2BweX8L84aNYN6csfz6laeJGHuY%2Fx9341OTkzVZUckvzGTdzi30LRxu7rsVmIj92ELnNOmMz3Dr5xaY%2Fmo8vrTjr2U7po3ASYCAcHaaVzaewvw8cv0easMRIp0HqHVO4AvlmXQeXMGv%2F7aCCSOL0HSZsLWlR%2FiR1g3CmlDFmK%2F5ILQMc%2BIiJgwn21BRzEsMwiSOsY9JjJ%2B1RBzFa%2FdHgxqN%2FfgJRkCMebxpKoGWNiLRGHKij85QnGyvE7lXwl00ilNOnYo%2Fs5DJUyeTZ%2FpESQocjMb6J5ZDA6DFNVxusZyUvHrqK1m%2BYR%2FkT%2BCKc2YweFAmfMEltABNwV5OkRXakZg%2F6suMzUkqD1TZiSqP4JQZpcxIhNm09bdsbJjKVENm0uhrOLsgnWXbn6Yu93rK%2FL6jFrDEyMObVcyWphaGjfCaW4QTiRiHwqVM96s0yhl8atJXyPa4cYhyFAeJ7krWtuxCUjI4fdhCSwzzLnBzeoo5e96NxLU44fatLG%2BScTq8lJedQVHxHILdVfx28xLKFiwYSCtkjAdrqYpVMFERljLplOVOptTpQUuEqa%2FZghHpZmXXcL46fQZpkk5BXw17Qh2U%2BL0D%2BfQzYS7eCWVHMCZRkJGJyyFkk4j2K1oMI0DCUEhze3BJCmlSlGA8CY2wrNb1OHFTQdCDpPjwOV0ohh%2Bf4gAiVFUvpUHXGVl4DoFwmGK%2FD6fDZeLU3h00lR%2BZ3hycioOeQAvpeTNwqx7wCF8zAXrC7bSHtrCprgrFk0NZmgv6nORlZJppgn372dC4G6ThnDLiXBZGlrH54AvonllM8LbSEzrM5jofDsVNaZoTKSiR6cvB5XCj5s6h9eBr7I5LuAovwSUcHAt%2FMPEQIccw0pwe3Kpof2GaQ110tK2hPaCiFM4jTSx8Kg70YCvLu0bzNRNrg5y%2BWvZFwsS0KMIqSPiTaQu3kZnhS1FeHV0N9pONgI2AjcCJjsDg7%2FXQ8koy7rQcrrv%2BYn7%2Bm1%2FSfPZZ5DsibNtRzcXXfgoj1svSF54m2%2BPClVXMnNOvgfvu494Hapg5Mp2tr79G2vzrmF6eR%2FuCS1j2wMM81bsAo3EXR9wz%2BHxFDvs3qTTsWsVzxm6qt26gx1fBj788hvy0iYycLdgyCPV1MKdsPffc9jMWnDeX1p1L2Rmu4L9OraDp9TQKy8cze848tGiId95YTm1HDFU12LPuDZ494mLflrfpzv4U100rZ3uli44Dm1i%2BtAGnw0lGwXhmFbjILR3JzFlzcMb7CO9ZRnVLN4sWnc%2BNsw1z29KW1%2F7K0sMS00flUbO3hoyCMebHM9ZRw8o3lpgfQFf6MGaPc5Celcv0mXMo8kik9Vbxh81V6BeOo3zqfMoe%2FxHL4xN5YHIFshzA4XTi9HiZetaFrP%2F5r7jzf7uZU55F%2FcGdeOd8nikOJ%2B21O3jjjShORSF75EzOnj2aFBdvQ9edHWojcBIgICYD4h0SW92EdYQ4GcN0jLh5KeVzFpDnVajp6yDqyKOiNIfGXUEyzNVioTWR8Wdl8vbhPibnpyPFAtTV1hHvbaOupYPygiy00GHSHYUn3YlYstPDyKIdNLeFKPKpBNpraWwP0B2upz2QQa7boKlmH7ljLz%2FpFEwnwWt10oooFjQmn34WL973Ao9lBPF17aYyXMEPJhRhbHczcuJELlx0AZ5BjsnECVbagRaaInFGOiS6m%2Bpp7QqZ996ikfgVncb6GGPP8fVrayXyR8%2Fm2tHmIOddvIVzfzlGR6DOPFFw%2F74XcBZcQrqwqlVdhONd9ETCKLJKmjsfKdJDIBFG0%2BJEjCJGZHhQ4x6y0jPwppeycMrpPLL5Na4%2F49N4ZXHSj2pOfoXSI7tgFo4N%2F8tm5dMMy3LQfGAFWSXnU%2BRz0qqm4XWmm0oEy9JDzZ7CedlTkrzqcZxynE7BpyKcdjvJcqXTHW03rfa2H6lh5vhrkPWouQ0nZiSIhQPk5YzBK4vhZ4TWviM40dlZtZrho7%2BE26HgVJKWEmLyL%2Fp2WXYgO32Mc22lsmEiFV6Nd9oOMbP0CvREkNa%2BBnSji9ZgJ%2BX%2BXLRIBwnVz7iiLJbsepu0cWNwO7LxS4ppPaIKJ%2F4emR31hylztNLtKKI8K5eAr4mm7ho6enfTIHtQlDJ8xjr2NNWQSzt1kTCT5TTGjr2WyQIBQ8NbWsrKXTs5fWQelc1BThtbhlqf%2FA6J0xszR57B6h3bKXDE6K59B0OaQXnRAnKr65haMhun4iXdnU1Lq1UnEhkZUzgvI4mxlghRWDSTrOxuVh5qJLdgMm5jJxMKTzMVIhmeLHrbhSWO2J4lvoNpnJ7dyNPNWdx0pjh8QDeVX56s4cyqfpC9TbmUZqWT5spnZsVC1sfHMK2kBJeaTobLSW%2BgA7czjfHOjextnECZJ8E7HdXMKl2EVuBjxb4dzCt2sy0wikUT0m0lyrtvrf3LRsBG4CRDQOrp6XnPxhph0ml5nh3AwzydJ0J7QzV79%2BwjoGYzedJEcvwOmqt2UNcdw5AkPJnFzJg0kmhvB4f3VVLTEmT4xJmMG1WC2yGTiIVpb6pmz95a1MxiJk8aS6ZXpa32IJWH6sw8cgoqGDasjAxf0kLF4kFYlUQCPdQfqmLPvkNkDZvI5EnjSHfLBNsa6DYyKC3KxEjEOVJVhb98JFrLPvbWtoPkIKdkBCMrivE6pIHyxPGDiuokK28EY4e5qWsxGDU8H%2FQ4XQ3VhN2FlBRkmBMEUX5fZwu11QeprevAXzKKiWOH45HCbNuy3VzJFh%2BxtMwyRo%2FKo7e5naJRo8xTi%2Fra6qntczF2WC4kBI6HaNLymTqqwDSd7KyrQc8qJcfnINTTxqG9lRxsC1E%2BYgLjR5UQ7zzCroP1xBPi2GOV7JLxTB5daG4%2FsPCx7zYCJy0Chk5LzQFiaeUUZir0NB%2BhM2qw6n9vZ%2BLXfs8po7KIhbo5sHMbjSEXxQXpeItGMyI3aeIeaDnIHf%2Bzlu%2F85FqyCFHf0GxaXzjTcynOdrP1iduJzv0BZ04sPKmUBcIXVfeBxbxaVc5%2FXDSFUEcdLWZfr5BZUEK6qvPXh57i%2FBuvY2T60f31SdsWbcFPCATENpKe5jp2VlYRd2UzacpEctPdxPqaaA67qSjMfc%2F3V4tH2Pvq%2FWzL%2BQ8%2Bd1oFnfW1dIZjIClkFxTjUzp56k%2BvcOVXbsLnENsijgGVodEVbCIQDwEqbkcO2d50FNkgGKinKx5BMwxk2UmaKwdFC9AbD5jOa9NchebWHz0RMi14vU6Xac3aF%2BzA5clBlQyikS5kZ7ZppSA40BMROoPNhHUdjyObTG%2BGuV06HGrH4c41t%2FANyaqh0xtsojceNA9jViQPGa50eiKtaGIs5Coiw%2B0xFR1d4Q6iehxJ8pKXVohD1ugJNBDQYoADnyufLE%2BaedpObzhgbrN2yAridJ5QpBePOwsjHqA93EYCGa8zlwy3FyMRpCXYjDgsWZYzyfNlosd60YQCyOEgFGylKx7EoeaQ5XITSWh43V5kLUpHsJkYDrK8BXgcKlq8j45wJ5Lsxw2k%2BXLQEwEE7wnDgVN2kebNwm0p4IUeRY8TCLXRG4%2Fgcuaa9ZSIdKCp6bhM%2FzQ64XAHXdFeHEo6KF5yPG4i4Q66Y30gucnw5OPQQ%2BD0J085shqGGHcnQrQHm4gbMn5PIX6ni2ikk%2B5YDzoOMj3FOPRe9P7yhCpFiwfpjsXI9GUjGxq9kRA%2Blxf0CF2hNiK6QZq7mAyXQk%2BwiWAiiqr4yfRkEYt24%2FTkoCSCdEY6iOvgdeWR4faZW%2B1FuwxqOpneoqOUa8doyXawjYCNgI3AJxqBWCxm%2Bm9NFSI9Pd18PH4lSmpq%2B7eNgI2AjcDHHAEx%2BO5uayMttwCH8v4HkelajNZ97yCVzaNgkDIgHu5l%2FfYmZs4ajdfx%2Fvl8zCH5UOzF41F2Ha5n8qgRprPrdzMxiEXaqT4SZdSYUvu0sHeBsX%2BdtAgYJMIdHDrQw%2BjJIwf8mplwGDrh1iqqQjlMGZ53UiljT9rmYAtuI2AjYCNgI%2FCJRsBWonyiq89m3kbARuBDI2AecTHkGuqgLMUpE8kgYYmXeiUd5wlLaWFYfvJd7ye%2FRRuM2cmHki2xjYCFQLIvGeqdsN8XCyP7biNgI2AjYCNgI%2FDxR%2BD9lCjH5xPl4y%2BjzaGNgI2AjcB7ERikEHlvBCtEHPlp%2FT76PtRk6OgYJ%2FbT%2B8n%2FfrQTGxVbOhuBYyFg9yXHQsYOtxGwEbARsBGwEThREDj5bNNPlJqz5bARsBGwEbARsBGwEbARsBGwEbARsBGwEbARsBH4SBGwlSgfKdx2YTYCNgI2AjYCNgI2AjYCNgI2AjYCNgI2AjYCNgKfVARsJconteZsvm0EbARsBGwEbARsBGwEbARsBGwEbARsBGwEbAQ%2BUgSG9Imi6zrxeJwBT4sfKUt2Ye%2BLgHDcYHnATI1oOXQYTLPCRdx%2FRkvNe3C6D0qzyhoq3bFoVrjgNTVdqpz%2Ff9EGl2E%2F2wh8nBD4KN6H1DIG%2FxZYWO%2Fn8dBEHOsS6azn1N9WnkPl9360D8KHyCc1%2F6GeRZh1DY5rhYv7h6Wl5mH%2FthE4kRE41jsiwsVlvbsWBlb48dBS8x6c7oPSLD4Gp7PCBT%2FHS7Nkse6p6aww6%2F5haVZ6%2B24j8HFE4MO26w%2BSLjXu4N8CE%2BvdPR6aiGNdIp31nPrbynOo%2FN6P9kH4EPmk5j%2FUswizrsFxrXBx%2F7C01Dzs30MioGvau21kUIz3KFGE9%2FhYNMpDf%2Fi9GdXAQJxJkXoXBCsMA%2FE%2FspSMc7y01PTiyAuz7SYTD%2BRtxRE0K38rzLpbNN0QfJqMDaRP5cI3mIcAACAASURBVMWKL%2B4irriGyvOf0UQ7HZyXlU9qeR8VLoNltnj7MLiIuk%2BtSysv8%2F5PaAL81PgCR4GLuI5qO%2F3tRVCEU8rjpVl5CwZFutT6NpkWGb4PTaQXl8XX4PSDeUktLynDe9uLWW6y2KPaklmQ2acLho7GRWBsOeNMld0sbwiaWXZ%2Fex2czion9Z56%2BkNqWYPzGUyz8ni%2F9FYc636sPAaXZcW37kOlGyrsePIx8%2BzH2Mo%2F9T6A8SAMzbytvi2FZrUPK52Vl%2BBPvBv9zWygbQ%2FQBbU%2FgtXWrDzMlKmJRaLB7aKfl1S%2BUtvo4Dw%2FLC2VJ6vNHYsXS2arfzPjD%2BLTktkS%2F%2F3e%2BWPRRPmiCsw3dAhcknC921ekyv5BaZYsVrrB9Z2s5eQ7eyxaqqypeFp5Dq5vs%2BqHkstqMsegfVJxGVyP%2FwwXqw1Z7cvC1%2Fx8pLxTqbimtpf3pDdfr%2F7xyHGMTyx%2BU%2FkUvKTWv0VLDRvgVxAHlXO8NCuedbfyOZbsVlsaLLOV%2FnhxseJbd0s%2Bqz0LOf8vcBH5fxjMLL6suylvksmj%2BtmBNnEMmkgvLkseqxsWwRZtSJn7xxKpNNF3WPkca7yQmqdVl1af839BE3lYPA3c%2Byt9MC0Vs1SaCUj%2FP1bdpMpl0Y%2FKvz9w8BjE%2Bm6Lu7hScbHyGXxPjftBaVb5VjqrfOvZun%2FYMlLTm7KkyGXRrPuxyhZ0iybuAhnr22elte4WxqlpjkUzwwd9K1LTWXmZJfa338F5pdZzanzRPizaUOUMxLU6mJT%2BzmpDJubidRuCZvJpEQbFsdKlttHB5R2LNvh9ttKJ8gb4ssZ5%2FeWntlErvriL%2F4eiiXzElfoeH5XuGN8bE8%2BU%2BrLEH%2BhHUmiWfFacofr%2FgThJMJMDpn4AUmnit1m2iJdSRvJx6P5YiGjxNVhOi5Yqs1XGh8HFxPo4MRuQq79N9Yt0lFxWnJSm%2BZ66smR4P1zeT74LL76YkpJSFEURLBx1ST09PckWkhJsvvii1A9zmZIkP1zvSf5Jognm%2B5UAR8lh4fJJoQ0lhyXDx402mJ9UPm2aQCB5vR8uIkYqfXA7%2Fb%2BgiTJS803NczDt48bP%2B%2FFq00RtJa%2FU%2BhUhqdj8u2mp%2FAzm5ZNEs3gdSoYThSbk%2BDhdoh2fCHgLTIeSw3pPPym0oeSwZPh30AaXmcqLTRMIJK8Pi4tInZp2cDv9v6CJMlLzTc1zMO3jxs%2F78WrTRG0lr9T6FSGp2Py7aan8DOblk0SzeB1KhhOFJuQ4jkso18Rf6pWenm4%2BvscSRYQOlSA1sf3bRsBGwEbARsBGwEbARsBG4N%2BAgJg0JBKg60iGDtb2a2F2rIs%2FsXRnIIlnLSFGdcgNtUi9PckJR%2F%2BAUKqrRerpThGgf9W1sQGppyslvH%2BiMmggORBB8CNo1n2AkJJuKJoVz6TJaOMmHj0BNsetEnr5MEhLe7cMRUUbM14snyZzkGUM1THwG1UFWbj8kzAcKkhyMq4IF7%2Fty0bARsBGwEbARuBfRGBIS5R%2FMU87uY2AjYCNgI2AjYCNgI2AjcBQCAilgaXw0HQkofgwn3XzLtfXIiXiSO3t0NuD3NUB3V1IsRhyQ52ZoxQKgVCgCEVKMJDc5hKLQiwmNBfvxhF5i8tSHvQrJpKBKeFWgLXglqowsX4Lvgdfx0MTaQanTVW6WDRxf08RSYXQUcWa8VIiOhwYLrdp5m0qT9xeU2liiDJ8%2FcoXoWjxeE1FjF5QhOH1YuQXYvh8GAVF4POhFZeB05lUwCgKhjDfFsoY897%2F25L3KIbsBxsBGwEbARuBkwWB97VEOVlAsOW0EbARsBGwEbARsBGwEfjXETCSFiDC8kMoRsy7Zlp6SD09SH09SJ0dpsJDWIRI7W1IwSBSdxeEgsl4gb6kQsTcHC%2B0GSmKAotBoUBwODEyM5NUlxs9Jy9ppeF2Y%2FiTZsZi8m9k5WCYFhmAPx1DWHP052kIpYoI83r7c7bKkzAyssDrsUr8aO7CcqalqZ89IXc%2FP8LIpasTSSiILDxEWEtzv2LGQIpGkPp6k%2BREIompUDAlNKTuTjOeFI8jC6sbw2BgZ%2FtghUj%2Fs5GdiyGwzM3DcLowcnKTypb0TDMMoYDxp6OL8PRMxLNQtBiKmlS4CKXL4Lw%2FGhTtUmwEbARsBGwEPiIEbEuUjwhouxgbARsBGwEbARsBG4FPMAJCgdFvQWJulYlEkEJBiISRwmHk2hpksRVG3OuPIB%2BpMS1KhLVIcouNnrQeEToCMUkXVg9i4u3xYoitKWLC7nKhl1WYFhF6xQhzUq6XloMILyk3J%2FemdYRQjog%2F4aDddHgn9VtNJLexmJN4K84nGPLjYt3EV0sqUfqtc5JbnfrrSyhfxBYnM56O3Fhv1pvU2YnU1ZFUbol7bx9yS6O5PUqKxyAaTdZ3PIZQwpjPQjki%2FixsJRkjMwu9rBx92Aj04aPQhg03LWCE5Yvh9YHHgyG2EtkWLcdVnXYkGwEbARuBjzMCliXKh1KiCMezg52sfJyFPeF5EwM7e9XjhK9mW8APi4CBrif7rGP3W8aAtfngOKb3eFG0cC71YVn4BKd7P%2Fkt2mDMPsHi2qzbCCQR6J9wJyfeGpJ47utF2bUDddtm5H2VyG0tSQVKJALiz9w6I2GIebac3P6hDx9pKkWENYM2aix6YTFGXh64%2BpUowpeHywWq2JIitpIM2EnYNfHvQMBUlCXMrVMDShRh6ZKIm3Ws1NYgdbQjH6lGOlKN%2BdzelrSKsRQ4gm%2BHE9weDKFAcXtMvy7avFPRR45GGz8pabliKmL6twn1K8T%2BHSLbZdoI2AjYCNgIHD8CH0qJIgbMhq4TDQWJGk7S%2Fa7kpEJ8dGT53QmGiGcYaPEIfSGN9AwfsiTohrkYIAbc5py%2FP554MMTHx7Tg7J%2BmSNJ7jgUzy%2B9PYw3aZfHhEYe%2BmeFinvPus%2FgtyhE0MUMaMIxNydvKU5iOSpKQLxlPTJck02lZ%2F%2BRqIM27E7J30yaBlwQG1kSrn0%2Fd0AmFovh8HpNmpTGl7Pf4%2Bx7ZzfmawETAmsTDlMGUUzwbiLJMmXSdRLiPsOEizedKHu2k6wOyJrFO4nD8zcOOaSNw4iBg6An2bF6Pb%2FRsKjJdyb5nkHgiTm%2FdDmJZU8j1J%2F1ti3dOvD96LMiWA33MGF%2BAqpx8Tgm1RJyqIy2MHlaCKb7o2%2Fr7OS3RS1NLnJKS3AEfj4OgtR9tBD45CPSPFYTiRK6rRdm5FWX7FuSaQ8i1R5A62kxrBjGWEIcAi%2B0eQklCWQV6eQV6cSma30Vtt0Hp3BmQlZ1c4EgORIh1HKRBK2F4oe%2Fd8dLHHB1r7JHcXmMpk5NjriTryZMLzJGTOcgyB3L9C2394y6Bq5DYGh993GUWIyiLZ8Fr%2F7A0ObAaJJ94FJYqXZ3IbW3I7a1IbS1IzQ3JNnSkxrRQksLCh41oOLrpm8UoKkZYGgmFijZ5KolpM02LJBMa0V7MQfLHHCibPRsBGwEbgZMQAUuJMuTpPEPhoWtxAq2HefzB%2F%2BGtwxH8qk7e2Plcs2gOSx99lmt%2BchfF3mR20VAXa156jOeWvEVC9RBPH85Xvnwzs4Z7Wf7IzzDmf5vzphQRC3Tw8n3fJe2yO0nf%2FTj3PbsBr8eBJ7OQCz99A4sWTsVpeV83dPqa9%2FLf%2F3Ub%2B3sdOFXIHXUKN33lJkZnwc4lD%2FLnNVG%2B95NvU%2BRK8NQv%2Fwv32V%2FmilNHEmo%2FzBMPPkbxuZfz1gN34r%2Fga%2Fzg8wtwSjo99Tu47%2Bf3op5yM%2F95fg4%2F%2FMb36Vb8qJKML2s0X%2Fzqtex84uccLLqOH990Di6jjzV%2Fu4eWEZ%2BibdUjrN%2FfRldPH%2F6sXArGzuP2H9xKrkchHu5m%2B7In%2Bc2Ta8nI8KCmj%2BQrX%2F8Cq3%2F9Q9483Ifb7UJ1ufjUjT8g%2F%2FDz%2FPr5zXjcKoaaxinnXspV8%2F389oUGvvvNz5LukAj3tPL0H%2F5A9hmX8NZDj3DL%2FfeQFTrE04%2F8mXf2tQsrYDKGzeXrN13C%2FT%2F6Go1BJw5Zxpuey3XfuoNTx%2BQOjAOGql87zEbgRERAKCgTgSYWv7KUC26ZjkG%2F4neQsKGuBh5%2BZB1Xf30CNdtWsXLtVjojMGLWuVwwu4Lu1x9gi%2Fu7zBmVfXK9R3qCvrq32bzLQUWug5WvL%2BZAbStKWh6nXXwlY7IMFi9%2BhUs%2F%2BzmK%2Ff2nYwzC1n60EfhEIBCLoVTuRN34Duqa5Sj7KpMKE7HIk5tHg5YgOOtsXNkhfr%2B9hSZ%2FGn0yzDn9Bq779GlkeJ0YWowjqx9jjTSfazyw9NlHOVTbgiO9lPMuv5QSKcGy51%2Fgczd9Bo%2BasvD0MQXIQKe94U1WN%2B4lgk6aaw4Lx81GD1Tyxr7VxF2Q5T2Ns8ZMRYo0s7zyZXrlOE5jJBdOvwg1VMvbdStpjXWhJMqYNfYiRmT4P6bSJtkyjATtzRtZUb0BzWngc81n4fgZKJEmlle%2BYsrnYhQXTLsAOVLHmn1LaSOAW57IWePOJnf8GGrqV%2FD63jXMuuyXTC9IQ8FAbmlC2b0D%2BWAV8uEDyE2NKFs3oq5ebipphGPcxBlnkzjtLLTps9FLSmyrpI91S7GZsxGwETjZETg%2BJYqhEw12seTBOwmMvIEHv38KigjrCxAN1NPdHSGe0JMWIVqchh3LeGFTjG%2Fd8zDFPomOfcv5xW8eJv%2BOmwl3dyL3x9V1jZ6uCEo0hhKMMf6K7%2FHdyycSaqrkLw%2F8Hl%2FZ3VwwLmegjjQtgpE1ntt%2F9j3KPQYbnrqb5158m1svH8eS17bSGtB4dUM1X1owgvMvP5M7HvwLk0d8g4bX%2FkxT5lQuLjJ4KhwmtHQJhy89lVHeODUbXmF3Y4ARHZ0YuvDSPpu77vgOBW4ZVVGIdNWwrKWDfXv%2BwGszR3PJlHQCPV1oShY3%2FuA%2Brmqt5iff%2Fzk33%2FsHxuWn4XIo5pGDoY5qFr9WyQ%2Fu%2Bx0jMp1IsooWaiccdXHlN3%2FExTNKEVY0YmV35e44E6%2F4Ht%2B6bCJa9xEe%2BZ%2F72TPvdvQjT7Gz9lLmV7jpbdjKvt40bsiXeCHaRijcyztP%2FpWaggu5%2F%2BvzcSoSsWA3qhrF0Mv47j13Mi7HhaKqqKp6ck38BlqM%2FeOkQcDQaKjaRXPMScehfXhLJzBr6micskH7gbUEfeWUuaNUbdnA3ppOisfNYvr4cpziBTQ0OuoqKVxwKYV%2BF%2BrUs7lu0hkI65RVf19C89xxzL36HJZs3MPMEaeiWordkwDcRDzE1pf%2FwbhFd%2BL2Z3H%2BFZ%2FnXMMg2r6Xp%2F%2B2kdFfn88pRd2s2tvCtXNK7X7mJGgTJ5SIwtogGkXdsgH3XbeZvjGEfLrTQVNGBnsWXMvsmz4DXjdL%2FucnhGb9P%2Bbpb6CNvIq7rj0HJdLKz757O1vmTuHMsfnomsZL76hc9I1ROL0uLrzyc%2BZWwr7G3fxkVQ2%2FvHgkZa517OmJMSNbWMVZJg6DUDU0QrEwmh5BQ8KppuFWVWKxXkKJKIriw6M6zb4LOblgoiUiaJKMpsVJ6FEMVJyyg7gexpA8%2BF1eMBKEY33EDQOXmoZLVYnHAmhiPKdruBxpqCQ4tPcv9OZcyaR8PzsObWHWtK%2BT54qwddNPaQ1M4PDhXSyYdTMZikTl3j%2Byu3kEnsb7GTPqxwzLSKOjeTmbW7o4taicsyZ8AV1PEO%2FayarGvQzLmMNQ9nyGoRGJBkkYMRKGjNuRhktRiCeChOIhDMmF3%2BUnrsVxqE5USbgriZIwFNBjxPUoCRRcsgNNj6FLCj6nWBCDcLSbsJBP9eNWHYixZFxLENUjONVM3LJOfe0a6lyTmZztY29zE3On3kiRQ2L19mep7x1H4tBvGDfqB5Rn%2BGhvWsaWli4cra%2BTX34dZ2WrhGoXs7bxEBeNGoPXOYPTivcQFVu1xJ8Mwq%2BNsFRi4QWmNUry%2BGkNed8eHEteRl27CnXdGtRVy8ytPomzzyP6lf9MpjEtrge1EfvRRsBGwEbARuDfisBQ37L3MCRWc6OBDtYccnLBOfPwe7z4fGlk5efiEl%2BopI2jedMTIao2rWL%2BJRczIj8TX1oaeePPZmxaMzuPdA9srUkWkjzOzjT4lCScLjcebxq5pRNZ9KmZLF29m1AkTDAYJBZPmIMRXUsQj8WJ9nXR2BxBcaq0V2%2BiKXcut37uAvaseIWQLpMzdgHXnJ7JPT%2F9KU%2FuzeSaKy%2FAoyrIiotpxX2sWn%2BQYG8Xy96qYea08aYpuq7rxFsP8PIzj%2FP000%2BxdN1eojqovlxu%2BOp1rP37Q%2BxrCaLpBrLiwOn24Ha7cTgcuD0ec8IWjYQJR%2BPInlyGFcT447138fcXllHXHkhucYpF2bLsJZ5%2B5imee%2FFVOkIJc4tUb1cr9bU17Nm5lVotjdLsLM6fUcBby9YTCfaybflySqfPIdstm1ufEqEWqpp0rrvsNDL8oj68ZOTkIUsGWqKRN158mqeefoLFyzYSjAsbUvuyEThRERCm5To7lj7Pb%2B9%2FgPZYnDeffpBXtjaiazE2rlhH%2BdTZqFqQ3dUdyMR445F7eONAb791tk5vWxdjR%2FnN7TqyIpSbMtGOgxyMBshTHSiZk%2BhJNJIQzglPokuPhTh0cAxFOWlJpa%2BqIhsJ9m%2FZANOG43Q4GDZmAo37G6yvwEmEji3qJxoBsV0vFMR978%2FwfO9W83Qc4bMifPevCfzlSd4673TWTzoDPa%2FAdA6acDjQVBVNlkmIbc3RKF2NtfTFhUJCMRWIQllgjMmh2OMwFSTmAoae4OD2bcwfW4RDVRg1wsn%2Bw8GBYdN7MRTbihO8tuVhdtbX0d59mCU736QzGice7aY32sGufX9nc3M3dZW%2FZ29XO5oeZ8eOX9MRbuPFjX%2FmcFsDR6qe4cmti6nvqmfT9j%2FTGY3QWLuY5Qcrae06xGu73qE33se69T9mfU0N7R1bWLZrKbF4gLpQPb3hZqKai2lj5vHOngd4ZtuDtGd9kSx3FAkdv%2BrGoboo8uVSGzjCkWAB6a40HIoDv7%2BU2vZOcx%2BMIgklR4JddatxewqPoWgVW707WbL2bqpaW%2Bjo2MPSXS8R1RIkYn30RNpoqF%2FGqiOtbKv8K5UdEWLxCKu3PkZtsIPXzXTNHDn8Ck9ue4ranlq2V%2F6Fna3d9PZs5%2BU9O%2BjoOchbu14lFA%2BwdedveX3%2FZrp7j%2FD8xmfpiUZo6jtEX7iRqAYTC0tYue3XPL3914R9EynyBKkPFeB3C%2FnEVvYSato6qI0WUJLlMHHwFYxHDjajo5JXmI9DUTjK1kgozIRjWeFMWPjD8fow0vxoM2YT%2Bf5PCD75MqGHnyD67R%2BhF5WgrnwT71e%2BgLr0VRAnPZnbi97bWuwQGwEbARsBG4F%2FDwLHZ4li8iYLjyboKQsnKT%2BP4t7c9ilC%2BiMIXyjmT%2FGPpKBpmvk9EN8EEVcx%2FZikZiEIujlhObDmaZ5dsYfM0WdwzYJ89K7DPHTvz0hzucgtmsKlZw3nnUceQZIncbAmhla%2Fmy21fSwYmcH0BYt4e8VPGX3ldxiV7yPQKqOqTk4%2F5zTeXLuMhqxhNKXPZsGYEGva%2BrcuO52osmx%2B%2FOLCT4skoThc5Iw6nYun7%2BHvT77EZC2OMviDJha0Oo%2Fw8G%2F%2BRIecxiWf%2FzJXfu0njFy%2Fhsqq3fz2nje57IZbEMcKKqqSlFmLoPfn01G5khe6NxHsaIC8UylIc5F31rm8%2FoelHKzPZlUVXHnxeBSpKQmUIXymWA5%2Bk0Cb8Jq%2BXVzmCruQQk%2F070lOhdf%2BbSNwwiFgmP3KiHP%2BHxeeO5qM1j3saWgnPl5h3WGFa64djp7ohHAn%2B2ub6OrrYs%2FhNj41LhNJ%2BG9SZPwO4dBRJx4JsW%2FDUlbuaGPBpVfiVRWispOQFjvpxrHCR5RGPk6nhFBgh3uaWPbKy3Snjec%2FzhuGqkioThdaT%2FiEa1G2QCc4ApqG46V%2F4Hj1RfRxE4jc%2Bh30CZMQ2yq0RBTD5yEuXLUJPx76u%2F7cxKil6q3nuWf%2FGjy%2BLGZcdQtTyzKT%2FsgwyPZ7UMQWIF0j1H6IJa%2B8QShvBleNS0dVQHU7CYbEcb3iMug8Usn6XYeRskexcN54nObSlo7mGMv0CvGsk2h%2FkwNt8xihttEYaSWQ6KS9q54JIy5l68H9lBk%2BtkdHM8Yhke0fx7jC0cQczTT2lTAibwy%2Brt10xyPsa67GyNJoDEnEw%2Ftp6puCLLuYUjERn1JCdf3jGNJppDt8eNLGkKWEeebgbmZN%2BhIFjjiVex7jSOAKNHPkJsZpkmllYvqQIyK8tvVLpZn%2B6XQjQU93NesPLEPKWMhppUXWsDApfuq%2FpnXMMMYWjcUjJwj2vEZjIkpWuJPGvmoiiU42tlfz5YqRrGrYQLmSS5tjEvO8MlVKOWOKxqG0tbEjDsOyR1MY2MuGYC%2FpLWtRPfk0hhyE9RYOhzQ0I5dJZXMYlimzf8%2Bf6YtdTrorD8U%2Fliy3ytv7dnHa%2BFso8sKWPU9Q2ZGNYUSSi4BmremmkkxCM%2F38mSNZXUPv9%2FlyTAujVHnFb0uxIo5HdrnQsnPRRo8lfs6FOF57EedfH8L9wL0EzlhonvAzOLn9bCNgI2AjYCPw70PguJQowkGrOy2Hs8e5ePP11eScPwOHrBMJRZDjwjIkSkdbC%2B6w09w%2BMnLWfBa%2F%2BjpTyvwUiu08hzdQGy3ikuH5NJcVs3zHTmaVu4l31nKwy8mkbD8BQyfY00lrSxPhlgMsXbmNT91wFWMqZvDt2Zfh8rgJt%2B5GzRnNV7%2F1A0ZmOnGoKu37V7DsgMTkOW5zBWHYyGyee3k9p3zjfNxpmRQVesjLSUMxTfAlZEUld8x8ytbczeP%2FqGTqeTeTG3wL2kQlSChpxZx1%2FsXkie08DidSrM30sq%2B6PMy%2F4joq7%2F4%2B%2F9gb4%2Bozkjqid9UX4Mgs5Ybv%2FtA8slCs1nZ1hBgzayFjpvSx5PE%2FsLuhz6SNm7OAC6aVmM52Pa6kZ%2FYRZ1zLNy6bQKzjEH%2B5%2F2EaQ59ldMlUJuY%2Fx%2BNPP488fiHjitNJdDSZgxPFV8CEcplnX1rFFy6YiluBSCiIP11Y22Qw9%2BwLGZ3lMGUQNPuyETjhEZAUXG6PaRkmJvdaIkGgbivx4XMZkeum8e1lvLovzlevvJQ9y%2F5Gk6UIlSRU3aAlmGB4Roz9a%2F%2FB4zs9fP26a8hO8yQdYmsBcp0Z73F2faJjKisKqnKYQDCBP9bOX%2B%2B9l%2BFXfIPLxhXhkoUiVyMc6MZTPvzYk6MTHSRbvk8mAmIRoqXZPFEnccoZ6KPGYgjnYmIRRVEoKM5izZ5dNJ1agRJt51BnnHkFGSiNMmPPvIpvXHsOXoeKy%2BU0rbSSixgyDa09xBIJ5FALD%2Fz3g8y%2B5hbOGVWAoggrUo1QT4SCivQBzHz5Izj99LLkuGEgVOhzwwRjUSSHQWdMwRk6yNPNB7hq%2BkJ6I%2B20JgycrkL8sddZWeNh%2FPBrcCk9qLJqji2EM3%2Fzt5BHWIMg4VIyyMyayTCvm2klC8zFlnZJQZGVpLN6s3whiUEiEaQnEKclkYXfJRZmnJR4szmiy7hkmfpgL6VuhZpAH6OKhuMJGzT1tpPlzKSt%2FQBjCs4lFqji5Z0vMX38l6jISMORshUyEeqmrQ%2FycoVyKelIVTeiRMR2JTlGIBrEr0V4oWoHZ407C4erinXdBr7cuWTX%2F5mqqm4mjb41uWAkOUzrQcmUBVNe8VtcDmcWhZnTGe33oRYLi2GZXZKKqjiQZKEMEYtRSX1GXIvRFwnQE48x2e1EVWVyXTo1EZkRGRrNfR1kOjNoaT%2FI2MJzcbT2cLClk%2FSCdNobd%2BJMP8X8XiTENiM9TlwXW5PcyCQtlVKr95i%2FhULFn45ok46Xnksex6yLhUf7FMZjYmYTbARsBGwE%2Fg0IHJcSBUnG6U3nvC99j7%2Fd9yt%2BtPxxJEMjZ%2FyZ3PDpOXj1Fu7%2FyfdN80VPyWR%2B%2BK3rubruUe6%2F%2FTtIqkI8lsUtd97OsOx0cs%2B9kcrf%2FZzbvvc0surhzM9%2Bkxnl6Wz0eqlb%2FBC3rZbQ1Swuvf5rLBibY%2Fr68PjEN11Hc3pJS88gI82H16NgaBp1%2B%2FYx%2FMJbueXaWbhlje7m%2Fdx%2B28O09C2kxKni9ThxKqr5hVRVNxmuTLxp%2BcydM4nfLD7MFyaXE97uxOnyoKguHD27uPe275iTJU9aLtd95SZ8HhceVcWdUcKnr7uB3Xc9it%2FnNAclYluPx%2BHHpcioLid%2Bl8fkta%2FtEC889Cu2NERRDQ1%2FyTy%2BOaOYV5cZvP7XX7HK6TCtYhZc%2B21KvB7S%2FGl4PF6cmfmUF4t9zKA4fZwyfx6Lf%2F8GN187E69DIaR4kjK4%2FZx39Y10%2Fel%2Fue17fzMHEBlFs%2FjOt6%2FC5WjnoZ9%2F37SocXn9XPX1Ozl7Qp49yfk3vGB2kR8NAhIyHp8bn9drTgicLiduJUHlyiXMmvef%2BFSZzJLRKA0P87v716JJBjNnuZPMyQo5FcN5cesRZuRUsOOdFfQ2%2BrjnjtU4sibxrduux1W9Fkf6%2BORg%2F6MR6WNRiuJKY96pQQ43tOJWq9jQ0MuBR%2B%2FnTUlm2NzP8%2BUrJrBn0wHGnr7A7l8%2BFjVmM3HcCAh%2FG5ddheP1V3D%2B6XeoK5cSvfXbaNNnIasK48%2B6hskHHuBH312BpEWZdfk3OG1ULl3dfjLTMkn3%2BczxSWp5iqIyuqWaqrYow0LbqWntpunP9%2FGqqlK26D%2F56qmF7GsMMfM0Z%2F%2FhKxIujxcxbHj3Slpz6HqQ7bv%2BwJ5YDzPKb2B8YSZdrUt4ensV4z0j8PszUBUncwtK%2BNORJi7M9yATRJFVc6FFdvjxOpIn9imKUII4OGXMWazc%2FShrtV5yvAtZNOV0FMVtjnck3PicHlTZwYjsyTxV9Utay3%2FIVRV5vLr5LvoMmfLMKzknuwhn2hm8uu0%2BFhtxppZez8wcH2R8gzU7HuKhAz2UZFzKpyrSaTr8DA2JBtr33W3yNb70Js4ZNsbsKyJte3h50uNUNQAAFxdJREFUcSvXffFi0%2F%2BcMPMTp32t2XYfDQmZGRWfo9DhYby7mZd3%2F44Kzxnke4pQFS8jiobx5KEwN%2FuzUKReBO5C9SM7fPjEupRQICkKLslBSen57NvyJ55KtOL3zOXyaYtMenJhTSHDmW7ylp9Zxht77qK94IvMLZ3Cy5t%2BSkBWqMi6hHPKSlD1r5nyra7qpUzINzwTKfMKNux6jD9W11KefQ0XjKhAJsLbW37Oxr569PafEZd%2BwSlFSn99v1vLR%2F2yjtPWEki9PTiffBTH4ueRenqIL7rCtFJ5%2FwyOys1%2BsBGwEbARsBH4CBCQenp6kl%2Fs4yosuVe3t6uLhOIhMz3N9MERDwcJi1m%2F2JrjcOHzuE1FQjTUS18ojj8rB7fjXfcrwk9BX28IyenG73ObHz8tHiMYFibhEi63F5c4fmfQJTTxiVgc1WkNQCARi6LLTpymbxaxbVQnGo7h9Ajtv4gvVnJcpiWKSYvEcLrdoMWJxDXzlByx3zQmVldUiXAwQLzf74FQkHi9box4HMWZPBrVPOI5GsEhlC7mSqwoL4rT4xl0xKdhOpkLBnqJaQrp6cLfgkQiEiIcS5hGr8Lk0%2B1NQzES6JLYV5vcoiN4Fibygi72RkfCMVwif6u8SNT0xyIWdQwtQV9vNzHDSWaGH0U2TIuUmOm8VyyqKXi8vpNu8jeo6diPJwEC4r0xZKdpMq%2FHo6aTwg0vPcfoiz5PaZZQmAjfTn1EdKFcdWAoDlxiBRSIBdp58aE%2FMuVz32RcvvcotGKBVh7%2B4xOc%2F%2FkvMSpPaHRPoktYCHYc5u%2Bra7j%2BsoWDJo0G4b4jPPP8Xi679jwynLbJ20nUMk4MUc2jjI%2Fg%2Bs1%2Fm0oUSdPRho9EmzgF7fSziE%2BfSZ8i%2Bgo3aX6v%2BY0X1iRxQ8Yp9uYMusT3uvPAMpZsT%2BMzV5929JjA0OitXsOzGzU%2Bf%2FVC00F1svcZlInYFKNF%2Bce21SyatoD%2Fr707ga6qvvMA%2Fr33vnvfkj0hAcIS9k3EpUVZXaunOFIXLJ2pVo9zPDp1HK1UT2WwBS2nrlU7jkunWut4OqNF22FaxWVULIgOCLI5yJKQsIYlCdnfu%2B8uc37%2F%2B15CIAHUpybhe88J7%2BUu%2F%2Ff%2Ff%2B4j8L75LxGZQLaLzfeS2LX1eWzQz8G3R47qdMLWLi792nc3Vq3GquosTPvGSFghHa53EG8u%2F2%2BcO%2BX6Y69c5LvYsnUxdmefg%2Bn9ixDqanLer72FXVQg3QNSHuXL82Bs2wLjg2UIrfpQrRClNRyCn1%2BAxD%2F8CPZ3ZgGxjv8mdVEyd1OAAhSgwFcgkF7i%2BDOGKEHN2ufiOF5NZcJHrccF6CfevuO1X3rQyCjhL9cgo%2FU9gSbxFAr0BAH5e6H%2Bk6rpHX8GSWx8xKcXOVc%2BAPlaKDX0r72Fckzm9Qs6tB1xYftpvfaZar%2Frq%2BEIR35eUcbyW1QZDnDy0fTae35SNUx%2BTrgujE2fwFy8CMbHq2BUVgCudAfV4Q4fCef0ifDGT4A3YCD8fqVqslk1QWgnUOpnietCD3XyiyDPgevrwd%2BlTq5N75Jw5KOqTTij7BSE9KPDmvR5MpFtedUqFPT%2FJvpEetYS4%2BpnhzREzSMic840Yf3m1Rg36lw17KerHyeyBHF51QcYPHASLFn5pqdsMnysuQna3j3Q9%2B6Gvr0cxtrVCK1ZCa2hQf3iUU00O3I0nHMvQvKyWfBz89TwMv5w7Sk3mfWkAAVOBoEvFKKcDEBsIwUoQAEKUIACJ4mAhIGOA81JQjtUB%2FPl%2F4S59H%2BgHaoF4nEgaQcTZ0ioYRhwz5gId8w4uGPHwxs9Vk1Ii3A4mFfFkmVtuw4%2Fji8qoYL69UvXyyCrQuQXVUEqfMKTmR7%2Fxb%2BmM1JtltD7mDU4UZtjFpL5g6kwTpP3ibxfEgno9XXQy7fAWLsGxuqVan4T6XkCzw3CESsMPxJVExrbM2fBnThJrd7jSwAnqT2XNs78fWKJFKAABb6gAEOULwjIyylAAQpQgAIU6IUC6UAlkYAMrdBqa4LeA5s3wdiwFnrFNmiJuBqKoT4U6zr8rGw17EIe1fK1JX3hlfSDP3AQvLKh8AqL4OcXBsvcGiH4stxt%2Bks%2BLLMrV%2Fd7I6WCEemppLmu6rGkuiXKxME7K1Pviz3Qd%2B%2BAvmsntMZGIBGH1tQIrbFBBSmqUXJ%2FZcLY3Dw4p39DTWLsjR4Hr08f%2BPK%2BiGUDphm8H%2Fg%2B6H7vA9aIAhSgwGECDFEOw%2BBTClCAAhSgAAUo0KVAOlhxkkAyCX1HJbQD%2B6Hv2wtNhmfs36c%2BVGu1B6HX1akP00eVpWkqWEF2DvycHHglfYFoDH5eAbz8fCAcgd%2BnWPVA8IuKVdDiFxQC0jNBPlynwhY%2FHbrIPk2XmVSDMYrp%2FUe98Em0Q4IPuVcy85x00pFeH6q3jjz31JL2al1iOcf3gnsm57S2qmE1MrErEq3Qa2oggYkm97WlGVpdbXBuQ72a%2FLUzUQlJ1FdhURCglfSDV1wMv98AeIMGB4GJaQX3M31POyuI%2ByhAAQpQoNsKMETptreGFaMABShAAQpQoMcIpAIWyFAgx1E9FmRIkAQs%2BrYtqqeC1tgEfcd21Tvh8CEfMnxIhn6oTUIQ%2BZKtLRCR8ERTy96q0EWCmMFDAJkPRNfhlQ2DzKbtmxa8QWXBtRKuhELwLSsIEiRkSS3frMIYCRXkHNOELz0gZEvPFSWPsi%2B9Pzj65f9p2yq0aKuLPJFsSKoqvX6kJ4jUWTbxln2pcESzk7LKgLpAztV371IBiZyqy%2Fw2yaS6THoUqeFZMplr1XbAkYAlWBRBlSnlyZcKWPygZ4hpwQ9L8GHCj0ZlzWTV08gbXJaaH6cE%2FqAyuGVD1TEVeMm57FmizPkHBShAgd4mwBClt91RtocCFKAABShAge4rIB%2FQbRsqRJHgRFYPlA%2F4tg1dejpU71FfunzYr94Lrb4OWjwBvbI8%2BHCf%2FpAvj%2BnUI%2F1cwoZUICBHVciiVhAKggf1oV7maUnlEAopPfdG277UExlmJMfUpsFPhxcyTb56veCIL71g2rbPc0zVFJqsiCizd0sA1fZaqYKlTWIkE%2F1K9aSd8oeELmkP6TEigUh6k5UNU%2Beq8qRM1TR5TBcSBEuyGpPMX%2BMNHQZEYvCGDFW9Sdwhw4JQxLJUQAWZ58aKBMHUVx0wpdvFRwpQgAIU%2BNoF0iFK%2Bl%2FJr71CrAAFKEABClCAAhTotQLyAV4mnw2HIUN6ZAtiBFmA%2FTibDEWRcEVChaYmaK0twfAUGX5iJ1TIoIacyHEJGiSAkWOpoEENS5HeG7Kl99XWAM1N7S8s9ZNln%2BV1mmR%2FunbBKjrquvaz25%2FJdYeFK%2B0HTvA6CT1kSFNeXvul6TLlWOkgQHqBpDcjBK90QFtvHZmc1S8uUQGJzDUjywOriX3luQyHkjKk505%2BAdRQqKws1ZskXRwfKUABClCAAp9V4HMtcfxZX4TnU4ACFKAABShAAQp8QYEOYUVq3o8ji%2BxwTvqgBCKdhR3poCTddaNjdqKuTgca6aIOf8zkMdVbRAo%2FrC5BBdpfMf166ty2C4LjcuzI7UTPO%2FI6fk8BClCAAhToRIA9UTpB4S4KUIACFKAABSjQbQU6BAXpYSrdtrasGAUoQAEKUKBXChw%2BoLVXNpCNogAFKEABClCAAhSgAAUoQAEKUIACmRBgiJIJRZZBAQpQgAIUoAAFKEABClCAAhSgQK8XYIjS628xG0gBClCAAhSgAAUoQAEKUIACFKBAJgQYomRCkWVQgAIUoAAFKEABClCAAhSgAAUo0OsFGKL0%2BlvMBlKAAhSgAAUoQAEKUIACFKAABSiQCQGGKJlQZBkUoAAFKEABClCAAhSgAAUoQAEK9HoBhii9%2FhazgRSgAAUoQAEKUIACFKAABShAAQpkQoAhSiYUWQYFKEABClCAAhSgAAUoQAEKUIACvV6AIUqvv8VsIAUoQAEKUIACFKAABShAAQpQgAKZEGCIkglFlkEBClCAAhSgAAUoQAEKUIACFKBArxdgiNLrbzEbSAEKUIACFKAABShAAQpQgAIUoEAmBEKZKKS7l%2BH7flBFTYOWwcpKub7nQUrXNA26zkwqg7wsigIUoAAFKEABClCAAhSgAAUo0K0Eev%2Bnft9DonEfNqxejZ218Yzh%2B56LhuqteO7BO3D5pZfgnx%2F%2BHXbX20jnNRl7IRZEAQpQgAIUoAAFKEABClCAAhSgQLcQOHaI4nuIN9ejYsP7eGL%2Bbbhi5gzM%2Bt4P8PAzr2BvTSMcL9XDo1s0patKeGjZvxbPPPwg%2Frq16aiTPDeBimXP4OrvXYfXK5uPOt7VjmS8Ge%2F94XdYvPxT5BUWYf%2BmLWjyQshoV5euXpz7KUABClCAAhSgAAUoQAEKUIACFPjKBboezuN7aK7bj5eeuh%2Bvr9yCpK%2FDMEzArseHf3ken6z5ED9ZMB9jSrK%2F8kp%2F1hf03CScpAO3s9DH9%2BEkbcQTcTied8JFO8k4tu2pQN%2FhF%2BH%2BhTdBd1zk5mV2uNAJV4YnUoACFKAABShAAQpQgAIUoAAFKPClC3QRovhw7CasWfxLLFm5DcMnX4bZl8%2FAiNJ8wHfRWFONrTtsDCmIqgr6vgc3aePgrs1Y9dFGNDomRp1%2BNk4ZMQARy4DnJFG%2B7B2sTUQxY%2FKp2Lb%2BQ3xaVYeSkRMw5YyxiFpBNWSITLy1GeUbVmLj1j0w80tx1uSzMaAoG7qmwW5txOplr6Eep2Da5H74eMUnGHveOSgMOYg3H8Kmj1dhc9UBmLklmDhlKgYX5%2BDYXW2O9pV5Thr3bMQby7fgtGnTEWvahZVrNsKNDcDUcyahf34Mrt2M1W8uwZaqGjQalXh18Z8w7MxzMbUgB24ygZZD%2B7Dmo4%2Bws6YFBaVDcfY3z0RhTkS14ehX5B4KUIACFKAABShAAQpQgAIUoAAFeoJApyGKBAmt%2Bzbj14vWIzbuStx%2B69%2Bjb8xsa09uXgEGDEt96%2FtIJlqw6%2BPXcN8jz2NfUxLQdZgvv4jps2%2FDjVdNQyhpY%2FM7r%2BKFfRGUHngXjy9aiZakg5AVw3tX3oW7fzAJpuahpeEA%2Fvybe%2FHSexWq14hmhPDSH8dizrx5mDgsX4Uoy197AVvjF2PLkpVYsac%2FFkyehlhLNV548Gd4c2M1bMeFpoewaPG7mLtwAU7r317vtgYc64nvo37XOvz%2BhT8hHm7Fqj%2B8hMq6BHzNwB%2FfOQ8PLZyDYrRi7dtvoHK%2FDV%2FbiFcWVWB6bDgmjSrBwe3rcN%2FCB1FZ0wjp%2BGKETLw4fDLm%2FeRWjCrJhq5ncmrbYzWExyhAAQpQgAIUoAAFKEABClCAAhTIpEDnHTUkSDiwHQ26jjPPm4yiSMcgQnqeBMNjPLhuEod2%2Fx8WPPQcvLKpmP%2Fgk3jssUcx89QCLH%2F5Cfx5Q2NQXx9wdm7EM6tzMff%2Bx%2FDAgh9jVFYc6%2F%2FrEZQftOE5CWx%2B7VdYtHwHJl%2F1T3jkX57EfT%2Bbg%2BL4Zjz1b79F0nFVOZ5rY3fV69jc5yL8%2FIEfY1gW4Do%2BtOHnY878B%2FDLRx%2FF3FuuhL7%2FY7zx2hp4nQ3hOQFB12nE4n9%2FBxfc9HM88ujDmD2pP%2Bo2vYtXV5RDs7Jx5Z134%2BwRYQwcfQkeffxJXH%2FRBNj1FXhi7r3Y2ZKHa%2B%2B4D796%2FHH89Nar4Fcsxb8%2B%2FbwKeHrCLDInwMNTKEABClCAAhSgAAUoQAEKUIACJ51Apz1RlILvqTlSZeneDpvvw7Xr8fbTz6Nq0Fn424tPQdW6pWhyB%2BP%2Bu27HsAIL8D1c%2Fo%2FzsO%2B%2BeVi55APMHDNd1gCG1Xc8Fi68BQOyLTjxUlx9XTnmP%2FEGappaYev7sOiV9Rh%2F2R24%2Be%2BmI2IA7sD%2BuPOmrbj1kVVYX%2B9ijAFAN1BUdgbumXMN%2BkQNyHI4ek4RJo%2FqgxUr3kKL7SBpJ6CFDDQ316NteeMOjTj%2BN4aZjcvmzMPMqcOheTb63jwX76%2F7IRqqaqGFRiGvsABZsTBi4SIMHDQYJhx8%2BtZfsVHLwQ%2Fn%2FxzfGl8KXfPhDBqEu5oOYu6z7%2BP96htw%2FqCQUHCjAAUoQAEKUIACFKAABShAAQpQoIcJdB6iaBpyigYjy%2FWxbvU6NFw4DoWSagCQnhResgkb33oLa88owuUXjMah6io01G%2FCLbNntAUEvudBN6MYftpuuKn5WvW8PBRZweSrmqYjklus5izx4cNprsOGplYkXpiPWb8POsgEAYgPw8rCzgMeRvcFDN1CUcFZyFP18eEmG7Ds2Xvw1NKDOOW00ci2dPiq98kXSyp0PYx%2BhVHVHqmxbuYjGu1q8R1pgY%2Fm%2BhZo4SgGFGUhGLWjQdMNlA4ZBN9bivpmT%2Fn1sPcIq0sBClCAAhSgAAUoQAEKUIACFKAAgE5DFAkNskrH49oLs%2FH0ey%2Fity8PxI1XTkFO1IRM%2Ftra0oy466peHrpuIL%2BkP0zzU%2BQW9klNEutDQhToFvoU5rQFK0EE0THckO%2Fk9ULZeRhvhbDJykJ2dhbMUBCkuI4DM5qNmGUEqwdrmpqgVXpz%2BD6QbNyLJUs2YfB3bsePvj8Nluag4eBO3LN%2BWSry%2BXz3OahX6lpV5Y717liqillQOrwMWsO7WPK%2F21A2YwJipqaWiH7zL%2B%2FAyhqGsQONVLjS8Wp%2BRwEKUIACFKAABShAAQpQgAIUoED3F%2Bg0RJHUQ3p%2FTLnuIWysuhvLXnwYnywdgMLssBqq01J%2FEHtDFsYPL0N2JIphEy%2FF8P%2F4AIesMGKxcCq8MBArmYAbbr0CpmYfW0KG%2BuQOxjU3fxu%2FeHYFYjEJUdIxho5Tz78G3xoSQryhYzFyhhHNx5B%2BwBuv%2Fhpz1y1GNAQ01ezBjlqgKIhdOl70JX2n6TqKx56HGy58G7957l5seX0AciI6kvEG7NxbiynfvwsjouZXWKMvqaEslgIUoAAFKEABClCAAhSgAAUocJIKdD6xrPQO0QxkFw7ETQt%2BgRtmX4wSM47tFeWo2FmNUJ8RuOr623Dn7EkImxby%2Bo%2FB3QvvxMQRxWr54%2Bp9tYiWDMOlsy5B%2F2gIhmEgHIshFjbblvmVYS6mFUY0GoWha9BDEYyYdj1uvPoSFEcd7Nu7FzVNDoZMOA9%2FM%2BNsGIaGkBlGJBJBOJzKfjQNoXARvjv3p5g6phg1eyqxp7YVIyd%2FF6eNG4qwaUCGDZnhCCLRSFvvlg73WtNhhSOqHiFDV51lQuEYotEIQqFU7xfoapWdWFY2TLVPgxGyEIlGEQ6ngxENZjQf06%2Bbj2uvuAARpxYVlVVo0gsw8%2Fo7cdMVk6HK7%2FDi%2FIYCFKAABShAAQpQgAIUoAAFKECBniKg1dfXH3vBGN%2BH4yRhJ%2BJqdRlohgoPLDPUFohIY2WYj5wTT9jQdBPhSBhm6hzPdZBoaYFrhBGNWCo0UefbNuykh2hWDKHU0r9u0kYikVCr8eghKxVuBENpHDsOOylLGJuIRK22Xh2%2B6yAej6euMSF1s%2BNxhCIxWCEdyURczctiWBbCZsfON77vwo4nkHQ9WJEoLEOHnWiG7Ui4Im0woMlqRE4SrS1xWKqXjAEvmYCddABVl7Ca2yW46T4cO2iD4wEhy0I0Eu5g1VPeHKwnBShAAQpQgAIUoAAFKEABClCAAkBubq5iOH6IQi0KUIACFKAABShAAQpQgAIUoAAFKHASC6RDlC6H85zENmw6BShAAQpQgAIUoAAFKEABClCAAhQ4SkDzg3WEjzrAHRSgAAUoQAEKUIACFKAABShAAQpQgALtAuyJ0m7BZxSgAAUoQAEKUIACFKAABShAAQpQoEsBhihd0vAABShAAQpQgAIUoAAFKEABClCAAhRoF2CI0m7BZxSgAAUoQAEKUIACFKAABShAAQpQoEsBhihd0vAABShAAQpQgAIUoAAFKEABClCAAhRoF%2Fh%2FuTcdZ7vGT7oAAAAASUVORK5CYII%3D)%0A%0A%0A%0A%23%23%23%23%23%23%205.2.7%20%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%0A%0A1.%20%20%E4%BF%AE%E6%94%B9Controller%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Resource%0A%20%20%20private%20DiscoveryClient%20discoveryClient%3B%0A%20%20%20%0A%20%20%20%40GetMapping(%22%2Fdiscovery%22)%0A%20%20%20%20%20%20%20public%20Object%20discovery()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20List%3CString%3E%20services%20%3D%20discoveryClient.getServices()%3B%0A%20%20%20%20%20%20%20%20%20%20%20for%20(String%20service%20%3A%20services)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22service%3A%22%20%2B%20service)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20List%3CServiceInstance%3E%20instances%20%3D%20discoveryClient.getInstances(%22CLOUD-PAYMENT-SERVICE%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20for%20(ServiceInstance%20instance%20%3A%20instances)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.info(instance.getInstanceId()%20%2B%20%22%5Ct%22%20%2B%20instance.getHost()%20%2B%20%22%5Ct%22%20%2B%20instance.getPort()%20%2B%20%22%5Ct%22%20%2B%20instance.getUri())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20return%20this.discoveryClient%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A2.%20%E4%BF%AE%E6%94%B9%E5%90%AF%E5%8A%A8%E7%B1%BB%0A%0A%20%20%20%E5%A2%9E%E5%8A%A0%40EnableDiscoveryClient%20%E6%BF%80%E6%B4%BB%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableEurekaClient%0A%20%20%20%40EnableDiscoveryClient%0A%20%20%20public%20class%20PaymentMain8001%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(PaymentMain8001.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20request%3A%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fdiscovery%0A%20%20%20%0A%20%20%20response%3A%0A%20%20%20%7B%0A%20%20%20%20%20%20%20%22services%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%22cloud-payment-service%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%22cloud-order-service%22%0A%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%22order%22%3A%200%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%205.2.8%20Eureka%E7%9A%84%E8%87%AA%E6%88%91%E4%BF%9D%E6%8A%A4%0A%0A%60%60%60%0AEMERGENCY!%20EUREKA%20MAY%20BE%20INCORRECTLY%20CLAIMING%20INSTANCES%20ARE%20UP%20WHEN%20THEY'RE%20NOT.%20RENEWALS%20ARE%20LESSER%20THAN%20THRESHOLD%20AND%20HENCE%20THE%20INSTANCES%20ARE%20NOT%20BEING%20EXPIRED%20JUST%20TO%20BE%20SAFE.%0A%60%60%60%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%9C%A8%E4%B8%80%E5%AE%9A%E6%97%B6%E9%97%B4%E5%86%85%E6%B2%A1%E6%9C%89%E6%94%B6%E5%88%B0%E6%9F%90%E4%B8%AA%E5%BE%AE%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%B8%85%E6%B1%82%E4%BC%9A%E5%B0%86%E8%AF%A5%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%AE%9E%E7%8E%B0%E6%B3%A8%E9%94%80%E6%8E%89%0A%3E%0A%3E%20%E5%9B%A0%E4%B8%BA%E7%BD%91%E7%BB%9C%E7%AD%89%E5%8E%9F%E5%9B%A0%EF%BC%88%E5%BB%B6%E6%97%B6%EF%BC%8C%E5%8D%A1%E9%A1%BF%EF%BC%8C%E6%8B%A5%E6%8C%A4%EF%BC%89%E6%97%B6%EF%BC%8C%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%B8%8E%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%97%A0%E6%B3%95%E9%80%9A%E4%BF%A1%EF%BC%8C%E4%BD%86%E6%98%AF%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9C%AC%E8%BA%AB%E6%98%AF%E5%81%A5%E5%BA%B7%E7%9A%84%EF%BC%8C%E8%BF%99%E7%A7%8D%E6%83%85%E5%86%B5%E4%B8%8B%E6%B3%A8%E9%94%80%E8%A1%8C%E4%B8%BA%E5%B0%B1%E5%8F%98%E7%9A%84%E9%9D%9E%E5%B8%B8%E5%8D%B1%E9%99%A9%0A%0A%3E%20Eureka%E9%80%9A%E8%BF%87%E8%87%AA%E6%88%91%E4%BF%9D%E6%8A%A4%E6%9D%A5%E8%A7%A3%E5%86%B3%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%98%AF%E5%BC%80%E5%90%AF%E7%8A%B6%E6%80%81%0A%3E%20%E6%9F%90%E4%B8%AA%E6%97%B6%E5%88%BB%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%B8%8D%E8%83%BD%E7%94%A8%E4%BA%86%EF%BC%8CEureka%E4%B8%8D%E4%BC%9A%E7%AB%8B%E5%8D%B3%E6%B8%85%E7%90%86%EF%BC%8C%E4%BE%9D%E6%97%A7%E4%BC%9A%E5%AF%B9%E8%AF%A5%E6%9C%8D%E5%8A%A1%E7%9A%84%E4%BF%A1%E6%81%AF%E8%BF%9B%E8%A1%8C%E4%BF%9D%E6%8A%A4%0A%3E%0A%3E%20%E5%B1%9E%E4%BA%8ECAP%E9%87%8C%E9%9D%A2%E7%9A%84AP%E8%AE%BE%E8%AE%A1%E6%80%9D%E6%83%B3%0A%0A%E5%85%B3%E9%97%ADEureka%E8%87%AA%E6%88%91%E4%BF%9D%E6%8A%A4%0A%0A1.%20%E4%BF%AE%E6%94%B9%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E7%9A%84yml%E9%85%8D%E7%BD%AE%0A%0A%09%60%60%60%0A%09eureka%3A%0A%09%20%20server%3A%0A%09%20%20%20%20%23%20%E5%85%B3%E9%97%AD%E8%87%AA%E6%88%91%E4%BF%9D%E6%8A%A4%EF%BC%8C%E4%BF%9D%E8%AF%81%E4%B8%8D%E5%8F%AF%E7%94%A8%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%8D%B3%E6%97%B6%E6%B8%85%E7%90%86%0A%09%20%20%20%20enable-self-preservation%3A%20false%0A%09%20%20%20%20%23%20%E6%B3%A8%E9%94%80%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%BF%83%E8%B7%B3%E6%97%B6%E9%97%B4%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA60%E7%A7%92%0A%09%20%20%20%20eviction-interval-timer-in-ms%3A%202000%0A%09%60%60%60%0A%20%20%20%20!%5B3e829cf810bdab75f0d608d3487dd97d.png%5D(en-resource%3A%2F%2Fdatabase%2F926%3A1)%0A%20%20%20%20%0A%20%20%20%20%0A%0A2.%20%E4%BF%AE%E6%94%B9%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84yml%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60%0A%20%20%20eureka%3A%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20%23%20Eureka%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA30%E7%A7%92%0A%20%20%20%20%20%20%20lease-renewal-interval-in-seconds%3A%201%0A%20%20%20%20%20%20%20%23%20Eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%94%B6%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%BF%83%E8%B7%B3%E5%90%8E%E7%AD%89%E5%BE%85%E7%9A%84%E6%97%B6%E9%97%B4%E4%B8%8A%E9%99%90%EF%BC%8C%E8%B6%85%E6%97%B6%E5%B0%86%E6%B3%A8%E9%94%80%E6%9C%8D%E5%8A%A1%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92%0A%20%20%20%20%20%20%20lease-expiration-duration-in-seconds%3A%202%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%205.2.9%20%E5%81%9C%E6%9B%B4%E8%AF%B4%E6%98%8E%0A%0Ahttps%3A%2F%2Fgithub.com%2FNetflix%2Feureka%2Fwiki%0A%0A%23%23%23%23%23%205.3%20ZooKeeper%0A%0A%23%23%23%23%23%23%205.3.1%20Zookeeper%E5%AE%89%E8%A3%85%0A%0A%3E%20%20%E5%8F%82%E8%80%83%20Zookeeper%20Installment%20%E7%AC%94%E8%AE%B0%0A%0A%23%23%23%23%23%23%205.3.2%20%E6%94%AF%E4%BB%98%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E5%88%B0zookeeper%0A%0A1.%20%E5%BB%BAmodule%20%0A%20%20%20%3E%20cloud-provider-payment8004%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%3E%20%E5%BC%95%E5%85%A5zookeeper%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--SpringBoot%20%E6%95%B4%E5%90%88%20zookeeper%20client--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-zookeeper-discovery%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BAyml%0A%20%20%20%60%60%60%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%208004%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20utf-8%0A%20%20%20%20%20servlet%3A%0A%20%20%20%20%20%20%20context-path%3A%20%2Fapi%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-provider-payment%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20zookeeper%3A%0A%20%20%20%20%20%20%20%20%20connect-string%3A%20master%3A2181%0A%20%20%20%60%60%60%0A%0A4.%20%E5%90%AF%E5%8A%A8%E7%B1%BB%0A%0A%20%20%20%3E%20%20%40EnableDiscoveryClient%20%2F%2F%E8%AF%A5%E6%B3%A8%E5%86%8C%E5%90%91%E4%BD%BF%E7%94%A8consul%E6%88%96%E8%80%85zookeeper%E4%BD%9C%E4%B8%BA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%97%B6%E6%B3%A8%E5%86%8C%E6%9C%8D%E5%8A%A1%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.springcloud.payment%3B%0A%20%20%20%0A%20%20%20import%20org.springframework.boot.SpringApplication%3B%0A%20%20%20import%20org.springframework.boot.autoconfigure.SpringBootApplication%3B%0A%20%20%20import%20org.springframework.cloud.client.discovery.EnableDiscoveryClient%3B%0A%20%20%20%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableDiscoveryClient%20%2F%2F%E8%AF%A5%E6%B3%A8%E5%86%8C%E5%90%91%E4%BD%BF%E7%94%A8consul%E6%88%96%E8%80%85zookeeper%E4%BD%9C%E4%B8%BA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%97%B6%E6%B3%A8%E5%86%8C%E6%9C%8D%E5%8A%A1%0A%20%20%20public%20class%20PaymentMain8004%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(PaymentMain8004.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20zookeeper%20jar%E5%8C%85%E5%86%B2%E7%AA%81%E7%9A%84%E9%97%AE%E9%A2%98%0A%0A%20%20%20%20%20%20%20%3C!--SpringBoot%20%E6%95%B4%E5%90%88%20zookeeper%20client--%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-zookeeper-discovery%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cexclusions%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cexclusion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.zookeeper%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ezookeeper%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fexclusion%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fexclusions%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%3C!--%E6%B7%BB%E5%8A%A0zookeeper%203.6.1%20%E4%B8%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%89%E8%A3%85%E7%89%88%E6%9C%AC%E5%8C%B9%E9%85%8D%E4%B8%80%E8%87%B4--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.zookeeper%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ezookeeper%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E3.6.1%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%0A%20%20%20%20!%5B9dc770ce2869c2e3be528d94402029b7.png%5D(en-resource%3A%2F%2Fdatabase%2F927%3A1)%0A%0A%0A6.%20%E4%BD%BF%E7%94%A8zkCli.sh%E6%9F%A5%E7%9C%8B%0A%0A%20%20%20%60%60%60shell%0A%20%20%20cd%20bin%0A%20%20%20.%2FzkCli.sh%0A%20%20%20%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%2011%5D%20ls%20%2F%0A%20%20%20%5Bservices%2C%20zookeeper%5D%0A%20%20%20%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%2012%5D%20ls%20%2Fservices%0A%20%20%20%5Bcloud-provider-payment%5D%0A%20%20%20%60%60%60%0A%0A7.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20request%3A%0A%20%20%20http%3A%2F%2Flocalhost%3A8004%2Fapi%2Fpayment%2Fzk%0A%20%20%20%0A%20%20%20response%3A%0A%20%20%20springcloud%20with%20zookeeper%3A8004%099cf857e1-e7e5-4329-bd7e-61ba7d9eb1f0%0A%20%20%20%60%60%60%0A%0A8.%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%9F%A5%E7%9C%8B%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%0A%0A%20%20%20%60%60%60%0A%20%20%20cloud-provider-payment%20%E4%B8%BAzookeeper%E5%86%85%E9%83%A8%E7%9A%84znode%E8%8A%82%E7%82%B9%0A%20%20%201bc5975a-13e6-42a8-8dae-519d0a3139be%20%E4%B8%BAznode%E7%9A%84%E5%94%AF%E4%B8%80%E6%B5%81%E6%B0%B4%E5%8F%B7%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60%0A%20%20%20%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%2011%5D%20ls%20%2F%0A%20%20%20%5Bservices%2C%20zookeeper%5D%0A%20%20%20%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%2012%5D%20ls%20%2Fservices%0A%20%20%20%5Bcloud-provider-payment%5D%0A%20%20%20%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%2013%5D%20ls%20%2Fservices%2Fcloud-provider-payment%0A%20%20%20%5B1bc5975a-13e6-42a8-8dae-519d0a3139be%5D%0A%20%20%20%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%2014%5D%20ls%20%2Fservices%2Fcloud-provider-payment%2F1bc5975a-13e6-42a8-8dae-519d0a3139be%0A%20%20%20%5B%5D%0A%20%20%20%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%2015%5D%20get%20%2Fservices%2Fcloud-provider-payment%2F1bc5975a-13e6-42a8-8dae-519d0a3139be%0A%20%20%20%7B%22name%22%3A%22cloud-provider-payment%22%2C%22id%22%3A%221bc5975a-13e6-42a8-8dae-519d0a3139be%22%2C%22address%22%3A%22DESKTOP-L9SDH81%22%2C%22port%22%3A8004%2C%22sslPort%22%3Anull%2C%22payload%22%3A%7B%22%40class%22%3A%22org.springframework.cloud.zookeeper.discovery.ZookeeperInstance%22%2C%22id%22%3A%22application-1%22%2C%22name%22%3A%22cloud-provider-payment%22%2C%22metadata%22%3A%7B%7D%7D%2C%22registrationTimeUTC%22%3A1597988679352%2C%22serviceType%22%3A%22DYNAMIC%22%2C%22uriSpec%22%3A%7B%22parts%22%3A%5B%7B%22value%22%3A%22scheme%22%2C%22variable%22%3Atrue%7D%2C%7B%22value%22%3A%22%3A%2F%2F%22%2C%22variable%22%3Afalse%7D%2C%7B%22value%22%3A%22address%22%2C%22variable%22%3Atrue%7D%2C%7B%22value%22%3A%22%3A%22%2C%22variable%22%3Afalse%7D%2C%7B%22value%22%3A%22port%22%2C%22variable%22%3Atrue%7D%5D%7D%7D%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60%0A%20%20%20%7B%0A%20%20%20%20%20%22name%22%3A%20%22cloud-provider-payment%22%2C%0A%20%20%20%20%20%22id%22%3A%20%221bc5975a-13e6-42a8-8dae-519d0a3139be%22%2C%0A%20%20%20%20%20%22address%22%3A%20%22DESKTOP-L9SDH81%22%2C%0A%20%20%20%20%20%22port%22%3A%208004%2C%0A%20%20%20%20%20%22sslPort%22%3A%20null%2C%0A%20%20%20%20%20%22payload%22%3A%20%7B%0A%20%20%20%20%20%20%20%22%40class%22%3A%20%22org.springframework.cloud.zookeeper.discovery.ZookeeperInstance%22%2C%0A%20%20%20%20%20%20%20%22id%22%3A%20%22application-1%22%2C%0A%20%20%20%20%20%20%20%22name%22%3A%20%22cloud-provider-payment%22%2C%0A%20%20%20%20%20%20%20%22metadata%22%3A%20%7B%7D%0A%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%22registrationTimeUTC%22%3A%201597988679352%2C%0A%20%20%20%20%20%22serviceType%22%3A%20%22DYNAMIC%22%2C%0A%20%20%20%20%20%22uriSpec%22%3A%20%7B%0A%20%20%20%20%20%20%20%22parts%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%22value%22%3A%20%22scheme%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%22variable%22%3A%20true%0A%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%22value%22%3A%20%22%3A%2F%2F%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%22variable%22%3A%20false%0A%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%22value%22%3A%20%22address%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%22variable%22%3A%20true%0A%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%22value%22%3A%20%22%3A%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%22variable%22%3A%20false%0A%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%22value%22%3A%20%22port%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%22variable%22%3A%20true%0A%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A9.%20Zookeeper%E4%B8%B4%E6%97%B6%E8%8A%82%E7%82%B9%E5%92%8C%E6%8C%81%E4%B9%85%E8%8A%82%E7%82%B9%0A%0A%20%20%20%3E%20zookeeper%E5%9C%A8%E4%B8%80%E5%AE%9A%E6%97%B6%E9%97%B4%E5%86%85(%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92)%EF%BC%8C%E4%BC%9A%E5%B0%86%E6%B2%A1%E6%9C%89%E6%94%B6%E5%88%B0%E5%BF%83%E8%B7%B3%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%B3%A8%E9%94%80%0A%0A%23%23%23%23%23%23%205.3.3%20%20%E8%AE%A2%E5%8D%95%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E5%88%B0zookeeper%0A%0A1.%20%E5%BB%BAmodule%20%0A%0A%20%20%20%3E%20cloud-consumerzk-order80%0A%0A2.%20%E6%94%B9pom%0A%0A3.%20%E5%BB%BAyml%0A%0A%20%20%20%60%60%60%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%2080%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20utf-8%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-consumer-order%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20zookeeper%3A%0A%20%20%20%20%20%20%20%20%20connect-string%3A%20master%3A2181%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableDiscoveryClient%0A%20%20%20public%20class%20OrderZKMain80%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(OrderZKMain80.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Configuration%0A%20%20%20public%20class%20ApplicationContextConfig%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Bean(%22restTemplate%22)%0A%20%20%20%20%20%20%20%40LoadBalanced%0A%20%20%20%20%20%20%20public%20RestTemplate%20getRestTemplate()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20new%20RestTemplate()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%20%20%20%0A6.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fconsumer%22)%0A%20%20%20public%20class%20OrderZKController%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%2F%2Fcloud-provider-payment%20%E4%B8%BA%E5%9C%A8zookeeper%E4%B8%AD%E6%B3%A8%E5%86%8C%E7%9A%84znode%E8%8A%82%E7%82%B9%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20private%20static%20final%20String%20PAYMENT_URL%20%3D%20%22http%3A%2F%2Fcloud-provider-payment%22%3B%0A%20%20%20%0A%20%20%20%09%40Resource%0A%20%20%20%20%20%20%20private%20RestTemplate%20restTemplate%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fpayment%2Fzk%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20restTemplate.getForObject(PAYMENT_URL%20%2B%20%22%2Fapi%2Fpayment%2Fzk%22%2C%20String.class)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%205.4%20Consul%0A%0A%23%23%23%23%23%23%205.4.1%20%E7%AE%80%E4%BB%8B%0A%0A1.%20%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F%0A%0A%20%20%20https%3A%2F%2Fwww.consul.io%2Fintro%0A%0A%20%20%20%E7%94%A8go%E5%BC%80%E5%8F%91%E7%9A%84%EF%BC%8C%E5%BC%80%E6%BA%90%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%E5%92%8C%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%0A%0A%20%20%20%E6%8F%90%E4%BE%9B%E4%BA%86%E5%BE%AE%E6%9C%8D%E5%8A%A1%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%B2%BB%E7%90%86%EF%BC%8C%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%8E%A7%E5%88%B6%E6%80%BB%E7%BA%BF%E7%AD%89%E5%8A%9F%E8%83%BD%EF%BC%8C%E8%BF%99%E4%BA%9B%E5%8A%9F%E8%83%BD%E4%B8%AD%E7%9A%84%E6%AF%8F%E4%B8%80%E4%B8%AA%E9%83%BD%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E9%9C%80%E8%A6%81%E5%8D%95%E7%8B%AC%E4%BD%BF%E7%94%A8%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%9E%84%E5%BB%BA%E5%85%A8%E6%96%B9%E4%BD%8D%E7%9A%84%E6%9C%8D%E5%8A%A1%E9%A3%8E%E6%A0%BC%E3%80%82%0A%0A%20%20%20%E6%94%AF%E6%8C%81HTTP%E5%92%8CDNS%E5%8D%8F%E8%AE%AE%EF%BC%8C%E6%8F%90%E4%BE%9B%E5%9B%BE%E5%BD%A2%E5%8C%96%E7%95%8C%E9%9D%A2%EF%BC%8C%E6%94%AF%E6%8C%81Linux%2CMac%2C%20Windows%0A%0A%0A%0A2.%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%3F%0A%0A%60%60%60%0A%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%0A%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5%0AKV%E5%AD%98%E5%82%A8%0A%E5%A4%9A%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83%0A%E5%8F%AF%E8%A7%86%E5%8C%96Web%E7%95%8C%E9%9D%A2%0A%60%60%60%0A%0A%0A%0A3.%20%E4%B8%8B%E8%BD%BD%0A%0A%20%20%20https%3A%2F%2Fwww.consul.io%2Fdownloads%0A%0A%E2%80%8B%09%09https%3A%2F%2Fwww.springcloud.cc%2Fspring-cloud-consul.html%0A%0A%E2%80%8B%09%09https%3A%2F%2Fcloud.spring.io%2Fspring-cloud-consul%2Freference%2Fhtml%2F%23spring-cloud-consul-bus%0A%0A%23%23%23%23%23%23%205.4.2%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A1.%20ubuntu%E5%AE%89%E8%A3%85%0A%0A%20%20%20https%3A%2F%2Flearn.hashicorp.com%2Ftutorials%2Fconsul%2Fget-started-install%3Fin%3Dconsul%2Fgetting-started%0A%0A%20%20%20%60%60%60shell-session%0A%20%20%20%24%20curl%20-fsSL%20https%3A%2F%2Fapt.releases.hashicorp.com%2Fgpg%20%7C%20sudo%20apt-key%20add%20-%0A%20%20%20%24%20sudo%20apt-add-repository%20%22deb%20%5Barch%3Damd64%5D%20https%3A%2F%2Fapt.releases.hashicorp.com%20%24(lsb_release%20-cs)%20main%22%0A%20%20%20%24%20sudo%20apt-get%20update%20%26%26%20sudo%20apt-get%20install%20consul%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60%0A%20%20%20consul%20--version%0A%20%20%20%23%23%20%E4%BD%BF%E7%94%A8%E5%BC%80%E5%8F%91%E6%A8%A1%E5%BC%8F%E5%90%AF%E5%8A%A8%0A%20%20%20consul%20agent%20-dev%20-node%20machine%20-client%200.0.0.0%0A%20%20%20%0A%20%20%20%23%23%20%E9%BB%98%E8%AE%A4%E7%AB%AF%E5%8F%A38500%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E7%AB%AF%E5%8F%A3%E5%8F%B7%20-http-port%208888%0A%20%20%20consul%20agent%20-dev%20-node%20machine%20-http-port%208888%20-ui%20-client%200.0.0.0%0A%20%20%20%0A%20%20%20%23%23%20%E8%BE%93%E5%87%BA%E6%88%90%E5%91%98%E5%88%97%E8%A1%A8%EF%BC%8C%E6%88%90%E5%91%98%E6%9C%89%E4%B8%89%E7%A7%8D%E7%8A%B6%E6%80%81%E5%88%86%E5%88%AB%E4%B8%BA%20%20%22alive%22%2C%20%22left%22%2C%20or%20%22failed%22%0A%20%20%20consul%20members%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%205.4.3%20%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%B3%A8%E5%86%8C%E5%88%B0Consul%0A%0A%0A%0A1.%20%E5%BB%BAmodul%0A%0A%20%20%20%3E%20cloud-providerconsul-payment8006%0A%0A2.%20%E6%94%B9pom%0A%0A%09%60%60%60%0A%09%20%3C!--SpringBoot%20%E6%95%B4%E5%90%88%20consul%20server%20--%3E%0A%09%20%20%20%3Cdependency%3E%0A%09%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%09%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-consul-discovery%3C%2FartifactId%3E%0A%09%20%20%20%3C%2Fdependency%3E%0A%09%60%60%60%0A%0A3.%20%E5%BB%BAyml%0A%09%60%60%60%0A%09server%3A%0A%09%20%20port%3A%208006%0A%09%20%20tomcat%3A%0A%09%20%20%20%20uri-encoding%3A%20UTF-8%0A%09%20%20servlet%3A%0A%09%20%20%20%20context-path%3A%20%2Fapi%0A%09spring%3A%0A%09%20%20application%3A%0A%09%20%20%20%20name%3A%20consul-provider-payment%0A%09%20%20cloud%3A%0A%09%20%20%20%20consul%3A%0A%09%20%20%20%20%20%20host%3A%20master%0A%09%20%20%20%20%20%20port%3A%208500%0A%09%20%20%20%20%20%20discovery%3A%0A%09%20%20%20%20%20%20%20%20service-name%3A%20%24%7Bspring.application.name%7D%0A%09%20%20%20%20%20%20%20%20health-check-path%3A%20%24%7Bserver.servlet.context-path%7D%2Factuator%2Fhealth%0A%09%20%20%20%20%20%20%20%20%23%E9%BB%98%E8%AE%A410s%0A%09%20%20%20%20%20%20%20%20health-check-interval%3A%203s%0A%09%60%60%60%0A%09%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%3E%20%40EnableDiscoveryClient%20%E6%BF%80%E6%B4%BB%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableDiscoveryClient%0A%20%20%20public%20class%20PaymentMain8006%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(PaymentMain8006.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A6.%20%E6%88%90%E5%8A%9F%E6%B3%A8%E5%86%8C%E5%90%8E%E7%9A%84%E6%95%88%E6%9E%9C%0A%0A%20%20%20%3E%20%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%E4%B8%BA%20yml%E4%B8%AD%E7%9A%84%20service-name%3A%20%24%7Bspring.application.name%7D%0A%0A%20%20%20%20!%5B14a4e0a6ad984b75c5bb6fb822935128.png%5D(en-resource%3A%2F%2Fdatabase%2F924%3A1)%0A%20%20%20%20%0A%0A%20%207.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%20%20%60%60%60%0A%20%20%20%20%20%20%20request%3A%0A%20%20%20%20%20%20%20%20http%3A%2F%2Flocalhost%3A8006%2Fapi%2Fpayment%2Fconsul%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20response%3A%0A%20%20%20%20%20%20%20%20spirngcloud%20with%20consul%3A8006%0925c07bdc-7f97-4ef6-9d42-4fdc79c24126%0A%20%20%20%20%20%60%60%60%0A%0A%20%20%20%20%20%0A%0A%23%23%23%23%23%23%205.4.4%20%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E6%B3%A8%E5%86%8C%E5%88%B0Consul%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%20%20%3E%20cloud-consumer-consul-order80%0A%0A%0A2.%20%E6%94%B9pom.xml%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--SpringBoot%20%E6%95%B4%E5%90%88%20consul%20server%20--%3E%0A%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-consul-discovery%3C%2FartifactId%3E%0A%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%20%203.%20%E5%BB%BAyml%0A%0A%20%20%20%20%20%60%60%60%0A%20%20%20%20%20server%3A%0A%20%20%20%20%20%20%20port%3A%2080%0A%20%20%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20%20%20spring%3A%0A%20%20%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20%20%20name%3A%20consul-consumer-order%0A%20%20%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20%20%20consul%3A%0A%20%20%20%20%20%20%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20%20%20%20%20%20%20port%3A%208500%0A%20%20%20%20%20%20%20%20%20%20%20discovery%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20service-name%3A%20%24%7Bspring.application.name%7D%0A%20%20%20%20%20%60%60%60%0A%0A%20%204.%20%E5%90%AF%E5%8A%A8%E7%B1%BB%0A%0A%20%20%20%20%20%20%3E%20%40EnableDiscoveryClient%20%E6%BF%80%E6%B4%BB%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%0A%0A%20%20%20%20%20%20%60%60%60java%0A%20%20%20%20%20%20%40SpringBootApplication%0A%20%20%20%20%20%20%40EnableDiscoveryClient%0A%20%20%20%20%20%20public%20class%20OrderConsulMain80%20%7B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(OrderConsulMain80.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%60%60%60%0A%0A%20%205.%20%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A%20%20%20%20%20%60%60%60java%0A%20%20%20%20%20package%20com.chris.springcloud.config%3B%0A%20%20%20%20%20%0A%20%20%20%20%20import%20org.springframework.cloud.client.loadbalancer.LoadBalanced%3B%0A%20%20%20%20%20import%20org.springframework.context.annotation.Bean%3B%0A%20%20%20%20%20import%20org.springframework.context.annotation.Configuration%3B%0A%20%20%20%20%20import%20org.springframework.web.client.RestTemplate%3B%0A%20%20%20%20%20%0A%20%20%20%20%20%40Configuration%0A%20%20%20%20%20public%20class%20ApplicationContextConfig%20%7B%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%40Bean(%22restTemplate%22)%0A%20%20%20%20%20%20%20%20%20%40LoadBalanced%0A%20%20%20%20%20%20%20%20%20public%20RestTemplate%20getRestTemplate()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20RestTemplate()%3B%0A%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%7D%0A%20%20%20%20%20%0A%20%20%20%20%20%60%60%60%0A%0A%20%206.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%20%20%60%60%60java%20%0A%20%20%20%20%20%40RestController%0A%20%20%20%20%20%40RequestMapping(%22%2Fcustomer%22)%0A%20%20%20%20%20public%20class%20OrderConsulController%20%7B%0A%20%20%20%20%20%20%20%20%20private%20static%20final%20String%20PAYMENT_URL%20%3D%20%22http%3A%2F%2Fconsul-provider-payment%22%3B%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20%20%20private%20RestTemplate%20restTemplate%3B%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%40GetMapping(%22%2Fpayment%2Fconsul%22)%0A%20%20%20%20%20%20%20%20%20public%20String%20paymentInfo()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20return%20restTemplate.getForObject(PAYMENT_URL%20%2B%20%22api%2Fpayment%2Fconsul%22%2C%20String.class)%3B%0A%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%7D%0A%20%20%20%20%20%60%60%60%0A%0A%20%207.%20%E6%B3%A8%E5%86%8C%E6%88%90%E5%8A%9F%E5%90%8E%E6%95%88%E6%9E%9C%0A%0A%20%20%20%20%20!%5B2e689d13dc2b795ce9484d71a151761a.png%5D(en-resource%3A%2F%2Fdatabase%2F925%3A1)%0A%20%20%20%20%0A%20%208.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%20%20%60%60%60%0A%20%20%20%20%20%20%20%20request%3A%0A%20%20%20%20%20%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Fconsul%0A%20%20%20%20%20%0A%20%20%20%20%20%20%20%20response%3A%0A%20%20%20%20%20%20%20%20spirngcloud%20with%20consul%3A8006%09eb16d116-7849-4d8e-8782-0e13aa027a3f%0A%20%20%20%20%20%60%60%60%0A%0A%20%20%20%20%20%0A%0A%23%23%23%23%23%23%205.4.5%20%20HTTP%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5%0A%0AConsul%E5%AE%9E%E4%BE%8B%E7%9A%84%E8%BF%90%E8%A1%8C%E7%8A%B6%E5%86%B5%E6%A3%80%E6%9F%A5%E9%BB%98%E8%AE%A4%E4%B8%BA%E2%80%9C%2F%20health%E2%80%9D%EF%BC%8C%0A%0A%E5%AE%83%E6%98%AFSpring%20Boot%20Actuator%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E4%B8%AD%E6%9C%89%E7%94%A8%E7%AB%AF%E7%82%B9%E7%9A%84%E9%BB%98%E8%AE%A4%E4%BD%8D%E7%BD%AE%E3%80%82%0A%0A%E5%A6%82%E6%9E%9C%E4%BD%A0%E4%BD%BF%E7%94%A8%E4%BA%86servlet%E8%B7%AF%E5%BE%84%EF%BC%88%E4%BE%8B%E5%A6%82%60server.servletPath%3D%2Ffoo%60%EF%BC%89%E5%88%99%E9%9C%80%E8%A6%81%E6%9B%B4%E6%94%B9%E8%BF%99%E4%BA%9B%EF%BC%8C%E5%8D%B3%E4%BD%BF%E6%98%AF%E6%89%A7%E8%A1%8C%E5%99%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%0A%0A%60%60%60%0Aspring%3A%0A%20%20application%3A%0A%20%20%20%20name%3A%20consul-provider-payment%0A%20%20cloud%3A%0A%20%20%20%20consul%3A%0A%20%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20%20port%3A%208500%0A%20%20%20%20%20%20discovery%3A%0A%20%20%20%20%20%20%20%20service-name%3A%20%24%7Bspring.application.name%7D%0A%20%20%20%20%20%20%20%20health-check-path%3A%20%24%7Bserver.servlet.context-path%7D%2Factuator%2Fhealth%0A%20%20%20%20%20%20%20%20%23%E9%BB%98%E8%AE%A410s%0A%20%20%20%20%20%20%20%20health-check-interval%3A%203s%20%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%205.5%20%E6%80%BB%E7%BB%93%0A%0A%23%23%23%23%23%23%205.5.1%20%E6%B1%87%E6%80%BB%0A%0A%7C%20%E5%90%8D%E7%A7%B0%20%20%20%20%20%20%7C%20%E8%AF%AD%E8%A8%80%20%7C%20CAP%20%20%7C%20Health%20Check%20%7C%20%E5%AF%B9%E5%A4%96%E5%8D%8F%E8%AE%AE%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E6%98%AF%E5%90%A6%E9%9B%86%E6%88%90%E5%88%B0SpringCloud%20%7C%0A%7C%20---------%20%7C%20----%20%7C%20----%20%7C%20------------%20%7C%20-------------------%20%7C%20---------------------%20%7C%0A%7C%20Eureka%20%20%20%20%7C%20java%20%7C%20AP%20%20%20%7C%20%E9%9C%80%E9%85%8D%E7%BD%AE%20%20%20%20%20%20%20%7C%20%E6%9C%89%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E5%B7%B2%E9%9B%86%E6%88%90%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20ZooKeeper%20%7C%20java%20%7C%20CP%20%20%20%7C%20%E6%94%AF%E6%8C%81%20%20%20%20%20%20%20%20%20%7C%20%E6%97%A0%EF%BC%8C%E5%8F%AA%E6%9C%89Linux%E5%AE%A2%E6%88%B7%E7%AB%AF%20%7C%20%E5%B7%B2%E9%9B%86%E6%88%90%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20Consul%20%20%20%20%7C%20go%20%20%20%7C%20CP%20%20%20%7C%20%E6%94%AF%E6%8C%81%20%20%20%20%20%20%20%20%20%7C%20HTTP%E3%80%81DNS%20%20%20%20%20%20%20%20%20%20%20%7C%20%E5%B7%B2%E9%9B%86%E6%88%90%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%0A%23%23%23%23%23%23%205.5.2%20CAP%E7%90%86%E8%AE%BA%0A%0ACAP%3A%E5%85%B3%E6%B3%A8%E7%9A%84%E7%B2%92%E5%BA%A6%E6%98%AF%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%98%AF%E6%95%B4%E4%BD%93%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1%E7%AD%96%E7%95%A5%0A%0A%3E%20Consistency%20%E4%B8%80%E8%87%B4%E6%80%A7%0A%3E%0A%3E%20Availability%20%20%E5%8F%AF%E7%94%A8%E6%80%A7%0A%3E%0A%3E%20Partition%20Tolerance%20%E5%88%86%E5%8C%BA%E5%AE%B9%E9%94%99%E6%80%A7%0A%0A%0A%0A%23%23%23%23%206%20%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E5%92%8C%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%0A%23%23%23%23%23%206.1%20Ribbon%0A%0A%23%23%23%23%23%23%206.1.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20Netflix%E5%8F%91%E5%B8%83%E7%9A%84%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%EF%BC%8C%E4%B8%BB%E8%A6%81%E5%8A%9F%E8%83%BD%E6%98%AF%E6%8F%90%E4%BE%9B%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E8%BD%AF%E4%BB%B6%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%92%8C%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E3%80%82%0A%3E%0A%3E%20Ribbon%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%BB%84%E4%BB%B6%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E7%B3%BB%E5%88%97%E5%AE%8C%E5%96%84%E7%9A%84%E9%85%8D%E7%BD%AE%E9%A1%B9%E5%A6%82%E8%BF%9E%E6%8E%A5%E8%B6%85%E6%97%B6%EF%BC%8C%E9%87%8D%E8%AF%95%E7%AD%89%0A%3E%0A%3E%20%E5%B0%B1%E6%98%AF%E5%9C%A8%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E5%88%97%E5%87%BALoad%20Balancer%E5%90%8E%E9%9D%A2%E6%89%80%E6%9C%89%E7%9A%84%E6%9C%BA%E5%99%A8%EF%BC%8CRibbon%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%9F%BA%E4%BA%8E%E6%9F%90%E7%A7%8D%E8%A7%84%E5%88%99%EF%BC%88%E8%BD%AE%E8%AF%A2%EF%BC%8C%E9%9A%8F%E6%9C%BA%E7%AD%89%EF%BC%89%E5%8E%BB%E8%BF%9E%E6%8E%A5%E8%BF%99%E4%BA%9B%E6%9C%BA%E5%99%A8%0A%3E%0A%3E%20Ribbon%E5%90%8C%E8%BF%9B%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AE%97%E6%B3%95%0A%0A%0A%0A%3E%20%E5%AE%98%E6%96%B9%E8%B5%84%E6%96%99%EF%BC%9A%0Ahttps%3A%2F%2Fgithub.com%2FNetflix%2Fribbon%2Fwiki%2FGetting-Started%0A%E7%9B%AE%E5%89%8DRibbon%E5%B7%B2%E8%BF%9B%E5%85%A5%E7%BB%B4%E6%8A%A4%E9%98%B6%E6%AE%B5%0A%0A%0A%0A%3E%20%E6%9C%AA%E6%9D%A5%E6%9B%BF%E6%8D%A2%E6%96%B9%E6%A1%88%EF%BC%9A%0ASpring%20Cloud%20Starter%20LoadBalancer%0A%0A%0A%0A%0A%0A%0A%23%23%23%23%23%23%206.1.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A1.%20%E4%BB%80%E4%B9%88%E6%98%AF%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%0A%20%20%20%3E%20%E5%B0%86%E8%AF%B7%E6%B1%82%E5%B9%B3%E5%9D%87%E7%9A%84%E5%88%86%E9%85%8D%E5%88%B0%E5%A4%9A%E4%B8%AA%E6%9C%8D%E5%8A%A1%E4%B8%8A%EF%BC%8C%E4%BB%8E%E8%80%8C%E8%BE%BE%E5%88%B0%E7%B3%BB%E7%BB%9F%E7%9A%84%E9%AB%98%E5%8F%AF%E7%94%A8(HA)%0A%20%20%20%3E%20%E5%B8%B8%E8%A7%81%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%BB%84%E4%BB%B6%E6%9C%89%EF%BC%8CNginx%2C%20LVS%2C%20%E7%A1%AC%E4%BB%B6F5%E7%AD%89%0A%0A2.%20Ribbon%E6%9C%AC%E5%9C%B0%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%92%8CNginx%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%0A%20%20%20%3E%20Nginx%E6%98%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E7%9A%84%E9%9B%86%E6%88%90%E5%BC%8F%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%EF%BC%8C%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%89%80%E6%9C%89%E8%AF%B7%E6%B1%82%E9%83%BD%E4%BA%A4%E7%BB%99Nginx%EF%BC%8C%E7%84%B6%E5%90%8E%E7%94%B1Nginx%E5%AE%9E%E7%8E%B0%E8%AF%B7%E6%B1%82%E8%BD%AC%E5%8F%91%EF%BC%8C%E5%8D%B3%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%98%AF%E7%94%B1%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0%E7%9A%84%E3%80%82%0A%0A%20%20%20%3E%20Ribbon%E6%98%AF%E6%9C%AC%E5%9C%B0%E7%9A%84%E8%BF%9B%E7%A8%8B%E5%86%85%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%EF%BC%8C%E5%9C%A8%E8%B0%83%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3%E6%97%B6%EF%BC%8CRibbon%E4%BC%9A%E5%9C%A8%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E8%8E%B7%E5%8F%96%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E7%84%B6%E5%90%8E%E7%BC%93%E5%AD%98%E5%9C%A8JVM%E6%9C%AC%E5%9C%B0%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%9C%A8%E6%9C%AC%E5%9C%B0%E5%AE%9E%E7%8E%B0RPC%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E6%8A%80%E6%9C%AF%E3%80%82%0A%20%20%20Ribbon%E9%9B%86%E6%88%90%E4%BA%8E%E6%B6%88%E8%B4%B9%E6%96%B9%E6%9C%8D%E5%8A%A1%E8%BF%9B%E7%A8%8B%E4%B8%AD%EF%BC%8C%E6%B6%88%E8%B4%B9%E6%96%B9%E9%80%9A%E8%BF%87%E5%AE%83%E6%9D%A5%E8%8E%B7%E5%8F%96%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9%E7%9A%84%E5%9C%B0%E5%9D%80%0A%0A%20%20%20**Ribbon%20%3D%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AE%97%E6%B3%95%20%2B%20RestTemplate**%0A%0A3.%20%E5%B7%A5%E4%BD%9C%E6%97%B6%E5%88%86%E4%B8%BA%E4%B8%A4%E6%AD%A5%0A%0A%20%20%3E%20%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%85%88%E9%80%89%E6%8B%A9EurekaServer%EF%BC%8C%E4%BC%98%E5%85%88%E9%80%89%E6%8B%A9%E5%90%8C%E4%B8%80%E5%8C%BA%E5%9F%9F%E5%86%85%E8%B4%9F%E8%BD%BD%E8%BE%83%E5%B0%91%E7%9A%84server%0A%20%20%3E%20%E7%AC%AC%E4%BA%8C%E6%AD%A5%E5%86%8D%E6%A0%B9%E6%8D%AE%E7%94%A8%E6%88%B7%E6%8C%87%E5%AE%9A%E7%9A%84%E7%AD%96%E7%95%A5%EF%BC%8C%E4%BB%8E%E8%8E%B7%E5%8F%96%E5%88%B0%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%88%97%E8%A1%A8%E4%B8%AD%E9%80%89%E6%8B%A9%E4%B8%80%E4%B8%AA%E5%9C%B0%E5%9D%80%0A%0A%20%20%20Ribbon%20%E6%8F%90%E4%BE%9B%E4%BA%86%E5%A4%9A%E7%A7%8D%E7%AD%96%E7%95%A5%EF%BC%9A%0A%0A%20%20%20%3E%20%E8%BD%AE%E8%AF%A2%0A%20%20%20%3E%0A%20%20%20%3E%20%E9%9A%8F%E6%9C%BA%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%A0%B9%E6%8D%AE%E5%93%8D%E5%BA%94%E6%97%B6%E9%97%B4%E5%8A%A0%E6%9D%83%0A%0A%20%20%20%0A%0A%23%23%23%23%23%206.2%20%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%92%8CREST%E8%B0%83%E7%94%A8%0A%0A%23%23%23%23%23%23%206.2.1%20Eureka%E5%B7%B2%E9%9B%86%E6%88%90Ribbon%0A%0A%0A%0A%0A%23%23%23%23%23%23%206.2.2%20RestTemplate%E7%9A%84%E4%BD%BF%E7%94%A8%0A%0A%201.%20%E5%AE%98%E7%BD%91%0A%0A%20%20%20%20https%3A%2F%2Fdocs.spring.io%2Fspring%2Fdocs%2Fcurrent%2Fjavadoc-api%2F%0A%20%20%20%20https%3A%2F%2Fdocs.spring.io%2Fspring-framework%2Fdocs%2F5.2.2.RELEASE%2Fjavadoc-api%2Forg%2Fspringframework%2Fweb%2Fclient%2FRestTemplate.html%0A%0A%0A%0A2.%20postForObject%20%26%20getForObject%0A%0A%20%20%20%E8%BF%94%E5%9B%9E%E5%AF%B9%E8%B1%A1%E4%B8%BAJSON%0A%0A%60%60%60java%0A%0Apublic%20CommonResult%3CPayment%3E%20create(Payment%20payment)%20%7B%0A%20%20%20%20%20%20%20%20return%20restTemplate.postForObject(PAYMENT_URL%20%2B%20%22%2Fapi%2Fpayment%2Fcreate%22%2C%20payment%2C%20CommonResult.class)%3B%0A%7D%0A%0A%60%60%60%0A%0A%60%60%60java%0A%20public%20CommonResult%3CPayment%3E%20getPayment(%40PathVariable(%22id%22)%20Long%20id)%20%7B%0A%20%20%20%20%20%20%20%20return%20restTemplate.getForObject(PAYMENT_URL%20%2B%20%22%2Fapi%2Fpayment%2Fget%2F%22%20%2B%20id%2C%20CommonResult.class)%3B%0A%20%7D%0A%60%60%60%0A%0A%0A%0A3.%20postForEntity%20%26%20getForEntity%0A%0A%20%20%20%E5%8C%85%E5%90%AB%E5%A4%B4%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%93%8D%E5%BA%94%E7%8A%B6%E6%80%81%E7%A0%81%EF%BC%8C%E5%93%8D%E5%BA%94%E4%BD%93%0A%0A%60%60%60java%0A%40GetMapping(%22%2Fpayment%2Fcreate2%22)%0A%20%20%20%20%40SuppressWarnings(%22unchecked%22)%0A%20%20%20%20public%20CommonResult%3CPayment%3E%20create2(Payment%20payment)%20%7B%0A%20%20%20%20%20%20%20%20ResponseEntity%3CCommonResult%3E%20entity%20%3D%20restTemplate.postForEntity(PAYMENT_URL%20%2B%20%22%2Fapi%2Fpayment%2Fcreate%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20payment%2C%20CommonResult.class)%3B%0A%20%20%20%20%20%20%20%20log.info(%22status%3A%22%20%2B%20entity.getStatusCode()%20%2B%20%22%2Chead%3A%22%20%2B%20entity.getHeaders())%3B%0A%20%20%20%20%20%20%20%20if%20(entity.getStatusCode().is2xxSuccessful())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20entity.getBody()%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20CommonResult%3C%3E(444%2C%20%22create2%20method%20operation%20fail%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%7D%0A%60%60%60%0A%0A%60%60%60java%0A%40GetMapping(%22%2Fpayment%2Fget2%2F%7Bid%7D%22)%0A%40SuppressWarnings(%22unchecked%22)%0Apublic%20CommonResult%3CPayment%3E%20getPayment2(%40PathVariable(%22id%22)%20Long%20id)%20%7B%0A%20%20%20%20ResponseEntity%3CCommonResult%3E%20entity%20%3D%20restTemplate.getForEntity(PAYMENT_URL%20%2B%20%22%2Fapi%2Fpayment%2Fget%2F%22%20%2B%20id%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20CommonResult.class)%3B%0A%20%20%20%20log.info(%22status%3A%22%20%2B%20entity.getStatusCode()%20%2B%20%22%2Chead%3A%22%20%2B%20entity.getHeaders())%3B%0A%20%20%20%20if%20(entity.getStatusCode().is2xxSuccessful())%20%7B%0A%20%20%20%20%20%20%20%20return%20entity.getBody()%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20CommonResult(444%2C%20%22get2%20mothod%20opration%20fail%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%206.2.3%20Ribbon%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AE%97%E6%B3%95%0A%0A1.%20IRule%3A%20%E6%A0%B9%E6%8D%AE%E7%89%B9%E5%AE%9A%E7%AE%97%E6%B3%95%E4%BB%8E%E6%9C%8D%E5%8A%A1%E5%88%97%E8%A1%A8%E4%B8%AD%E9%80%89%E5%8F%96%E4%B8%80%E4%B8%AA%E8%A6%81%E8%AE%BF%E9%97%AE%E7%9A%84%E6%9C%8D%E5%8A%A1%0A%0A%20%20%20%3E%20AbstractLoadBalancerRule%0A%0A%20%20%20%20%60%60%60%0A%20%20%20%20BestAvailableRule%0A%20%20%20%20RandomRule%20--%E9%9A%8F%E6%9C%BA%0A%20%20%20%20RetryRule%20%20%0A%20%20%20%20RoundRobinRule%20--%E8%BD%AE%E8%AF%A2%0A%20%20%20%20ZoneAvoidanceRule%0A%20%20%20%20AvailabilityFilteringRule%20--%E6%A0%B9%E6%8D%AE%E5%93%8D%E5%BA%94%E6%97%B6%E9%97%B4%E5%8A%A0%E6%9D%83%E9%87%8D%0A%20%20%20%20WeightedResponseTimeRule%0A%20%20%20%20%60%60%60%0A%0A%0A%0A2.%20%E6%9B%BF%E6%8D%A2Ribbon%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%0A%20%20%20%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AE%97%E6%B3%95%E4%B8%8D%E8%83%BD%E6%94%BE%E5%9C%A8%40ComponentScan%E6%89%80%E8%83%BD%E6%89%AB%E6%8F%8F%E5%88%B0%E7%9A%84%E5%8C%85%E9%87%8C%E9%9D%A2%0A%0A%20%20%20https%3A%2F%2Fcloud.spring.io%2Fspring-cloud-netflix%2Fmulti%2Fmulti_spring-cloud-ribbon.html%0A%0A%20%20%20%20!%5Bbdf07f420d879e44cdfa7815c78d4373.png%5D(en-resource%3A%2F%2Fdatabase%2F928%3A1)%0A%0A%0A%0A%0A%20%20%20%20%E6%96%B0%E5%A2%9E%09**com.springcloud.myrule.MySelfRule**%0A%0A%20%20%20%20%60%60%60java%0A%20%20%20%20%40Configuration%0A%20%20%20%20public%20class%20MySelfRule%20%7B%0A%20%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20%20public%20IRule%20myRule()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E9%9A%8F%E6%9C%BA%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AE%97%E6%B3%95%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20RandomRule()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20%E5%9C%A8%E4%B8%BB%E5%90%AF%E5%8A%A8%E7%B1%BB%E4%B8%8A%E6%B7%BB%E5%8A%A0%40RibbonClient%0A%0A%20%20%20%20%3E%20name%E4%B8%BA%E5%9C%A8eureka%E9%87%8C%E9%9D%A2%E6%B3%A8%E5%86%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%BA%94%E7%94%A8%E5%90%8D%E7%A7%B0%0A%20%20%20%20%3E%0A%20%20%20%20%3E%20configuration%E4%B8%BA%E6%96%B0%E5%A2%9E%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%B1%BB%0A%0A%20%20%20%20%60%60%60java%0A%20%20%20%20%40SpringBootApplication%0A%20%20%20%20%40EnableEurekaClient%0A%20%20%20%20%40RibbonClient(name%20%3D%20%22CLOUD-PAYMENT-SERVICE%22%2C%20configuration%20%3D%20MySelfRule.class)%0A%20%20%20%20public%20class%20OrderMain%20%7B%0A%20%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(OrderMain.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20%60%60%60%0A%0A3.%20%E7%AE%97%E6%B3%95%0A%0A%20%20%20%3E%20Rest%E6%8E%A5%E5%8F%A3%E7%AC%AC%E5%87%A0%E6%AC%A1%E8%AF%B7%E6%B1%82%E6%95%B0%20%25%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%86%E7%BE%A4%E6%80%BB%E6%95%B0%E9%87%8F%3D%E5%AE%9E%E9%99%85%E8%B0%83%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%8D%E7%BD%AE%E4%B8%8B%E6%A0%87%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%AF%8F%E6%AC%A1%E6%9C%8D%E5%8A%A1%E9%87%8D%E5%90%AF%E5%90%8E%2Crest%E6%8E%A5%E5%8F%A3%E8%AE%A1%E6%95%B0%E4%BB%8E1%E5%BC%80%E5%A7%8B%0A%0A%0A%0A%23%23%23%23%23%23%206.2.4%20%E6%89%8B%E5%86%99Ribbon%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AE%97%E6%B3%95%0A%0A1.%20%E5%8E%9F%E7%90%86%0A%0A%20%20%20JUC(CAS%2B%E8%87%AA%E6%97%8B%E9%94%81)%0A%0A2.%20%E6%B3%A8%E9%87%8ARestTemplate%E4%B8%8A%E7%9A%84%40LoadBalanced%0A%0A%20%20%20cloud-consumer-order80%0A%0A%20%20%20%20%20%20%60%60%60java%0A%20%20%20%20%20%20%40Configuration%0A%20%20%20%20%20%20public%20class%20ApplicationContextConfig%20%7B%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%E6%89%8B%E5%86%99Ribbon%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AE%97%E6%B3%95%E6%97%B6%E5%8E%BB%E6%8E%89%40LoadBalanced%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%40LoadBalanced%0A%20%20%20%20%20%20%20%20%20%20public%20RestTemplate%20getRestTemplate()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20RestTemplate()%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%7D%0A%20%20%20%20%20%20%60%60%60%0A%0A3.%20%E8%87%AA%E5%AE%9A%E4%B9%89LoadBanancerr%E6%8E%A5%E5%8F%A3%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20interface%20LoadBalancer%20%7B%0A%20%20%20%20%20%20%20ServiceInstance%20instances(List%3CServiceInstance%3E%20serviceInstances)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A4.%20%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%AE%9A%E4%B9%89LoadBalancer%E6%8E%A5%E5%8F%A3%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Component%0A%20%20%20%40Slf4j%0A%20%20%20public%20class%20MyLB%20implements%20LoadBalancer%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20private%20AtomicInteger%20atomicInteger%20%3D%20new%20AtomicInteger(0)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20ServiceInstance%20instances(List%3CServiceInstance%3E%20serviceInstances)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20int%20index%20%3D%20getAndIncrement()%20%25%20serviceInstances.size()%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20serviceInstances.get(index)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%0A%20%20%20%20%20%20%20public%20int%20getAndIncrement()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20int%20current%3B%0A%20%20%20%20%20%20%20%20%20%20%20int%20next%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20do%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20current%20%3D%20this.atomicInteger.get()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20next%20%3D%20current%20%3E%3D%202147483647%20%3F%200%20%3A%20current%20%2B%201%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20while%20(this.atomicInteger.compareAndSet(current%2C%20next))%3B%0A%20%20%20%20%20%20%20%20%20%20%20log.info(%22%E7%AC%AC%E5%87%A0%E6%AC%A1%E8%AE%BF%E9%97%AE%EF%BC%8C%E6%AC%A1%E6%95%B0next%3A%22%20%2B%20next)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20next%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E5%AE%9E%E7%8E%B0Controller%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fconsumer%22)%0A%20%20%20public%20class%20OrderController%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20RestTemplate%20restTemplate%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20LoadBalancer%20myLB%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20DiscoveryClient%20discoveryClient%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fpayment%2Flb%22)%0A%20%20%20%20%20%20%20public%20String%20getPaymentLB()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20List%3CServiceInstance%3E%20instances%20%3D%20discoveryClient.getInstances(%22CLOUD-PAYMENT-SERVICE%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(CollectionUtils.isEmpty(instances))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20ServiceInstance%20serviceInstance%20%3D%20myLB.instances(instances)%3B%0A%20%20%20%20%20%20%20%20%20%20%20URI%20uri%20%3D%20serviceInstance.getUri()%3B%0A%20%20%20%20%20%20%20%20%20%20%20log.info(%22uri%3A%22%20%2B%20uri)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20restTemplate.getForObject(uri%20%2B%20%22%2Fpayment%2Flb%22%2C%20String.class)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%206.3%20OpenFeign%0A%0A%23%23%23%23%23%23%206.3.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%60%60%60%0Ahttps%3A%2F%2Fcloud.spring.io%2Fspring-cloud-static%2FHoxton.SR1%2Freference%2Fhtmlsingle%2F%23spring-cloud-openfeign%0Ahttps%3A%2F%2Fgithub.com%2Fspring-cloud%2Fspring-cloud-openfeign%0A%60%60%60%0A%0A%3E%20Feign%E6%98%AF%E4%B8%80%E4%B8%AA%E5%A3%B0%E6%98%8E%E5%BC%8F%E7%9A%84webservice%E5%AE%A2%E6%88%B7%E7%AB%AF%EF%BC%8C%E4%BD%BF%E7%94%A8Feign%E4%BD%BF%E7%BC%96%E5%86%99webservice%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9B%B4%E5%8A%A0%E7%AE%80%E5%8D%95%0A%3E%20Feign%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E6%98%AF%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3%E7%84%B6%E5%90%8E%E5%9C%A8%E4%B8%8A%E9%9D%A2%E6%B7%BB%E5%8A%A0%E6%B3%A8%E8%A7%A3%E3%80%82%0A%3E%20Feign%E5%8F%AF%E4%B8%8EEureka%E5%92%8CRibbon%E7%BB%84%E5%90%88%E4%BD%BF%E7%94%A8%E4%BB%A5%E6%94%AF%E6%8C%81%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%3E%20Feign%E8%87%AA%E8%BA%AB%E9%9B%86%E6%88%90Ribbon%0A%0A%23%23%23%23%23%23%206.3.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A1.%20%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%E5%B9%B6%E4%BD%BF%E7%94%A8%E6%B3%A8%E8%A7%A3%E9%85%8D%E7%BD%AE%E5%AE%83%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%AE%8C%E6%88%90%E5%AF%B9%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%BB%91%E5%AE%9A%0A2.%20Feign%E9%9B%86%E6%88%90%E4%BA%86Ribbon%0A%20%20%20!%5Ba1122fcf35fd971c084509f28cb9af9d.png%5D(en-resource%3A%2F%2Fdatabase%2F934%3A1)%0A%20%20%20%0A%0A%23%23%23%23%23%23%206.3.3%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloud-consumer-feign-order80%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-actuator%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-devtools%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-test%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Etest%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecom.chris.springcloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ecloud-api-commons%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E%24%7Bcommon.api.version%7D%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--eureka%20client--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--open%20feign--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-openfeign%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C%2Fdependencies%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BAyml%0A%0A%20%20%20%60%60%60%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%2080%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20utf-8%0A%20%20%20%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-order-feign-service%0A%20%20%20%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%3E%20%40EnableFeignClients%20%E6%BF%80%E6%B4%BBFeign%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableFeignClients%0A%20%20%20public%20class%20OrderFeignMain80%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(OrderFeignMain80.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%3E%20%40FeignClient(value%20%3D%20%22CLOUD-PAYMENT-SERVICE%22)%20%E5%A3%B0%E6%98%8E%E6%AD%A4%E6%8E%A5%E5%8F%A3%E4%BD%BF%E7%94%A8feign%E4%BD%9C%E4%B8%BA%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%92%8C%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E6%8E%A5%E5%8F%A3%EF%BC%8C%20CLOUD-PAYMENT-SERVICE%E4%B8%BA%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E4%B8%AD%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%0A%20%20%20%3E%0A%20%20%20%3E%20PaymentFeignService%20%E5%AE%9A%E4%B9%89%E4%BA%86%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3**PaymentController**%E5%8E%9F%E6%A0%B7%E6%8B%B7%E8%B4%9D%EF%BC%8CURL%2C%E6%96%B9%E6%B3%95%E9%83%BD%E9%9C%80%E8%A6%81%E4%B8%80%E6%A0%B7%EF%BC%8C%E8%BF%94%E5%9B%9E%E5%80%BC%E5%9B%A0%E4%B8%BA%E6%98%AF%E9%9D%A2%E5%90%91%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E8%BF%94%E5%9B%9ECommonResult%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Component%0A%20%20%20%40FeignClient(value%20%3D%20%22CLOUD-PAYMENT-SERVICE%22)%0A%20%20%20%40RequestMapping(%22%2Fapi%2Fpayment%22)%0A%20%20%20public%20interface%20PaymentFeignService%20%7B%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fget%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20CommonResult%3CPayment%3E%20getPaymentById(%40PathVariable(%22id%22)%20Long%20id)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fconsumer%22)%0A%20%20%20public%20class%20OrderFeignController%20%7B%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20public%20PaymentFeignService%20paymentFeignService%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fpayment%2Fget%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20CommonResult%3CPayment%3E%20getPaymentById(%40PathVariable(%22id%22)%20Long%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20paymentFeignService.getPaymentById(id)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Fget%2F3%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%206.3.4%20%E8%B6%85%E6%97%B6%E6%8E%A7%E5%88%B6%0A%0A1.%20%E8%B6%85%E6%97%B6%E5%8E%9F%E5%9B%A0%0A%0A%20%20%20%E6%B6%88%E8%B4%B9%E7%AB%AF%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%E5%B0%8F%E4%BA%8E%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E5%A4%84%E7%90%86%E6%97%B6%E9%97%B4%0A%20%20%20openfeign-ribbon%E9%BB%98%E8%AE%A4%E6%B6%88%E8%B4%B9%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%E4%B8%BA1%E7%A7%92%0A%0A%20%20%20%E6%B6%88%E8%B4%B9%E7%AB%AF%EF%BC%9A%0A%0A%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Ffeign%2Ftimeout%0A%0A%20%20%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%EF%BC%9A%0A%0A%20%20%20http%3A%2F%2Flocalhost%3A8002%2Fapi%2Fpayment%2Ffeign%2Ftimeout%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Ffeign%2Ftimeout%0A%0A%20%20%20!%5B97a79fd127364347209578517ffc90ba.png%5D(en-resource%3A%2F%2Fdatabase%2F933%3A1)%0A%20%20%20%0A%0A%0A%0A%0A2.%20%E8%B6%85%E6%97%B6%E8%AE%BE%E7%BD%AE%0A%0A%20%20%20%3E%20%E9%85%8D%E7%BD%AEyml%0A%0A%20%20%20%60%60%60%0A%20%20%20%23%20%E6%B6%88%E8%B4%B9%E7%AB%AF%E8%B6%85%E6%97%B6%E6%8E%A7%E5%88%B6%0A%20%20%20ribbon%3A%0A%20%20%20%20%20ReadTimeout%3A%205000%20%23%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5%E6%89%80%E7%94%A8%E7%9A%84%E6%97%B6%E9%97%B4%0A%20%20%20%20%20ConnectTimeout%3A%205000%20%23%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5%E5%90%8E%E6%9C%8D%E5%8A%A1%E7%AB%AF%E8%AF%BB%E5%8F%96%E5%8F%AF%E7%94%A8%E8%B5%84%E6%BA%90%E6%89%80%E7%94%A8%E7%9A%84%E6%97%B6%E9%97%B4%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%206.3.5%20%E6%97%A5%E5%BF%97%E5%A2%9E%E5%BC%BA%0A%0A%3E%20Feign%E6%8F%90%E4%BE%9B%E4%BA%86%E6%97%A5%E5%BF%97%E6%89%93%E5%8D%B0%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E9%85%8D%E7%BD%AE%E6%9D%A5%E8%B0%83%E6%95%B4%E6%97%A5%E5%BF%97%E7%BA%A7%E5%88%AB%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%AF%B9%E8%AF%B7%E6%B1%82%E8%BF%9B%E8%A1%8C%E7%9B%91%E6%8E%A7%E6%9D%A5%E4%BA%86%E8%A7%A3HTTP%E8%AF%B7%E6%B1%82%E7%9A%84%E7%BB%86%E8%8A%82%EF%BC%8C%0A%3E%0A%3E%20%E4%BB%8E%E4%BD%8E%E5%88%B0%E9%AB%98%E5%88%86%E5%88%AB%E6%98%AF%EF%BC%9A%0A%0A%60%60%60%0ANone%3A%20%E9%BB%98%E8%AE%A4%EF%BC%8C%E4%B8%8D%E6%98%BE%E7%A4%BA%E4%BB%BB%E4%BD%95%E6%97%A5%E5%BF%97%0ABasic%3A%20%E4%BB%85%E8%AE%B0%E5%BD%95%E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95%EF%BC%8CURL%EF%BC%8C%E5%93%8D%E5%BA%94%E7%8A%B6%E6%80%81%E7%A0%81%E5%8F%8A%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%0AHeaders%3A%20%E9%99%A4%E4%BA%86Basic%E4%B8%AD%E7%9A%84%E4%BF%A1%E6%81%AF%E5%A4%96%EF%BC%8C%E8%BF%98%E6%9C%89%E8%AF%B7%E6%B1%82%E5%92%8C%E5%93%8D%E5%BA%94%E7%9A%84%E5%A4%B4%E4%BF%A1%E6%81%AF%0AFull%3A%20%20%E9%99%A4%E4%BA%86Headers%E4%B8%AD%E7%9A%84%E4%BF%A1%E6%81%AF%E5%A4%96%2C%E8%BF%98%E6%9C%89%E8%AF%B7%E6%B1%82%E5%92%8C%E5%93%8D%E5%BA%94%E7%9A%84%E6%AD%A3%E6%96%87%E5%8F%8A%E5%85%83%E6%95%B0%E6%8D%AE%0A%60%60%60%0A%0A1.%20%E9%85%8D%E7%BD%AELoggerBean%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.springcloud.config%3B%0A%20%20%20%0A%20%20%20import%20feign.Logger%3B%0A%20%20%20import%20org.springframework.context.annotation.Bean%3B%0A%20%20%20import%20org.springframework.context.annotation.Configuration%3B%0A%20%20%20%0A%20%20%20%40Configuration%0A%20%20%20public%20class%20FeignConfig%20%7B%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20Logger.Level%20feignLoggerLevel()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20Logger.Level.FULL%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A2.%20%E9%85%8D%E7%BD%AEyml%0A%0A%20%20%20%60%60%60%0A%20%20%20logging%3A%0A%20%20%20%20%20level%3A%0A%20%20%20%20%20%20%20%23%20feign%20%E4%BB%A5%E4%BB%80%E4%B9%88%E7%BA%A7%E5%88%AB%E7%9B%91%E6%8E%A7%E5%93%AA%E4%B8%AA%E6%8E%A5%E5%8F%A3%0A%20%20%20%20%20%20%20com.chris.springcloud.service.PaymentFeignService%3A%20debug%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Fget%2F4%0A%0A%20%20%20%60%60%60%0A%20%20%202020-08-27%2015%3A51%3A42.220%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20---%3E%20GET%20http%3A%2F%2FCLOUD-PAYMENT-SERVICE%2Fapi%2Fpayment%2Fget%2F4%20HTTP%2F1.1%0A%20%20%202020-08-27%2015%3A51%3A42.220%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20---%3E%20END%20HTTP%20(0-byte%20body)%0A%20%20%202020-08-27%2015%3A51%3A42.244%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20%3C---%20HTTP%2F1.1%20200%20(24ms)%0A%20%20%202020-08-27%2015%3A51%3A42.245%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20connection%3A%20keep-alive%0A%20%20%202020-08-27%2015%3A51%3A42.245%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20content-type%3A%20application%2Fjson%0A%20%20%202020-08-27%2015%3A51%3A42.245%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20date%3A%20Thu%2C%2027%20Aug%202020%2007%3A51%3A42%20GMT%0A%20%20%202020-08-27%2015%3A51%3A42.245%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20keep-alive%3A%20timeout%3D60%0A%20%20%202020-08-27%2015%3A51%3A42.245%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20transfer-encoding%3A%20chunked%0A%20%20%202020-08-27%2015%3A51%3A42.245%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20%0A%20%20%202020-08-27%2015%3A51%3A42.245%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20%7B%22code%22%3A200%2C%22message%22%3A%22query%20payment%20success.8001%22%2C%22data%22%3A%7B%22id%22%3A4%2C%22serial%22%3A%22ethan%22%7D%7D%0A%20%20%202020-08-27%2015%3A51%3A42.245%20DEBUG%20469768%20---%20%5Bp-nio-80-exec-2%5D%20c.c.s.service.PaymentFeignService%20%20%20%20%20%20%20%20%3A%20%5BPaymentFeignService%23getPaymentById%5D%20%3C---%20END%20HTTP%20(84-byte%20body)%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%207.%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E5%92%8C%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%0A%0A%3E%20%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E4%B8%AD%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E6%9C%89%E6%95%B0%E5%8D%81%E4%B8%AA%E4%BE%9D%E8%B5%96%EF%BC%8C%E6%AF%8F%E4%B8%AA%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E5%9C%A8%E6%9F%90%E4%B8%AA%E6%97%B6%E5%80%99%E4%B8%8D%E5%8F%AF%E9%81%BF%E5%85%8D%E5%9C%B0%E4%BC%9A%E5%87%BA%E7%8E%B0%E5%A4%B1%E8%B4%A5%0A%3E%0A%3E%20%E6%9C%8D%E5%8A%A1%E7%9B%B8%E4%BA%92%E8%B0%83%E7%94%A8%E9%93%BE%E8%B7%AF%E4%BC%9A%E5%BE%88%E9%95%BF%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%87%BA%E5%B7%AE%EF%BC%8C%E6%95%B4%E6%9D%A1%E9%93%BE%E8%B7%AF%E4%BC%9A%E5%81%9C%E7%94%A8%2C%20%E7%94%9A%E8%87%B3%E6%9C%8D%E5%8A%A1%E9%9B%AA%E5%B4%A9%E3%80%82%0A%0A%23%23%23%23%23%207.1%20%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%0Afallback%3A%20%E5%AF%B9%E6%96%B9%E7%B3%BB%E7%BB%9F%E4%B8%8D%E5%8F%AF%E7%94%A8%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E5%90%91%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E6%96%B9%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%60%E7%AC%A6%E5%90%88%E9%A2%84%E6%9C%9F%E7%9A%84%EF%BC%8C%E5%8F%AF%E5%A4%84%E7%90%86%E7%9A%84%E5%A4%87%E9%80%89%E5%93%8D%E5%BA%94(FallBack)%60%0A%0A%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%E4%B8%8B%E4%BC%9A%E5%87%BA%E7%8E%B0%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%EF%BC%9A%0A%0A%3E1.%20%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E5%BC%82%E5%B8%B8%0A%3E2.%20%E8%B6%85%E6%97%B6%0A%3E3.%20%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%E8%A7%A6%E5%8F%91%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%3E4.%20%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BF%A1%E6%81%AF%E9%87%8F%E6%89%93%E6%BB%A1%0A%0A%23%23%23%23%23%207.2%20%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%0A%0A%3E%20**%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%20%3E%20%E8%BF%9B%E8%80%8C%E7%86%94%E6%96%AD%20%3E%20%E6%81%A2%E5%A4%8D%E8%B0%83%E7%94%A8%E9%93%BE%E8%B7%AF**%0A%3E%0A%3E%20%E5%BD%93%E6%9C%8D%E5%8A%A1%E8%BE%BE%E5%88%B0%E6%9C%80%E5%A4%A7%E8%AE%BF%E9%97%AE%E8%B4%9F%E8%BD%BD%E5%90%8E%E7%9B%B4%E6%8E%A5%E6%8B%92%E7%BB%9D%E8%AE%BF%E9%97%AE%EF%BC%8C%E7%84%B6%E5%90%8E%E8%B0%83%E7%94%A8%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E7%9A%84%E6%96%B9%E6%B3%95%E5%B9%B6%E8%BF%94%E5%9B%9E%E5%8F%8B%E5%A5%BD%E6%8F%90%E7%A4%BA%0A%3E%0A%3E%20%E7%86%94%E6%96%AD%E6%9C%BA%E5%88%B6%E6%98%AF%E4%B8%80%E7%A7%8D%E5%BA%94%E5%AF%B9%E9%9B%AA%E5%B4%A9%E6%95%88%E5%BA%94%E7%9A%84%E4%B8%80%E7%A7%8D%E6%9C%8D%E5%8A%A1%E9%93%BE%E8%B7%AF%E4%BF%9D%E6%8A%A4%E6%9C%BA%E5%88%B6%0A%3E%0A%3E%20%E5%BD%93%E6%A3%80%E6%B5%8B%E5%88%B0%E5%8A%A1%E8%B0%83%E7%94%A8%E5%93%8D%E5%BA%94%E6%AD%A3%E5%B8%B8%E5%90%8E%EF%BC%8C%E6%81%A2%E5%A4%8D%E8%B0%83%E7%94%A8%E9%93%BE%E8%B7%AF%0A%3E%0A%3E%20%E5%BD%93%E5%A4%B1%E8%B4%A5%E8%BE%BE%E5%88%B0%E9%98%80%E5%80%BC%E6%97%B6%EF%BC%8C%E9%BB%98%E8%AE%A45%E7%A7%92%E5%86%8520%E6%AC%A1%E8%B0%83%E7%94%A8%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%B0%B1%E4%BC%9A%E5%90%AF%E7%94%A8%E7%86%94%E6%96%AD%E6%9C%BA%E5%88%B6%0A%0A**%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%E6%9C%89%E4%B8%89%E7%A7%8D%E7%8A%B6%E6%80%81**%0A%0A1.%20%E6%89%93%E5%BC%80%0A%0A%20%20%20%3E%20%E8%AF%B7%E6%B1%82%E4%B8%8D%E5%86%8D%E8%B0%83%E7%94%A8%E5%BD%93%E5%89%8D%E6%9C%8D%E5%8A%A1%EF%BC%8C%E5%86%85%E9%83%A8%E8%AE%BE%E7%BD%AE%E4%BA%86%E6%97%B6%E9%92%9F%E4%B8%80%E8%88%AC%E4%B8%BAMTTR(%E5%B9%B3%E5%9D%87%E6%95%85%E9%9A%9C%E5%A4%84%E7%90%86%E6%97%B6%E9%97%B4)%EF%BC%8C%E5%BD%93%E6%89%93%E5%BC%80%E6%97%B6%E9%95%BF%E8%B6%85%E8%BF%87MTTR%E6%97%B6%E9%92%9F%E6%97%B6%E9%95%BF%E5%90%8E%E5%88%99%E8%BF%9B%E5%85%A5%E5%8D%8A%E5%BC%80%E7%8A%B6%E6%80%81%0A%0A2.%20%E5%8D%8A%E5%BC%80%0A%0A%20%20%20%3E%20%E9%83%A8%E5%88%86%E8%AF%B7%E6%B1%82%E6%A0%B9%E6%8D%AE%E8%A7%84%E5%88%99%E8%B0%83%E7%94%A8%E5%BD%93%E5%89%8D%E6%9C%8D%E5%8A%A1%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AF%B7%E6%B1%82%E6%88%90%E5%8A%9F%E4%B8%94%E7%AC%A6%E5%90%88%E8%A7%84%E5%88%99%E5%88%99%E8%AE%A4%E4%B8%BA%E5%BD%93%E5%89%8D%E6%9C%8D%E5%8A%A1%E6%81%A2%E5%A4%8D%E6%AD%A3%E5%B8%B8%EF%BC%8C%E5%85%B3%E9%97%AD%E7%86%94%E6%96%AD%E3%80%82%0A%0A3.%20%E5%85%B3%E9%97%AD%0A%0A%20%20%20%3E%20circuit%20breaker%E4%B8%8D%E4%BC%9A%E5%AF%B9%E6%9C%8D%E5%8A%A1%E8%BF%9B%E8%A1%8C%E7%86%94%E6%96%AD%0A%0A%0A%0A%23%23%23%23%23%207.3%20%E6%9C%8D%E5%8A%A1%E9%99%90%E6%B5%81%0A%0A%3E%20%E7%A7%92%E6%9D%80%EF%BC%8C%E9%AB%98%E5%B9%B6%E5%8F%91%E7%AD%89%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%B8%A5%E7%A6%81%E4%B8%80%E7%AA%9D%E8%9C%82%E7%9A%84%E8%BF%87%E6%9D%A5%E6%8B%A5%E6%8C%A4%EF%BC%8C%E5%A4%A7%E5%AE%B6%E6%8E%92%E9%98%9F%EF%BC%8C%E4%B8%80%E7%A7%92%E9%92%9FN%E4%B8%AA%2C%E6%9C%89%E5%BA%8F%E8%BF%9B%E8%A1%8CQPS%0A%3E%0A%3E%20https%3A%2F%2Fwww.cnblogs.com%2Flongxiaojiangi%2Fp%2F9259745.html%0A%0A%23%23%23%23%23%207.4%20Hystrix%0A%0A%23%23%23%23%23%23%207.4.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E4%B8%80%E4%B8%AA%E5%A4%84%E7%90%86%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E5%BB%B6%E8%BF%9F%E5%92%8C%E5%AE%B9%E9%94%99%E7%9A%84%E5%BC%80%E6%BA%90%E5%BA%93%EF%BC%8C%E5%9C%A8%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E4%B8%AD%E8%AE%B8%E5%A4%9A%E6%9C%8D%E5%8A%A1%E4%B8%8D%E5%8F%AF%E9%81%BF%E5%85%8D%E7%9A%84%E4%BC%9A%E5%87%BA%E7%8E%B0%E8%B0%83%E7%94%A8%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%A6%82%E7%BD%91%E7%BB%9C%E5%BB%B6%E6%97%B6%EF%BC%8C%E5%8D%A1%E9%A1%BF%EF%BC%8C%E7%A8%8B%E5%BA%8F%E5%87%BA%E9%94%99%E7%AD%89%E3%80%82%0A%3E%0A%3E%20Hystrix%E8%83%BD%E5%A4%9F%E4%BF%9D%E8%AF%81%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%87%BA%E7%8E%B0%E9%94%99%E8%AF%AF%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E4%B8%8D%E5%85%A8%E5%AF%BC%E8%87%B4%E6%95%B4%E4%BD%93%E6%9C%8D%E5%8A%A1%E5%A4%B1%E8%B4%A5%EF%BC%8C%E9%81%BF%E5%85%8D%E7%BA%A7%E8%81%94%E6%95%85%E9%9A%9C%EF%BC%8C%E4%BB%8E%E8%80%8C%E6%8F%90%E5%8D%87%E7%B3%BB%E7%BB%9F%E7%9A%84%E9%AB%98%E5%8F%AF%E7%94%A8%E6%80%A7%E3%80%82%0A%3E%0A%3E%20**%E6%96%AD%E8%B7%AF%E5%99%A8**%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BC%80%E5%85%B3%E8%A3%85%E7%BD%AE%EF%BC%8C%E5%9C%A8%E6%9F%90%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%8D%95%E5%85%83%E6%95%85%E9%9A%9C%E4%B9%8B%E5%90%8E%EF%BC%8C%E9%80%9A%E8%BF%87%E6%96%AD%E8%B7%AF%E5%99%A8%E7%9A%84%E6%95%85%E9%9A%9C%E7%9B%91%E6%8E%A7%EF%BC%8C%E5%90%91%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E6%96%B9%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E7%AC%A6%E5%90%88%E9%A2%84%E6%9C%9F%E7%9A%84%EF%BC%8C%E5%8F%AF%E5%A4%84%E7%90%86%E7%9A%84%E5%A4%87%E9%80%89%E5%93%8D%E5%BA%94(FallBack)%0A%3E%0A%3E%20%E8%80%8C%E4%B8%8D%E6%98%AF%E9%95%BF%E6%97%B6%E9%97%B4%E7%AD%89%E5%BE%85%E6%88%96%E8%80%85%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%E8%B0%83%E7%94%A8%E6%96%B9%E6%97%A0%E6%B3%95%E5%A4%84%E7%90%86%E7%9A%84%E5%BC%82%E5%B8%B8%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BF%9D%E8%AF%81%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E6%96%B9%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%B8%8D%E4%BC%9A%E9%95%BF%E6%97%B6%E9%97%B4%E8%A2%AB%E5%8D%A0%E7%94%A8%EF%BC%8C%E4%BB%8E%E8%80%8C%E9%81%BF%E5%85%8D%E6%95%85%E9%9A%9C%E5%9C%A8%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E4%B8%AD%E8%94%93%E5%BB%B6%EF%BC%8C%E5%8F%8A%E8%87%B3%E9%9B%AA%E5%B4%A9%E3%80%82%0A%0A%23%23%23%23%23%23%207.4.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A1.%20%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%0A2.%20%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%0A%0A3.%20%E6%9C%8D%E5%8A%A1%E9%99%90%E6%B5%81%0A%0A4.%20%E6%8E%A5%E8%BF%91%E5%AE%9E%E6%97%B6%E7%9B%91%E6%8E%A7%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%207.4.3%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0Ahttp%3A%2F%2Fgithub.com%2FNetflix%2FHystrix%2Fwiki%2FHow-To-Use%0A%0A%23%23%23%23%23%23%207.4.4%20%E5%81%9C%E6%AD%A2%E6%9B%B4%E6%96%B0%EF%BC%8C%E8%BF%9B%E5%85%A5%E7%BB%B4%E6%8A%A4%0A%0Ahttp%3A%2F%2Fgithub.com%2FNetflix%2FHystrix%2F%0A!%5Bf395355f8982899ebba7badbfefba0db.png%5D(en-resource%3A%2F%2Fdatabase%2F936%3A1)%0A%0A%0A%0A%0A%0A%0A%23%23%23%23%23%23%207.4.5%20%E6%94%AF%E4%BB%98%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%84%E5%BB%BA%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloud-provider-hystrix-payment8001%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--Eureka%20client--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%09%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%09%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%3C!--hystrix--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-hystrix%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BAyml%0A%0A%20%20%20%60%60%60%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%208001%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20%20%20servlet%3A%0A%20%20%20%20%20%20%20context-path%3A%20%2Fapi%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-provider-hystrix-payment%0A%20%20%20%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20%23defaultZone%3A%20http%3A%2F%2Flocalhost%3A7001%2Feureka%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20instance-id%3A%20hystrix-payment8001%0A%20%20%20%20%20%20%20prefer-ip-address%3A%20true%0A%20%20%20%20%20%20%20%23%20Eureka%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA30%E7%A7%92%0A%20%20%20%20%20%20%20lease-renewal-interval-in-seconds%3A%201%0A%20%20%20%20%20%20%20%23%20Eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%94%B6%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%BF%83%E8%B7%B3%E5%90%8E%E7%AD%89%E5%BE%85%E7%9A%84%E6%97%B6%E9%97%B4%E4%B8%8A%E9%99%90%EF%BC%8C%E8%B6%85%E6%97%B6%E5%B0%86%E6%B3%A8%E9%94%80%E6%9C%8D%E5%8A%A1%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92%0A%20%20%20%20%20%20%20lease-expiration-duration-in-seconds%3A%202%0A%20%20%20%60%60%60%0A%0A%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableEurekaClient%0A%20%20%20public%20class%20PaymentHystrixMain8001%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(PaymentHystrixMain8001.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fpayment%2Fhystrix%22)%0A%20%20%20public%20class%20PaymentController%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20PaymentService%20paymentService%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Value(%22%24%7Bserver.port%7D%22)%0A%20%20%20%20%20%20%20private%20String%20serverPort%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Ftimeout%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_Ok(%40PathVariable(%22id%22)%20int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20String%20result%20%3D%20paymentService.paymentInfo_OK(id)%3B%0A%20%20%20%20%20%20%20%20%20%20%20log.info(%22result%3A%22%20%2B%20result)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20result%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Service%0A%20%20%20%40Slf4j%0A%20%20%20public%20class%20PaymentService%20%7B%0A%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20*%20%40param%20id%0A%20%20%20%20%20%20%20%20*%20%40return%20%E6%AD%A3%E5%B8%B8%E8%AE%BF%E9%97%AE%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_OK(int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20%22thread%20pool%20%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%20paymentInfo_OK%2C%20id%3A%22%20%2B%20id%20%2B%20%22.%22%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20*%20%40param%20id%0A%20%20%20%20%20%20%20%20*%20%40return%20%E8%AE%BF%E9%97%AE%E8%B6%85%E6%97%B6%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_TimeOut(int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(3)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.error(%22error%20happened%20paymentInfo_TimeOut%20%22%2C%20e)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20return%20%22thread%20pool%20%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%20paymentInfo_TimeOut%2C%20id%3A%22%20%2B%20id%20%2B%20%22.%20waste%20time%22%20%2B%20%22seconds%3A%22%20%2B%203%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A6.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20request%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Fok%2F4%0A%20%20%20response%0A%20%20%20thread%20pool%20http-nio-8001-exec-3%20paymentInfo_OK%2C%20id%3A4.%0A%20%20%20%0A%20%20%20request%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Ftimeout%2F4%0A%20%20%20response%0A%20%20%20thread%20pool%20http-nio-8001-exec-2%20paymentInfo_TimeOut%2C%20id%3A4.%20waste%20timeseconds%3A3%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A7.%20Jmeter%E9%AB%98%E5%B9%B6%E5%8F%91%E6%B5%8B%E8%AF%95%0A%09%0A%20%20%20%20!%5Bb0030e1e7e50272c86d55e3d7df269eb.png%5D(en-resource%3A%2F%2Fdatabase%2F935%3A1)%0A%20%20%20%20%0A%20%20%20%20!%5B110ce360ea53f3d169b17158ed32c27e.png%5D(en-resource%3A%2F%2Fdatabase%2F930%3A1)%0A%20%20%20%20%0A%0A%0A%23%23%23%23%23%23%207.4.6%20%E8%AE%A2%E5%8D%95%E5%BE%AE%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E6%94%AF%E4%BB%98%E5%BE%AE%E6%9C%8D%E5%8A%A1%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloud-consumer-feign-hystrix-order80%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--eureka%20client--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%3C!--open%20feign--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-openfeign%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%3C!--hystrix--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-hystrix%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BAyml%0A%0A%20%20%20%60%60%60%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%2080%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20utf-8%0A%20%20%20%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-order-feign-hystrix-service%0A%20%20%20%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20instance-id%3A%20feign-hystrix-order80%0A%20%20%20%20%20%20%20prefer-ip-address%3A%20true%0A%20%20%20%20%20%20%20%23%20Eureka%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA30%E7%A7%92%0A%20%20%20%20%20%20%20lease-renewal-interval-in-seconds%3A%201%0A%20%20%20%20%20%20%20%23%20Eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%94%B6%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%BF%83%E8%B7%B3%E5%90%8E%E7%AD%89%E5%BE%85%E7%9A%84%E6%97%B6%E9%97%B4%E4%B8%8A%E9%99%90%EF%BC%8C%E8%B6%85%E6%97%B6%E5%B0%86%E6%B3%A8%E9%94%80%E6%9C%8D%E5%8A%A1%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92%0A%20%20%20%20%20%20%20lease-expiration-duration-in-seconds%3A%202%0A%20%20%20%0A%20%20%20%23%20%E6%B6%88%E8%B4%B9%E7%AB%AF%E8%B6%85%E6%97%B6%E6%8E%A7%E5%88%B6%0A%20%20%20ribbon%3A%0A%20%20%20%20%20ReadTimeout%3A%205000%20%23%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5%E6%89%80%E7%94%A8%E7%9A%84%E6%97%B6%E9%97%B4%0A%20%20%20%20%20ConnectTimeout%3A%205000%20%23%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5%E5%90%8E%E6%9C%8D%E5%8A%A1%E7%AB%AF%E8%AF%BB%E5%8F%96%E5%8F%AF%E7%94%A8%E8%B5%84%E6%BA%90%E6%89%80%E7%94%A8%E7%9A%84%E6%97%B6%E9%97%B4%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableFeignClients%0A%20%20%20public%20class%20OrderHystrixMain80%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(OrderHystrixMain80.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20PaymentFeignService%20%E5%AE%9A%E4%B9%89%E4%BA%86%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3%5BPaymentController%5D%E5%8E%9F%E6%A0%B7%E6%8B%B7%E8%B4%9D%EF%BC%8CURL%2C%E6%96%B9%E6%B3%95%E9%83%BD%E9%9C%80%E8%A6%81%E4%B8%80%E6%A0%B7%0A%20%20%20%20*%2F%0A%20%20%20%0A%20%20%20%40Component%0A%20%20%20%40FeignClient(value%20%3D%20%22CLOUD-PROVIDER-HYSTRIX-PAYMENT%22)%0A%20%20%20%40RequestMapping(%22%2Fapi%2Fpayment%2Fhystrix%22)%0A%20%20%20public%20interface%20PaymentHystrixService%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fok%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_Ok(%40PathVariable(%22id%22)%20int%20id)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Ftimeout%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_TimeOut(%40PathVariable(%22id%22)%20int%20id)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fconsumer%2Fpayment%22)%0A%20%20%20public%20class%20OrderHystrixController%20%7B%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20PaymentHystrixService%20paymentHystrixService%3B%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fok%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_Ok(%40PathVariable(%22id%22)%20int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20paymentHystrixService.paymentInfo_Ok(id)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Ftimeout%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_TimeOut(%40PathVariable(%22id%22)%20int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20paymentHystrixService.paymentInfo_TimeOut(id)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A6.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Fok%2F4%0A%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Ftimeout%2F4%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A7.%20Jmeter%E9%AB%98%E5%B9%B6%E5%8F%91%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%3E%20%E5%AF%B9hystrix-payment8001%E5%BC%80%E5%90%AF%E9%AB%98%E5%B9%B6%E5%8F%91%E8%AF%B7%E6%B1%82%0A%20%20%20%3E%0A%20%20%20%3E%208001%E5%90%8C%E4%B8%80%E5%B1%82%E7%BA%A7%E7%9A%84%E5%85%B6%E5%AE%83%E6%8E%A5%E5%8F%A3%E6%9C%8D%E5%8A%A1%E8%A2%AB%E5%9B%B0%E6%AD%BB%EF%BC%8C%E5%9B%A0%E4%B8%BATomcat%E7%BA%BF%E7%A8%8B%E6%B1%A0%E9%87%8C%E9%9D%A2%E7%9A%84%E5%B7%A5%E4%BD%9C%E7%BA%BF%E7%A8%8B%E5%B7%B2%E7%BB%8F%E8%A2%AB%E5%8D%A0%E7%94%A8%E5%AE%8C%0A%20%20%20%3E%0A%20%20%20%3E%2080%E6%AD%A4%E6%97%B6%E8%B0%83%E7%94%A88001%EF%BC%8C%E4%BC%9A%E5%87%BA%E7%8E%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AF%B7%E6%B1%82%E7%BC%93%E6%85%A2%0A%0A%23%23%23%23%23%207.5%20%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%60%60%60%0A%E5%AF%B9%E6%96%B9%E6%9C%8D%E5%8A%A18001%E8%B6%85%E6%97%B6%E4%BA%86%EF%BC%8C%E8%B0%83%E7%94%A8%E8%80%8580%E4%B8%8D%E8%83%BD%E4%B8%80%E7%9B%B4%E5%8D%A1%E6%AD%BB%E7%AD%89%E5%BE%85%EF%BC%8C%E5%BF%85%E9%A1%BB%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%E5%AF%B9%E6%96%B9%E6%9C%8D%E5%8A%A18001%20down%E6%9C%BA%E4%BA%86%EF%BC%8C%E8%B0%83%E7%94%A8%E8%80%8580%E4%B8%8D%E8%83%BD%E4%B8%80%E7%9B%B4%E5%8D%A1%E6%AD%BB%E7%AD%89%E5%BE%85%EF%BC%8C%E5%BF%85%E9%A1%BB%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%E5%AF%B9%E6%96%B9%E6%9C%8D%E5%8A%A18001%20ok%EF%BC%8C%E4%BD%86%E8%B0%83%E7%94%A8%E8%80%8580%E8%87%AA%E5%B7%B1%E5%87%BA%E6%95%85%E9%9A%9C%E6%88%96%E8%87%AA%E5%B7%B1%E5%AF%B9%E6%9C%8D%E5%8A%A1%E5%93%8D%E5%BA%94%E6%9C%89%E6%97%B6%E9%97%B4%E8%A6%81%E6%B1%82%EF%BC%8C%E5%BF%85%E9%A1%BB%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%60%60%60%0A%0A%23%23%23%23%23%23%207.5.1%20%E4%BB%8E%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E4%BE%A7%E8%A7%A3%E5%86%B3%0A%0A%60%60%60%0A%E8%AE%BE%E7%BD%AE%E6%9C%8D%E5%8A%A1%E8%87%AA%E8%BA%AB%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E5%B3%B0%E5%80%BC%EF%BC%8C%E5%B3%B0%E5%80%BC%E4%BB%A5%E5%86%85%E5%8F%AF%E4%BB%A5%E6%AD%A3%E5%B8%B8%E8%BF%90%E8%A1%8C%0A%E8%B6%85%E8%BF%87%E5%B3%B0%E5%80%BC%E8%A6%81%E6%9C%89%E5%85%9C%E5%BA%95%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BD%9C%E4%B8%BA%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E7%9A%84fallback%0A%60%60%60%0A%0A1.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%E5%90%AF%E5%8A%A8%E5%8A%A0%20**%40HystrixCommand**%0A%0A%20%20%20com.chris.springcloud.service.PaymentService%0A%0A%20%20%20%60%60%60java%0A%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20*%20%40param%20id%0A%20%20%20%20%20%20%20%20*%20%40return%20%E8%AE%BF%E9%97%AE%E8%B6%85%E6%97%B6%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%40HystrixCommand(fallbackMethod%20%3D%20%22timeOutHandler%22%2C%20commandProperties%20%3D%20%7B%40HystrixProperty(name%20%3D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22execution.isolation.thread.timeoutInMilliseconds%22%2C%20value%20%3D%20%223000%22)%7D)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_TimeOut(int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20int%20sleepTime%20%3D%205%3B%0A%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(sleepTime)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.error(%22error%20happened%20paymentInfo_TimeOut%20%22%2C%20e)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20return%20%22thread%20pool%20%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%20paymentInfo_TimeOut%2C%20id%3A%22%20%2B%20id%20%2B%20%22.%20waste%20time%22%20%2B%20%22seconds%3A%22%20%2B%20sleepTime%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20private%20String%20timeOutHandler(int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20%22thread%20pool%20%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%20paymentInfo_TimeOutHandler%2C%20id%3A%22%20%2B%20id%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%3E%20%E6%B7%BB%E5%8A%A0%40EnableCircuitBreaker%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableEurekaClient%0A%20%20%20%40EnableCircuitBreaker%0A%20%20%20public%20class%20PaymentHystrixMain8001%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(PaymentHystrixMain8001.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20request%3A%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Ftimeout%2F4%0A%20%20%20%0A%20%20%20response%3A%0A%20%20%20thread%20pool%20hystrix-PaymentService-1%20paymentInfo_TimeOutHandler%2C%20system%20busy%20or%20server%20callapse%2C%20id%3A4%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20hystrix%20%E4%BD%BF%E7%94%A8%E8%87%AA%E5%B7%B1%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%AF%B9%E6%9C%8D%E5%8A%A1%E8%BF%9B%E8%A1%8C%E9%99%8D%E7%BA%A7%20HystrixTimer-1%0A%0A4.%20%E6%9B%B4%E6%94%B9%E4%B8%9A%E5%8A%A1%E7%B1%BB%E5%BC%82%E5%B8%B8%E7%B1%BB%E5%9E%8B%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%40param%20id%0A%20%20%20%20*%20%40return%20%E8%AE%BF%E9%97%AE%E8%B6%85%E6%97%B6%0A%20%20%20%20*%2F%0A%20%20%20%40HystrixCommand(fallbackMethod%20%3D%20%22timeOutHandler%22%2C%20commandProperties%20%3D%20%7B%40HystrixProperty(name%20%3D%0A%20%20%20%20%20%20%20%20%20%20%20%22execution.isolation.thread.timeoutInMilliseconds%22%2C%20value%20%3D%20%223000%22)%7D)%0A%20%20%20public%20String%20paymentInfo_TimeOut(int%20id)%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20int%20i%20%3D%2010%20%2F%200%3B%0A%20%20%20%20%20%20%20%2F*int%20sleepTime%20%3D%205%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(sleepTime)%3B%0A%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20log.error(%22error%20happened%20paymentInfo_TimeOut%20%22%2C%20e)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20return%20%22thread%20pool%20%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%20paymentInfo_TimeOut%2C%20id%3A%22%20%2B%20id%20%2B%20%22.%20waste%20%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22time%22%20%2B%20%22seconds%3A%22%20%2B%20sleepTime%3B%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20return%20%22thread%20pool%20%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%20paymentInfo_TimeOut%2C%20id%3A%22%20%2B%20id%3B%0A%20%20%20%7D%0A%20%20%20%0A%20%20%20private%20String%20timeOutHandler(int%20id)%20%7B%0A%20%20%20%20%20%20%20return%20%22thread%20pool%20%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%20paymentInfo_TimeOutHandler%2C%20system%20busy%20or%20%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22server%20callapse%2C%20id%3A%22%20%2B%20id%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20request%3A%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Ftimeout%2F4%0A%20%20%20%0A%20%20%20response%3A%0A%20%20%20thread%20pool%20hystrix-PaymentService-1%20paymentInfo_TimeOutHandler%2C%20system%20busy%20or%20server%20callapse%2C%20id%3A4%0A%20%20%20%60%60%60%0A%0A6.%20%E6%80%BB%E7%BB%93%0A%0A%20%20%20%3E%20%E6%97%A0%E8%AE%BA%E6%98%AF%E8%B6%85%E6%97%B6%E5%BC%82%E5%B8%B8%E6%88%96%E8%BF%90%E8%A1%8C%E5%BC%82%E5%B8%B8%EF%BC%8C%E5%8F%AA%E8%A6%81%E5%BD%93%E5%89%8D%E6%9C%8D%E5%8A%A1%E4%B8%8D%E5%8F%AF%E7%94%A8%EF%BC%8C%E5%B0%B1%E4%BC%9A%E4%BD%9C%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%0A%0A%0A%23%23%23%23%23%23%207.2.2%20%E4%BB%8E%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E4%BE%A7%E8%A7%A3%E5%86%B3%0A%0A%60%60%60%0A%E4%B8%80%E8%88%AC%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E9%83%BD%E6%98%AF%E6%94%BE%E5%9C%A8%E6%B6%88%E8%B4%B9%E7%AB%AF%0A%E7%83%AD%E9%83%A8%E7%BD%B2%E5%AF%B9Java%E4%BB%A3%E7%A0%81%E7%9A%84%E6%94%B9%E5%8A%A8%E6%98%AF%E9%9D%9E%E5%B8%B8%E6%95%8F%E6%84%9F%E7%9A%84%EF%BC%8C%E4%BD%86%E6%98%AF%E5%AF%B9%E4%BA%8E%40HystrixCommand%20%E5%86%85%E5%B1%9E%E6%80%A7%E7%9A%84%E4%BF%AE%E6%94%B9%E5%BB%BA%E8%AE%AE%E9%87%8D%E5%90%AF%E5%BE%AE%E6%9C%8D%E5%8A%A1%0A%60%60%60%0A%0A1.%20%E4%BF%AEyml%EF%BC%8C%E5%85%81%E8%AE%B8feign%E4%BD%BF%E7%94%A8hystrix%E8%BF%9B%E8%A1%8C%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%0A%20%20%20%60%60%60%0A%20%20%20feign%3A%0A%20%20%20%20%20hystrix%3A%0A%20%20%20%20%20%20%20enabled%3A%20true%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%3E%20%E9%85%8D%E7%BD%AE%40EnableHystrix%20%E6%BF%80%E6%B4%BBHystrix%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableFeignClients%0A%20%20%20%40EnableHystrix%0A%20%20%20public%20class%20OrderHystrixMain80%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(OrderHystrixMain80.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A3.%20%E4%BF%AE%E6%94%B9%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%3E%20%E6%B7%BB%E5%8A%A0%40HystrixCommand%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40GetMapping(%22%2Ftimeout%2F%7Bid%7D%22)%0A%20%20%20%40HystrixCommand(fallbackMethod%20%3D%20%22timeOutHandler%22%2C%20commandProperties%20%3D%20%7B%40HystrixProperty(name%20%3D%0A%20%20%20%20%20%20%20%20%20%20%20%22execution.isolation.thread.timeoutInMilliseconds%22%2C%20value%20%3D%20%221000%22)%7D)%0A%20%20%20public%20String%20paymentInfo_TimeOut(%40PathVariable(%22id%22)%20int%20id)%20%7B%0A%20%20%20%20%20%20%20return%20paymentHystrixService.paymentInfo_TimeOut(id)%3B%0A%20%20%20%7D%0A%20%20%20%0A%20%20%20%40SuppressWarnings(%22unused%22)%0A%20%20%20private%20String%20timeOutHandler(int%20id)%20%7B%0A%20%20%20%20%20%20%20return%20%22I'm%20order80%2C%20the%20service%20provider%20system%20busy%20or%20server%20callapse%2C%20id%3A%22%20%2B%20id%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A4.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20request%3A%0A%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Ftimeout%2F4%0A%20%20%20%0A%20%20%20response%0A%20%20%20I'm%20order80%2C%20the%20service%20provider%20system%20busy%20or%20server%20callapse%2C%20id%3A4%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%207.2.3%20%E5%85%A8%E5%B1%80%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%0A%0A%60%60%60%0A%E6%AF%8F%E4%B8%AA%E4%B8%9A%E5%8A%A1%E6%96%B9%E6%B3%95%E9%83%BD%E5%AF%B9%E5%BA%94%E4%B8%80%E4%B8%AAfallback%E6%96%B9%E6%B3%95%EF%BC%8C%E5%AF%BC%E8%87%B4%E4%BB%A3%E7%A0%81%E8%86%A8%E8%83%80%0A%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E6%96%B9%E6%B3%95%E5%92%8C%E4%B8%9A%E5%8A%A1%E4%BB%A3%E7%A0%81%E6%B7%B7%E5%90%88%E5%9C%A8%E4%B8%80%E8%B5%B7%EF%BC%8C%E5%AF%BC%E8%87%B4%E4%BB%A3%E7%A0%81%E6%B7%B7%E4%B9%B1%0A%60%60%60%0A%0A%20%60%60%60%0A%E5%85%A8%E5%B1%80%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E8%A7%A3%E5%86%B3%E4%B8%A4%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%9A%09%0A1.%20%E4%BB%A3%E7%A0%81%E8%86%A8%E8%83%80%0A2.%20%E4%BB%A3%E7%A0%81%E6%B7%B7%E4%B9%B1%0A%20%60%60%60%0A%0A**%E8%A7%A3%E5%86%B3%E8%87%B4%E4%BB%A3%E7%A0%81%E8%86%A8%E8%83%80**%0A%0A1.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%3E%20com.chris.springcloud.controller.OrderHystrixController%0A%20%20%20%E5%9C%A8%E7%B1%BB%E4%B8%8A%E9%85%8D%E7%BD%AE%E9%BB%98%E8%AE%A4%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E7%9A%84fallback%E6%96%B9%E6%B3%95%0A%20%20%20%E9%9C%80%E8%A6%81%E6%94%AF%E6%8C%81%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E7%9A%84%E6%96%B9%E6%B3%95%E4%B8%8A%E4%BB%8D%E9%9C%80%E8%A6%81%E9%85%8D%E7%BD%AE%40HystrixCommand()%0A%0A%20%20%20%60%60%60java%0A%20%20%20%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fconsumer%2Fpayment%22)%0A%20%20%20%40DefaultProperties(defaultFallback%20%3D%20%22paymentGlobalFallBack%22)%0A%20%20%20public%20class%20OrderHystrixController%20%7B%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20PaymentHystrixService%20paymentHystrixService%3B%0A%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fok%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_Ok(%40PathVariable(%22id%22)%20int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20paymentHystrixService.paymentInfo_Ok(id)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Ftimeout2%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20%40HystrixCommand()%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_TimeOut2(%40PathVariable(%22id%22)%20int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20paymentHystrixService.paymentInfo_TimeOut(id)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%40SuppressWarnings(%22unused%22)%0A%20%20%20%20%20%20%20public%20String%20paymentGlobalFallBack()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20%22system%20is%20busy%20%2C%20pls%20try%20later!%22%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A2.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20request%3A%0A%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Ftimeout2%2F4%0A%20%20%20%0A%20%20%20response%3A%0A%20%20%20system%20is%20busy%20%2C%20pls%20try%20later!%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A**%E8%A7%A3%E5%86%B3%E4%BB%A3%E7%A0%81%E6%B7%B7%E4%B9%B1**%0A%0A3.%20%E5%AE%9E%E7%8E%B0PaymentHystrixService%E6%8E%A5%E5%8F%A3%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Component%0A%20%20%20public%20class%20PaymentFallBackService%20implements%20PaymentHystrixService%20%7B%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_Ok(int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20%22PaymentFallBackService%20fallback-paymentInfo_Ok%2C%20the%20provider%20collapsed%2C%20try%20it%20later.%22%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_TimeOut(int%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20%22PaymentFallBackService%20fallback-paymentInfo_TimeOut%2C%20the%20provider%20collLapsed%2C%20try%20it%20later.%22%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A4.%20%E9%85%8D%E7%BD%AEFeignClient%2C%E4%BD%BF%E7%94%A8%E6%94%AF%E6%8C%81%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E7%9A%84fallback%E5%AE%9E%E7%8E%B0%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Component%0A%20%20%20%2F%2F%E9%85%8D%E7%BD%AEFeignClient%2C%E4%BD%BF%E7%94%A8%E6%94%AF%E6%8C%81%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E7%9A%84fallback%E5%AE%9E%E7%8E%B0%E7%B1%BB%0A%20%20%20%40FeignClient(value%20%3D%20%22CLOUD-PROVIDER-HYSTRIX-PAYMENT%22%2C%20fallback%20%3D%20PaymentFallBackService.class%2C%20path%20%3D%20%22%2Fapi%2Fpayment%2Fhystrix%22)%0A%20%20%20public%20interface%20PaymentHystrixService%20%7B%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fok%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_Ok(%40PathVariable(%22id%22)%20int%20id)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Ftimeout%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20paymentInfo_TimeOut(%40PathVariable(%22id%22)%20int%20id)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%0A%0A%20%20%20%3E%20org.springframework.beans.factory.BeanCreationException%3A%20Error%20creating%20bean%20with%20name%20'requestMappingHandlerMapping'%20defined%20in%20class%20path%20resource%20%5Borg%2Fspringframework%2Fboot%2Fautoconfigure%2Fweb%2Fservlet%2FWebMvcAutoConfiguration%24EnableWebMvcConfiguration.class%5D%3A%20Invocation%20of%20init%20method%20failed%3B%20nested%20exception%20is%20java.lang.IllegalStateException%3A%20**Ambiguous%20mapping.%20Cannot%20map%20'com.chris.springcloud.service.PaymentHystrixService'%20method**%20%0A%20%20%20%3E%20com.chris.springcloud.service.PaymentHystrixService%23paymentInfo_TimeOut(int)%0A%20%20%20%3E%20to%20%7BGET%20%2Fapi%2Fpayment%2Fhystrix%2Ftimeout%2F%7Bid%7D%7D%3A%20There%20is%20already%20'paymentFallBackService'%20bean%20method%0A%0A%20%20%20%E5%8E%9F%E5%9B%A0%EF%BC%9APaymentFallBackService%E5%AE%9E%E7%8E%B0%E4%BA%86%E6%8E%A5%E5%8F%A3PaymentHystrixService%EF%BC%8C%E4%B8%94%E5%9B%A0%E4%B8%BA%E6%8E%A5%E5%8F%A3%E6%9C%89%E5%85%B1%E7%94%A8map%E8%B7%AF%E5%BE%84**%40RequestMapping(%22%2Fapi%2Fpayment%2Fhystrix%22)**%EF%BC%8C%E6%89%80%E4%BB%A5spring%E5%9C%A8%E5%AE%9E%E4%BE%8B%E5%8C%96Bean%E6%97%B6%E5%8F%91%E7%8E%B0%E4%B8%80%E5%90%8C%E4%B8%80URL%E4%B8%8B%E6%9C%89%E4%B8%A4%E4%B8%AA%E7%9B%B8%E5%90%8C%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E4%B8%8D%E7%9F%A5%E9%81%93%E8%B0%83%E7%94%A8%E5%93%AA%E4%B8%AA%0A%0A%20%20%20%60%60%60%0A%20%20%20%40Component%0A%20%20%20public%20class%20PaymentFallBackService%20implements%20PaymentHystrixService%0A%20%20%20%60%60%60%0A%0A%20%20%20%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%0A%0A%20%20%201.%20%E5%B0%86%2Fapi%2Fpayment%2Fhystrix%E5%86%85%E5%B5%8C%E5%88%B0%E6%AF%8F%E4%B8%AA%E6%96%B9%E6%B3%95%E7%9A%84URL%E4%B8%AD%0A%0A%20%20%202.%20%E4%BD%BF%E7%94%A8%40FeignClient%E7%9A%84path%E5%8F%82%E6%95%B0%0A%0A%20%20%20%20%20%20%60%60%60java%0A%20%20%20%20%20%20%40FeignClient(value%20%3D%20%22CLOUD-PROVIDER-HYSTRIX-PAYMENT%22%2C%20fallback%20%3D%20PaymentFallBackService.class%2C%20path%20%3D%20%22%2Fapi%2Fpayment%2Fhystrix%22)%0A%20%20%20%20%20%20%60%60%60%0A%0A6.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%E5%81%9C%E7%94%A8PaymentHystrixMain8001%E6%9C%8D%E5%8A%A1%0A%0A%20%20%20%60%60%60%0A%20%20%20request%3A%0A%20%20%20http%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Fok%2F4%0A%20%20%20response%3A%0A%20%20%20PaymentFallBackService%20fallback-paymentInfo_Ok%2C%20the%20provider%20collapsed%2C%20try%20it%20later.%0A%20%20%20%60%60%60%0A%0A%0A%0A%0A%23%23%23%23%23%207.6%20%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%0A%0A%23%23%23%23%23%23%207.6.1%20Hystrix%E5%AE%9E%E7%8E%B0%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%0A%0A%3E%20SpringCloud%E6%A1%86%E6%9E%B6%E9%80%9A%E8%BF%87%E9%9B%86%E6%88%90%E7%9A%84Hystrix%E5%AE%9E%E7%8E%B0%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%0A%3E%0A%3E%20Hystrix%E4%BC%9A%E7%9B%91%E6%8E%A7%E6%9C%8D%E5%8A%A1%E9%97%B4%E7%9A%84%E8%B0%83%E7%94%A8%E7%8A%B6%E5%86%B5%EF%BC%8C%E5%BD%93%E5%A4%B1%E8%B4%A5%E8%B6%85%E8%BF%87%E8%AE%BE%E5%AE%9A%E7%9A%84%E9%98%88%E5%80%BC%E6%97%B6%E9%BB%98%E8%AE%A4%E4%B8%BA5%E7%A7%92%E5%86%8520%E6%AC%A1%E8%B0%83%E7%94%A8%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%B0%B1%E4%BC%9A%E5%90%AF%E5%8A%A8%E7%86%94%E6%96%AD%E6%9C%BA%E5%88%B6%0A%3E%0A%3E%20%E7%86%94%E6%96%AD%E6%9C%BA%E5%88%B6%E6%B3%A8%E8%A7%A3%E4%B8%BA%40HystrixCommand%0A%0A%23%23%23%23%23%23%207.6.2%20Hystrix%E7%86%94%E6%96%AD%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%0A%0AHow%20it%20Works%0A%0Ahttps%3A%2F%2Fgithub.com%2FNetflix%2FHystrix%2Fwiki%2FHow-it-Works%0A%0Amartinfowler%0A%0Ahttps%3A%2F%2Fmartinfowler.com%2Fbliki%2FCircuitBreaker.html%0A!%5B01006178d15515156067e120e1815cb3.png%5D(en-resource%3A%2F%2Fdatabase%2F929%3A1)%0A%0A%0A%23%23%23%23%23%23%207.6.3%20%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%E5%AE%9E%E7%8E%B0%0A%0A1.%20%E4%BF%AE%E6%94%B9%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%3E%20com%2Fchris%2Fspringcloud%2Fservice%2FPaymentService.java%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%A8%A1%E6%8B%9F%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%0A%20%20%20%20*%20%E9%85%8D%E7%BD%AE%E4%B8%AD%E7%9A%84%E5%B1%9E%E6%80%A7%E5%9C%A8%E6%8A%BD%E8%B1%A1%E7%B1%BBHystrixCommandProperties%E4%B8%AD%E5%AE%9A%E4%B9%89%0A%20%20%20%20*%2F%0A%20%20%20%40HystrixCommand(fallbackMethod%20%3D%20%22paymentCircuitBreakerFallBack%22%2C%20commandProperties%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%40HystrixProperty(name%20%3D%20%22circuitBreaker.enabled%22%2C%20value%20%3D%20%22true%22)%2C%20%2F%2F%E6%98%AF%E5%90%A6%E5%BC%80%E5%90%AF%E6%96%AD%E8%B7%AF%E5%99%A8%0A%20%20%20%20%20%20%20%20%20%20%20%40HystrixProperty(name%20%3D%20%22circuitBreaker.requestVolumeThreshold%22%2C%20value%20%3D%20%225%22)%2C%20%2F%2F%E8%AF%B7%E6%B1%82%E6%AC%A1%E6%95%B0%0A%20%20%20%20%20%20%20%20%20%20%20%40HystrixProperty(name%20%3D%20%22circuitBreaker.sleepWindowInMilliseconds%22%2C%20value%20%3D%20%2220000%22)%2C%20%2F%2Ftrip%20circut%20before%20retry%20%E7%9A%84%E6%97%B6%E9%97%B4%E7%AA%97%E5%8F%A3%E6%9C%9F%0A%20%20%20%20%20%20%20%20%20%20%20%40HystrixProperty(name%20%3D%20%22circuitBreaker.errorThresholdPercentage%22%2C%20value%20%3D%20%2260%22)%7D)%20%2F%2F%E5%A4%B1%E8%B4%A5%E7%8E%87%E8%BE%BE%E5%88%B0%E5%A4%9A%E5%B0%91%E5%90%8E%E5%90%AF%E5%8A%A8%E7%86%94%E6%96%AD%0A%20%20%20public%20String%20paymentCircuitBreaker(int%20id)%20%7B%0A%20%20%20%20%20%20%20if%20(id%20%3C%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20throw%20new%20RuntimeException(%22id%20%E4%B8%8D%E8%83%BD%E4%B8%BA%E8%B4%9F%E6%95%B0%22)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20String%20serialNumber%20%3D%20IdUtil.simpleUUID()%3B%0A%20%20%20%20%20%20%20return%20Thread.currentThread().getName()%20%2B%20%22%5Ct%20%E8%B0%83%E7%94%A8%E6%88%90%E5%8A%9F%EF%BC%8C%E6%B5%81%E6%B0%B4%E5%8F%B7%3A%20%22%20%2B%20serialNumber%3B%0A%20%20%20%7D%0A%20%20%20%0A%20%20%20%40SuppressWarnings(%22unused%22)%0A%20%20%20private%20String%20paymentCircuitBreakerFallBack(int%20id)%20%7B%0A%20%20%20%20%20%20%20return%20%22id%20%E4%B8%8D%E8%83%BD%E4%B8%BA%E8%B4%9F%E6%95%B0%2C%20id%3A%22%20%2B%20id%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20com%2Fchris%2Fspringcloud%2Fcontroller%2FPaymentController.java%3A39%0A%0A%20%20%20%60%60%60java%0A%20%20%20%2F**%0A%20%20%20%20*%20%E6%A8%A1%E6%8B%9F%E6%9C%8D%E5%8A%A1%E7%86%94%E6%96%AD%0A%20%20%20%20*%2F%0A%20%20%20%40GetMapping(%22%2Fcircuit%2F%7Bid%7D%22)%0A%20%20%20public%20String%20paymentCircuitBreaker(%40PathVariable(%22id%22)%20int%20id)%20%7B%0A%20%20%20%20%20%20%20String%20result%20%3D%20paymentService.paymentCircuitBreaker(id)%3B%0A%20%20%20%20%20%20%20log.info(%22paymentCircuitBreaker%2C%20result%3A%20%22%20%2B%20result)%3B%0A%20%20%20%20%20%20%20return%20result%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%E2%80%8B%09%09%0A%0A2.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%201.%20%E4%BD%BF%E7%94%A8Jmeter%E5%A4%9A%E6%AC%A1%E8%BF%9E%E7%BB%AD%E8%AE%BF%E9%97%AE%E6%AD%A4%E8%BF%9E%E6%8E%A5%E5%90%8E%0A%0A%20%20%20%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Fcircuit%2F-10%0A%0A%20%20%202.%20%E5%86%8D%E4%BD%BF%E7%94%A8postman%20%E8%B0%83%E7%94%A8%E6%AD%A4%E8%BF%9E%E6%8E%A5%0A%0A%20%20%20%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Fcircuit%2F10%0A%0A%20%20%20%20%20%20%E4%BC%9A%E5%8F%91%E7%8E%B0%E5%8D%B3%E4%BD%BF%E6%98%AF%E5%A4%A7%E4%BA%8E0%E7%9A%84%E6%AD%A3%E6%95%B0%EF%BC%8C%E4%BB%8D%E7%84%B6%E8%B5%B0%E7%9A%84%E6%98%AF%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7%E5%90%8E%E7%9A%84fallback%E6%96%B9%E6%B3%95%0A%0A%20%20%20%20%20%20%60%60%60%0A%20%20%20%20%20%20id%20%E4%B8%8D%E8%83%BD%E4%B8%BA%E8%B4%9F%E6%95%B0%2C%20id%3A10%0A%20%20%20%20%20%20%60%60%60%0A%0A%20%20%203.%20%E7%AD%89Jmeter%E8%AE%BF%E9%97%AE%E8%BF%87%E5%90%8E%EF%BC%8C%E5%86%8D%E4%BD%BF%E7%94%A8postman%20%E8%B0%83%E7%94%A8%E6%AD%A4%E8%BF%9E%E6%8E%A5%0A%0A%20%20%20%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Fcircuit%2F10%0A%0A%20%20%20%20%20%20%E6%B1%82%E5%BE%97%E5%87%BA%E6%AD%A3%E7%A1%AE%E5%93%8D%E5%BA%94%0A%0A%20%20%20%20%20%20%60%60%60%0A%20%20%20%20%20%20hystrix-PaymentService-10%09%20%E8%B0%83%E7%94%A8%E6%88%90%E5%8A%9F%EF%BC%8C%E6%B5%81%E6%B0%B4%E5%8F%B7%3A%20fdea7e0aead64adbb1fbb5bb046b2b3c%0A%20%20%20%20%20%20%60%60%60%0A%0A3.%20%E6%80%BB%E7%BB%93%0A%0A%20%20%20%60%60%60%0A%20%20%20%E5%85%88%E5%90%AF%E7%94%A8%09%09%20%20enabled%0A%20%20%20%E6%97%B6%E9%97%B4%E7%AA%97%E5%8F%A3%20%09%20%20sleepWindowInMilliseconds%0A%20%20%20%E8%BE%BE%E5%88%B0%E8%AF%B7%E6%B1%82%E6%95%B0%E9%98%88%E5%80%BC%20requestVolumeThreshold%0A%20%20%20%E9%94%99%E8%AF%AF%E7%99%BE%E5%88%86%E6%AF%94%E9%98%88%E5%80%BC%20errorThresholdPercentage%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%0A%23%23%23%23%23%207.7%20%E5%9B%BE%E5%BD%A2%E5%8C%96DashBoard%E6%90%AD%E5%BB%BA%0A%0A%23%23%23%23%23%23%207.7.1%20%E5%87%86%E5%AE%9E%E6%97%B6%E8%B0%83%E7%94%A8%E7%9B%91%E6%8E%A7%0A%0A%3E%20Hystrix%20%E4%BC%9A%E6%8C%81%E7%BB%AD%E8%AE%B0%E5%BD%95%E9%80%9A%E8%BF%87Hystrix%20%E5%8F%91%E8%B5%B7%E7%9A%84%E8%AF%B7%E6%B1%82%E4%BF%A1%E6%81%AF%E5%8C%85%E6%8B%AC%E8%AF%B7%E6%B1%82%E6%95%B0%EF%BC%8C%E6%88%90%E5%8A%9F%E5%92%8C%E5%A4%B1%E8%B4%A5%E6%95%B0%E7%AD%89%E5%B9%B6%E4%BB%A5Hystrix%20Dashboard%20%E5%9B%BE%E5%BD%A2%E5%8C%96%E7%9A%84%E7%BB%93%E6%9E%9C%E5%B1%95%E7%A4%BA%E7%BB%99%E7%94%A8%E6%88%B7%0A%0A%23%23%23%23%23%23%207.7.2%20%E6%90%AD%E5%BB%BA%E7%9B%91%E6%8E%A7%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20%60%60%60%0A%20%20%20%3E%20cloud-consumer-hystrix-dashboard9001%0A%20%20%20%3E%20%60%60%60%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-test%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Etest%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecom.chris.springcloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ecloud-api-commons%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cversion%3E%24%7Bcommon.api.version%7D%3C%2Fversion%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--hystrix-dashboard--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-hystrix-dashboard%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C%2Fdependencies%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BAyml%0A%0A%20%20%20%60%60%60%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%209001%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%3E%20com.chris.springcloud.HystirxDashboardMain9001%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableHystrixDashboard%0A%20%20%20public%20class%20HystirxDashboardMain9001%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(HystirxDashboardMain9001.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A5.%20%E6%B5%8B%E8%AF%95%0A%20%20%20http%3A%2F%2Flocalhost%3A9001%2Fhystrix%0A%20%20!%5B7e6bc9e06042c20673b53a16e94227b7.png%5D(en-resource%3A%2F%2Fdatabase%2F932%3A1)%0A%20%20%0A%0A%23%23%23%23%23%23%207.7.3%20%E7%9B%91%E6%8E%A7%E5%85%B7%E4%BD%93%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%0A%0A1.%20%E7%A1%AE%E4%BF%9Dpom%E4%B8%AD%E6%9C%89web%E5%92%8Cactuator%E4%B8%A4%E4%B8%AA%E4%BE%9D%E8%B5%96%E5%8C%85%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-actuator%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E5%9C%A8%E5%90%AF%E5%8A%A8%E7%B1%BB%E9%87%8C%E9%9D%A2%E6%B7%BB%E5%8A%A0%E5%A6%82%E4%B8%8B%E6%96%B9%E6%B3%95%0A%0A%20%20%20%3E%20com.chris.springcloud.PaymentHystrixMain8001%0A%0A%20%20%20%60%60%60java%0A%20%20%20%09%2F**%0A%20%20%20%20%20%20%20%20*%20%E4%B8%BA%E8%A7%A3%E5%86%B3hystrix%20dashboard%0A%20%20%20%20%20%20%20%20*%20Unable%20to%20connect%20to%20Command%20Metric%20Stream.%0A%20%20%20%20%20%20%20%20*%20%E6%AD%A4%E9%85%8D%E7%BD%AE%E6%98%AF%E4%B8%BA%E4%BA%86%E6%9C%8D%E5%8A%A1%E7%9B%91%E6%8E%A7%E8%80%8C%E9%85%8D%E7%BD%AE%EF%BC%8C%E4%B8%8E%E6%9C%8D%E5%8A%A1%E5%AE%B9%E9%94%99%E6%9C%AC%E8%BA%AB%E6%97%A0%E5%85%B3%2CSpringClou%E8%A6%81%C2%B7d%E5%8D%87%E7%BA%A7%E5%90%8E%E7%9A%84%E5%9D%91%0A%20%20%20%20%20%20%20%20*%20ServletRegistrationBean%E5%9B%A0%E4%B8%BAspringboot%E7%9A%84%E9%BB%98%E8%AE%A4%E8%B7%AF%E5%BE%84%E4%B8%8D%E6%98%AF%22%2Fhystrix.stream%22%EF%BC%8C%0A%20%20%20%20%20%20%20%20*%20%E5%8F%AA%E8%A6%81%E5%9C%A8%E8%87%AA%E5%B7%B1%E7%9A%84%E9%A1%B9%E7%9B%AE%E9%87%8C%E9%85%8D%E7%BD%AE%E4%B8%8A%E4%B8%8B%E9%9D%A2%E7%9A%84servlet%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BA%86%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20%40SuppressWarnings(%22unchecked%22)%0A%20%20%20%20%20%20%20public%20ServletRegistrationBean%20getServlet()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20HystrixMetricsStreamServlet%20streamServlet%20%3D%20new%20HystrixMetricsStreamServlet()%3B%0A%20%20%20%20%20%20%20%20%20%20%20ServletRegistrationBean%20registrationBean%20%3D%20new%20ServletRegistrationBean(streamServlet)%3B%0A%20%20%20%20%20%20%20%20%20%20%20registrationBean.setLoadOnStartup(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20registrationBean.addUrlMappings(%22%2Fhystrix.stream%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20registrationBean.setName(%22HystrixMetricsStreamServlet%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20registrationBean%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fhystrix.stream%0A%20%20%20%0A%20%20%20!%5B4864e3866e5b6399f6c47bb14becb839.png%5D(en-resource%3A%2F%2Fdatabase%2F931%3A1)%0A%20%20%20%0A%09%0A%20%20%20%0A%20%20%20%E4%BD%BF%E7%94%A8Jmeter%E5%88%86%E5%88%AB%E5%AF%B9%E4%B8%8B%E9%9D%A2%E8%BF%99%E4%B8%AA%E8%AF%B7%E6%B1%82%E8%BF%9B%E8%A1%8C%E5%B9%B6%E5%8F%91%E8%AE%BF%E9%97%AE%0A%20%20%20%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Fcircuit%2F-10%0A%20%20%20http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fpayment%2Fhystrix%2Fcircuit%2F10%0A%20%20%20%0A%20%20%20!%5Bf44c4edcb3b823f2061ed677b5b6ee9b.png%5D(en-resource%3A%2F%2Fdatabase%2F937%3A1)%0A%20%20%20%0A%0A%0A%0A%23%23%23%23%208%20%E6%9C%8D%E5%8A%A1%E7%BD%91%E5%85%B3%0A%0A%23%23%23%23%23%208.1%20SpringCloud%20GateWay%0A%0A%23%23%23%23%23%23%208.1.1%20%E5%AE%98%E7%BD%91%0A%0Ahttps%3A%2F%2Fcloud.spring.io%2Fspring-cloud-static%2Fspring-cloud-gateway%2F2.2.1.RELEASE%2Freference%2Fhtml%2F%0A%0A%23%23%23%23%23%23%208.1.2%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20SpringCloud%E5%85%A8%E5%AE%B6%E6%A1%B6%E9%87%8C%E9%9D%A2%E6%9C%80%E9%87%8D%E8%A6%81%E7%9A%84%E4%B8%9C%E8%A5%BF%E5%B0%B1%E6%98%AF%E7%BD%91%E5%85%B3%0A%3E%0A%3E%20SpringCloud%20Gateway%E6%98%AF%E5%8E%9Fzuul1.x%E7%9A%84%E6%9B%BF%E4%BB%A3%E4%BA%A7%E5%93%81%0A%3E%0A%3E%20%E6%8F%90%E4%BE%9B%E4%B8%80%E7%A7%8D%E7%AE%80%E5%8D%95%E6%9C%89%E6%95%88%E7%9A%84%E6%96%B9%E5%BC%8F%E5%AF%B9API%E8%BF%9B%E8%A1%8C%E8%B7%AF%E7%94%B1%E5%B9%B6%E6%8F%90%E4%BE%9B%E5%BC%BA%E5%A4%A7%E7%9A%84%E8%BF%87%E6%BB%A4%E9%93%BE%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%A6%82%E7%86%94%E6%96%AD%EF%BC%8C%E9%99%90%E6%B5%81%EF%BC%8C%E9%87%8D%E8%AF%95%E7%AD%89%0A%3E%0A%3E%20SpringCloud%20Gateway%E5%9F%BA%E4%BA%8ESpring%20WebFlux%E5%AE%9E%E7%8E%B0%EF%BC%8C%E8%80%8CSpring%20WebFlux%E5%9F%BA%E5%B1%82%E4%BD%BF%E7%94%A8**%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84Reactor%E6%A8%A1%E5%BC%8F%E7%9A%84%E9%80%9A%E4%BF%A1%E6%A1%86%E6%9E%B6Netty**%0A%3E%20%E9%80%9F%E5%BA%A6%E6%98%AFZuul%E7%9A%841.6%E5%80%8D%0A%0A%23%23%23%23%23%23%208.1.3%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A1.%20%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%0A2.%20%E9%89%B4%E6%9D%83%0A3.%20%E7%86%94%E6%96%AD%0A4.%20%E6%97%A5%E5%BF%97%E7%9B%91%E6%8E%A7%0A5.%20%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6%0A%0A!%5Bimage.png%5D(data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAA5sAAAJHCAYAAAAe4ELwAAAgAElEQVR4Aey9h5IkR5IkqkGSZ9EmIDO7s3tyJ%2FLu%2F3%2FmRPbdvJ3BAGhWLKuSBX2iam4RkVXVjUZ3YabR8AayIsKJubm6ubuZ06Rt2xbxX0QgIhARiAhEBCICEYGIQEQgIhARiAhEBJ4QgfQJaUVSEYGIQEQgIhARiAhEBCICEYGIQEQgIhAREALR2IyCEBGICEQEIgIRgYhARCAiEBGICEQEIgJPjkA0Np8c0kgwIhARiAhEBCICEYGIQEQgIhARiAhEBKKxGWUgIhARiAhEBCICEYGIQEQgIhARiAhEBJ4cgWhsPjmkkWBEICIQEYgIRAQiAhGBiEBEICIQEYgIRGMzykBEICIQEYgIRAQiAhGBiEBEICIQEYgIPDkC0dh8ckgjwYhARCAiEBGICEQEIgIRgYhARCAiEBGIxmaUgYhARCAiEBGICEQEIgIRgYhARCAiEBF4cgSisfnkkEaCEYGIQEQgIhARiAhEBCICEYGIQEQgIhCNzSgDEYGIQEQgIhARiAhEBCICEYGIQEQgIvDkCERj88khjQQjAhGBiEBEICIQEYgIRAQiAhGBiEBEIBqbUQYiAhGBiEBEICIQEYgIRAQiAhGBiEBE4MkRiMbmk0MaCUYEIgIRgYhARCAiEBGICEQEIgIRgYhANDajDEQEIgIRgYhARCAiEBGICEQEIgIRgYjAkyMQjc0nhzQSjAhEBCICEYGIQEQgIhARiAhEBCICEYFobEYZiAhEBCICEYGIQEQgIhARiAhEBCICEYEnRyB%2FcoqRYETgd4RA%2B1G8MlSLRGE%2FLoaRtRgIMT8qqV8M5DR%2FMaAC%2FBpu30fx16X4PiqH7k%2FB1yHFz%2F9K8H6u3u%2Fj6b4fpff7eNyv5%2FnLOD2W14exeszu%2B%2FU%2BRunw%2B35ohjkM8Vj6vze3x3J5mIeHIT4k3T1GXx9Wh7h8%2BKv9QAvQx%2Fw8jD4c%2B2G59enGt49H4MMofywdLw1%2FPkbV%2Ffh0fz7t3X09RQ%2Fh3%2FEZEfijIBCNzT9KScd8PkDAOwJ7%2BheDJV23QSPTfg2oilBla1v%2BgCT0HMPQg4ihw%2Bk7Hu%2BAHjAih2H6j4f4cPzDOE7Nn4e%2Bv%2F7rKTtJR%2FTXc%2FHEMR6Aw0Ll%2F4ccsqwbSsGD8MZPIkFIO4FgMMfr%2FvOJc%2FBFkXsMng%2B5mR%2F%2Feigb0ElaH9hx0N0IYMk4ooSb74eLc5zSFwXMEzJjuT%2FErCMfoJFvB4RhJrceui6Kv6Qm%2BpLhDwTz4F%2Fh02WsA%2B7RPHooeibDoMN3j%2FmgwUjQUma94%2FBw4fkYCXn9MQvkHjq%2F7pNYEraDMupIHAKqMg1Oh%2BFJpQXaJjToh21Npxt0kZRi1yYN2ypP2sv4kAP3jc%2BIwNeLQDQ2v96yjTn7AALqRmg0qjsxA7IPniDtFAKGYGfTIEWLpqlR17Vi0chMaWNYt2bdm%2Fc37pakwUjpPPpkDt7u83DgGT6cxsd1Vd6x%2BfMxir%2Fk5il9Do3H0iC9p6b5WDq%2F6DZUCJMWqWRiyJ0hIIOTeocGG4wqBx34L01TJEmGhGXt%2BUpoBiVmCgVZcix%2FkaffYYAu38z%2FAFO5D76ZNaF2AIZMeeVahiaVO7AsLLQGd7ohAFPW6UV0k07Rc3k6IByQDEZs%2BPrdPoQHuSc%2BtFk6B5M7ZZ0SqiExtK1GTtC0wcjh8yDzhhX%2FNq2Z7Wz3%2BDND%2FiDwV%2FzR9wPDTJqruxhylEXCblAb0gegBszpJrkNsi88E8poKAuj4MSNhPw7J70o3mGhHQaIX48iYJL92ACh%2B%2FTR2qRR40EfKy6WsffH1haxHBKG68qNhUIJacAit3%2Bsb26QWl9A9%2Ft1SekMKHns%2BIwIfM0IRGPzay7dmLePRkD9eeg0aDxqBJqqgWZZpDnI4GTn0jSVeiUZGd3MStAI2PPwlbSC8cGPrj96L0fWeVnkQOsgrAii79neT1GUBt6D1wOKH%2F0R2PlsOm5oMGHTgz%2BahacOqBJhhoaZkqbRBLPGUzTlXcoGlYum6QYPnAafrlCQREOZoYGZGvH7yTjlr%2BX5UFqHoPa5PAjHDxlLZgia3LM4WsHGejf0N%2FPJjCVT7qxOyeDqjPn3I%2B1m1uOc9Tx%2B9NtBZj461ucFJPOmDfd0Bt%2BEUwZSYvJHbNz2IVpcm2FWDaP3SKgE2lYGp6CkF3XmPkif3lf3Zial%2Ff2lzAXjUsGCAAj%2Fe7h6H8DiYnvRDUixnXDB4dMANhd7vw%2B5y%2B0vcRb9DxEQjhoUuI%2Bo42%2FhrXUPbmEQgYMEFQeU28YGk0P7YnWPYf1nhqjVOhsEs%2FrFUmO6Vg8HVVT9AmPf5%2BqQ%2B%2FgVEfj6EIjG5tdXpjFHn4LAoPUPXY91CNZn6D1pZVbYrCdnADIqcNIoZAQ6CfZN7GyCavyR3HAkldRE8T1xSLhL5T1hQk%2FmmQhd4%2FsDf5yPKbIfF%2FYXQwVMByz%2BYpSnDCAErZBElsqAKx1mTNpINz3NiEyRcPaSSmOSduXvKoOFSTSTRCMp1X%2BJzYD8i43qp8Tt02mZzNpfCiTRthki0qRNbqZjUNpbGvyhLgRNzdT8BE1iODOGKW33p4O6VA7YZXE%2FleJOZdSUyoMkfvMPR%2FEwH0NX8mUzMm1n1JAtxqDfEBu%2B%2B8%2BU4ixLkWng5DfPyheTgLVBH2iJOkuBYexnqBGzXpaFcsC3DwUgy60fSfs2xugw8uDfvc%2BBj8WXwwf4HEaI75Lt90Pa42g1Y1hiFkvdA2cp%2BamCdlCtjllpWjumusVwJMMBnq6s3s8Bgyi4k43PiMBXjkA0Nr%2FyAo7Z%2B3UIPN4BqMcRIS7d439UhetOf%2FOlM6Yys4eirmemqaVvk1zWDT3GkZZchW7qMX9z89me94cY%2Bnhq%2Fhz6%2Fer3D%2Febv5oceXoSvn51yiFdDhwoT33GxJMc%2B2kduqlUuZJafjZjySWzpolYCC9tDTIMDMye%2Bicw%2BhVEuZ9%2F%2F6YO7%2B98minvQkEV0FxdeeuMTRlO9LPyM6NqKElOtQdPxhnrqpz4dxi%2BD%2Fer3h4m86ui%2F5rAlpTlmbwbNuGbWXG5VM5ofGt6HcTGQvcxGNb%2F61EgljaIQqoi%2BWsY%2FMrDSn6EihsalmHhJ8BsJUzLPRUcJun2eFtMIiqf0C4wiomglYDZqG6k3AdToT3C4Hk%2FXPzuETAp5uokrZDoPR6%2BdYVhqwAYQH07a07LwS329gky1rGkUb%2FeG58sVQ46WGPmbZQSORjYeZhsdIkI%2FNEQiMbmH63EY35%2FAQG3FIIq1nUa7JU4q9Kibs3YNKUiKMaaceEsDcOwD%2BJ%2BzrD3c2gjqmNyBWLICgNZJzl0%2FZx3sfE5BEJcy%2FkTEAoknoqvz%2BFIUHfmzlD3S5CkpnyrPMIeLWmQnmCY4dan3iUZbh4dGk6PFbXT%2BUqfxLabEAp5NBiCxdd5Uj2z%2F0wmeqWt0cxcUMAT21PIvYdUBG0vIsvIFT3Gfv%2B%2Fh1Xu91UoQ257s9FWOfh3NxDCQRDZRGGlhPYOh1C%2BH7Mz7gNlh68xRVt1g3p0%2FMeKLVk2pLwkesOw5VaJhHJJP86EWd9QaVkyl92bzNteWJotLAsrD4fXjU3%2FPnySrhfQoU%2F8%2BjACakLUaw%2FCabBl8O2v7Lf1nqDmMtrQVLHcOOPPFRXcQ56yzdF%2FLgPWBnkJ2S59lxM%2B%2Fd0Tis%2BIwB8TgWhs%2FjHLPeaa3YBZHOrLZSR%2BoGswFYE2ZI42NaWsShLUsJ8t%2BjMFUMoeV1BxDjT0QtbluLJ9H%2F6DQPc9P%2FlbVMnSJ1MIXaXZAJ9B5TDqU%2FB1SPEzvqgUNlTMTak0OyjVoT8cLGC5ZVQjqUeKcQvIdx4BISXS1ExkGuUO2ilZ6vSM7uUzGP19Re2q1nAMpTt0w%2FJCOO0XFs2G6lETWSnwYVE5jUwO8jT8mRtxT1JT9GwfnArnUZBYimH77Gcr7iYf70%2FrUQY%2Bw%2FF%2BSr2ZQpniwJi3OTS%2B7b2TNh5axX1nMjh5wBnARZ1cKmsqsxeAlQJLgzS6dvEz%2BP56ohJjGhY%2BS2bo2qAHZISoDwiHMBFJfleElgZK3jfAqhN%2BBkBXSETqfikP0bO2qW9MPhR2GO%2BP%2FG7gDv86GtoKE7A%2FQDJ8WD%2Ffos00F62BR8blwXHsB1h%2FOGTAGsT2X%2FVF0sFQXqj%2B9FT7JwerY%2F3q8YhvfxwEorH5xynrmNOuW7ee5aCzuYeOuoswOq33MPJZtw3KNtHIZ5FkKGlsJimqpkVRt6hrHrRhCkKSmqLH%2BB9Ky5L%2B5RB9Z3aP2Uc%2BnZo%2FHwny0U7edfrzoyM%2BEtD58ecjQf4lTm5sciKibmq0UhmBLAHyJMUkTzDKUoyyBDlHu6l4pObPAQV%2BcxYj47uPnqvgQ06fArx%2FCTK%2FnKiy%2BUiw%2B2XMGRy66QRHGZa2%2FJCKe9k2NpuQJCjbFEXZomw4w8C6ZHWKhqaMzaCwZdlgwKhT9B4yQv7892vq0ENK5J05%2BOcU5gP8yFAwyMWJWb7WtoQBIRo0mo0JzzxNMEoT5GkKdvb8jflNozMMBEhhDhXgfpqPYfCHcXMwzErsTAo6azAkDDZWLfsA9gmcFQP2oS9QP0CZp%2FzWlJyOYA9ht3LmPWIV%2BhJFkNj9c2SvZ%2FB3%2BtYNkDrmng87gIx1%2BL6P6lRY2KQip0GZJaDdyTGDcdJirPdUfQKNzUx79Pv2xeK9v4yioenlEJ9%2FNASisflHK%2FE%2FcH6Hncvw3SGhUsAOR%2FNZ1mvIi4qEzVxyJDtDmWXY1y22dYJN3WLfNNgUFW43O9xt99gVFaqKp9YaZVENiqGn9fBpaT90dxd2YMNObPg9dLfwj%2BXPKX3q82Eqv47Sb8HTr%2BPgYWjlKUBJZbBpG3BAgf8oAjQw56MRFtMpFtMx5pMRpnmCaZZgNuIvxYhGZzA42aCOkmCEisbnovaQ5y%2FRxXP5mBRbudPElK2kJYfUsTUjlABFy7rUoKgrKezbGrjd1VhtdtjsChRVjapuUOlpxif3GCYpTXz%2BrABDMYZUepR6tZKcOKe9v3E1%2FP5y3u%2FXGeFLA0Qs6qtjlvnMOSCSJxjnmX7TUYblbIyj%2BQSzcYZxlmIGYELZFnq2n9Bnfvkk1cdQ6hL66l6YW0PUsxZs7zBzHFzVJ1CObdksBxkpwyVoYAL7ssGubHBbVFjtSmyLEkVZY19UKMpKM%2FNcAs4ehgjr6cbm%2BwAPgy1hWYWz95s%2F77PTo3Pf5zFWPhy692Xcj6H3WBq%2F4NYZm7Y6xUMrtTAYeMgHWaELT6BtMRlnyPNEz%2Fl0hOV0jKNJhnme2cBjkmAE%2FmiIhjrERLp0%2BfEb5c0zE58Rgd8RAtHY%2FB0V1u%2BN1QeN%2BZNl4JDyYZN%2B%2BDUMOXy%2Fr1wcfpsy13CvmM9cavYFKBtgVzVY7Wpc3u1xvamwKWtsigKrzRa3my02ezM2aXB6mlJeniT%2Fnj8%2BqRkOvy0BpRmMZU%2BfPsN3j3XIkoV43M9C%2Bj6Yw3jhKyiqQz8PTzZJ%2FT4PIRddlGEYD%2Bv8%2BLML3L14SDrw3UO6YucBh%2BEYyr41s2OrpmRsNlQhU45o22zmbDTCfEJlncbmGItxiuUkx%2BlijLMFjdAMkzTBGPzZwVFjGpy%2BBFfJH6bdfzmvPdfO7cNnH%2BuhX0%2Fnod8vuXws3feFc%2BPHeLClaH1%2BZMRTjQuDNjIypaQnKFpgXTW42Va4uVtjvS9wu%2Bd3iZv1Hmsam0Wlu21lcHJqUzNyXNeco225eHlgcIpF58CfVtb2RR6HWNHV%2FEn4fTn8JQTpb3GHtIexHncfuro8eizSM%2B4CbQUOPIZ3hrWqzhmbVgoyZ9%2FHOWfj7becjXAyn2E5H%2BN4NsUZ38cZZmHQhLM2RFAHoXjiA5SMR3LTc3uI0%2FDLlhgOyNx77Wnc8%2FiEz8PyMsofR7%2FnmKh73nzJamCla7P8Kqx%2B0JEDkKVmMYF10eJuX%2BPmboub7Q7XG%2FYLO6x3pQYeaWzuq0az8i33YIRFmMJTjHyYZw3T%2FOJg5SfA954oD7kxF8PMfcPTPztaDGU%2Fl2d%2FMkhf2zwin%2F7eEfnFF4fNeLLgTsX6HK85A%2Brac8mwHtKT4bfzXSPNWkwmKfIMmI5TLGZjHM8nOF9OcTKb4Hg%2Bx3w8wjxPMUuhtl91KNQjUuOyW5a0%2FXvIJV08VQ%2FF533Ohn79%2B5Be7%2FqxsYcx4ntE4J%2BFQDQ2%2F1lI%2F4HSeV9T%2BLQQ9Kl4w90339Zk9yGCstYx0DfznbpCBVYdOhULGpl2SECFVMv79i1wV7SacbnZFHi32uD15R3erbbYlFQm%2BKv1K2toVtPOhrCu1nSF0O0%2B1qMMmT3ocg48uhxYjkjIfwOvYEYNY7Lr5dIvR2KoAHhMsXVPqZHbR3SCh2lZBHb6Hp%2F%2BNN759LA6cEEdcx%2BuCzMISxoMy%2BeQntMhRebnME%2F8sou1Le%2BeS4tlvNGHyjr30dBupzQ0Mjh5zgr3bGZpgxF%2FWYVRutXMEGc2Ocp9fjTFy9MjPD9e4GiSYzlOMeeMZzjRkAan8dwi4TQ3E%2BX5LXZYqKwEXqXCb6bseHkenWM9ySADaH7QfYy6pSIK7tHh1Dn84kuPZh%2BU9OnuT%2Fp4uP5pKwKsFLiMkAf5cJMrjXjVJZ3OyYO1bMm5K%2BmbssGqaHC1LfHudoM3Vze4ur1VHduUnCni0nSuEOC%2BWntKPCULrKH9bKlLgHFBjln6dX8apZbB24xUrwZa%2BbuUMC7%2F%2B9R%2FRu1h7MfcveQ8tGRX%2BerTV54YMKAuH9VhEyyTd0Yy2WDuKK%2BcmcnT1mbYwWejGfjj%2BRTPTpZ4cXKE8%2FkUx7MJThcjLMaJwmpWnsvIOUMqE972p5mANpaMroOwlI0vQyyw2dXBjrcDPMOIjmXpM%2F96SfV4mZwOqojaEPMfLl8cxhi%2Bu5xLChg31EvuIZZch5NmuR%2BzaIBN2eJm1%2BDyrsC72zXeXa1wvd5gtStwR0OzYh%2FCpbUJqoYHx5mksVL0823k4JCL%2B8Aopx8Ocj%2FKZ3%2Ffl0%2FKoq1McJ%2BQhzBLeFjetfLkbr20eO0kDnSlPLhMmAQNw74vE%2BIj9A%2B2BsVCOmdm6FkKnqKeAcOHafRmISmlaYNsWyFJamSsR3miVQEnc9aXGZ6dHuN8ucTpbIKTSap2f5ZxebotU7fVLaw7rYxOL19yZG24ceBF6u2nEFD97iRZMkjx8GrvtPqno8TYpGg4umt8RgS%2BFASS1iX9S%2BEo8vG7RqBrQH%2BzXNgyOjWs3q5KSfNm1h2tczQ2%2Bu7FfMll%2BNGBSoV%2BpsA0aYoKCXZNg13DZ4LbssG7VYGfL1Z4t1rj6m6Hi7s9VttSezW1PyfN0PLHeQKdKGMdqWHSp3wITe8uRfrRzsL5tbB9fH7f%2F9GX%2BfWw9i4KoYPuQhhjAQvHr4%2FZp%2BN%2BQ5fDdyc1fLoawZB0p2IgYzKwxqWnOe2v8GMYGidUVTSrHPglHTdMZW%2B5SSB%2F41e5DIdvGA92bH2jY3ssfYPECttQY1z7uTzQfDEpGObEBiKMjxZ5UmOWA0sanIsJnh%2FP8YK%2FoxnOl2McTzMsaHQmwJTLFXlIS1sjSRpdKqnZ8oYGLg8iyoL8hfMsgywfoktlIygqpCE8%2FSCXvvzvl5xLwH1aD7%2BFfCcHTl8I6I9TCngRdy01NiwNLzsxtqRxyIOxspHuJmW94L5LGZppigLAprJlsu9ud3h1s8ab1RYX6x0u7zZaHbCrWP4jtAnrEo1WzrmRPT%2BQwwSFJlGdjNHINAqKvKTfFjpmqAx35SxDnWQ0x0ST2TLkyC2vNKilCBoSyvRDmD7oYtQspuPFCJQwFnHvZiE9fctXH5JvjNHTY51wV5dWOcjdeeXT54ztyZwmdYWm3CNHg8U01wzNCWc3ZxM8O5rj2%2BfHeHY8xXzEWZoE0xQgovxpryeNiaZB21B%2BebdwpvIgH6b0W%2B48h3YXsfkO65aVo82fWt4sT5%2F6l2oLJc1xMLRSMH2dAEsPbx%2BEk4Ho3L4vXafbtwLsC9Junz4HSnZc5r2v8e5uj1fXa7y5XuPtDfuEtVa5MExBI5OGVDrSj31CQ2OzpSz7j5X9oEQfZYs8Wd%2FwqPeTORpCfemYZBmydGWtMm7dWA6nrQcpN0nnoBpbcLXinfQbkywQ0pMZFuo32z%2B2rF2IEMddDp%2FkSX2D9yUHtcVM10ztreM6fIa6dtDGsl31norU2Q6w9%2BeQQo22LdE2pdqIcQZtpThdLHB2tMTLozmeH83wfDHB6SzHcpJoefoYrc14sqVpOEjDBJmOpcVBXxvIYJPG1tOk0gZEwgFEhCnoJR6dSHBAVDirsKyE%2BhLzsjrELH5FBL4EBKKx%2BSWUwlfEgzWbv2WGfsnYtLTVJLOx7rq7MJbM9n7g6p24%2BNYMTAKeMlskiZb3XW8rXKwLvL7Z4R8XK%2Fz0bqVlUvs2RYkRCo1WkyhPK7Ej0r1TpqLddwTWz3r3YFyqxwhakV2rMgx%2FiKLH9Cd9vXN5%2FMmQln9lOnRph1Q7LA464Pth3s8VQ1o6fRxXjsVVoMswVBJqKYBGj8bmiHsdB8amG5mVZpfNQKUqoDDMsRuUQZHsczgcRXZDk2aElQlxcE49z0ZLKnOQCc%2BDYax8dekYz2b0VsjbCiNUGKPGImtxvhjj%2B2dL%2FOnZMb47W%2BLZYoLjUYY5D5VoK2SokVFRCCcZczUoVSMam%2BSM2odOth2UA5UMx9IUFVdcLO5h%2BRsSngM%2BRXfo8N53L8E%2B3wzqdcgpdbhxBrht9HPe67pGRaNEs5k8sTnXHXWsAzxEq%2BKhP0i0OuByXeDNzQY%2FXd7gp6s13nLQpjQFnffa1QlNIy6RNaWMOpqpoy7N5JPK70i%2FmqYUZ4hDGdOHs5p5WyKjEamwGZokZynI1%2FJEE8jC8kmlj38%2F6Z%2FkhGgYSkbfKBlffWlYqF6W%2B5K7n7bTCpIb0rBQPT1PxZR8tj40NjnAwXrTIGkq7SsbccYzaTBqa0ySBkfTHN89O8E3z46lND9bTnAyzbDk8kEhS3OeS2y5dJk48QRgx9lWSmi1hEaA%2BlzazJIZ%2FD4Tb4Mltkt0iM0nYa3qYsYmlXXDj4MvZmyakh6w1KoFtn%2BGl4U%2BTNVnGU3t58CI7dvmbKZmJZMMBVLt0%2BeSWfYHr64pvyu8vl5rO8VqX%2BlgIIzGSLKRDE3Fp2HF5d5EkY1by%2FpuA0VWupTPwGv3HPLHUGoeho5P%2Fi50Bm0PE3CuXKatjrlhRlf7r3ehocmGzYxNyqGXf88wQwdjMwwSWe32u6k95T71Pq61h0zBDU62jwypOmULR3RoDw%2FuYdoBvb7PZx690xfh0HerhbE4NDaZB85s6m7NxAZbmrrUcnMuU5%2BPMpzPxhpg%2FOZkjm9Pl%2FjmZIbTaYZZ0mLaNphzVlT1pkWS2aAZOwC1kSpTyjDLNgxtcDCHeQl3e4o98duJr0pFBqfq3BAZIRCQGLrH94jAl4FAXEb7ZZTDV8HF493DPyNr91M2xaJP2b5dcWfow7a67%2FapXOw5%2B9K0uNpW%2BPnyFv%2F9%2Bgr%2F%2Ffoab2732MnAHKGi4sqfZjJJ35Qw9mPWmdgSQnaFHXehYzzkyzuJYefehzh8I6WOmnexIYjT6Z%2BmmtPbeHksNukxRv8M5AYP8zeH4fuQEw%2BuNEIgPth5%2Bj8amkNjk1npFRXLWa%2Bq9GHVIZMWwwfaPhpsfFtOG166HVQPmRC6845GBsvG%2F1lYjdMrPAvF3MSLFK6gorjBOyg3pp%2B2nDPLUPHZVij2e2z3a9xtNrhe3eJ2fYZ%2Ff3mO%2BmgOTDIkPDZVjNea8Jauw2%2BNXDMnNpotDoNSzPdOcoKbst7%2FeaT8PY%2Bf83SkAtADUuSTruI%2F4ESkNBvU1PLIshF4uT1P5CzrSrOJNDZ3DZehN3jLQZt31%2FpxRvNm32DTjrBLxqgSmuSkaLtdZchwdiAsa1eZEa2gLLKMeWAXZ5A4Y8k9oSYPNLJs5tiHK2hWajmkZMKlzrBnjiljjGvPQaY%2F%2BtVkJqi9oWx8gOkelsKOCqTLompNF%2BcwScYN8igOrX2xdA5Dmhtp8axZo80lsWlSaxawaogAB0lSFG2F9WqPq7uf8eb6Bn96eYp%2Fe3GK%2BnSJdJZLOaaB6TKYaVk0bU7uPeSgCWc4WU7853l3rhhrmDcLI4G3CE%2FzV6KqP0ZPMPqg3WNJDMJ23iYzPefGpUx27smsWxRoJM9cMsuZzL%2B%2FvsKPl7e43JS4LeyguH07Vl%2BgmUzOoMtQtRl93sWpUSbhJZNdMt2j5i3cPTkRjyE%2Fg3ahY%2F0pXwiNjUl2VN2QowPrj5coAzqnzA25t2%2Fm00IzhskgHRx3vrPdC8am2mWjq6XF99Lv4xlLonKvTfY%2Bnf15qP7GnfjQn47X0HqJB%2FMhXSZq7QE5pmJg%2B2rtjtT%2BzmVbtcRTs3lmA%2BViV%2Bxwx%2F25t3f67YpnaJ4f4Xyaqy3koAsLmiea810DQF059hx0DLLWcCUBZzvD8mTLubW5XVQiqvbNfQe03Ck%2BIwJfGALR2PzCCiSy86kIWIfWd4P3uyqj68pT38CbCqtlftyLo2V%2BLS62Bf7x7gZ%2Fe32Bv7%2B5xs%2BrHdZNjjrPUWcTGRtUdHlIiXe11r32%2FFtn7R1t7374xo7CDVP6fKjjIK3H6N2LE4LYHsQ%2BNY9NvhjDgtlf46IPe%2F%2FN%2Fdl%2FdnEHRtj98IGFThHht6tU7idFQbPPrpQbT8NwHMGmKsA4%2BoXIrmQwXTqRpzQ4Wrduqo6bn4obZmAYQ8qJIW%2BThqQg3YBPjxtmY5kGE2AeFCZFxrJvMh1QowmLBqi2BXblbTgUpEEp5X2BZjHCPEltD52UDipGlFSmFTIkgC0Rd%2FLZGKYrRWOobSjHxtOHZcbDfN5TilgoQ5YHS4V3OPo%2Fr1dUzjifwRNkOZPZZCm2dYrrXY031zv8480Vfnh7hberrRT1fTpGmU1RJhNdIcSBgS4%2FoWBp8lgtpU%2BY3e3MqSAXzkh4qrwHsjH8ZhCWJ2UgoK9YVKjlp7%2Bf8icISVc2%2Fn1IS0UdnIbpH3JzGMfxF0UNaB3621fPP2oy8i4AACAASURBVOmauPDNZiartrRlphq1yTQJtdneYlfegIYo98VyCWp6tkQ6t2XQVmvDcsmUhg9ne6yElI%2Bg%2FHuZMTWl3bHHUHT5Df6JdKAvJZ0zhpaO2qnwHlzEhzsZRyGuysskmBLNeS3doZylaNMEZQXc7Ar8dHGLv%2F58qYFHGprbJgMXKFfJCE02RpPnoGHpGHibwZkqLz%2FHwtL3kL3IP4ZS1x485vlUbo7bgJ64C2080TGe2aKamcz60%2BgkVkd1EFmvzDdz7vlkOBqkffvqVH3018IzsscxmpZ2308MUyLVgx8%2FZLBZLP7t6nrIz0F8eoZ%2FatEUhkLO%2BhT6CrHO1RbksEbNgTSenl1V2BUFNtudThxmHUpeHCOb5%2BBKAg6UcZ2GhsNYkJzpFF1jusfGGPBv6x1sZYfzdmhgmsFJP5N5Mhj%2FRQS%2BXASisfnllk3k7BEEPr7jte5dHU2go7hqk70TYhcQ7sxsuIwP2Na2TOpvby7w159ea2bzatdgn07Q5DOU6RgF94q1NDRtdL8nGbSwA77ZOfWd2YHXwYd1M%2Bb0sR2H0%2BWTv2DAqPeRKRNSMNqi%2BhiL3mE5uQO%2B%2Bo5czm4fBRYf49Q46eN5utZ19zn0uAdP8keH8AyvUiYYX2H1x%2FNs9KjWmEoX0NZhPxxYDkuVDuLQYvb4A4uDCeuTy3BtAECGb6dQDzv2xK5JabgUdookH6NptrgtNygvtyiqS5Rlq%2FtXm%2BRIezl5XUre1DI6R9qvyf1wTNCUEjdANUhwIOheaK6yKjP3Suk3%2FiQLYaCBKRkH%2FGtTCmmWyxBnfeL9mDy1mffQFk2Ky12DHy%2B2%2BPvra%2Fz49hoXt3vsmhxlOkJFYzMZ2SqBoaGpNExRZSqHOfayY%2BkwRc6v0I3cmJ8Zp%2FTjt4exJ8NYXkhfJWzZUMbMYBOxT%2FpjfHhU02PdzZ99fg7bBsrcIIxbKwELj6U8dfJhyLhk2JN0zN2UZ8OJUNBf85xphnSUqn6Uje0%2Fb9tLVPsSbVkifXGKdDHR3nNyZGwlSFOLY0tqLZfGsbU35E1LZsW7lxqf%2FnNknuapKttDJqJKX2%2FOmXLQSYhzZa78MhlmVaShyZl47rvUdgokWBWllsz%2B35%2Fe4m%2Bvb%2FBuXWKfTNUX1MkIyCZaOsuGi%2FtINQbj7ZcSCyl2%2B%2FOIRkj3AVeP4KI9foHGI96%2FhdM9SJWE1SWXMOOHcnBYth6z57fH2cK6rAp3ot81bxbX67D7P5Y%2FT1VFF1a9uJtXIT6tPnGm0Kj0OkBPlWGYN6ZuBp0dbkbDmEtcuRVA5UVhEx3b911zawAJ1yXKdYGyukRT83TAGul3Z0jmIy335SnlXGvASqQ2PvQzqo2kp2xb3smzscptCnyzr8B9YNrCeg6YJ%2B0LPQjrvvEZEfgyEIjG5pdRDpGLj0CAHcH7%2Fw0aZQ%2Bm8PywkfmgVooEXal6cm8gl%2FhteKVJA1xtKvz3myv8n%2F%2F%2BET%2B9u8K2zlCPF2jzmRag7ZsMJa9bSHMtI0ul6DIJS9Q65MMuwjhzpoY58M7EQvRK0jDM8H2Qx6Ck9B0y6YdOkV1j6F2VahjNtRDef%2FWciio9h%2BRDskOn7r17GfL28J2QaPVo6E89GmcC%2Ba4fB7oZToqwhScrvkCPqj9%2F3dEiIuIqunInRYHONCwdj14xMtWG%2Fozlygf9ZZyG5UhSJoSBzzL705QhMit%2BLUlNSGomLBwEUqe5LFHuy7or92hua7TJHdosQ5vlep7OMkx4QE3SIst4AijNJMtLr7SRDHNMI9kMUUc2ZF2fgVX3euKnUjqkGfItDOjjOGiWggcCMScwJT3MaHI%2FMw3Nv1%2Fs8H9%2FXuGHtytc3hba6ZqMp6i5JF2DPBQCDtxwJN%2BuNrHESfH%2Bz2qxcWhlSARV3kHpsr24ttzWjEmGNkOTw0su6IzDsDZIEbIkZe%2BR%2FB%2Bi8Z4vMdCz3vFOJwNsSJkuwSYMvgzWh%2FA3fzqNPrDTdSPVyoA5tDBm0vhskiaVWiJSo2rDAUCTBdImx77c4OJmi2pXoC25SDzTDMzZnPtvTenmaMIkS5FxGS3rj2m5Jvden1sz%2FU2GO0bct8OePk%2FyjzOaYVbzw%2FTIs5ARND2mjGUzSJQQ7rPUoKP6gxarXYWf3l7jrz%2B80gqX612LZjRHm1B%2Bcx3%2Bk6RjyW%2FT1LrehLTZ7nnZSs4ka8ahS7TSVatyWO738yGYPdx9zyf8Ngk1gsyDvlUfjFMZSzK8iCVD8K8PzribUxkibPsxGV7%2F1Ga4vw38dLKtVE2%2BPpQ1pR54Iwds%2Bp2ixzP%2BzYPv%2BlbaHsKf1gaLpv54G2wna3cGZ5A1cKCGK1ta24fL%2Fehc6bIqdvj%2FXl%2BgLLnwukX93TnOFyMdvDXhfmKu0lE%2FQtw6juSurQFi0FBlB9Pnx95MP%2FB4IbBnIT4jAl84AtHY%2FMILKLL3MQj0zbKHlouWYFKRCA13CGZfpnpU3JfDpbNti6tdhR8uVvg%2FP7zC%2F%2F35HbZ1gvHiCJgssK8S3PH%2BTCrV%2FKnzoHIXzAT1aey0qLL4v2GH0Lsedot09x%2FjDcM5HX%2BSHv2Nbh9ymE7fSTlV2dx9YI9ulIJ7792%2Feaq%2FxJWH62KGjp%2FfcgvsufLF8HQa%2FmRYuVHMpyIaRafjT0vPY3vq9q1OWx360BAx1YghHvsnugGkQMXNF%2FEoLu7liQpOmvPAE2hvYlPUOuAny2bIsxl2bY232xLJxRpSTniKZ7bAydhGuTteyGtI24wt2wOp%2FAcDXOkrJXvzuFJCe8%2FHsvYJbk7Qn0aCX3LhHzFAWedLUKWDElfz5Fnui8wzrDc1fny3wV9f3eJvF2tcbFrsMEGST4F0rLsHt2WNJm0xHqe615QHDVkCPsvcZ8FUNKmWxkJQ2TpJEoMsKAIXDis5EP4OuUCUMw1ulHpe%2BvQevikBOTulPgzrHXnufTz0ULH08AoVlG6LYUo73%2Fnr4%2FLbQnR0JDN9GPly6bdHCvHlzrC%2BbE9jF61makotmeX2uQRZS%2BV5ohm91bbCP97dAXhrBzR9cyyFWblrWpURFWYZmiEdyi%2FrNge4zNz1XBrHVm5kzuqh%2B%2F5zn0TDcPR0yZ0PNbDVJn7cM0xjkwOP17sSP7y5wv%2F73z%2Fhx9dXuCuBdnKEfLzErmxRlswSl5OnNquvcRCjozIjLkEemHseAEYeuI%2FW6o0NcxBbn4l23oZPcX3I%2BtD7E94HgjKIrSSMxU7%2B6E2cFENtYOjfDhofC9Gz6PTtKZL6I2JKkWGJt8Xxv3JVei7zvZQPGB2UI8lqsDI8GaqnS0eTQaN8z68j6ekGEQltvWipDQ4IkDDLOyDCg6Rsf3mL2XiCtM2xWl%2Fhrz%2B%2FRdVUGqTBd2c449HlKQe8bVBVRqegoBEuoREnqkP2Jl9mhJxJbFQC%2FPJ%2Fw3fD2X3iMyLwJSIQjc0vsVQiTx9AIDSyB%2B3r8KP3d9WGjTU7Lwtlf9nE25Ip26e5Kmr8cLnCf%2F38Cj9c3uCuzZFMZijSifbsbCoq0TzohUfZ83RBzmRRyQjGppbi8AoFKo3DjoBZYZp049PS7zM4dAvv96N7YEW10XmnOexK7d2Sup%2BKk7CnpdMlo5c%2BhuNGZ%2F7o04XtCLHjHXpYCE0uDnP5MKItXAzJccaSOVIZ8ToDLlntlBAm0fN1n5R9h3TFSuBpEIcUGMJ%2BHUKBdZuFGRoIHT4cxQ7j9r39ILVQY%2Fncd0NFgbM%2BZj5SYeTJq37NB9Pc4fV6h7q91mHFo3GG0ekU0zHvm4SW2GZNuJyFS%2Bx0nYMrRJTYoPWQAfvfMkJIpIHYjIwpI13B6KVH7dD9w1%2BMRaTeH9vKw1RBQ97mDO3UzgTUv8s2AesLT27%2Br7%2B%2Fw99vKlztUuySKaqRnQrbNLxOAqg1qcly4TCN5gP69AMbRN1mUOzNZcz4tEEjYm%2F8WElbSZksBQ%2FX2gZCG%2FKhbPdyQoweIkB%2Fc6XOyX%2Bef76JhOKZ8FqOLJz5O38hbmdo2oCV8evyyxhuBFtKjhDTYY6l9%2FYMBI4HaVAohInh4%2FyRmrVYnGGnn2WGpJKUp%2FVWuNmVaN%2FeIUtzjMc5RqMjZNNUJ9pycC5PEs57KqYbmlyZYAiahPiXPY1r93FUnuQpxq0sVA8CJjZwY9iZLz3Mc4iFQvhACfca%2B9UmRYW3Nxst%2B359dYfbokGdTrVHuyo5M0z8Ut0BywELlh%2BNehmU6gsCAtzjKsPMebFcs83zdq4re%2FN68NdWYzxw%2FkQHK29yN%2FwXYDPXXgwPZgxNWnwm0lG1JaqWB1J0uvbs66p7WZvmpaF0QxQP67wYrftSQ19GsFB9WHNxH8PW6izDsL4Qc4UP6dkHObd%2FPUVzYcocjGE4d9EqgTBow3af7TCXX%2FPQoDEPC8xn2JaNll1P%2FvGz6k%2Fy%2FFgHxfGgIP1CDkhTs%2FIhL5ITMcE%2FIcXQzg%2FLqn%2F3cP7sfeJbROBLQyAam19aiUR%2BPoyA2mC1yCGcmmy9u6vtX%2FAvPq1DsW7LVCLOwPA2LR4IxH2avI7hx4sVfry8w3UBNOMjJKMp9k2ikwh5CEQ2nqDNeNlFZstUZVhap2AMeAr8YrruN3ynn7sP3wdu3uuKqJGSbzA4%2BkFluvLn6krXnZpbl%2ByAdhfaRtW9nzNOAk6ddeW9rKdjDBmiTLlflChUg8Gk2Q0Za7YHRvylhg1VVJrjuhYmXDVDw4tZpkLgtPns%2Frmh1TkYP1KthZXmRS1ywFZ05Me3If9SIWxZpRKU5mDGroPRweVy4yXWGwDML5fNUUHI8lyKOVPiPZNlVcvoqjlbVFWo1wXyd7eYTSaYZBkmxyOMRwlGXMKp60JsZihkYICBMRLsBhMEYdAxKGXFYaGr59bdPv7Zx7a3Po3HaDAd%2FuOTUlfyipOWe91SGZrvVjv88OYaP17c4KoYY4MZCp3gHIwrykeWYcRlxrxaoK3R8j6YTvZImzw4HzaIo%2FwZgzJuFEZBjCMLbbLGWSvyZgd9mLx3fId0tDRNB7gEGfJMKXf%2Bx3mgjFr74XSGZeah3OihkWD1oidKkWOeGJ%2B%2BmlHTt12J4CkqVDfrarx5rowC%2FzoXoQKFyOZKLJkOv1Qj7XAT1SVeYWKnNGv%2FZqjmTKVJc522fLUvML7ZYH5xi8l0pNn6dCL1Gmw7aXBa8r6CICSuh6Xal1%2BHTFeaw9Cf%2Fk66AQOyw1dvSEg0eMsUlCczGsIrUVvDT3%2B%2FWZEDIOuywdsVT02%2Bwc9Xa9yWQJVNUSVjlHWKkpPvoxHS8UjXmRABNiAqH5ZZMNZk5is5HmpluRQy%2BqCD1YX%2B2h5n2sKahPCdJTPk2%2F3vP0Mi953vf5sQHri6kyCkPHrTr1Amx3aiqpUqnWlkOd4%2B2ENfk1P7OzSUH%2BaBwsgaagc7Wa1grsN%2FAbR%2BZp6DuaRrWDC3%2FPFLLkEkNWApN4a0WWM%2B3bj3GEIr9C20Kf2fsqVUbADBhVYpW3ehoJJ8xsvG2FY7lEmLST7V7P%2B22eHn6w2Wb26QZzmS0znyWYY854FBtpzWGLe8iKABaplyZu4%2FD%2BTXPQfMu1N8RgS%2BMASisfmFFUhk5wMIaAR50DgrKHv2vnNkN8Wmt%2B%2BQGD50c1QIQufCA2B0amZrF3S%2Fvlrr7rTLTYttOwHyGdqENynyoAieSjgCeNF8Q6W33xPpnRTpsjOy7o2MkYshr%2FbuLs4lQ7oPR8V1nE04SEI0pcSE5VidknKoM0lhDlio29G%2BN6MqntQJU%2FUhdfLPn1X9gEzoT5lOr%2F42UgRCXsLhLeq8iaF4Dcp8oMgvuww79MjGTMihGZmmANPJEJBBEMKZitEBYtZnSF5%2BUuKYGUYIGl1Q15VbOoXytXzRVRyHslFCCiNcWGZcbakwpvBIrWO%2BA3ljzWk4z6ZpyfyR7CWapRQmlJWM12zwgByiMdUJn6%2FvSszerbCcjLDIj7BY5JhSR%2B1ktZbyxqw1WhJJBno5U%2FFakQo7cuIKrPzCH8vh0OVj3hmLxPun0TEQqHj2voYBqVI3Ir%2FMa9XwiogWu7bFzbbAj%2B9u8NPFDW52la4LKnlKbXfQUsCTiVhCtldzMM9mWfUAZpSxzPiPZWuzST0vdGX9YflbhaIizxUIzvnQ2CR2nEk2%2FmWQdi0GYQ8ZVmrDlsQkpUvCElKowz9u1HjI8PS8ynxwfgJN1SdLy%2FLJOMSHz2BJBScmS1LE3hHp0ld4Sib%2FmfbNeiwqFJiEh5s02rPJAR%2BG9P2ZddKianm%2FYKJBkHebGpOLO0wmI4w5K59PkGec2Qz344ZUxA8HDAI3zlXHQ%2BfuEZ7qeZh74UFshAHTMMCsOMkdBzUMPONVra1wZEi29fsWWO1q%2FHS1wd%2Fe3uLNqsC24WmzI9TpGHXL2V%2BeOss7Xnm%2FK9PxEqPcmFx5lmko9XJrHGlbh9p1%2BoQ6Hk6s9SI2qvzLNpU0KKX9rGKfO77Jx1484fD1MQ%2FJRqgLzIt4CO0a98ELssHe5hBC%2BdZqDA2qBBk1YRAXwp14ECPJt8ss0TfZ44CdDkdWR6qabe1KYFwzixyoJBEZY1Zy90o%2BlDTpG1Ls360nM4OeeTJsyacPahkPTEr0RdRDimnLe2hozUcCJu5kJisdnuFgd6tWrFBhtvNyU%2BEHDTLOtMx2NkrBQ%2BLGOqF2UDLGmDNonEqGbUl27%2BE5sKcjYewZIgOq8TUi8EUhEI3NL6o4IjPvR8Bb5L7pPVBqTK%2ByTkPdinVoRi%2FE1d4iM0w5Os9TBzdFgzdXWy354%2BElPM6%2BkmE5Rt2kaFIu9KSCxmsuegXRRlhNWSBH1jVZp2XNfs%2Bv9%2F8DF%2BuoxRxD%2BxLKoAhJ4eNBkClQcxeRz01YSuxEXcHRW6d1Gi3n5yDvVDGpNVC5IV0qN%2FyU0UflPUEqQ9PTsuPaLQrpkiqXDZNO6AS9%2Fw%2FcmKpALAKHSo7Tl2FE2hUsHggkNUr9shkEUmoMIVfOqJBQmXEFUTxIYVaPLp4YlrFYMuTQUhZD8rc%2FFA4aGOGpC%2B9T5bfTNKnQhEu1zUAhzyZhrrYoJWPRsKQiKcWC10bwQCAus84BztZReWX8dKL8r4oNXl2tcTrJcTbJ8GyyxNGUShT3yxnn%2FCvyGlQh5naohDkOsxPcB06f%2F%2BqyY2XtdUtfwUlKp0lrgJVLyGzGQKsEWu5r5hUna%2Fz49goXt1vs68T2OZMGfxKorpTCtxmPNkdKFCxwgDpEtLpHInTn31QXyPMrzDiH8grM6e5NvUvuLCmbJWEbYPGYluRiAKCzyoQo75LBIHcMb%2FwdJKbYIjkoLNKxT0vLkrD4rLKB85A%2Fc6BhSJlOfRTLKAfULWXCY%2Fwbxf4vKfIfnwI7IBXkSnRTede8LzMYm2zjmJw4Yz3hPk60uKv2eHe3w%2BLqFsvZGMtphuk8l1xXCZd%2F%2B0FedqiTDQAo1yF98uLfxtnT%2FzX6nvMu2yEhU8QJCVciBMQZhRiGMqDRQFOZS8E3RYuL2wKvrzd4c7PD9Z6zvSOkuj92LAOT110x9wwfSqSTJ4Jr7UzIu4SC4HqiQZ7EH93NGOXJo8YraRpqegsfFtvDWH4sN46ox%2FKnu3%2FcU7GCwel5MmR7Xmh4%2Bl5dK1ZixvyyPWYzZ8Y8Dz%2BTiwYrbeCGNMUv5ZvGFk%2FmTnitTKP2kQft0cMklc8ElFHG4WE81id4z8BQRlHhQzmKB50%2BHtLyUIOBHDM0jT%2Bl0rXxIbcUCsbz8jKoByBaOOHVGbSNTiOmjlBxUIBBkgb7ssbr1Q5HizVOjuY4muVYjhNMQ98nY1U5s0EKaxuZlCqj0QmIGANC0KAPfweMxdeIwBeNQDQ2v%2Bji%2BWMxJ6XONLaQcVcE2ch2Tv524KDG%2F56PTra0Ls6UAuvNda2FDgaqgeu7Aj%2B9vcKb61vc7htUycRGKXnSXNiTKcNMp8%2BxCzXlQP1JMHKs%2B7FJCHMf8Eue1Il3oYIqQQ93C4H04GXSNbIsxShNUFU1MhpBCkpDz2KZQmAjvq6kmLLOLuzev6Cc6vAVdfRUEExhJUZSLkWfHT%2FnqWjg0ti0Tp1amc2OBGNby4d5eii%2FTcGQQSblgvGdO2bcVDneganRYyTgBfGchTJjzIxgXhZPFvRTHk2xqsP9f2kWFBGdWsr8eYkHpSPMlNpMEP2VIafYKyvkA1RtmD8a3Nx7SSXK%2BOOIuPId6DHVfvkY05R6I%2BoqZf2R2mKSFsqaOgsVUirgCUbYlzlutnu8urrFN4sJ%2FnQ8wbNpuFqCMi%2FDyaiLZJ9CnxdmScqQ5e%2B%2BkXSv1D%2FhUwn06Q0oqFw02m7cSVFnXqU4paiTBAXr03qPny6u8eb6DpuyQZ2MTXHTYV0uvP3MAktD8qt6b7Jrd20abWOBqbNUTP7oZnNSrBekFX6a%2FWFY%2BvvyOX4xFZN5N%2BLqmkp%2FjZZTU5RH7b1lxJAp6XusJFR4mUtJhXkLDCWjP5YiU%2Bnl3t28GE1KA19dSOPUKAVcm6CsSl03dPt67bwQR8tPzwXfgtbdlRO5sBlfUVelpwuD0s8GRVjbTcdu1RbYfbWc5WywKStc3O5wdLnC85MxTqY5JimXndq8sQ37hDaH7YIGSkIayvwhh0%2F5Zbk7pGh5o1tYDcJXBbS%2BRH2MHMKAW2iHeCo592uutgXe3KzxbrXFXcEBSa5oGaNJeOIsr7xKZWQyx146bgLZUxyIKXtj4vRhv8E4w1hsc4w%2Fyo681F5YnuxwIRusU35C76PcibilYDCTQiCmp9Ho%2FzL1x%2F%2B5T6Am6TRJpov9JNthYNLcmCsOXFAO7eomDirSoFd%2FpW0TvAaGO7G595HL5VmdTL6zLNcVUFYHa2Qa1LWVMjp8jz1Qwxy1rJ5BXgP%2FAtJOFidG4jusmmAaVjaGtn2FHPLwMvanqu9kxsK4yqH9to6hD6gauCokx0dcBMOYqfOcBk9NwsYPXunUlrirgHfrHd6sNjibj3E6HWOmPc8B2tDOKH5oHrsklRBTlXRYsormEnfAUQAnPiICXyYC0dj8MsvlD8kVFYF%2B6aZ10TbiGxRStsjWN%2BtpHaK5dX%2F7Vt%2FCqCexToudXq3%2FeP9fgrtdjbfXG7y6WOF2W6FqeWrc%2BECNopIJdSZs8NmpaMxW%2FYHU39BhMTEmrU7ZUu5YUmcbVIHOsXthh2GdhuJKCaTOZjOLedIiT%2B1ggabmbIQpdn3erdNk9%2BO57EiHXkuqTlD2NQNXl2YZs%2BNvmA73kqRoeVF1tUeS8OJpUyLIm%2FRv6UJU7sfacEK1l6zSCNaMKQ%2FC4M6ntpIhx1kPy4oZn1wqRUIqT%2BRIeTpriEsFhGXv18iYakb7i7OtNWrt56PaQCRz7fUz6WBOaQxayRr%2BQYHzkggzplIK3OSUwcnQpirzyTTtP0Jjvb5KPCwfsxF9KycpTUNlg5SkEdFMZ1543iSVWWJDmctQJZn2%2F1LOLm%2B3uN6UeLEYY6wW2HLMvYv%2Bj9yJgOTLXc1JRqYFMA9jS8EHIT%2FxtSfMt5DjQMsTMncZUByQARVwYFvUuLzd6WAVXhnBK4IaDtKoZKnbMaTJqWTB5Z5klazRpwJ%2BP9tkQOkpoEVgmeof5YqyLJmk9kZirJ2UGZaxpigBHdaSaiCHMk5fGptCnQqgDE4b7CFDXAGQc%2Fkvq4mUWptpUdk6ywEZ8sxUVYeNKb0bUiGQZVIfhi2VdGa2tnpBHroemfXGWg4%2B7dcjIBQNhkNOZIdSEaccEgqbMaLMqH1Qe8gJNZvhdGPHMDD6wi9pwYGefdtgtS1xebvB1W2BZ8s5JpMEYw5J8Qof%2FtRAMFukYggQI7EXZpUdgad%2BSmw6OTXqJhXmQ25Ulsw%2FDQjHTHjYmgUizfsS12WLd5Tf6zvcbErwmqua%2B%2B3yic1samUHZYE51TCbZJLFauWplJSivbkc80oVljPbTPZlvXFC6aRsSQ7IfiifXtptAKBVoirQMBNvrb1ybM5BDiz3Bzh3fZSjdeBrzLsT5VxlRlngf0EmulxZQEslpMX02eKx3lEeOMym66y4NYBDGTZYyXyzLWefg4TDFUBWl%2BovOMvJHBXs44hmmiPnYGY4VEeIh1lR64EZm3QOOAm5ML71IW%2FDncQ4kKtZfK5SIh8cTFK5sD542%2BFg%2BJO4GXaWmn91yZkckCZnVpmXpEGV5tjzlPtNidfXd3ixnOD5IseMx2ulPNk5lDL72q7BCymov2VZDFoQybCn7ZyYyNjS8feUr2cjPiMC%2F0IEuq7tX8hDTDoi0CPQdbZBTRi0n4PXLnzf5LJRHoxme%2FdgFo%2F8aKxUTQOaQ%2FuKs5o7vLq4wcVqg03BOzc5%2BsoqwSuYrePR7Jc6GjNImJ4pluyEqcwZB8Yt3%2B3nvFooxQo8M6Ri6tvD8ckUZP4waXaEVYlR0ug%2BRhqfDQ25sLRI3btYZMemWLalxWcW1DGFnkoj0rZsSX1awzNDaRgyHXa%2Bqa4%2FaNsKbbOXAjnKgkrNPXk0cGXopkhHdrE7jSrlWUapzA1whyt%2FWct9OCwLC6MctzSYTfHVvWW13atITjQaTsQTLufjVQxm8MmYT3lqY4OirqQYpOJLqrEpbzTKZcSETrhhalQuWJbMP3GjkRyQDoqRlYChbgWj3Kj8xG%2BnXPWlFShIHzSzgwLAPJoJpXgsE8U1ZZ%2B0WfqGUIZd3eCKI93XG7xYTDBdjqT42xyTyXAQlE5KjFfLn%2FPgYX7rp6NiubDUXMrtIA7b%2B8yDVW53Bd7erHF9t8e2AkqqnVpqzEEJlkooN2HCb6PqRUPqhvYwV32O%2FU2rIUNszcxLoTUlVvoiZ0kk%2BkTVlHwOAKCpVEd4Jx5NYPLDcmwbqseUdwpbo0EX8dJmyDgowhUGYRkmFVPjMhhxxnRg2HPkMhBkR4wb9wwhTDU4w3cbYqEvFU7N4CstyrvRc6SYtiiKVKDEx8DIU8Yt8yEd1gUFMh6Ji%2BoAiRiNLgvenhATzeBlOnV1V9W42ZaarX5%2BPMNiNNXeM5nDWhJPrix%2FAYiOdp9C7%2FNUb54DZkNVPRA2vOyj54yhw%2BwmkeESyDCrybteK2IlCwAAIABJREFU9wlwvS01UHJxu9E1V5TfNuMSWs7OZ6gbW1nCPDE%2BaXfIEjsZCEzX0nI%2F8anZd7aBbD%2B5JYPtA5eU2uUZbKcYzsqSMW0ZPx25jJTyyf20WolBKyX868wqlam73n%2BSnrjoYg1DSMzUbpmrzagaZetZhFzgz7gkRWHLO1j5zkOjslR1hQOkWcv%2BpUTO9ldGI0slR8E%2Bpi6FVZa2mKS1hiW4D5gINE3FnSMAcc%2FHNijCITwthgirfEJfGIaJHpQBebZyZ3sTjEhZbSx%2F69cSlqURVaYtD2GcagjOwbvl%2FcCJH4pMWaB8MAx%2F3E4xQdVWkiXK1NubKV4upzgeZZiktq%2BfWJkc9bTVxgzc6W%2FgMyFLpw%2Ft3Dx0cZ%2F4jAh8CQhEY%2FNLKIXIQ4eAjfxaw6lOMHRkdGFTO%2FynUL09pfaYDbVUAHpKA2Fjbks1bZaJRmWqE2Yv13v8fHmL1ZYj%2BGNUGffisPMkBS6xlPY1GHW0pp48MIRxGfqBEKvjz5l1JsX9MJbHYwz1VjpIhgowDUrOF1FVzmm41XxXV2zLWaV0cnbCTpXkMl%2FOLHGvYJrnOmmSB7aUJTvuFm1FXhNdyD4a5ZrZocbJZbW7XQFUNUbcp6rc77hwDNMsx3QykpGw3ZXYVoUp41J8Mi054%2FIhGXEpDWJgORljTIVhv0G520m5pwLC3zjLsZxNkWcj3G12uN3ukXOvmM0B2sxOW8uNhgCX807yTDww57ebPXZVpWONMs3aUFmjQtNgnKWYjEfK435bYM9L6UdjJFkKXrjN9bqcnbK1yFZqXnZWilRbbFhBZeGe9ySuL3EvOytPBqeCJkWGSmVQ6Cl%2FJo8sJxvEKJpCxubPlzf47nSKs%2BVIAwz8a0qSD5iwxMxI1rUSHU%2BdhP0TXkyImUu%2B8amikcRa3qkXUvbKBrjdlhq4udlW2PHUTirokmLONht6xMNoMXc2meC40t3LwzJ3P9P0Vc00Zb2pgIQy0%2FIqU91gaAokZ5Zzm6GWhJmxq9kE1qeGh%2BBwESk1WEo9rYRcp%2BFylpx1TwMiFS9W5GqHzAZywoy4oUAOQ%2BOjHLlr%2F2Qakg3LqVBUjnx2p200ADPisj7yQS2bdVWBzDCXjszqQAOUuVebZlRZ76VMiz75cWuHPISU%2BRBL%2FT7fzqnjy0uYWLjCnWi%2FetVk2LepVn68ubrDd%2BdHeH48RZVzPzv54uwV5dRKzHMfuOk4M9%2Bn%2BxuSE33y7OnaDLR9MYxJmaWrfGvpP%2Fm2QRIu5aexuUsAGgSvLm9kWO%2Fpn450EJDMkzA5TvraZ6nZP6sRZhx0wClV77uUJl04ay62QuPAABro4zJRyjWNS2vjZUQRV24tIL8Nf2wXRAhoOJhCOhzwsEFQx%2Fv9CDtCjtz7Q9JHtVvy67WTIFt%2BzZeY24nSqpWhfutqDw7%2BNHsNPM6nPMWdxnqOXVFhwzqFUofkTGSUlpiPR5hNcxRcgsu%2Br%2BH6I6Mvuee5BZSxFBjTSCv3aKudxJ%2FL4jlrrHY2VDjLoVpPDeZ4G2x4cUCTbVBqp9Nq0CD0%2BRwAYPMtOg9xcrqGXJCxYOQLJVY%2FLv3VthceqDUFmgJVU%2BOObePNGlcnC7w8GmGeZ%2BHANCEtxA1Xo6u%2FQVQaK3iTZTKhau7laaX14dKMvhGBfz0C0dj815dB5IDtp3pnU0RtRD90ZmyGQ7vvXZ0DpuaWDW%2Fw7xro0HR3GghVEobTYSa252ZXtbjZ1Li6K7FrMpQJT5OjcmzLAqVgiC7%2FuMpiCqCnbz72dZ83upKfvkvoQ3v3bS7qOWw5T82ZF3LRYDLOMJ%2FkSGtTjjXDqYM7qFUrM6Ykpxw5puacYzydY7ZYIslybPYlblZrrO82qCoe3wJM0xGOZiMcH80xylPsthu8e7vGbrfFuC60nC9vCkzHOZ4fzfD8%2FFRKx7uLC1xUG2w5OdRmqJoEdV1qFHo8noAj1KT77fkCs6zCbtVidbVFsSuQpykWkynOjuZ4fn6OUTbC67dX%2BGm%2FQZW2KBLY1TLaQ5cgbzLkbSLj9XQ%2BwdnpUvl8k1a4Wm2BtsI4HdmVGVJCKpwcL3F2dipz7c3rC1zebDAaj5GMUpRcLs3lgLSGKAZa1uklyPJhCVnpCUeZ3AoqzKwMzRjtY4VyJagqY5MPUxsazepS4aCCRGWJwcwoJz8tVrs93q6Ai%2FUJvmuOdViGilDGu0mM4jDeYMYiJDdk45%2Fw7vzYs0%2FQMKNSqFM8q1bLLVebEpsqwb7NtN9Ny2h5%2F6AiHtLQVxjQkcIaykEGlVBjJM81Q1AZ9zKjAlrpSI6sbXQHZN2WmjWhcm6zUVzaZ3fhmRJMZkvw4lzaaXbsCOs85ZqEzZAd8chVXuNScU9nYbNJlC4q%2FlwqR%2BU2yTul1MrdcmD4WJkbQpQwERd95kFGbsJrc2rJes7l4mFGlUau6ncalmaHU7M5eKS9lRy04D2%2FOlXWgvZlYoMewswsG0c0tESOJWNQsIxDvvPNSsd45V%2FOXHNgruB1NnWNq%2FUe15sC26pFybtiKd%2BBssW1emEUvOT4NUx3yO1nvodEZRuEQQNHm5RNVownftl%2F9LASozTJ2NTdmq0GSt6xzSz7vfuUXxkQanMD1dAhWT59ttRzHfIUsuy5VwsRBp9kRAY54DaBtLHtB1wRwraUPZCtyGg0WKhlpapBNJBoGHG2faRDpJTfgINS7so08PHgEfqbe2XiWNnTGh3LAktYwxxdxjrpZoBgvKv%2F1sF2NIpLpPUOi2mKb87nODo%2BUZ9xebXCdbXWapBpzp3sXEJb4NvTJZ6dn2Fb1Xh9AVzcbbCjwZlWKNDoqpm6STAejTBKUlTYI2v34OwkcaUxJ4PTOQwGuNgLxaLi4wqebKqtGOzn2TYkGU8VDrKssadQDxhB5TwE91CSWcWEkdr4EI40aMxqIJgrpMhjhaLa42a9xdV6i3W5wHKcYSKZNXRJh30EB%2BU8RdVKqS5Bf%2FHzBCTbSjlIuXIa3h8UeHSICHwRCERj84sohj82E1LetF%2FTNvDbiC6XlGXh4AA2pmFoWQco2IyjN8pEz9%2B9CTY3d2U7zGbfDEnaHbx4mTMxpliMdL8cO3J1q0GZ6LsW0rEu9rCk%2BtQGKZmS03uFKO7gz54SOSN9ro5iZ8MlRcfLCV6cLZE1BdKmALvE6SjDNMvkz2Wq3BeipYzs8LMRxrMFJvO5OrrbTYXXGfCm3GJbU5lpMc9SnM9SfP9igaPlBKvrDOnmEpf7HSeIzOgZ11jMMnx%2FPsVf%2FnQmBX%2FarIH9jQ5QKtISBWdSS%2B7R2yLBDPPFFN%2BeHuE%2Fvz2SsbnKC4z311gVphA8n03xH9%2Be4OXzE3AJ46TZA7sV9kmKMkuxKSrcbnYoiwppm2KS5jhdzPHnl8f45uWplj7nzQbNlmf9NTibT%2FHs7FjKerHb4Ph4rnBUHkbFBmOUODo%2FQzuaYrVp0F6sNcvb6GAjyoKbPsQwqKdcwstSkEIo1VCKjO1JNXnr5cGkq%2F9r0sGSpSqo%2F6TT2f5RSV4QECpFu6rUQMfNlopHhSnv6WRq3UyYpUR%2BXDYOpebwq5ek3%2BrNpTs8xajtf6ORVtatyvBus8d6z72aqWaFap7aGU6SNEStnpq0M2c2U8cn6532OnVZsNz7pxuapuCF2SDOcFcF2mqPNqmR1FxmXmv5ndVWpmonBmupdVOgLjYasMi4EToNM6%2BUAS6p46xKyqsJbDkr64yWTroxpjaEh6DQyKsV38pMORGrfclYLmk81pyB1bJJMyZGoxSTPEHCAZayQFIZ36z3nOWqqhLcn51pf3KuGZAd09PM0ggtOFM0QsOrmHS9C2e3KCshdW8jQ7vSo25omjrrpdC7Mb8Kq6fme2VM0tix%2Bycr3G4L7c0txzmqjNfZpOLA0vDSMvllOh1Pvddv%2FxZgkIERjGjmrSulMEPnZhSN5u2%2Bwc3dFrfbHcp2rME7LsVnTnhmGpf6c8ZLe7MlB6rlygtRs3rKT0ucbv2Xo2ODhBxM4KoV%2Fti2J%2B0eaVtq%2F%2FaUB8NlUF%2FQNAmKstbMK%2BtG2TZqO4oy4dECaku5qiCUmsqOfWnXfQUeDh8BnK7HNF%2FLg9FiCM9PqJkmF13uPD8WUhSIL2fmua2gLZE1JZbjOb49P8bLl8coSiArN2jXNfIRcML96pSdOsFfvj3Bt98%2Bx65qcDIb4dXVCndFoxl1HjJ2s9lhvdkhwxijNsWIt2Nn2oChlT4lZ4E7Dm0583CQjlmVLLQ8m6BFVafdUl1gjoQGKNspNvbC02RFkQSmtSYGWXgnFipkS5nyRTT0xUORWu4B54w%2FDx%2FLUTd73O65qmWD232F09kIMx42z3Fi7W99rI8hO9ZOGsahfwp59ZI8LN%2F4FRH4MhGIxuaXWS5%2FGK7c0GTzzsad352xyXUzHO1TKx6WyhAZtfLW1PYdrUHm3%2FZk58Hm2kaf7fTFFEUF0BhbbfbYVxyFzLRkzEaNSUe9SF8GTCo4HTbw5NoMl2Hq92KH%2FT0M0cfu3yw9GpqcBeRJkDyF9vx0jv%2F8yzmmvNdOykmNWZZiJmW4xTRPdUE0V1RxZolLwfjjSD1nbdnZbqcJbtICRb3RHjUeub7MK5xPGzw7TjBvUqxnLfbYYjIZ48WLZzI4ufTp5bMFvj2hEdQi3S0wSc%2BkAGzbMVZFoj2H5c0a7X6P4%2FNv8P2zKV6eUHloUWd7XNd3SPfXMozPJqf4t2cznJ%2FkGr2dNEscjV9ihxRlmmK1K%2FD64hpv315o%2Be1iNNNSo39%2FMcM3z3mSa4XtTY67dzxUosVfzmf4n%2F%2F5LTjG%2FebVGy2vOssqPVfjBtNnC3z%2Fn9%2Bgzsf48c0Om22Bu%2B1e%2B4UoTJoJD4cT2a49Fk1je18lbGYyUsykQsiNJWYqmJWdl7IpGXSTDA%2FVAwYJwbQMOig93De8LSrcbNZSbhcjm2nWnt0gGL2y52JIQsaDuxw8Q7wDt9%2Fwg9xQsaIxVlQt1tsdVusNdly6rf2ydg8h32VwyJCmQUmULHf2pJstY7OBHmPajEozVUzdMpmm8kudcMSmgfuvmwJZW0J32M3HyEdcSj7Btkqw2ppybkvjaIzuMUpKnB1PcXK0QFm1uNtxTxVnT8gNb07krLrNxHK%2FldoPGRmcBWGaxjuN7G7%2FlwrZ5CBITCh4IaQDt7gSgMv%2FxpMUJ4sjPDueIWsqbFc32N%2ByftY4WSwwn01QVYUGR7hCgSsWaGhwr%2B%2B%2BbnWVDK%2Fn2Ja81TTs%2FxNkauVM3mQMeeETb%2FJBlsJohgvlQD6ZK%2FuPYf1nUzctly42bDcrrLcF1tsK%2BwkPvaKmrBEyGd%2F3RdC%2BQwUQA%2FdDGFtP8ZeUnfowRWXR67EMToPBZY%2BrXSjDlN%2Fb9VbGXUMBCzN27ItI2bd3yCAhQiRsQmrsDxMNvLiTnqFvo2FBI4QH4mQcBGx23MmI2TjByWKC48VUK1omY26HoLHZYL03g3O9457SFa7vtkgzzt7nNsturXQoVWX2AaTOi3kM%2B6zAPqMF8bAaagu0taycS8s168%2BVFqH9DHWY15MQeMoPV%2BW0TYU0qZAnNWY5cDzJcTpNUaQtbrIad9jjZD7FX747w8ksxzipcX68xNEy0eqi5fQZnp8tcStjM9FM%2Bo%2BvLvDj5hYoWc%2BnWC5HmHLbRGIH5vFMAUm42mlbDeJDVZQJ0zHUciAdT7Fa73VIGwf9dAVQ1qKhwZnaoXXESvVB9KxeS%2BUI5So5M%2Bu1a8mIolavtHaHLQtDMdkRc0EF%2B%2BOyxM12o%2F5uV09R5%2BQpdBFMSx1TSKSTZpNq40mZsQLzYB6%2Fc40vEYEvE4FobH6Z5fKVcsUm0xpf9VB6Z9dm%2F3hwwnicomlMLDkqyH%2FsLOwAhTBqGzoBa85NIVVnE%2Bh4Kq580JnKAd15rddGp2ZucXW7wY7bpKTQ8TATxvBYzpW5DH1CMrZ%2FyhU5OnrULkcW0ih1nl0wd%2BGTMyt1XWgZYJZzlqXAOG%2Bx5MmPXPLXphhzdjJtsci5%2F5LptbrLqyxKLZXlUrtNAazWtUbpVxdXKO6ukTcVpqMcs6TCuN5i2hY4Sudo0gaLtMTxuMU3L07wv%2F%2Bf%2F4H5fIJxnmpvDGdfaAYs%2F%2FQCf%2Fn%2BJfZtjpt9i3%2B8vUVb%2FoDNzR6jLMHL5QgvliMs0hY192pub5AVd1hmNY6Xc3xzMsXJJMEc3Bua4uj5DN%2Bez7GugQ2vG9jXWExHaHdrXGzXGINGdYkpKkzRYDbJ8KfzGbZXU%2Bx3O5yNWpzzOMyqwT4pdYroWc4rXGpcptxb2uAoq8EJitUEmOU8NbOSDq3BASnjpl4TQ5vdlLoUOnyWSBigcMtUpeYlRl%2BXsqCMmGoR5PuwxD0sn3Y6KE9DbnC93uJ6vcbZYqKBBO57lRiFUXL7tL%2BmhwxdGJLpuAFhcT%2F1r3F8GPswtcMQMkzasF%2Bzbmwf7maDouYsAw0kSk5Y7klCIhaQkGIrNIQay8SUf8%2BRtQmWvu1h1X427XG0q2h4qiTryCRLcDKf48%2FfnuP7b8%2BxXI6xLVr8%2FdUK%2F%2FX3V1hvNkKJK2MnWY2TkwX%2B9%2F%2F8E%2F79z89xty7xtx8v8Y83l9jsKozzEZaTifb%2FFvs9qn2BuuJQTookHyPnyaS60sH2%2BxmXMpFNHsKsks0Qcj6QrVKjk545D0OFfTkb4fsXp%2FiP788wTVpcvh7h6lWJSQr8%2B5%2B%2Fw7ffPAf3VRNtm1Hk0mug5JLWFlrK%2Bvefr%2FD3V1eaHde9fkqdbSVRtNkZw9vKU6hLVIKfilIOgwLv21ijw9zRkAg0dZ9sonK%2BYbu5GKEe2V5W5tLmVgfkwquV4UP3z3Mh78pEXwdEMLgFpb0PEeRJyxQZpa%2FbxJgnoF6u7rDabDVwx75Cdzzq4Cnu8bNBT45msYvQvk3PHxPpMmltAXmztE3efciEJUTbnKf3JjyFtd5ikpQ4nuf45tkRvntxhmcnHHAYYzziTBtXDUCzruyz3l3fYUxrlXvtueWi3AGc3dYMd7haROVF5myPpzhSsZNJr1E8aKjnVa7B2LFSNz%2B6s2baeiDWOy9lEtR6UcupZgSJJOtKifk0x1E2x%2Blyrv5ryuu20gankwT1Yoznp3P8x8tjPDuaYTlOtTqBAyzcz59NMywmc2y5%2BqgBLu8mqLZbbG9GKvLvvznHX%2F78As9O5zq5mThzDl4rUli%2B4jkYyp7jsCjKloUn%2BOHnS%2Fz17290H%2FC6SLHhMtymtNPOCXo4WVwYkob2aveYyPCkTtKbijYYQaw4%2FkJ4iI8PTOkQOWsr17s9rm9vsT2ZoeZeVhZVWD4rkQo6CEVYao%2F8reSYN%2BbQpEpw9KKnyPFPRODLRSAam19u2fzuOVN7rFxY12vNY3gPSox92f4Ihq%2FKCvv9XkHHY5upYKvLKzt0PDxn%2F8JsojW60lzVAJOW%2F7qRaO4rCldr8NgQLmPc83RFLWcpdAItDzLhCbVuiKjzvd%2BMqzP27tqKRh1Cp%2FR4cYX8uTs%2Fg9FsIR6jbueZcg5IM5zkc7fD3eUd2jFnWmqM2hKjpkJJvWc2xXgx00E%2F%2B9tb%2FPzTK90VyhlNGs%2FaUxWu3Bhzb8x4ipfnp%2FjT8zO8OF3i%2BckUx2NgcTrD%2BH%2F8G54vJzZKv79FPqoxScc6ATfn0lruE%2BVBDtQtyhrplutnV1oKezICZtMUL%2BY5ns8zGZcFarzkBdb%2F9i3QvMDxcoHvXrzA2WyEnNfObHdS1kajMeYZR6dTlGWLeZ5oH0uznOC75%2Bf4X3%2F5Ft89P8ZyxmPigfGLYxzl%2F4ndbo%2FjxQLnkzGyUYqjb15KLqYzLi0E8m%2FPsW0SzOY57hpgomP4acTvbdCCswFUn2QMtZqt4uAzlQMdCCUj08bFTVGzLt7Ul1B2DD8wj%2BzdjQ4v5aEcmFRKXihHGe%2FtA9a7Svf6leGwEtEJMwg%2Bkm5UBlc2SMaD4iPFRALmwvdJT%2BfUIw%2B%2FLcfuY%2FWL9U5qZ5hBK2ls7vagIsUBDztkq1dTNZvc1c1wyI1qrGHreWQqlm%2Fmj67OiR3aI6VXSrIZoNYulKj2e7T7KWbJCU4mQJ40mCQFRm2BKQcaslyyl1UFkv0O42aPI%2BquWYVJs8Gk3iAdZXj57ATfv3yOyWiEi3eXaIs7rNpCS0h5hjXqLRIuxUs44085IpeBTyqXxIX86Z2HuzSaZuF%2Bs0Z7nPe6k2%2BcVFjmLWZpgy0KrOstZmmOs0mG5wvuxYOM9j1PtWKyDeuhKaVcdlkXW%2Bx3a1RlgjbXnHmQCjcGBtApGnE248DUcS9P497KuF9%2B2TVXnjWS0%2F5MHtS1xep2jerFEqw8w1Ly8iI9k1BPx1Lwr897ukwwYz7EaMYGmfE%2Bh6HEh8ZiLNfGV%2BDMbAEdbsXlm%2B9Wd7jdlWh0UBpPMOVyUA5SBW6l%2FNvqGtEOho24CX8sKD%2BcEcoHXXXkmQ4J0rAK9yCUG4zTEs%2BORvjTi2P8%2BZtneHG%2BxGzMsDWqukBd8torzoTnOFqOMBsfab8vV77wuq673Q5VUqNNuSqDZdEv27f64%2BVgdVEGWViNQHnoWznKrHNvh%2Bnxk4caKWYTrjJRDMZSSiGfnM3k8nMCzsO6GpydHOPPZ0v86XSOb85nOJ7zSPMc8%2B9f4OV8pKXDWbFBtm8wH894zi7uii1YT%2FLxHPl4IuNtt6uwv77B%2FuYCzWalEp1nz7UE9XTO%2FZewZca1LfnWSEAwNh15ssUikD6QZajZl3DPSLVDU%2B7RVLanW3HZ%2BHA1gcqaf0Jkvdh%2BSqIkpDhI2Re%2BYUE%2FGdZMnQdCcRktA%2Fny6xS7osTqboNtUaBsuH2HAx9ddKVke9YlKRJooc08mJoUhNzqrkXuuPq8qhVjRwR%2BQwSisfkbghtJEwFrlLnkTK23WuoBMmrTTZmmoXlzs8LFu3cavzs%2FP8PJCQ9Q4aEc7FA9slr5roX2ptaa9XvqlAwD6zfYOVA9oXLMRp%2FKnJbQag7CuidLgX89DfLq6Q74Dq4WahiW76ZiWO4Zuw%2FV0zda6kDCKLM6J3YoHLm%2BW%2BHtqwI3KMFDe3ilyKStseR9mCdHmL14gcVijqwqUa3vsLm6AM9qTfOplgGys1NnSEUgS7GYTfHs%2FBQvTmdY5jwsCDrpNTs%2FQd6WePfuDa5e%2F4j91Qjz6Rhnx0vMTo50Wubd6g6czbjbNbjekbcCebnF6STVCDPvizzKoFlILm9cnBwhPV3KUJ2Ox1hMpzoJlwez3N1c42Z1i3w2x%2Fz8Bdp8iu3dFqvLK9ytVjIceArtYj7FeJSEaygSLGZjZOkptustxlkG7VzLMsyXCx2qkWVEucX4dIlNnWCftNhygIKzxVWhk3ETHRbDQxx535opVVoxR%2B2assVikox5iXl53yt%2FdfwhjLxC%2BYeHh%2BaMqYgGA4lSIUMsGXHNlZY7c8aCe8ZC1AMTzFVk87P8Pc4RQ3iqHuLXP43bUGFCDSDVQ8pE2Zcim%2BGopdtFqTrFd9YxWxIrLU%2FLkzX7IJacIvPj7%2FTgu%2BfUeee3GXE2w2Z6FuVayqOs91bX93ApLU9u5oR32VTIqy0yzRyFuyC5vK%2FdY9w2mKLGIgPqtNbM%2FjKr0KQpns1SfHeS6RTk9i7FNVcY5K32VXG%2FXJOUqLj%2FMq01i%2B61nIhwptXv8OP1FkKAM%2F1osGd2mAb5S%2B16IC4yHjUNJk2JCVcetAmoky8Szh6u8e7iSlfJ7BsetgTd18cTUlfbSgd%2FcV9nwjtvD5ALIuzwhadWhoSA5OywRA1zi0lgiS33mTn0dkInZ%2FM4WMd2c73foWhqDZgwIKVaVJyUUgjKcFeulnJg6TMfQjy0q5YoT8Ym86zPWuKqHoQuFta4ocFNeaKCb4Y5ZUmHdt3ttLQ9SWY6OIazeGJdUul56euG4nOwRU7kwTNPh%2BG3ccDc80fjgzOAaVtgPgZeni3w55dneHm%2BxGTEQ9v2uL65xdXqDruixmg6w%2FmzU5yczLCY5fj%2B%2BbEMzqbYIaluUTJdtmc0OGVoGQZMlf%2B4d5B1km0MjTm6siw5JESjlYMYdCV6XAaqcg57lbUtWXfNhsvAZGDZdgPWF80Uaik7T4XWaKTa28X4FM956M%2FpFMtZquW0NAzHizGSbY6bdxe4297g%2BeQlxulU8n7x88%2Fa0nL87CWW5y9QVQnK1TVu377C9uod0nKHLB9pW8k8SzCh0Vw2WF1yWfEGFQdDEq6kYK6VS5tl1IBBi%2BlkgrNnxxhNuW7GBhK4JJh55gAv74ylfOuOZBWq9QkmtWyJDc9ecDk4M9Rt3McGbdR2W2QreQ0GpCjr0gxNHj7GKCGMZkLp4t9u64YgdO7IeVLhabrVgNg9%2F%2FgZEfgSEIjG5pdQCl89D%2BzgH7aWbGyluIbugbMit%2BsNfvr5te63G40nWC6PtAyNhwXJMBAha%2FitAwgqq%2FW5apC9UbaZKkvDOiBTBHjYQ1Vz9LjWiLArwoFSYJVU7ncw8lIa9KEtQZ4eCyUe6CFDQ%2BephxlO%2BhiHnRLYcc0uykZQef3ILMsw4axmk2pp6TRJsBil2q%2FJAXDu2%2BQs53fPzpFy3w4vH5%2FMsE8y3JUNLlZrvOZSWu553BfY77lvjDOAQZGi4lUVIK2j2RjVnleYtOAMUF5X6tA5q8lluCkPX2kbzEYZzpZTLdtl%2Bn9%2BfoZvjudYpMCESvZkhHya251r1LHZmdO90ikbetdhHTxMouX1LCWur67x%2Bs0b3Nzc8Lpr8bvbF7hdA8X2FuNRCg48cIZ6t9%2Fr9FpeB8Pj48mvFK00KJV1g6ThbGmDfZGiKve6YoBp8XAPDi7oRFoWHrWprpRNAX2sLPsSvu%2BrAhYF%2BVix9ntvpHRacUvOZVTqLFLNqHAv6r7g%2FXl9FMq0%2FUzWDiXOOelDeJLm038NY3%2Fsu%2BeGtA4oSQcyA9PD%2BJMrBVhvi6rWbBz39vFKDFGQnGluoWMhTKCEjAi1zq9Pl7GDkSkFzJQ6KrdS%2B2TM0YhMdYBYxrtXebBWU2OmS9VrjOod8mKNUc15pTFQVxg1e7DX05PKAAAgAElEQVQOLUctjnLeINHgdJygPVkgHc%2FAOyTPx6kOammWIzTPj3G7m2i%2FJA86Skdc9mYXznN%2FlwYmqKDXlU523u8qaHBlMddBQ2xXdnWJy80Gl7c7lFwan1BmS4xo9KbQHmwuMzQjuFWdu7y9w5t%2F%2FKiTK0teDA%2FgruK1ES12DU%2BG5d7nEbI014oMa0%2FM2OL7vdLr8dV%2BOytZR14DeJJTL3EWNmlwOWGYaW55FQUvq%2BdAXY1dWWrAjt9m7zM8U3WqTHJAr%2BPA3TqHJ3hhmqT7%2F7P3nluSI0mW5oUBxomzIEmqaqZn9v0fZ3%2Fs2e3pqiRBnRsF3fNdUbhZRGRWZZHejsl1z7QwGKBQKioqXGLUwAcMBL%2Fi35gRtIWBb9lsvBJMp5%2BSJqpuhMV0ZxVyMBoenMEX%2BAuGM1qj7mg1sdlpHJ%2BPvx9vnDswqLYSGYD7Si2nE72%2BWunqYuHo45vNTm%2FefdSb97e6edhoV3Uajqd6sa71h%2B9e6OUFWsKhiqul9vcTZeVGRNsZTWeRk9KWMZlxLxpZGE18Ph%2B2ez2sd45QzvpxaI2Hhc6WMy2mY7tCFHlmS5mmabXd7nV7%2F6Dt9qBiONLZfKHVfKaCdB0Ev2G05J%2FlN3rJplZZHbR5vNf2cafssFZ72KgpM7XV2Gap5kUPBzXbjdrDToNJYaGO4xQAW1WltmxUIIABmvJM82KgxTDXfJirLNDcxh7HpgD9L%2Bfa9cdb%2FfTh1vvCqZYI8meGHj%2FTRkSqxh3k6nyl6dlMo3xkX1enosK6BaGD8UiciWEiHWdJv3pPQBpgFuDjf4PhTMgs7YH%2BV7zVM4LAIww%2Fbjx1Q5CxaMPwhyDL6Zh66wLgKMFS0qBbKG381zOzfa9OYY57X%2FS6L%2Fj8%2FTwD%2F6Uz8Mxs%2FpdO%2F%2B%2B98VOkyVhPEWMgxb6EiZ48vEMIMlJYQxKaE%2BcoA40a457WEai1J2efaPt0KERzPdERkmwYlrZrVdXkoESzGSSS%2B%2BEuBSHxaV%2B%2FXKe%2BCbrU%2F6XX46fv9wQYP5KJW2JO%2B74%2BvWvGNTOzNRzkulgt9T%2F%2F2x90PoUgbWwOOrF5YDCZ09HIaUSmo4lGo4m%2Bef2t6qxQkxfadwPdEdn1zbX9UjebrR4eHh2AZwqRezHTdJKrPGx0e3stAiy8fPFCM%2FJkYuVJ6pV8YD9PZufy%2FFyz5bkP9LIbattIw5%2Fe6%2FrmVq%2FOl7paTDUrZI1qno8dJOKw22uP%2FybprR34SFpMpzpbnWk2X9h8ucyH2t5vdHNzo9vbO5VlpeVsbmK3rCo9rit9fPdW49FAi8XCzzGjxa5wCP1WkBy703CAHg1iMrSE1WCophuqKm3MpPEQrSjzH8FAOvLa0ScWLNQgyYS2Xw2%2B%2B4Xl2yt7%2BvDpaWgxojzkAyUNpql0D10hbqEHA2sPSMlSNRAfBF%2FpzWRpi0%2BUDtPdT5r94kffZvTxl%2Fv6xUt%2F5UaQQOHv1Y%2Ba8VAz%2F5i5SDBMJEyYTQhY9hOBjyI7bIyaV2L39Q1Gvdb49hvH3CctpblzSzEPPcPpPiXimQmOkjBFA8OcXyENToMVQKMxMN5VGqtU5RnnHXL7VY7mPM0haFuN2lpnwNbLC82WZzpbTLWa5vaRXr1eGa7vtzvdrdciGtfibKVBgY9cwBL%2Bm0SvrcpS97d32jw%2B6my11NXVheELQnxTlfrhw0f933%2FZ6m6%2FV1F3GuJrOmjdF5K7I1gaZmiZ2P%2BBKRCMFDl%2B5GHKCPxiU4twBuYeXz1r15g%2Fm4Qb8hKs9ivXz%2FvJd2KaYCjRDsfCnjxnJcwbHYlamMqYd%2FxGCaZU%2B9u%2Bjc5uyrr6pYB%2FCwOo01CT%2BvRpG%2F%2F8r4DU05FGN4934nfAUvQlBFwBxL3AjScwqMx84AeEJZ4fIwh2I23FvHjOeJwQuCG9H2Y%2FKMN01Ot6XDOt4NcY3%2Fg2zqcLXazm9nEk5%2FHH23v9%2Bad3ene71qHJ1YJLt63uf3xvYc5o8FpLAq3Nh1qfjTWoJprMlzq%2FfKExDCcwhIByGBGYYWx2h1ofb9f6849v9f56o31T%2Bty4PJvp%2B28u9fJyqem4sJ9%2BURCltdP1zYP%2B%2FOdabyuijZd6PR%2Fqj9%2B%2F0Hwx8VnBns%2BIFE%2FYXPJctjCoW7150%2Bnn8k7V440%2B%2FFRpuL%2FUvHul6XKqumr0cHtv4d%2FF%2BZkuz%2BaazqaescmMaOKvzYTNl0uNh7nzLX%2F78lwdpq9E4kXYssPslUjN%2BIaOVNetHjcH3T7utK4HOmRF5PY1U5ZSI7W1XTSyYqLvm9ZpjoLpA%2F8qBAzMl8%2FnEFT02LdfThA6y23I4h%2Fjw1NGs4exgLJ4L%2FaWxZlpPyEQo26EAJxYUWP%2Fbv8NzXO8TlDktQ3Y6Z%2FxzR%2FfPQWUbj1%2FPc%2FAVzgDz8zmV7gov68ugaVPEeNxdEE0xu8ocTTLsx%2BdEbJP%2FiCsXA%2Fouq8v3uV2lIcYTgTU08kAUYU3JPQD0ebCh5Pck5Ym9k45Twj%2B07qPvf3yKp07cQilo%2BNpqKm4SSIfVBGIxn03oeIOHplQxuSh4WMWvpLOrZl1GuedpigNFWkZMCMt0BpRD2ayyVQIQyCIFgj8Fk0TkmQz1Y1gOIn2SpCeq8kr5ZO5n9%2Fd3WtQ5FotV07pgLkgTH3dNY6eRxvZEN%2FZsfC6RBPXlBBtYXbFzNLPCN8eARK2u73evX2n6%2Btrzwr50WaTif703XeaLScqxiMzm%2Ft95QAuwZQGcYsgAEIbrXaRhy8WhzMscFFkms0WJsinw5FICg7RTrCkPCMJeqMD48fvKp%2BpxCyNiIgPtYYfNlqTRoBcjB0RSzEVRMuJ%2BSOLZQh5WrVgkoCFfpXjUb9qqeBT%2Bc%2BfGoqST6NrfgIryJqB6m4Q%2BUpTYvZjfX1BvuPabT4xWceSn15Rtu%2FrL%2Ffy0%2FKf%2Fupb7e%2Bahzm52dfMc4NdMscLzWajykE26HGwiFFP6kci1GJrBmNyrJoyp%2F2lBp72n9AdsUTRBzQXUR6mz2a7HWl70JQUDr4y7DqtJoVens01ITIPfrrtUEDw1bzQbDSwud%2Bwqw1DhExejgZajdCmwPhJw0L2l26rgbpxrmI60tnZWMUot49xRa5ONJKjXNlkqItipcNipMl4pPGYXV9rMCp0ns00zq%2FUbB%2F1vx5vNKj3yuuDRjZjREOJ4INUK0QXRZuYaXV%2Bpn%2F7H%2F9D60OlPWaeRKN1sJStfvxwqzc3G%2B0PtTX6maOR9Awns346l%2F1q%2FvK30ZAX4vSdRFjD3EJkg9AABswmYZfq8HtnPSCkWX%2BEVbBqv%2FaXeK%2B%2Fo2e%2FVtOX9wOO%2BpOEXfvZFLhAwBJwFeaKMBf9OwFq1tiZEU%2B%2BcuDXHhLTHCXeM%2B1KGjLX8dm4zOn4Eb3pZ9YWMEQqbSKVFdFacROYjCNa83a7E3kor%2B%2FX9uPuirmDUtVNp%2F3jo9P6vJwP9e3qlYNMXc6D2ZzOxzo%2FG2kyxdcXzIKWrLQMjWjGq2mh%2BXilriJy%2BL12h4FWi6m%2B%2FeZc374609l8qGKASrd0lNx8Uuh8tNIy7zTLGmsOp91BFxPpfEWArBA4hGCpstVRnueqpjNNu3N1jx%2F0%2Fu0Hfby%2F07Sp9GoxUzUcqt7vtN9uNCwKrc5mmszHFliAr9H0jaZTTQf45w%2FU1KUahIPeX5mIzEteaNxpmFCEHHwInMVRtK8H2rWF9tlYpdMZsQZY0lTKG8pUmu4qkUZlAYPZIq8k3zZiVYJc9f6RvXiL5eM8CkzUg1SIHCyH8NrH74CtwFd9Sb6PcBjgQ12sTgo%2BdQJFvJshAOUeeB4ahZJGmImeoboemIBTa29dc8KV%2FcPU9vPX8wx8ZTPwzGx%2BZQvye%2BoOTAvoMNBgj5T7EfbIsUeYgdj7UiBlX%2FfF%2BtdAyaaSEvLl2jg6jvZ4LwgmXom7MEEYmqLNgvkkoF%2FtfHYdKlQj%2Bv64oNXTRk%2BvnzqRypwQLCeP%2BjdSN32IWKZpqounfRuppDUlcdA0%2BGB2lTbrtX74y4%2F6oIOjyE4gTjpyMg50ebbSi4srTaczp%2FX46c0HXd8%2F2swPv659NtD9odHb%2B0ftdzvnP0M6XJf4LxLEIbMkez6b6%2BrqpfO33T2u9R8318qbxprNUYbGkABAU52%2FeKnJ2Uibutb7m0f9%2FP5GHz7emeu4u3vQtBjofDY0EURUv5vbe73%2FcG1t6ngy0WQ602K11HCMr2JnhtgxS4tcy%2BVS33%2F%2FnbLRRO%2Fef7SWiLVBA11MRlouVyoG5CAdRHJ1op1yDheYxWYqikKT0UAFDHJbq97tHV1yUCDlL5Q%2FBRGJVfWBnWCAdehh6WT5Pltb1uq3%2FsV6GiosdQAaj39mmnv%2FzCxX1ZQ6lIy1h4fTtnooim%2FDcU%2F8nBY7Vn8CV5%2Fc%2FE0%2FqLL%2FfPlC35fYayaIessDe3%2BheQiNV2uvyWMN%2FR5w7fxI0pi%2Bxmj1WN5r4p58fo83Akcwj95KNksj%2FQl%2BybnGo5HNA8f5RN%2B%2FfqVittSmwZcrt7Z9lJU6n2Q6P1%2BayYPRg7Ddbg6qDo2K%2BkLTi5mZ2fX9Th%2Bub%2FSw2znPCsQ8JttZ3Wr%2FuNfHD3cWblxdnOl8NdNyNNQ0y7RZ7%2FTDT%2B%2BdaP7y5aXOLpd6NZ9qd3GmzbupDvudfa8L%2B42FgAR5A1r6EqaSORqNNV0O1I5L4TaKVrUd5JrOl8oGE7XtjdqbraM5G6YSXAQ2Os7s6Qx%2Bcf2rMBT%2BmvCa4Czq5D%2F%2BYMiswWYPnpiVxmPKJPj4orH%2FzBv9QCDKuWbCek1P%2Fyy17xQ2AUccAjCAPROIVQVMT2eKqD%2BL%2BD4yj7wTcxF1HGG7H1%2FMk08d6k7wmmoxDNYp%2FQ58UzBQCD8b7XZ7bXY79wETT0z9CQyFKwhCMQSHOyIr1%2BDnQnN8H2Yjjcb4L6LRL4RghFyh7z98sNXOxYsrXbw4c5C1b18stV%2FP9fhAqpGxvr%2BY62I6UFvu9PBwr%2B3m0Wfk1YsXWp2d6Y8vVqrW52o2j7IlAAJPBDBZq5Io2ncPwuwXixM0lUTQvZqPdTMb6Y68l03rnLcIIYbkDp2MNTg%2F00CY21d69%2FHR%2BUS%2FeXmlESbpjLGqtNk8aF81jhC%2Fk3S92evm%2FtY5nYl0jWbdprsWdpD8KneU9EM71H4wUkkoMJA8EWB95od1S0OE7MTs2QgXgWSGSwnmuXyIoB3YKPYRa9rDUchbLHd5wk39Wvdrz3cPb8dnvsP%2BNN7HlJZ9RMBDaCOe0tcQtLom48d0P51ECdpcPbDEvrRmPeHSONlO%2B%2FF8%2FTwDX98MPDObX9%2Ba%2FI56xNEcKPU4qB4hg9JPiHGYgsScUsKljjj7%2BLrrg2iNh%2F3xTwGjaP%2FzeasnpUyTwPDUapKfRF%2B5zyhX5NYTqufGUboYZb%2Fs2Bd3%2BipS5fH887lIddPzJKkc5JmmE0xjh9of9qqqtWrM5xSBRcqcHG2dZtOp%2FWkI2HH%2F8KDr2zsVk6nKTiqzXDsY6zzTYjHzwY9ZLKHoz1dTzceFU0Zkk4kuL1%2FY1O%2F2%2Fl6VtW2NNaUcvGgySDy%2FbyLsfU3kWOUuR3Clw26n99c3muBHOjzTeFyINCy7slKXDzVbnWuxmOv88lxnFyvl40JlU2qz3tiEaTA%2F02I20eshfp5TDUdDmyMS7AcmINNQC%2FzfyN8GA1qW2q3Xdrci56gc7AGiEak3IJH8MutWLQRxk6ncV9pvd2rrWsVgqg7CPR846AsMbRCorE6%2FYKfXafH81T%2Fv732x4qlUIk79K5U5qZJaemIGIrNpI3folwQDL51%2B%2BPXlfkot9J36p777EfJ9Wm%2FcP71DM9E3xsLzum1sTmvGycxPPDdon77qykKw8oudjcaeOtDPVXzTVuTl9Hp5w0YgLBP%2ByTQ0HxYWYjRjtC34lREZEi1mpeWo02xCWonQZhwOpW5uNsoLcnAOtJqMTKzeXD%2Foxx%2Fe6HG%2F1dnLC60uL9QRrKes9PHDjf7yHz8%2FweQ4f6ml91mn25t7%2FeU%2FftChKi3omQz%2FpPPzla4mY72YTPRQlcJHk%2FQXRPE0gTsq1IwLbdXqNjE99%2Bu19zUms4vlSsvlmc6nE3Xnmap9J3jgahtBTZ7m8QlNnU7409PffOE5TsxkT8%2ByLO4vgdr6veIlptGATOvsjZcDJn5zg%2F9wQfcqMYABOHTJAqQ0BT04effQN3OXsUcpwk9wAHuRsmjW0GjFTgt467dhxADghXTfe7nvfGow9SbuHqHXxrhdHaa0Gbliwa7BnPdMPGeSBWh5ppqJbyvLZophZlaJiMaO%2FAoDh796PnBMZIKlDdqwXvnhh5%2F1lx9%2Ftnbsm7Kydv3sfGmByMuLuU3Lr1YTXc2HmgwabQ4b1Zt7leu1x96tFiq6pXH55XKq%2B%2BVUIzSLjkoulXWlx7tbvfnhR93ePeri%2FFxD%2FVGz0ZVmxUDL8VAvV3PRs5fnZ1oQHA5LgmxkawHSe%2B32wTRy%2FDMjkxF%2BnVjloCVHY9k41Q9nWQXjamHMQG3dOZAX%2BJt7DULjDPY1h91W1fHBhcLAmqJCMzvssyPjGExkrm4wVNtipju0QCqtiOEgVhMo6P8C6vl9hKn07KlQuuhV%2BX6b96Btkqa8DWEr6%2Fj0miEKhhQmku10bIsWXM6NppZBduSFBht6v1GKZ6c19v1%2B%2Fn6ega9jBp6Zza9jHX7HvYhj%2B3ME3ZMjcWz3SJJSx5L91RPuTk%2FjvkNYnCDiX8e1fa3xDYpO5lQO3hNHD0QH6Jv%2FT4%2BYX0fg9Dx60ve%2BX0TufnoGUCJGHK0nHocXOFgIEOBou50mk7GuXi708mKiYbPTsBlrSiRamM2u1mjQajqb2F8Gwn5A%2FszVUiuCQ0wmwmqwGuSa5SOdZQMnYd9tNpoXhb49XzogxXyCxi9JU02AoTVZ6FVRKHPUzggU5CQheabhfO5AFIMu13Sx1EWTa72vdP%2F4qPV%2B58iUTvyObw2K4tFEZ5cvNaJv04kWlsCPnAqiLHd6fEBS3WiKtHeGz9BYF%2BdLB5oQ%2BefwCyt3UjvWZFRogEyiIcXFTuV2rZxgLVo4sAXEGUPg0A2mMzfjiYmf6TWk4VXpSKH5iHQXmcPfM98QmLEqseIBUaer2F9%2F%2Fv35in%2F%2BnN9H2OgJdt8KIIw%2Bp%2BBR9kV2FdQLURLvxnXATqjyDEZPJMVv6cUv9exv3XOLfRc%2BKXzaYn%2Ft0tZ0oe3yHuJW8oXuO8utY5WW%2BPxqzd4rfWE3439i8H2FvO2FT6ZpKVARflhoDrZlrcdtqXWTYFKNJnntVCLjfKpiVAjhCYKU%2B83e5tTLxdI%2BbiQ2uX9EkHKvbbnT%2BGylDn%2FobqDtvrJP28fre0c2nUynWq0WGo7HIuAT%2BRqv7zc6HPYaDId69fqlLhYrzbJcq%2BFQDRpYPMQ8V61qzBLzTI9trZ%2Fub3VbV%2FZNvrm%2BER%2BI0peXL%2FSH7%2F%2Bgi%2FNLXc4m2i%2BXul9UWh92OgRl7bnop%2ByTif2VH79WFvwEvHq9TPz2XrjBxHGffRYMWY87ey6Xp%2F3nVxr%2BF97mXKC1E8A6tm6inYfscHSMIdjsxw29zrWNCiiV%2FG8jZFiCLR88Pd7%2B%2FF403tcXw3JvXHG6is4FIoqe2FI6or6yXzBBDu10ML4I1mxs46QjpGOCAW5E9GKeEWeAPgPjBLjDH55CDZHcHx7145u3ent9E8GsRjcaLxcaTcZazsZazQkqNNbZbKTVuLCFCymtG3IrY6FKdO8p7gtoUyNa%2BWqJD33oaGHiCTJ3f%2FegD%2B%2Bvrd0s96Uuz1d6%2BeLMUcERPH776lLL2dLweraaOsAb7h1oRcklM55PVYxzW53k4HeCDSmze8VstdAAH%2FBBbu3dfnzQrJVG%2B0rbZqeGVD8wmwi0EtjB0ltz6Gi69iwx8se1o18H3Gy4NmwnvGFfZ%2FZ1ihSLRpT17PE1fYp3aIErnvafE0D2S31L%2Ff347X%2Bd1zUg0dDomyfl%2FRy83wtywp86tU6PDDvHN7jqf%2FXffbvP388z8HXOwDOz%2BXWuy%2B%2BgVz1S7lmyfkiBQgNpBwIGbwbK9LHxhEajBv5NZiyW%2BIWJrKPb8R40xGfIvm8ZYjTMJONgclHesQtSZmFjkCLRj2PQB1rse9Rf9f2P7%2BjVl9d9qePzGG9ITekP3e1ZziC6%2BWVmk9Qd04kuXpzr1auZhk2tiWrn4xsJM9qKsAgaFwMnnoc4GOcjvfrDt5qXSICR8Haq0dzlQ4ejuL170Me3pVajoV5fLvTyfKYJOQa7xpFdr28ftW06zRYLnV%2B90MhhDCt19UFNdfAsDMZjH%2FD0HeJgPJvaLCob5r4ek4JlMhIMp%2FKhpsuVpnOIpwitjwYZ4jsfhcay7WoHedhsH23q1I7DrAhJPhrNujyoKqdSt7C5Lz5BaHPbqnRaGDSoM8wWx0MNexNoGLcs07DANw%2BTqEKjQeF5Gg4LE0%2FOf%2Bh8mqxGmNF5QQxCAXvHdetXsv%2F%2BRw71vrZ4l38xKyPgJYgXbSz%2BucAjJXvoj7coDSGZ2k17JPLhUfKX%2Fn757i%2BV%2FPwebx7fDpjt7%2FU71u%2B4UDzxv702EZNlD4Yup03GC2kKYnzH4XzSWiL8XfXnHUu%2FeUYd7Ff2qaelJybtu9k5lRHMY11Vent9p798uNPtgWA2EJC1pnmt82mu%2Brtv9O3LFzoQRCobOqCWtZbtQKQaQWMCE0f%2BRfLWtpjb5ezAzPfXu1qkrMkHmbZVo03Vat7Qvnx9IKJyNtSmbLQ7NPZzLLqBxlmhMVp4a86s71CVdXpsKq13a33YbzUaT3TYHXR%2Fc6v9eqOsabVbbzQe5FqNZ5pNFjqbjHU%2BmWpSVLY8CBI5ZudXpu%2BT22lJPrnHD3Bl4KJYcXyZkzdbEOnsf4IyERzmCLQBwE%2FQE6v419byi4b%2FiRv9TjAT4YGF8MnjMbRwhTY8Nhkj8xitb4qzhNeItMp6Ymfgv2T2aAEUtzygnsHhR4wwlY53%2Bn%2FpzNMD4JWTJ3JR5mAAM4uYf3f2OwQX5MUgtIdtrbyuHfRs4JzA1NU6QjLuBDCa9lNMsEVUYgKMoZcl7yZm32WH7%2BZA99u9ru8e9OLqQqv5WKMi18TpQ3LjeX5ns4mFduViZqYcLSYWH8gwwKej8cjmvPbNBsbLRustkcJLw%2FZgu9ee%2BAcwq23ncVxdnevy7EKLGfBKFPlOu%2Bqg%2B4d74WM8m0993jAe%2FJTLqiTMsedlOJnY6gAmmj6MiqGKQ61sslH1uFeZguww1cYFtr9JeXjxHSanNtJJM%2B0w7jDqfBN0sMM9OyIC25KISlhT9nz4JHupoQ%2B46BnUtK6x4vybHvbrzffTevc3gbSANnpKfbDsjAutNK4srs%2FGNUZQftFMszsRVfLOsd1oiHWh33wFHHIRpfrWn7%2BfZ%2BBrm4FnZvNrW5H%2FjfsDugs8yXFugWsaTXoCgjRS9j8JP%2FYouT86Qr7X%2B0%2BEOSfVJCbTNQZ5dUSwiRKnVE%2B4JymlpZd%2BG9k2B4pPUWvdYNr2XZNMmoIB6bVbPYrvl8OIPXU7fX2C4LkXvTpF%2BvTLLcahlo7H4%2FtcMa4g8jj0COpAlL9ilNkPp8gggiJCLIkO%2FIHBcjL33EnIiQA7HHcqERyjog3bMPs4QsSgHVHbOEE53in405CX7HGz0w9v3ut%2BV%2BrF69f65vVQRNvZb9Z6uPmo3ebBzNrFi9eaLHNtq0wfbh71%2FvpO1zfX9pFzLtTV0vPJHOFDCVO62%2B613WxUlQcNukqLSaFXl0v75yxXK42mndYO3lALzSsRBd%2B8%2B6CP796ZmX6J2S3EzhCGMhhXJPmcqdyzaVfhhC%2BeVZh1%2FhxohQ60nQMKTWcjmyUTpXGP2WJdWwrOPMMMm8GzGSBLEdRFT8D2a%2F%2BPf0Oqx5%2BJYcg5Usv4w1QPPYc9rAG7QZbGHRM8Cab7PvTQFYQGd4%2B7LrXUF%2F1N3wGBp2%2Bm3vQN8QgwTn6ScTs9NAEF8YYpXIxlV8U%2BiL0Qo%2B%2FnoOebo8%2FH7vG8H8Xp3WP50%2F6FNg2CuGvrCKSBSR1xM21CLu2bRh%2FuH%2FXnN291va3ChK4lB2ep81mhBRE8r17av6sajNUUE9gNaTRRN0SD2aktBmqHESnY2keEOKwPgXJyzMlhQjO1RIzNc9UIegat%2FS7xvWwQ%2BAwGqlko4NfEZdLAwD84KAnwMRBBYEgdk5NQvml1v9kIM9qc%2FdxJm81GD5i5lwczmwgsbJSHgKWfvOPE%2Fc2rz%2Bc64B0cRK30LYR0IdgwhjKzBNM0HAzsF8uaW9AHbMBo8Nsvx3ffLepO0PI3%2B%2FX3Fvi0bs9IIvD78yFqDPgLpsJdTLxgL3xERobgihRLhxYcQy7J0NLzrlNFpc7599OIfmlk3AuXEB81xjBG%2F2Y28CNsazSbAzOFMIaTQaGRfdthCKX6UDl3LJYkzCtRYpeLuc4WM6cnwT96TcCbfaPRiPQdkHHh2wn%2BK8b4%2BKLRJ0I0eyQJZ%2BjBiTkpdTMHmMbuCCbXdtrsdxqNDxrkI623W5GCSlluxhihDZ8q5bTMhuOUSoo%2BpPllMjFvJTo1FiWjwmW4vrm9tYBzdbbUi6tzLdG0DjJHcd7cPdg3dbZcKZ9NnZ%2BWdF2kQuOc2uz3wuS9axoNWpjKTqS%2FIiVX3pJjVxoaR0WKLtjvggjU7UFDlRp1hZlOR35Wi2eng8rh9QmEBpQG%2FLOCn34CgrgblA3AcLr2p9eGsE%2BhxfiT3dU5R%2FSUM42AYMafQPGxVtMvqboQfgOs3OghL%2FoS%2F0Z%2FU2PPX88z8FXPwDOz%2BVUvz%2F9%2BnesRZxz3oMQeEYe5z%2BmIoO2DGQyinIPPPhiJcEHD4AMO4srCP4h1PIOolXp7rBy1Ul0gYb45SDnUg9mz9BIyADqAfJXTieaTkUr8ZFRZEsw7UWfPFKfefiKp7sdzOpLoTbx7OmbKxIw89cuMZS%2BV5DH1MTdERu10qBrd3O2VI5ltSufZRKcydMJ6%2FL0azce5zmHwpgttq1rv7vb6%2BHhwsATMapEyEzQFf8D9du0gQoNDpQ%2F5tcblXlfLhSbTiTaHTh9ut%2Fr5%2BoHyWOsAACAASURBVFb7bqjl2YUPRMykfvzLX3T94Y19Q%2F%2BtzXShkR72rX766Y3%2B%2FOMbkYLk5dWFD01yGJa7zoEfykOp9Xqju%2FsHPTyuTSDDLK6mQzXlQZdnC43HYw2nhRb5UOs6EyaJb95%2B0Jt37x0E42I%2Bj0AZWfivst5oRx1VFEJeBCqpdDhII3Pi%2BOQFw44pFITT3a5RPV6qaVEdxlqZQcFXCmad8pZm95GKWSfgJcp%2BzuicrvZvuw6YBu4Mu%2B4DEEnkx1oD1hEYnM4Ny7QHpJIjjj64eC99NwxFq5%2Ba3HLvFN7SQH9bB78o5bd7QE1Pn372Qhzup%2F0A1LM2SOrns5nH80CyQjYZXFIikHgF2D7uTleSWogtZ1zQ33HZ%2Fkf69vqyXQKPZBagwHCihelsvk2akwYz6TxTlQ1UKrfJNNp2hC0VmpkOpnCkpihUZkR7LRxgZDAYqsoLVeQbJGpogYVAp4MqrcutttVBo24SZtjpft4NVNkMlnaCAT10rXZNaficdGMzqF0BU8rKD0yo4xtN%2BgX2Pe0u5istL6509eqV5vO5fvzhR%2F07UTbXGzN3F%2FOFLkhNNJ9aM4S5LkQ4eQblxCnU9fesfWC6WFt0J6xMEK5eJQtfuApMazN%2Fr2uj2Wyk%2BXRq7WbItbAQAA4SuQ4%2BY2wW3MS9Hq%2F%2BPT38bPV%2F4Wcasxn3aLM%2FGU63RAjyGF%2BUtxzOJt6x18EaCOiWi6mmo7XW2zoimdp2PxinaDydaEyLBxK%2FP533%2FhwARtnrtMp%2FiDlDBkh%2FSHlE6o5dU2hTZ5pjoTKf6fLFpXabte7UaL%2FZqS53yotCy8VKf%2Fjmpb795qXG04k1iXebvaqy1Wow1KAgVybpoWb%2BPB72IhDRaDTWxdXKkV%2FREnKWYgoO%2FCGYxPT2w9293r79WY%2BbtfcWwdxWq0tNpkutCQT0sFYxGmtJUBuYSJjJYqRsMrUmE6EMAhUiw8K5HkhHcnen%2B5sHp%2B%2FKXr%2FUfL6I9CibnX5%2B%2B1bn65Wjk58vFhoXI0ffvXl%2FoyKH4Z9qPF9oW1a6ubnVj%2B%2Bv9dPtg%2B7vt%2BqcW3mkOZGnu8wa4KKpnD8XKyCywVpT6ZOf0EG1Rt1B46zUqM19do6JNJ0Y0aIrzaQiqIq%2FEP6AfgzbsUGSgDyBtQtS%2FgkQ0rvp6wR3xeuhTQWpZ6RlKgaaE7E6R1D6BErG%2B3TDAhAu%2BjPAiDFJRxJTGoJG%2BnD6%2BbQbz7%2BeZ%2BBrm4FnZvNrW5H%2FrfsT6LU%2Fhr8cSiB1SnEM880xbJmfo1siTSZ4S%2FgEwThYk5CksdZEJTMaEPUpso2Wo8W%2B7mA%2FaIf%2FojRn5Yjw63MSWo90%2F3hQ3o0cJS%2BYjyC64jBJI0iVH3t%2FfNqj%2B1SyPz78s%2B8T38e%2BfPrGUxmixTZyNMGu2uvju0aDeqtxhvlPrUF9UNHuNSs6vThb6E9%2F%2FIPOrka62zT6P%2F%2F9Z%2F37zzfq8nHSeBKxr1aH%2F6MazQaZ1m2t3fW1DlcrDf7tj7qazFRlherBWPu20OOeYBGtA%2FbMFiuhfVzfX9uflDQxEEkw6Ui%2FSfvAPSJrPtzf6W4oHYpM1W6r3XZnaXjZtMqHQ41tSjXWoK307vbekvPz83MV46mJ%2BYey1d1653FvDzUOn8pG4zAJhsFgwfg0uZbnl07IjXbFTGVZsZgOhARsuG9tq82%2B1N0jIZImOkAAVQSDgpXDhC20nqG5IMA8xDKmXknr%2FQnXc1zVv%2F%2BKlU2EN1ddpIUxtLeErGk1GyPwGFvjHLshQUrQGskEPOCW9ntYCTjse%2FTpr%2F7u3%2FPd19DX%2F%2Fm7x%2FvpKhFC9BlSmjQ8s%2FHYn2LdejzA%2B3FM1His5fNfbr%2FvxOeN9797zVki2tGImMWxuSM%2BXKGjgIgu0RYOELrgj0UFkRA%2BI1hQNnQwEcNFhyZroJ0DYDXa1bV2TeuAV6PFTKsXF2oec5uIo9WsYBSShhOGFsEOmlCI7QMaH7Q7aEYLNEGN6oJAXdLagU8yHdCAFiObuKMJBeYIilKVtUbFSNPhRIvp3D6am4eN7vJrz%2B2rV6%2F08tvvVMyn2pedtk30lTRFMAB%2F%2Fx8vxdrFu1HJcYUQhgUDCRNpTSomipk0m4wNs9bMpIb7LeNanipJHbO%2F39%2Ffw9%2F%2BBu2cfn7tzYBWiHkzJPQzqHYRkGw5n2s6vlO23R%2FzYR6376fQnHAhc8TY%2ByEDkf7V3%2FikZ9FHIszio0nIn7tNqfd3e00mQy2nhZbn5%2Fq2ru0isL67Vbk%2FaDgciQix37x%2BpbOLpVMm3d0fdLPeC4ELpttlQ6TYTKvlUn%2F87hunrXrc7W0%2Be3V5oWExclCe2%2FudHu82xoPTRaPhMNe2ybSuWj3uK42J%2Fj2ba3FxpclsqW2Tq7vdeM%2BQw3nfZtrWnTZ1p22F4IZzGlN0dIgw2AP35%2BZu7XQtj%2BcrxyAoRlOVVavtobTgczIlxzWRoLEg6HR%2BdqlRR7AeAt8tHVxov1s7ENebn9%2Fo%2FeNOVUtO5bHGuEkMcse8JkgcKY6IhJ6TZ5N9n9aUGR5mueudqNPZBA0yqcNgNts4Ux2fAEE2AsEjtgrYDzhi1fyX6g1YM%2FCE0K1%2F%2Ftl3DwKGCATeLUK4xm4e%2BMVCg3BmITxkpwWFErAUuDPA0%2B33lbnZ1KPUhd8G%2B5917vnn8wz8F8zAM7P5XzDp%2F39qMpiUz0cchzSEPlJF5POWura9qStEIXLJ3OaePCckjBEyEUfhF%2BxX0TOGn9f%2FKQru%2B4C0EjOaSZ5rNZtoAaF%2Fv7UmgxQZsCOByvvvqPcJr5t44FDqsf%2BX7fZ3%2BhLUZEH%2FCbnN%2BxApHGrRXm%2BLhkmd9Lg9aNeVGnYHTYedirYMZrM7qCrCr%2FOxapVXnR7rTLf7Vje7VgN8Ig%2BNOjR32Li1mL3ZCkpNhZle41yTu0batZlKovGNZqrzia7XB%2F344U6L%2BUSr%2BVKXL15rv310xNmiGJrowXyp1xDzfagq3d%2FfawLBMJtoOhrq4moWGkMSzduPj3cL%2B8yVu0ebL5HmYV3Wut1u9HG914f7re53B5VdrvF4pMnqQpPlubpiZCKeNcNkMRuPNdaZ%2FW7Qthyqg82php5jzCgbS9aRrvMZQyCksPqYggVUwG8SCTRylVl70zN3%2FeL9C79Z3%2FgACTCZfIDsysncEXg40iPM6FO7R%2Bjhln8FoDyN4anoP3lBtX1rT02c1Nk%2FeyKATnuABgDztQHS%2BrEmEFAQcFmkz0EDzWg%2F%2F%2Bvr7O%2Fz%2B5fa7p9%2F%2Bp3eTi%2BgBXYqFDOXREommiU%2BeoUjIrOnvQchKLNC2XCqNh%2Fa5JZVaPOxVIytUUAreWhhNidaXl3ou3yg6eOj0CYV06m1Oo6QCbwNR2oLhDUQuAMzmjCbTV6oLYaq60Z4PO9Jh5LJvmZrZdrlhfakecA8EgEHeA5l97ZUuSuVr6RLInz%2Bz0K7779zDljSDw0XC227gR72pT48bnS72zq4UVOMrBX5Eif9rRk9fR4cU9yJfyGEMZXFBw5NLxkJSR7BHsciBIsCawlTYLMeymOtgoj%2BfJ0%2FXcd%2Fza%2FP26D3wVZSf4zlWCb9tsASnBvm%2BfigLuZTjUknkiLGctqYv0iRQfu6gudI9RiHBHzHnU%2FHdLzHFSlOEveK2Wsu3W0O%2BuHdjYa0ezXTYjy1O8Plaqlqv1NHBO0CE9uppvO5z8S7bam3t2u9v99YO3ZVEZE4s%2BvFopjqv%2F%2Fpe51frLQ%2BlBpOplot5m77ATx7u9b28aBi0mlRDTQfjjRaXeplUejssLffKqlMRtOltZ%2B7ZqBti%2FkpeDgXeJZI5%2Fgj87F5ORYBGclXcpuGg8P3tbTZ1xpvD%2F5e4UdNEB77PQ%2F0sNnr7YcbTUYj5WcrrUYTTV9MzICC5%2Fdt%2BIYeDrWZVIxabKuNpUKNT3arfJLrfDHRf%2F%2Fjt5qdXYRLBnvJrhEWWYv0XaOu0USlLWvO5pPw2WRtHfyqUWb%2F1rA4YSWBFU7l%2BC%2FWk7OOv0%2Fh6PjruOrcO92JYB4izOL4HZGIwS1YtABr7J%2B%2BHc4k%2FzngXbKs%2BqwJ%2BvEJ9QFhkc6u6OER4o59er56noGvYwaemc2vYx1%2B170IxiqGGOg4TJgiKXgwm5jh4EeImQ8EGPJ0TM3sI4ITPQynkS0IFSR%2Bglh7k5PAvScIuW8t3ucwsX%2FZMNfZfKrlZKicgAxoDrthsLOYwSC5%2FuJwAa9HfcbwHk70gbu%2F9He8f9LXk4I%2BYBhTUDVm0mA5aiTGHb6aY6xrnWdvsVpoMR5oUrRaLmfKF2eqhxOVeaMqn%2FhTFDMTzWG3yeGGZxk6zkaz%2BVhnq6nOXpxpMFkkoqFQOSAR9libfaWfPz7o6vJco6u5JssLXb78TofdRrPlmfLxVKordQMIpZHaHK3jUOP5UrPlueYLmNS5ZtOZo95AlB9qiIbWQTcIf79anSvvUhCg3V55WyirBhpMBxocMvsyofHJpwtNzi41mEy1I30JSwIBsm%2BC%2BMZUGL%2BqjoD3uQMBsTZoqUiYotFUxaxQNhopa0hzMfwkaE0wm0Q%2FGdhnyKsKA5pMNU%2BW6J%2B6jFWHcAj9PUGOIhFHpTyrnf%2FubDHSuAizLUCPdxJtExCYQCdgKSCw79QvQ1X%2F9Ld%2F%2F1o9R%2FiNuk5%2Fu68wyJ2c%2B%2FV8PtFyMnJADrTYHdpbUjxY%2BxYUkS1HT7rV10f7XP9aP05eebq0oAaBhnEEbDzCKZK7yxoYm9BmwAk5IQf%2BkJ8Q7T8pEna1TEDXA5jGsXPurg%2B1HiCS553y6VjzwZXqEXuqs%2FYG5cQajQ5sVwHTit8dAYZy7TvgNHfAobIrfO%2BQFTpkudZtpk3V6b7JtNPQBDzm40MENm2ufSmV652GoztNpwstz2Y6v7zQWXbh4CxVJWuTDrtSH68f9PPtve52ex26kTXz%2FTwm6Pk7Z%2FJk5i0AM2uezAghlMGNWFfgK1fb9xrciTkg%2BNQE80kVx1UEr8W6Pi3av%2Fyihxi%2B%2B%2BtjI%2F1u8fz4cYLDVKTfb5iBny%2BmWkxGdl%2BwUAjYRVhi7R01wHwyYnwjEQqSIxWTfG5ReZwZx9Y%2FHbs1qi46UIYZKjBYHfTmZu0osFhlfHs50%2BV8ZIuboju3%2BSZeAry7qzrd3Jf6%2BcOtfnzzwdGSL5ZzYTqOfybMKwJZNLSL5UJlG6atnLGbbaW3H%2B715vpRu32pstionWz1IitsdjufzzRPuAftNUGxrm%2B3%2BsuHB31cH7RYTbWEUa6lHTCej9UMp6paUk6NdBA5mDO1pWwaPJgsdf5qZpeJ0fxMNYwpJq4jhCZnlvuhhUQzanN3ArvRMAYsCIuaTvlkpouXr%2FWavXa31uOu0qDJrcU91ATDKzSe5HqVX2p6Qb%2FYzwqzdeBSEiazI4IrOT%2B1NJkUBhPmE9oCFtNWMyfMZQ9FPezwguHnaYVjrU%2FXOa4DRriOOsJVw5YsMLYtqbcQZOVazIiyPrT5dtSeqWXgOVQNZ38YpZvG6RtPDT79BObSQRG0UN%2FzL3v2fOd5Br6GGXhmNr%2BGVfjd9KFHxKeIL7R4kbg%2BtHlI6DiaHfodrZV9SeKQQTMR2pAjozlKGPbItEYkUd%2Fu%2F%2BHb1E1IpDFbDEQeL0NYcAoQjW42zAVxTE69UYZvYwQLwOcD4iKq4rh6OjnC%2FPLp2GF88fxLEuPXFvOUPe6PmCiLLJS5oM90MiOhN%2BZ6RL9EszAa6ezlC333%2BlxTNJvDXLPZxAcu2pBdV9jkadyRDBytMZH9bJzswA4EE1pcXurb71%2Fq1cXMhzTpFrYtxHPm94lke3fo9NP1xhLui%2BlYy6vvdI7fy3QuiPK985%2BN1A4nwl0smy704vv%2Fpu%2B%2Bv9SUvNwEBqo6m0rdbyvdbw7a7A4m1jlgzxYTLadDzch%2FeL5QcSGNyk6Tx726Nzfa%2FPCzDvu9Srxqcoj4TA%2BPpaNzVuQt3O4dxOPqfKU52tJmoNyBHwqbIx2IJgndNZ9oNupU4oPXtDa5ZZ0gFsmvyEowTyRLh9iA0Ot9e9Pi%2F9oi%2Ft33bT7bwWSGdgjBBgz3JJfOZoXOZrmDgoTeNe2bANnPZOTRdJQ43V9%2Fd5f%2B7hfcndRkT6AHEUUq9MRszsa6mE00LwY6VCHNrw2HbBVHkEmb6Z%2FvezCaVEuArAjo87iv9fZmo%2FsNuTBLfXzYWPPHc1O3CLKaTNtSendDqpO16rrTzeNB20oqy1bv7zZOw%2FCwK70Hqqax6V%2FFHrzbub3tbq%2F7XWttDrjiYdfq7fVaa6LOkkZli89mobIba9%2BM9P6%2BVNM9aPfwqJtNrabO1G1K1e8eRNCqu5utbjeN9rtS%2B%2FpWzWCqqxetCuAbX0%2BIaCLebg96eNzo5u5BN3cbWya0RCs1wQkTFUKr346PTsHg5C1rgPEvQ8IHgV85AAt%2BbtO808r7GHPGCM4FFkQLGqxV4C%2FXzL1%2FfqlPO%2Fl0TW%2FDB5hbp40glUrtpq6EnumobYqtxTuBjwnWNcEEdT7yZzocqK5hQ4gWyxzUEQAJhs4MylM34jSAkUhuHk9zwCaJhlyYNYz2wj2EiL4UgL94PJT64f29XQ8e1yu9PpvobFpoBH5KZxjMEfD95uODfnr%2FUUQYB6%2Bs0BSC4xBa1K2qw17r9Tb8b%2FOh%2FSh3Vav3N4%2F66e1Hvb%2FfutxDc6%2FbSrraHHRxMdd8GgFrADYC8BBx9u37G%2F389kb7stW%2BqNTdblXsSm12O11vSh0GI5VMYztwvID8zYOacqPt%2BqD59EzfXF3p9eVSi%2FkwXB5Uqx3NtXj1jXPSXl0uNT5fqp0U2pCuaN%2BpLsm%2F2diCIJvM9fL7mZrVlZo3H1W%2BvVZ9QLA6VIl%2FdEqtVGIVha9jAgN%2F9UJnvlsC5AG9kdOTpUBEyXnWFYyXPYSZPecC60IN%2FfrFOc3qneyQzwCAV6g13oluYDnT2AVlMMAyoPFnPOg0H%2BVaTgrDHLSIW%2BNVV4FgMnClQSb15thgf3Xso%2Fc%2FhaPh%2Fqsv%2BPz9PANfzQw8M5tfzVL8XjqSsF4aDkgUCbCTZmN25%2FQInX3oDvhI1Y3KptEeX5BDo7v7R5VV4xQXD%2BuNZtOJ6mpovyFSBhDJDVMupMs2oYPYAVn7gLdoPhC%2FSfV0RCSkDkNHHeNcmg8znc2C4SR3WI6vIEeSmU20dhCpwVDGiNKB4h%2F9UYCfCgP9dMyfr6TPIgvVQ9pvZodCTE6cMu4zvXXOMZsGEl22JYK7hmhkhlMV86VG48zRaTnoifz5sEeiO5SKiZp8ZAKJwKx0HaImImYSaXOhbDJTNikc1GR7aE383h8aa1s6GLV9rT%2B%2FvzPjVb9c6dWK5N4EP8m0Lltdb2vdHaR1TVCVoXbdSA8Q7Nu9hjDtB%2BnhsbK51vubO%2Bcc3JNYPB9oNh3p8mymVxcLXZ7NtZiPNZiMTDwQbGK4uNBgukF5qodSent30P1jqYebW11%2F%2FGhfUAhAcro12UhXZwsNagLB1MLLigiSNkd0tNBCdZ4LQmRThkkt5rT4ZhZ5YaICTRgTGYRgWk%2Bvxd9ez8%2FX91d%2FUy3aDzSbg2A4s7ZUkdVaoVmfjiz8AAnbf8eQBIGT%2BgNYJW0rd0ID%2Fqut%2Fec9CIVQ1J9AHdgaMTyIOPLgDTKbUl8sZjpsGkHyYtYcExxMfW%2ByfOzoX983x3KfXqHlJpASb%2BcFvl6tPt496v7hTm17EDn9YBDbbKjBcKo8H3n%2Bm6rU467R%2F%2FPnd%2Frh5xvPJ3kLg6nodLjf6%2F5h4%2F3FXFsDAlPAJwDFpoKt8zzg5y29u97q%2FfU6MSS5NahNNpOGEz3upf%2FrP96p0BvjM%2FAA63yzvtd%2FvL2LIFXkTcS%2FeTBRte%2F0%2BO9vNXlzF6khyMup1gGv1puNdvt9CE8QKuVYPTj7oglh4xQznAklfTplf%2FtXMimlHsNZU0uN9cOOgD3KGl0uZ7pazTQbDoxDMW8PIQlrYQj92%2B38kyVi1Y9txV4JxtH0vvdLUtO5LUqEwNNv8Q%2FrMIgUNKMu8rAi0FxNxwJ%2B212mDQFdmkptk8nGHJhpU0%2FbqiI%2F7wBcwnpT4ad%2FvuO9m5gVC0HZymjiiQQeUbO7wdgm4JuyUvnhQXe3D%2FoJH8T52EyJ82rWtfB%2Fx%2FLkDrPUQ%2B13CKzTDCJXLJYf67LR3fW9%2Fvy%2F%2FiLMTwdYveBjWbV62FcOwlPCeA3HjoJ7d%2FOo%2F7h%2BsEknweYwjcZNYr%2FbOjDQviSS7cDn4O5xr3frn3RoDo5ci0G1MqKmT%2FVY7vXvP77XT%2B8%2BqKv3Nl3908tXqoupqnxkjSNCGHzz9xoqX0w0uTxTvhprk7Xabvfq9o0O60aPD1shzCGN1pxo5IuJ6nysdjhTqXvtm1bbZqDHptMt7iK7Vg8brBEa7RsEjeHLD2JAUTom%2BitRybta4%2BFAq%2FOJ8kmhNRYw%2BVg1cQa6MINHFGi4tz8tyDaYR1b2uMKf4qtYep6G6RVPLWPpWjXsH6w7CmmYdRoXuVbTgXHkYog1TvTRLC7nvUEo4IV63bxNuBNsP4GYAct73v3qhSs%2BO54KPV88z8BXNwPPzOZXtyS%2Fow75zA%2FiBemvw%2F%2Fj39S0Dmd%2BfXev6%2FtHPWx3jqq6Q4K%2FL%2FW43RpZt03tADSTYaFhLgdOeHFxoddXlxpOp%2BELmRB1nA0JS3%2FG%2FPVHBHnAwOqYr02KgU2nrs6Xerxe28wHkz%2FQPR9rB1kKI%2FMe4T%2BxAekIAt33tf%2F1daN%2FFA1iKb11qhEwMZvqzzGI4gwj6E2lQ4MGpdGHu1KbcUhfOcDX%2B1bX93utD506zPoyiM%2FaUt6cU67IHCQIYuR%2B2%2BjdzcHOschxSXj%2Fw%2FWD7na1SP8AM1ZWe71fl9b6YERWNpkZIqTCt5tKb242er9ptCH756DQDcT0j%2Ff66d2jVB0cLXAP80oOOPtNQqAVTpFw2Enbcq1313eaFtJytdDq6oWKxZn9f67XtR7rgR7LgerrR%2Fv6EMyhQdN5qNURVRbNwqbW5H5vhjNrCIVfWopcNaVTSBSjiSaLlYrx2BL%2FD3d73T1uVdato%2FQyrawmRD%2BHuk1nrZ2AYf1ta%2FnXV%2Fr4lNr40BYmtPZn7DCfLfTN1ZkullMNk7adVY2VpXeGwIAxWwGYrEgw96%2Ft47G3v35F66eQ73HZ6ivyqMJ0ApZYC7w8W%2Bp%2Bf699hakw%2BeQg5mIbUUcQVadt%2Fdp4uN%2BP%2B6Q8%2FnYsXBNRhYtB4XylbVdpV9X2i4tdXAi9K9lyyGeYI2wYzczgwWBChEfLpG2A0GTP5xaKDXrGEobT1oOdA2LRbJ4NVQwnGmQjtSSqx2S4a9RVsIXAENGPhxZkmEnFBKCtHIAEBt1rizTIn5hZAgUxVwy3KQkMVmlUbq3dZM4OValDSVAVNHoj5Zhh5sw6Y2QUATmeJar8tSk9mcbTS%2BOm9DJbgNpAlJiRsoPxfZsMpKvlXJfLuXEncAujCWz3rfepUk7r%2Fs%2B5DukHc%2FNLw%2F2l4R%2FLsQJBzKOdZwycBxD%2Fl8uFXpwttSl32teNfWoRovAuZ4PN7tGi1ZiIk6c51qwf47GNhOd7pO%2BUI%2BEnbv9iXuhyBzYrbFJbEhpWh7a01vxQ7oUbp%2FNqtq2jDu%2Br1kxikwN7A7WDLnIpk0%2FZqXgI2iO9v91quyk1mmD6nevQ4QOZ2dS1Ig1WgaYRbTnw1Oqwa7RrdpoUeDCjXax0KNG6EmCL%2FZCpq%2FndqEHAMxga9ggMhGYWuUuVo7FlzMFk3W4bvb8%2F2LR9VGBpUOn65k7X9whRZmomU20JuFVunU92%2B7BVvW8N%2B%2FSJXM6z9V6Ts5XKbKAPj3vdH3DJkN5x%2F8NaH%2B8HKvdb3T08WuuLCXvNnoQRdqqsTkPSHTXk2aw1nRS6evlC48VcP1wf9HFb6bGW9nZsYP%2FH3mQcycD2aR%2Bxrv47lWH09%2FhOBYAU%2Bzmzn7HmUKvxIHN%2Bz2kx0OViosvFTNMC%2F9fItQz8pVPC588TfRAg%2FoR3A6Z7yOYb2O9%2FP3X1tFfP188z8FXNwDOz%2BVUtx%2B%2BtM4EUOd6RJIdmBiIfTUGjsiJ9xcGf2hL%2BzkwmSdnrplJZljarVFuoKwbWnrRoS4zdT4%2F2QL2%2Bb8Qfp0KPivuStIv5EYTnKM%2BEz8s3L650vatVHqQD0mzK%2BEWIT%2BdJeWI4o37qjnF5tU4u%2F9bq9UTdqe9a9DEYnchvF%2BbFEBSDfOgDZV%2FV%2BngHwyQV%2BHU48qpE9FZC9W%2F2rfOiZYPCDJ9NcgmQAsPZDXVoKn1EXVjd6v62MAG5Kw%2F6sC21qWSTIvyIMAtcVzth19RkGx%2Fi0yEmvWg2G91uK90dch0Gc3VDND6N3q0b5e1OXXlwLkYCHDms%2FoBULiP7oRIgIUfb1MlSZqTzDxVJ7LHBPKjKRtZArncQVCPVh1ZljRw85VKzJD2IALQ%2F7fs7fbzbKGud7MLrVBH6ntxr%2BUij6VYwnURIxNfnbr23PzA1mMGMSfdyARNBsSaNzlGg%2FbeW828%2BpxkTHzRAlIu2tn8mgS3IOXo2G1sjHGUSEXzCKwQNEwR1NJZgMx78zfb%2F2QI0448DqkSjZkR8CakT2iEYDz6L6UQIb36%2B3ejugEZ7KJhB4B3GK2o4mfxf7SBlKN1%2Ff1mQp1465%2FwjOAnMHqanEI39HsW3Dqot6oKpDCYhuA3gpWd%2FIw9mZy1pwERoNmGOYTjbnIiS1JNL7cQRM0NjjYazUzuIpPROaWJfYLS5rWCCiTxqnBdsTlhhQLh7eJ01XXTZ48FMQzADGa%2BbOW2tycT3OGaFaN1YYPCN5YL%2F4rW4%2Fgf%2FBffRAvgF5htWFvNvNDOzcWGLBMxozWgiJDEEBMmbevEPtvyPvfZLQw4xTTyJHRV1R%2F%2F6f3kS1xD7EEEItmAEYKbf3e412NWOZpoVZGTMrNEEVtirWHoYPJ86wEXUF1dc98xAusM6sXmYY17H39iWMzwfCssSC%2FjaSnVJkK0u4XqEs0R7hT%2FFXz4cvIErfB4J9hY4PNO2KbRrRo4uO0QTW4zsE3nAdHTQ2ewVgQgnaDMcaTAMcQLMKHiVbEUZ%2BkBiBdjb326aPoO6OhaapgAAIABJREFUQasOGKefmJ0i%2FGNzkGIIVwW0vW2hossEs6l397q%2B25hhxr8VjeW2rHVfbXVLsLpRpqrZO8fyHhMdfPe90aTBrtGwfNRo29hMGBPiTQ0zOdD1rlX7%2Fl7ElK72W5u5IxStYSkd5I%2F5wZ%2BY4ECtGc6iqzTaVPp4%2BKjhbKubTanrXaNNM1QzGFrQaryAxtkjB2YYHLPQ%2F9uvcMDT5%2F8Cd%2F6kqONFCvSDsIa4ELNxrqvF3GnHcOMB3oA7NLD8BTzSeg9H0XY85ToVjBupnDFduvP89TwDX%2FcMPDObX%2Ff6%2FD56By%2BV6D%2FOWhD7eDh0omqIpcliYYILafL13YPKw9658s4Wc12crzSdjDTGT5FIiLOZ%2FalO%2Bb2nk9%2FEElMWqNtHviWVMY28Q041UDeHAZFAX16e6eJuo8dmp0HZ%2BpCHCoyqYDgD0btGa5mi%2Fr93YXrixu9BWPb9CtojtBOmiyF4I4E8hE1GWHnMkDYk3n60Fs9UaparqjuR%2FQPZ7aAYmtkzwQhvY62odQ82ZXzYVaoxkcobDQcQuI02LSki0AAWsmngYGRaekMi8G2r9X7jSJQQKJTZtbn90ZB4M8eYeWVNpqzG5AxCLKWfMDEFsT0MAUPbmMlkLGhQs660H1rzcFC9pe6RaiTpJDEfztDNao8pUteqgECDmEFFRdiorNXugTykG2uHQlsepAH5Fkl8MdyiYCpVteT%2BJGk5zAB%2BnUFKxNqmBYCBsOkU0AJsUMc%2F%2F%2BfaUkRPNJqkoWHc80muF2dzXWFKPC40GnTWrHilnmChb%2F9f1Zu%2Bvr%2F%2Fmx582YvgjBgjOniiVEI8LUaFzSyJ%2BogAp0LTQdCPRLr9UuvUwf6Nb66PV79UHtinBL637E1MYFkx4Bf4IqBKFEg8pgVImEuj5ce0dqAcU2oI%2FayxOT94wbBhkGD%2FRY%2Fwh4L%2BhRFAUWG4IT9hG7DqmCa8YxNp5iQoU5gG9nfXYfJIyhvMEWNsHilaVCPEKI82hz2PaXA%2FPlIx8BNcSS5O0nO4A2hTPf30zeRtTNPfmLZfnMsvbiYBG2lSnfQ%2BCOXxULrAhPZsaabTga7s2%2Fk01X973b5o6199gwlg%2FtIiAATJ5zGe9BN0PBsQSzDfwy6YTXz40d6uJo%2B622ydvsZZl8B%2FyRUEP2G0VmZFEEb6L86UvoXAIKk%2FBkbmNUE5TAgFEGAAu5jY2%2FQXhhbcyDAIEoPpfcQmYA%2BRAqrD4sVMaWhJcT25XR8csRbLgodtZ0Eg0Y4P7ViZJsKv94BgF5uXDAFhRF23W4HPjFxtFdYC4HmEQ%2FZlR8veIE7EgiAxylltnBxRdRF%2BoJGXaueVDU0wAqZdnau631uoSZAwliUETgM1da0GP%2F4iBDSkpGpqGFfSlOQa9qlyEERWezOYBwc7QqOaa1MPVD6WGrR7NXXlAFpEnuZjbSxC1gZmM1Op0G7mLYxsrdu7gwa7zsHBNs1ApaMCc0ZZCiD8d8EpR3iJlYx%2FWehYuH6d0%2BK7PPfMKrbsfiJ0Rz20O846nU3HerFa2K%2BdlC1mNKnAAqUw6wbf8FaPb5kzN9k3dPLTYAKIfwU776R7z5fPM%2FCrM%2FDMbP7q1Dw%2F%2BKdm4IihjYzjxAGVZiacYCDJUzcjch45t0gTUJGHqtD64d5EFuayr15eaT6baFTgI5PZ94EyqVITFyGR7yWRPYYOoiLpOYymOVRM%2BEEktxHY5HI5tTYGs5qHqnZgDKTKkXMTgiA0EHEgBbY3o3tyKDBPMdw4huLffvboRz8Z0SeemKjoizArUakdUNGgwFtB5MIcQ%2FAyR3xIqUBrAzQthKolam2eh4SUqJE%2B3INo5GAn8AEpHyA0tkTxazrhf2UfRyhzE07UzQrQHpJ88g8SzKRx%2BH2IEHwgSehdJ30HK4kPJHkJB93IBFiRk6w%2B%2FNsaH%2BSFCCOSZYSYr1VnhDzKlKW8gzWmT02kjaB1HFzw78RRFWILQoZVbYQpMb2AuBl4jbKWOUN5FASjD2qfzpkGDalWCPQBMxFahPAVDk4kyICwZASQgtlIq8aP4EafVufLi09X%2BNPn%2FVpTc8COzSzrvYpB7SjIL88XIgDTrMhMiIQGKcwRj3X19fTfCXYST2OY72Hm%2BNK%2F%2FipNB1PrUScCPqhn1gnTMST1BL%2FIdLkc6%2FXVQtfbg%2FbbWmVnnYwZQfZQD%2FeMKmaxX42%2B6%2FGkH3V%2Fl%2B9%2B1kPzBheL5jA2X8TVQMCBbIVFN0cWMGIT1eSf64Fg5obmnUE1ZvyALihidhfaGvZNMHPRcs%2FcmhDEBBINp1%2BBSUy4x7ATXCk%2B6jCajM6MAkyjGdxk2YHpLZ2HwHRf6HKMh3Gy973i1OnrQBqBl2iPUrR1MjGnk%2FV03c9kP8%2BBjfpfLsY0GOax7IiUSYOMKLSViqzRfFzo1cVSV2eYAKKnxcONHqQ%2BJvzn%2Fn7R7tONdNGv4uf3%2F8Hfac%2F3GDhqObYRPTyONjAAaDbuUZI1x2Mf%2BH15NhP783q9026zV9fAXGJtAkwETIXJ8wmzjyAjuMSE63uMT%2B20Q5T1BJOsmvcScNDfC2bUOBCTboR5wBbv0qStgiJytjEikYGJvHxo9e76UWt85gcDlbtW22ymXUEkd2B8rHw4dsCsOmkl0ViTfsn1tyGE8dmWIsEC%2BzCbaOipwxpL43paxpzWCNWwzLmDmTxCEsxsrXrPCzUIMXFMtSAvzrpgWDk%2FQsvKOdGiWXW6IHPTjiY9yXKPBd9Y8DdR6kmDRuRzzoeSXLfgFG%2BBgbKcuQ93jc4ZNMNA1WcWa0zUclv4VGoR%2BpXkyqU%2B5nmUhJ%2BUtojIEbTBHWFWfwpV0AQBXadbjvXhNvsBM2TvH847amz2Ur3XbF7oxdlMV8upFmNiYitpkWN9ASvONeaixyWB1gJ%2FpGafNgj98IcX0xlw2qengs8XzzPwFc3AM7P5FS3G760r%2FZHrcRljhuQZaT2BejLyMA4LYZQGep7WrbbrmTWYo%2BFQL1Yrvb44t2YTHqQ37%2BqRr2lFfmCSloilOB64GYe8iU4fB4kUQrtpc87OfmZn06Feni307mGnu8NWOwIPcJhblcER1BNraXUgIGnLxEW0E4i%2F7xXlkvQ6EWT%2Bner59FDo6zZl4QOKA9sHswmSRKxyIPObNlH1QahSt4PeFD6cHaa%2FrTRSIzN9%2BNKgHaRcPoworNYGwdqUThviwzO140hEiRg20YCZFHkJmSyIWvuiwdRiWBcRXCF8IUrcS4LtQEVBBdiVCWKetkLKbBNhyltDUFrzSr%2FQfsI04%2F%2FDn5kHp8FBC5VpzDpgOjaEGCdCbxQcFGk909oeScfEuEPrmNBgnlh0yIGoA82VT%2Bu0hpZr9%2FT75%2Bvtt07%2F6aE61vt01RN5GEymCRbWFfNZJPGV5hPp5XLmz3Kc2w8Oz7s8RQ7uW0lTkWA4fnm0ZmYCVjzs%2FoX%2FzG83H0Q2bTJe4NDEGMGP%2BNivb6BZkTt1wx9enunDeqvb%2Fb12zV5Zhk8wYp8wpff28ejSHv1kzgOefmlIdMXtm%2FiFyAxNtdWOwCcEswlfElfCEHXK8SfzBu3hMAhsnM3Y4zy3n7MZPVrgd6qbOhPMhLqTeWALwoAQdIinaHt6nBDQgHkuWiF0SOwf%2F8erwTcaxhGCIMiiDgQh9MXMqTX43tyeIfrCi2ZM3BsWgZEdMZ1xXAILF%2FnknyjpeeOSN7%2Bw0GAd0sfMZqUsc8xOTYe4G4TZ98Vi5NRL3tVUw4Qnw8MQlsX4o2d9J9xo%2BtE%2F75%2F9s9%2FUdzoTX7ZlXv3ktucbbRJ7Lt3HZ5Ptj1%2Fq5WKsb64Wend7r7v1VntsUIdYvAyTX22sdUQwTUyhhQrMB7X0f5%2BN1aATwhng3xprL3O4mHDPEbHNuEYU4hBWBCxg5WJoNwNnqHDU2Kqsdfe481p0wmdxrF0xUNl2GuVDjYgc3mb2OYYxpB7YawfsQ0sOhvaZQzqQYBrZLzagzmHKaJVxIdxktSOidyg7mcDQwGZDBIsIXsI82FrYYmT3AWIlODor2nuCKg1aNTk%2Bp%2Fhzc7ZxpiFZjNMCzS70QZ4WiP5husu5E8wYe529GVifsyXwOXudvQFZa6yuzsIk1oZzgTrAXYiK0h7CXz8JaTEXp1bKPM09y2m8e4S0vl1m0h9bLyAAQEDq01FdW6vc3Ws6aHSxuNLri4UuFkRxJuVRYkyZVqaQj8%2FOgB2fp76kdh6GQJSrhA5812PxY8o9%2Fz3PwNc9A8%2FM5te9Pr%2BD3oENTz6mdWAOOSBAzOkwc1j5zgnuJ0Vus9kpjGgR%2FpUmQZMkOJjORF2Z6OmnyejYB4AJWuPgTxExv0Ibg%2BlUptkoN7P5DQEDyk57%2FEhqNHDBYFHetaa6YICORJZrS0de34dUPh1Ex18xB67mWNRXMFHWxlBTIoA5EK3paNpIZ9K3AvHs%2Fzh3MLsyxeu5zJz9utNwiLazwEXQzJ6ZRwgKEyyYa3VhzgQRgBYxG4hccwMkwEEFJxMveDRynjL7zEec8RzxEOkciqhgg9DspdsM3JxxWge0NZDdHOIQELmyYmh1AowwwVtM5DAT1pIFc0gUyAN%2BmA1%2BqrkGQ5jSMDFmbXtpvzsF8WyCPBarLwcBwnwbxvyc8R5XJIh4GItou19n%2F%2F5kjWKdP7l18sM8q39DFIS02mS4Q96HAGBGTrjzub7BbHs%2B0cSmVPhJBdFrQcITzEQfTRcGSJ%2B09v%2F9ZQ%2BzjLNnSuihZyUF1YKIJcjKfDzQi%2FOpvrta6Xq91%2BERU1JgAE1fcKvWpHis3tUnA%2BL3yfqkOeXr0xXoiUuDTDB7qb5gpCKypJm8VJ%2F7ba15FibmSYuIFQN%2FfVka4o7JeRYAs3uCo9h8NfBVnmNZEIocTCHxL2d8aPohaOFi%2Bv6yN4zqEhELbHIvJ09lv3dhdoywkKv0QWcCVgFYBDTeUv1EuMtHxJdI7jQOf33yT%2BzfI3Ade%2FdJsbTLYdJJz1NqavPZiTV9RKHFf9sMvLVjCNRC6MB6xk77tL7PV%2FLzp%2F%2Fa3wly%2BEoA268B7aRbsS6AYT%2BHZqDCtxpiiEi7aKBI23G3Ic0HUVlLdZhZwE6CU5KWGpzmuU2aZ88r6%2Bi%2F%2BI52ESqkM499A3PqPLQhuGD%2BOFc6gvEYXvBBDobTPU8wZMFVh%2B8wuZgxcaUvpPaIvJHW1BOFO8c1gef4LHeqnAlroI7IuqnP1IvFC3%2FAns%2BfBIMN4aXxby7GDlLFOrYk0UR56bEH8xP3YUJDuMOIQzibDgprSYkbgJsF2B44Bm6Dya1hghkb5xgaSvLZ0jbnGMHFikjJgh0BJzLjhXlkF%2FYwfLrGT3s47eBTJpGF5x00ph1MLIJIH5DUSuozXDY4UYPp7lcv9i5azcBNsbbJxD1OwKe9aZkm%2BJ%2B0J8QcGDQ6X4y9f16s5k77RZodUp5gJs8o3FUqNaD0sBOtfPnv8Tl4hF%2Fghb6vX5Z%2FvvM8A1%2FPDDwzm1%2FPWvxOewIqPP3EAY2EuXDy4mD%2B0NxBuE1HhV5cnpnBmI6LiOLZM5kJrULacCjwSaxWzJ19HKO1JwIr4XEjZpfi4McULBz0Sfx8vhjqm4ulA%2BKQl%2Bx2XarC7NP5EUPTEUQjgRGQX8MIJqbP%2Fh790vWt9OOlL3Es9k8o6UOR844DxudNXz7KxsnDA%2B5bDJ%2Buk5aO13ptiqWwYY5F8WiH0QdBYEImleeM5Wil%2FhZNirWMnbUvEJEhmacuEp9hXphK288IYiExUhDaHL68T%2BgKNK2JofBI8ImziW70A8l4XZNeplVRdBo46EZoMc1%2FmAm26tq%2BNk%2FpcSrC%2FuPBSbCMlIoG5tdzHoSfCaw0%2Fb62vyqpayBsgukIiT3jYuTRTsBHMMX0OWauJ1fiTlSbyBk62v89XUa5%2Fqe%2FIV4TATvsGo1VaV50uppN9f3Lc3374lyr%2BdgBqkyUQDzSL%2FyzguIwYHh%2B3SZtRD%2F75vtiT7%2F%2Fky4YTz8mmjC8uq1%2BxKlr%2FsKcunUEz1kxsCT%2FZnPQrnlQS1Cn5GtoeHfFUTujC0IuiLlPZ%2FSvDCwRWfFu0jYZRFnZ%2BLOW3A0C20EgWhABIZ%2BCgVk7ac4jFg1YDcEKsADLCYELsRmw4bBYXRkRbk2oV2o6LAV4LxhOa3EHIUTgLYhQ9xM8xp85x7AR9571%2FukfRe%2BD%2BA%2FcyBPjuRP8BrwyV6nGeNn%2FxvvHeexnIyD8pOBTaUoEyc%2F6NRpmjaZZ43yPry9X%2BubqXKvZVCMEYWZhYo79nvfU57X%2B5%2F2mzRjbL7dxuk1dIvXv6Z30%2B3RWGA1nCQaYnAf413334iIiFn%2B41%2F2e4Gb4POJHzj4Nk2wLllI3qD9gpe8XMBcImW%2BzR2jOjDdh3iIlEjCDK4QFgtYohhAPphbog%2BkEPG3ZY8sAcNoToneZxtpBguSE0ALcTohmAurUVW38Qp%2BdciVYu8jlnM6XgN3ECFrDBiyDc5J%2FsGGNaLyMMvaCv31EBe4HpNHWAqn4Tts%2F3%2F1P85AOas%2BZJ5%2Fxx1wyO3EdZXtGyniR%2BUpnHU%2Fj%2FZjR2BX9yvKUszLZviRBI2a0KSSSBbKY0tpf1ZrTEBcUtoLASuNYl%2BtO4wlMECtMK%2Fx5DfiO2wZK5BHQFcQygGpYLKb64%2BtLfffiUhekfBmisY2gQD3d4ibSvsYjxHUnXAU8pVvx4PTfJDDh%2BV8td%2FrO8%2FXzDPwXzsAzs%2FlfOPm%2F%2F6ZPkfenozWSNMI0aefjDGS9WhIA6HsfXOTYxF8mTPXiMIMI75GrD%2FP%2B4DVaPqLmQMK0eYKO02MQPW1BXBDYZImvznKs9W6uHXZTdaP1oXVSeJhLorxmRIR02xAaPQPKEU5tcUjGCBkzFE367okj0wd9%2FxLh6unhH9pIfc2C3O0aCOg4DH2w%2B5APhiRq7onnIIh9LFkLExJxfGuCPYR4wWzKpIuDIIT9H8ybRdXByMI42pzTNXnaaIc64o9fIcV%2B8jWzPSoMaSJUPNdoOyCuKct4MbtCUB0MUxgXQl8xYJ4h%2BQ4tj8dlBjbqcB5MB4eAqUWDCtGVNK02O%2Bsp3X5emcp0micNBANBi0BXgR1Msuw7l0YF48rbEPdBvvOAnvB3Wi%2B347dBDgk2JVwUxiLgGDUDcFkkRnOZN7qc5fr%2Bcq4%2FvTzTi9VUsyHRW2HOEjPRfzNFAQ2GqGA4j8xxWpkgQU66ljr7n%2FblPp30zU1DBFqDFwIIpp1dQTTKWY658ESbl2dOg9PcbJ1LD1%2FdKglHTH5ThwlkGDrI%2Fb8%2BqH5V%2Bm%2B4OJu7%2BzU05AHD7CDvmUSkRivxFkw9Wnm0ijbtS2WDeOzbZ7OGkMeBhVhra6%2FYczDOkfvQKYMBAJYI2DADDNwDSz1wpIlLq2OoMZH%2BNIp4QtOej3jPa82rhrlU1s8D5j1vX0CsK3F9CTr9frzNv0kAZSYjNGzsXWDXAYHIAdseNMkOOh9L355N9Yerc70%2BXzr4E8npe9xpM1AzCz1UpgH%2Bf%2FDFKGM0NHbEV246aXz6J%2F2MWIvk0ukNV8KO54LzIHIwQxDNi4G%2BOV84ujUCtew60mvswkMg%2BfM31k6FECE0k67I%2F9C74wf4AyaMK5Ifvs8NBB6UQ9vmbsCoGXLT%2B%2FTVwBJyR%2BChh0WizfpMCYEDWAeoR%2BOJe4U15A5m1dg6BSwXOCr6RX8wpTW%2B8j7CsiXNq7WMHAt1CInog7XZvMtfnF9xBRrH%2FxGmkEBu9IQ2YTgZTESeJyK5a%2FeCsGa58V%2BagdDysRrgZ7fPeGDKGwt2sIBB%2B4tUIHrBiDgLaA%2Bo9IIm8QvnGuU4C%2FuZCSbZQhzvg2D8Ked1SZGpmVPm0S4Ynv2Aj1iXtB68H1MS7SdmFSNdcno61cow0%2FcvzvU%2Fv3upby8WWowiAm3fU0%2Bjq479zMLzn0UN%2Fa0E3bTNXz9Crhk9AjCfaX4SZZ7%2FfZ6Br3UGnpnNr3Vlflf96jF6wpqWOgbhY2lonEmW3sJgLuazYIBsYhiaAR9PieBjakDAIG7%2FWRoLxRc%2F05efQww8PUiHM8cQxxRSxgkHSy5dTQeqLmZqa0zIOucru9uQxzHMaghO4KALMJocBtRrn7EYR38Emkg1kRvMSzTPwdD3ijM3Tqr%2B6OZJEBvpjs1buU6Mm4cV74e3ZoyTEhxOSEQ5yjHBtUkU3mKYZPmwxHwxpgASAWbP9Zo4CAKfriE9jn6l8eCvY02oi8dBzyWEtCtk9qMFM5M%2BKlOb9g2lj7TFXxDrjBHpevwRoRO%2FzpBq99NjKXbDuEPjxwiZSR%2FEmJtRW5of37U2IBh000RElxwiRohoikGMMKYwI%2Bb%2BE1NJo4PQinHXn6R98nwYzvr1Zb2DB%2FF46BPmYWgtTKzzG%2BqullO9qNG0aHQxyfT9xVT%2F4%2FVKf7yc6mwMzLWGMWAQH1i6ATwdIYRrftHntHj%2Bzb1jqZjHf%2B2%2F9KMfOzW7F72Ap9%2FGnhcECGiQg1jrez92kAv8seE4FxHRElPwZqv7mnyTpOyIHH4wnHXS5sA0Ah8O6JSGdDrSHmw8GylwlKHNBFe80BNyLttP2yfzlWpk2QkkxFitTkiFvRGA8Qjuw%2F5mT7ERgCNwlecHwhcmpM3CdczlKMb9IMTdhzRP5u3cRVPAYTLbj7EHfPoZSOBpjeltPKa2HmqPYwBk%2FcQNxH0LePySgSoWMF4P32VbKbCxyf%2BJ%2BWMIiwgLNmz3GrU7rUadvjtf6t9eXeiPl0u9mI80zXFdDH%2BzYDSpGpLXvUyj%2BfUvusB6RYd%2BvdxvfcI6WNF2Mh1%2Bt99HaV6PMBEF6e%2FTudHPfaoDbOhAV8i%2FSAZ8uVBdlWrKUm29Vr2vjT8J3sSscezEWcAeAH4DH%2FgM6PHs04Bi%2FYxm%2BynzXospMd5zoKlAQ4FXAtOAR3u%2FSvBvDwuGNGAmLTXYcQBcGq3FbMNEe73SSj11x2sRIMdcGvzSwx4HWABneI79ElwZ%2BJKCAXxe0WRpwnXvMBFw1QtMQ9PXrz%2FlzCq6Ilfm6kB1DIez0kKeJLRhjp9GnYrbasVjSkx8gi5X5NUBj6UTyDjU2%2FjEHJozIzGqJ%2F2gj2aL3Rc6w1md2qBt9nqCYphLBDDsHSwCirbSsD1onjV6tZzo316d609XK13OhprnBKFKms%2F0vs%2FNtH58mYzxOJ6w%2FxFW09oYdgONpFriQQLhVOr563kGvr4ZeGY2v741%2Bf31yEQaaDKdFAldmxBI6SGCpuZIiTQD5mew3EkHkwm9Hkn3mLX%2FppSvk0gwzSC3eiLYBXx29ERbaDYpA6Jvhpm6JUEgVnbgz6pa1WajtiF8CG4kRRBrGUcGudbwPYRZQjDdOHJeBwHnIAFoKoNJgfz4gsYykXPs2acLbk42mNmTcfTVHOeQc4%2B64wjviR58XXw490R4IjZMZHGA2jyLWY2AKtFEENFP08ms%2BYflrCHH9u%2F%2BfipJoWQKHbOa7p9oFY%2F1p7oS8wQk0BdDhM1ouQ4Y4XwPmor6iKqY2X%2BHKImmCwATE3vBQDLekKoz%2FzEvwAsMAVPEPFmb6cYSDNIPPv7fZFt0ldG6kcQAJkLOxGAqiyaC3kaPMT2Uzb0zpzgh32gtaNWLSaE%2FXc31f3x7rj%2B9XuhqXmiM1L%2BNdzCpI43C%2F8vee37JcSSHvtG%2Be7yHI7wnQLNc7pK7Kz1J5159ePd%2F1WedI%2BlKT44iuXRLEiBAGML7AcbPtH%2FnF5HRVd3TAwyAATEYZAE9VZWVJjLShctIxVrQyPBsWDRiyV4MD9pj7GOA9dXclPgMcFgtDWfaWkaXhoKTfgNsDjtEFAtLvlCQbHbU9ggzntbmpNVgT3FZJFtSM%2FV2A5IPRz05dS6i456ewPgKjK%2FiXvsL2gmajPa0NoPBVya%2Fa3ZJ9VOHl4R6Wb8ILwqzjtHwjZpaW5smxtkp3VNJyZzhx%2F5mzrvVMoMJeypDx196rPpn7sl3D3Xs%2Bfuz73RREyx5PwUaJeGTcdXJJgjswlwL7lRDi2arWZdc8DpbydZlpJSRvWNlObJ7XA7tGpfpkbJq4pn1OLtRPSfrXs2gEQrMXRhVnRIZqD6qOt%2BcEUxivfCT9jX6R2e8KGL75mctlXzSnmATnAaSi648nMuYzejYpe2ylbxkpkdtDyFau9llqa%2BtSa3Rkky%2BLNlcSTFuqxY4JRXzB32HUOuvqq2DSQlLARp4%2Bpi2eqiDakgRaahlB01pY0KnIjTIKvMw5k1bWgOCYEgRzOyZkYLupUeGAAz0CIR5AcJOQ1iPV8%2FfoRdTDjAZzNQi9CssUkIc8uOL4lPHE%2BPM1KE2boETll1FoJafCnYUYk2tQAU4yIfYIUctRXFE39ZGIrZpM6mbQqfrhwlJHccg3qI7rJ3EmobZmnxU4JujB2dMa024CjWtvsRh3ehcoQ%2BHxagjXKQhqSHHmuTa9hM8z7brUillZPfokBzZMy4Hp8dkaiAvgwVzPoWJNs6BlKbRdSVVVigUASSoNYjt3oEnYNC%2FaRulPq7PLfUxPkYMvGYMRGbzNTfAW1G8Li4%2BFabuurgFDGCNFjSFEFForzSmOi8wcxEmeZYFO1sxlY8uKeRDWFjJOoj1KdnvFovFwnLgnLW2VEiJc9ShgmRbQ9Jcq0pzdVXyCyuywjll7ZqdKYmDnmxRWvmMSkkbmCPhyKZelUadA9xxV5mTQtGOA8EzpZXIAvm0y%2BNx738ZvMl3I1aIawuxkQJh4SRyWNg8N4tPzbsvJR6oP8RgAEPjQIBoQCpFWAg9JL02e66Wn5YW6m4QeutoPawyLO8pNsXOTjTpfdjHlDNCS80lnWBAtqDEm1FvEG8oBbL5rJpxNapVPUIFj8aY3UIsaJ6hTODUnuTEhPcFZyY7GDLNspFDgQmFSMScULWZLSW%2BSzk7DqLdWpNWc1VKOZGpgQE5vGtUTu4bl0PTAzIxwHmUTck08PKJl1Q8%2B5oRthPm1j4pRkkRCtAQlUqddEIc16%2F6bijjr3UM72npcn0kEQYhxaJC7AERmRkoSHP3qNTrTWk2qnJ%2FbllqakybkRpnwaKdqYSbAAAgAElEQVTKxM6AsyvV7I20SiJrbnzVjqwjXxtIM1eNqpZiRL3H0uidXhdCtbOmGt8j6T30eWDWOQhtpY0Ro73tnEHVvOL4o9XS45nUKzMeZ4Mm00ry%2FtJVQN8Xxxn3jSBLEhLD24BQG%2BPq7AQs0ZfUoy0um7N6vJEyLcqIU0Lb9vzBBDUwH8RktCVZPE3jqKZZV6%2BZU4MFNZs9tGtY9k8Oy%2BRQQQbyIqWwnxF7ASOUTavI2H827EktXsXTs8pPY43y18f3mYy2w4%2BpdgLB2zWW%2FoXRshQKM1IocEzGQ6ndfSKry8uaj563ifUNDAtsU%2BCU0I25BhKmifVKucXQhghXgMSZik5fQHCpx%2FnQRlk9P5P%2BRcfUYzs4ZkpPq9L9BNZzGD%2FBHMA0Y%2Bn5ndraT3sZ7dWRxzpmvP5E5dmg8VCHzXBHLnzxuYj5dz1G17WzLhJmIaD5hHWJYGODk5bR%2FPtkabWwucFgM%2FYTiwOD2WMQTog1h2VlMGtddM4PjLTGtOeUiYalhkFXXJmFDZprYLPyQBWOtDg%2Fui7ZZlXa1WXBoGbX2KScPrRXDu8ekbGBnAou8HLM2DEvtMaKJzgyCB0DQErv8Pfw2HXz%2Bnm8p8XtShhfIgZeIwYis%2Fkakf%2F2Fe0TK3fTijC5sp5CdGIiiufFtSpSwraUikUpcLyHTv82taq2Q1PbApLgMKyknaUm%2BRKWHluUdOGzJTiQbHo6l%2B4PYV1nxR4oSG7PhAyVSnLzwWO59WhBHi2tSo1FJVuSTKEirUZeYC1N%2F9FWr7mZonneozzVtDXcANTkt2mI1j9Tn2ddQRsXoiW8utXEFiGeqYgTBLZ8OeZJw6LZoRE0aoJLhSKAkpDxAV%2BeSQrMEDUVwmMITWVmIUbpeJpOmKfWBd6IK%2B0haJFU88c%2BOdMGJPWy%2FXmcA8ePC4K7hLZZqS7zbIyBMc6JIL7TlxFNAZ%2BqeTfqhD1yikEQFZhUpPXAwTmvyhrD2Dbrkm01pSAcONCWXKsu7eaq5HMNGRuqyMGZETm6Z0JNaMfKWSmjYQ4eGfF6yDEESr5ovSAiTfNhKA5%2FgxbPxkoa%2Bl%2F3GWggswxnG5etbabEEntWFWrdbzVayMvRPeMyUC7K9XuzcuP%2BY5lbWpBcOyeD2ZI0czmptxpS5%2BiDTMHMwptom0yYoJpGmkf3uyHsMfyw51Ih8w7VFzQ%2BWvzezw6vDwZlGWjngi2LjUZDarWa2rflw9m%2BODpqVFfVUYxOJQwzMjbOtLeIp5RNL2MOtHufhD1BXkm7U6YLK7R8%2BhGadSwXwn5v2gvHX5hXZvSMXTOdpUQYTfYNo9Us51syPlCQvRODcnj3uPbdicGiDOQyuqc9bf6nJpm0rU%2B3DqU1lfErhClQ%2FvH13p8NirIhOh7pT3k0ZbboaLuOFnOyb3IUmxX10Fp8OCezy3VZq69ILlOQdrYoGc6BVLtIY0fM9sHwRJ7eh8FE4B8DUgJ03JiUERoElqauXtFtn7ApJ7GYsbMlq7Wa7Y8Me9AZnZqTTbFdCE96WBjD2oVCf%2FJEpPAuljx0YCRaKKEr71SinnB7textTu3k4OX0CEMpVuMrKNYmfTPVWDDVxqp6Gk9tKak1l7%2FZE2EGE%2B%2BdN62GapcDN66WVETUZcMEEZRIkO7jxTqF%2FZloM7NtGR0flt1jg3Jkz6TsnRyWsXJO966jzcQvBEIMZhW6FdhIYPYaWoiH%2B92%2F9t79u997v8f3iIHthoHIbG63Fnlr4DEqDboROg1iG%2BJubm5Obt%2B5o%2BaPu2d2ycToqHovhYpRAkd5KP1jS4XOtpaXLSOpBSQsWqDUCGUiJ995YwFhECizGXYHZgtZKY2W1TNuuZiTcjEvxYfz8mBhTVZaVT3DjLMh1TECjk1UI4i5kpl1Uh7LCSWZcZM36tOWhqd9sxw9l849xTinqhWWUyMxkqU2aCM0MWUZfL7qAWvnCug0%2BC3us6DrpA0PGn9dIgJMaNAbX9%2BV8Lb%2BgFDB%2FoUFH4m0EvQhByVuzQm%2BWnqB6QwMpjmCUEcVCAdUb9bqnNnWXa7V0MT9JvwAH0qw675QJNhN2wcVEAQMOZhMzmZjvw6mVK2GlLItGa7kZWpsQvZMj8ueiRGZGS7JEK7uW%2BH8tWA6l8%2Bg1TSNGowyWnw13%2BpCmiEvkIfeTAo%2BoKxDbXfFtvytf3n9Qq3HMaboYaVMW4awGMgVVRDA8RmDxbzcvv9YHi%2BuSrWJnlNkpV7X81alUJZWtqCmtbQu7CSHxiv6tU9YvqbpZYAZw5ZgpB9MhPULt9AwEmwvJUKJBudMcv5pSzh7j1GsmkBqFBQ0mKFy2RAEPouXID5d3sbl96ZK0vd7sjL5YmS2zWY6gSo3Yqac2WAVgmYOxgkNDKbdutMwgxl3XQpqPtuQcrYlk0ODsm96VPbPjMneiWFlPHWPZnCiRlsyxpRQDgxBunYGqcHWEWL1A38bhlEPx6q3kjMEWHWA54FcViYHC5LJjUihVJTKQFluPZqX2cWqLNdbstaqSR0nZOzbhFVUBpCuacxhp%2B8p0gxz5LuO5SC%2Bfg5zZGDqlbkBd2pWbkefMC%2FoHBLaxcw%2FLe%2FkLz3b3hLUp8dLuuZJDJ662jG8dOfEW3dIdw6ptzBuUyH66KV3wjU7%2FgD1xnnzlbS2PpjG0QKsvnyzHNL5mKdeHalh7Cbl29wP7tXEXM1yfUybmbw6OGoxjmxrBlpK5vzBXEYmhgZk39So7J8eld2jFXUIV8raHk2EkTp%2BVHS2ca2s1h1MdD04nMR5WryuRPElYmCbYYBxEK%2BIgVeCAZ8kNfPO2gE133lJFAIsAO22VNfW5MH9%2BzqrDg4MyujQkGAO6XkoE2IrcrIcJdn1LIBAwARv904m9mB%2FWdBhINptNXWBjEMPWcA0ciAvxeywMp3Dg2UZm12Qe%2FMrMrdSk%2BWGSK2dl0ZGjSLt%2FLWWntDeYahY6tR1j56nl1740gBs9tmx6fc%2B6VKflPgNJkO2RBkmOqgKcT2J38nV43gYzaU0d58i%2BwV5er9bnE5u1ibKLNLkHq4UQtJSBFOwdgvzmKmwBcIFBg1tJfs51XuhxmtIRrUBUOM4pUG%2FEPZFdgMTwA4EhZZFcbb%2FiJbKgwV1fkPGaIQg8ozYwCFECSa0WZVcsy5DpbxMj43InskxPUdzemxQRgcKMpQXGchyzDpScGMocWwBYQhvoA44lKA04YliXuF0YO3ub47r3ncP%2F3XulA7CEigYX96KkNuGTshu9vllZBDJfqsthUpOyrkhGSnlZWKgJHdn5%2BTR3LI8xhEXmgLJq1au2W5IM1uQNo6E2HuLDgOvlqqxI3%2Fbg8s04PsfrX8C00YEXQJvN54Mcq0DTC39qmFemtn%2FVsxhpdgSDis0LXsok65JuDME6X6sBRgshid%2F7lMy3as7uPOWhBtG%2FQNv4Ba8cCU1DuMFDEEUN83Uj3MzcWCiDk2kIYVsQwZybRkuFWRiZEB2TY7IrolRmRodlLFKQSq5jJn9YRJtVqXqjCewQA5G6m7wGTSp4NSjC49SQdvmMd0zqCNWKdQFhsKOTW3hH049vBaLgzJQystIpSi3H83Jw%2FkVWai2ZAUtOBatKr5k%2F3E4TApTa%2B0jnCXJyoJQ0pgaSlGhiWPC%2B1Dw5E3%2Fwh8A81ixyJaArFpx4J3dtK%2FW8vRdc51mGZkHY55t5fPs%2FW71tTbzsK4746CrMa2TJumIncZaV%2Bo%2BL88Tl%2BRdhffJD8xRd%2F6m4ga6wmvW9U1z9XqZ4DKVUqujUBLIXI%2FJuXoYN6%2B1KvZq11RwU8xiHpuV4VJOpoZLsmdiWI%2B1mhkty2gpo86ASoLlAD%2BEVrRPEJanRmtvxSif4nux5eEe39974%2Fn3eI8Y2I4YiMzmdmyVnQBTmBF1QtdZ0adGVnCrIMSiEt2Y0LKoBuk8B6hDiOtB6kZRJvxpknwTWLIFqVOgF9xJGYDUUw7s7E2KUxfxaKzYN1POSakwICNDJRkbGZCRh0%2FkwfyyPFmuyUK1Kcu1qlTV5C8rmXxB2RT2oCkdqto4L8zr7%2B%2B%2F3r3fAtav9H7xtP36Rd4gbLO1tJaxRd8pGyvfpMyd7INGs8NY8KD0AERYQ83KMHuEEWi2GsooQNg60UjbJ8RXJ9fkIQWwki4QhjAzaubKMw5omrq3DTNFCPZyti0D%2BZYU8y0ZyBdkZmJU9u%2BeUWZzbKAoA3lzMsJenVImK4UMZrNGGKk5ne7zUyNRLUfVGaGfGxuRgLe9nkBWupc48nqIPoAOGhck%2B7q%2FFYYTfJRzMlQckNGBokyOVOTuwydyG7PEoCVaaaxIrVmQOns4A8NJiTB8aBrdgYo7XekMae2otJzD1Iu53nBN0CFsddyH4xswuyabQgYHR1mpN9C6tiWPibb2D%2FI2z7Na1WDWa%2F2YckJZSvw6i9ZbfoiWYjbTsCfQUSBvHmJPnTfVhpljE6s9EyRMM%2BOjJtl2XXJSlwJCD%2FplMSvDxbxMDhb1sHnOfZ0cHZLBckHKuazuN4ZALug5yNYbKR7ovUytSXhR0YJqni3A4xiG6BeKIf27nf9461BXY7QMdky2YdxhXOAV86WMlMeKMlwaldFyVu4OFFRYouvBak019PU2pv3MR3gyp89iYWv7kjG11dzU4yrYSzCmTwASBGrqC6DRUOFUAeEBx3DpHucguEr1RW8jw3G6Jz0L60n5G8d07BBjM%2FF7c0qn7%2F220ftG5fTLy%2BNu%2FM2ZZ8V3GHOKfZLq3Os1Cx0gePXVLQ%2B6D70p%2BSwm5yIjA0UZGyzL1HBFdo0OyK6JQRkfKslQMSOVXFuU0aS%2F6L5%2BcyZknssT4ZjV2uH1e2fmWIeUJEZ3ynURY0DEwDbFQGQ2t2nD7AiwOjMkD52XTtWSBcCc7EBIskyyPwrmUxd6Fl498sQXlE7yTT6sL7c7oeWftWP1FEqO3UASyTEhOfY1FXIKU7kwLKMDJXmyXJWHCytyf25JHs4vy%2FxqVc2oUGByPhdu23EMBIHcu1ewu%2By38E0X%2BqQtuzSbuu4Hk6aAGmL2xoEswAOsCiTqOAdiL1VONdRN9Qgs2l7K2IVO9qxeQHFGXgZT6CaAGpEJ4V1E053H22NGBos51QBNDJZlZmxYpsdHZGywIsOlvDlUCQ4h0G2o3lvpf2Os6Q%2FApVoyvH0oYAk%2Btn%2BP2BiTfKEm3BnH2nZBop9V8zO8T8KkZ6Q4kFct53AZ7dqQPHiyJA%2FmFnRsYTWw2myquXqzXeuMJW1PJc%2BDp96ANp9HDLKN4VuP2wTvymzqcUHmZZL3XB3Pzux3rEsxX5B8Ky%2F1el2sjwUGj4ih3yb5GwYcE0af98ClTCL4MhiMUUxySCALcULydeHBg6Yz32i%2FMCzMZluSyzF%2FoV3JSLmQk5GBsowNDcj4YEnGB4p60PzkyKAMV9gbz74yNKHmnAYdXD4IbfSIEUDrjKWeuoQ2Bza%2BKIydhxCYVG3bPnVqFZBsW79NK4Vlgl1ZyeWzUh4uyGBxVDXDMJoP5pblwZMFmV9Zk5VaU9Yadak3W1LH27Ier8ReWnP0ZbMK48N105YzJdAfbL%2BgSWKJwy7O1tqS7lunLXEIpbAqTIFzenPQ%2FHrbv2Ptk%2BA8nDkSRqIxhPlcTvLZvBTyWbXOwAkcgkUsVqbGRmR6dFSmhsu6DqDhhAktZtm%2FjxWLjSOsYxA10Vb68y7U6WjA0PXyenETS48YeIUYiMzmU5C7nsjtlUw9JXH89EwM%2BFqphBLHWjTRbrbVZKjZNJNGtJusAmou9wrmZTPDg8EwJoAi1NiJvU6ZtuBt1lzZ56VQystgsSLjg2WZHhlU85nHy1VZXK3Kcq0uS2tVWVqryWq1LrVqQ3DwoEcmBI3tMxHyNkSA8QoEOtXtHWNKdKe%2BK%2FkVFmn6wtraqqytremxGiODg5pXq4WrJghsdqVZH4JQoN%2BQ%2F%2Bb7TjDPhETQdPjryEqlVJDhSlkGK2WplAvKVGIGOjFU1r4wXM6ruSWOVMy9Pdo8TCwx%2FzXqW%2F1MhPYFHv8BH%2BOAu3qtVObsFXT0X6FvOS3lRZl22ZhsrZEOeEyR1Z2wZIoQchUZKpdUu7ZneUwWqzVZrDZlYbWh42ppdU1WqzUl2hs4uYFZT7Fo2od472h5vPTnu9PlrC9ydmgiEFDrinxbcvmWNOpL0lhdNeatjJfSQldfNrqRmpo56%2BYISbC2cXs7ToOFYFKpoPEnwPpSVpmUHARyjn3mBSkXS1Ip5mS4UlDLjJFBcF2UwUJOBvJZGShkZbCcl1KOfZ3h7FeYbJxZKcsKZPzTgRrGhMHaD2LCvDba1Am02%2FwpQA7wOhitHlr7YElDX1bmm%2BNjEIi2RXLKZORkbKAkk0Ml2TM%2BIIthDWAdWF5dk6XlFanW63o0VgMLGOUNKc%2BOLUmEDYaihq6BNltg6cO2kuXFRVW%2BlUtlKZdLUiyWtc09bYdLCvjf5sh%2BreDpOHcIwjBl%2FPg44xMezEvFrJRLWRmsVGSwXJKhcl7GKnkZrRRkeKAiw%2BWSjqMK1hoqqMEpGj8TVCuTGaw7yFw1z%2F0GjcMS7xEDOxwDkdnsaeAOcdoTHl%2B3HgM%2B8TtBw6RfLpdl165dSlQODQ7qPhVdCJQBMSkuiyxxt%2BoyYs0ZAOgNKIyseXLUoy7M0QY0cqPNmVkZGS4WZHyoILsbQ7JSbyqRsbiyJktrdVmt1aVaRQNiRKu5mTCXEF0wp1e4rg879CUwmo5vaqkEU8CDP6fb1sOIi1ZpdnZWbt2aldZaS6anB2V8bEz3UiGwQKtDfI4LQHPIpWSdenrdXH9R0jrAY8cPmIOogUpJ9FcqqmZzqGgEOw5wimg%2B1ezS9ungTCbYUTsEgSEwAhO4HD5jNre2P2vFf%2BU%2FoMy7cxrTPrb1Gx940LNfDQf5QsYcB5XyMjZcVpP01UZLltaaJsRZq8pataqCGxyINfRoCDuOhH5ivIGX%2FPyVTvqXPimzkYTRjJg8iKwsr8jdu3dFWisyMTkhM9NTOlfhHdQqnobBK7oZeHRQbCaideYQk3p3tORBeAGDyBjI5%2FKB2SzofvOhSkGGKkVzdMY%2BVNW8236yUpb9mTCX5gQIQRvQM5K41BESjyrws8K7SfN0vS0tIek%2BEEDepjdvK9qB9cWOJDFmmW9mBsmSYE68cLSmB53Y0SgZkUo%2BI8OFkkwPl2S13pDlWkNWqjVBULK8sio1zpht4BXbzpR1RCjmtKDE3Jg2bTaaUqtVZX5%2BXu7OPZFH927I3r175Nj%2BfTI4OCj5YkG1m3Cgaeynn72MeE8w4ONa76GDKs6UlrAA%2FtLOxUJeSsWSMptDlbLuy2ev%2BUAhI8VcVgUPNuebp1n3%2Bsw4UkazMwbIMZy3Cija3vS1BK74FDHwNmDgrWM2TXrdr2kTDUOaGO6NuXH6JGaaWE5CX%2F5po7LT5W0Uh9LT8TaCpjf9ZtJslNezwp3ZxCkHF0dXjAwPS6lSVi1DIY8ZS3AO1LWsPivn5%2FtOnYHFGABgYSUwDQpEF4uHsorBOyFKV85P4xzB4XZGqs28rFQysjpYUNO%2FhprQwvSExQUixnLoAKY1NoqmE7bjH3SNDatsWliwSTzU6nW5N5yT7PIjuf%2FggRSrc7JraFKmpialXK4okQ0OrT2tHG1XPZJgY%2BzSxx0cbaoQlRyUeIeAx5wqn9UjSzA5VG%2BD7ENEw4HpFBoh7SsQrBjKwaS4AIO7kyAOR2rPXyfe5sao57Ad76F119FShINnxlNwk6KaXEzNGOFFTM8lIw2ECu2cekStNUpKpNchwINJut7TnI%2BJK156drAuaPOQ4lUfTTiAdcKNGzdk%2FvaaFPNNObprTI4c2S%2BVSqXTb15HWwBzZ%2B4KOkgIZeYx67cZMwHM56SofZf%2BjOAs9FvVYGLBQd81b9XaS%2FHwGyrUuftDD6Z13FjjdqFA4epy3%2BK47WTUFf%2F1vgAT8GV0XtdznqlYZ1Iwc0hg7Oy9C2Od%2Fa0tzofOZjVttZCTaikrtYG81Ibpv4O2d5M1IfQpz5ZXXfvC%2FAfW0aQvLS3J%2FfsPpPpoUYrVeZkqiZw9sEs%2BPHNEytrnsrptQI%2FqCO3h2PX768Xn9i2dftl7gUe9Ag%2BIGTqO5%2FLZnDGdecxkM8IefKxXmOeZ35nHzEuzzWk6DMieM6C1N5kwQLPXI7XCuFIYIsPZ2w7xfWdj4K1jNvs3J4Qf%2B%2BtsIlKiiH2CPgl1EoVJqfNuDzaBwbCwVDsB0D9uT9IXeO0zWQYzU4fjRcVmfSfijoOWfvh4AfB7kuikDLENQS9ZyRezUspUOhovlayTRidxlRG6YVdPTi%2F7Sv3IgwUCLpEFw7QaThyb7qOlLu2JweCB2MB0spzLSK2Ql2ZgbLrWtJ6uoC3YFeFlYX870kOIjRfakll6Iu2lWVl9dEtWhotSHCnLzMSwDAwMKJHNuA3dRdu0X792jNHm7Almf5Y2Uxhe2i9DJI3jzxAYymBa%2B0O8M%2Bptr5sRIWl9g6bVjtU9fmh%2BDabHUTYEigc4cG%2FY3bu53wMqe2phhLsaDwQzMyfaIMYZU4wnHDu3ijB77CQ0hQD35NlzD9hWkzgP6ylyU68OdSpyyA4LhSe3m5KrLgpajn1jg3Jgclg1m3Qa1d72SZ7k9DJwJbls9KQmeuGjdTU7VgeQTFiG6acxmkocK3NpM5wzT3yn%2F%2Fm7ksUKtmvd%2BpTu46yn7v5Kcp47U51%2F6JPV6w7yWjLHI0hMwwzY%2FuMD410P50l5bQXviJg4u7SUbUuD%2FltgxzZ6Y9Yt05hqb9HxnjJ%2BUPkUe%2FybsrCwKPMLszJ3%2B5os378ro%2Fm2nHn%2FtPzm%2FdOyf9%2BM5PLkaXMGY0ibKCDPx8brxuUbVX7AofdV1oFs29YDnhkvJkikzZnn%2BR523eoRKaYQt%2FWj00usx4T%2BTtvz6G2lweHbG4WrCGzEwEtg4K1hNhNGzBaSNGHHwuKLC%2FEsLgfKG2b5ZnSgm7v5TJFoQ20qaQWCMTGXS5fzEu0UkjpsCbx84GBwFjGrA8%2B9cG5c8npC3KdES8N3iC0uHPdsbX2sDPCMCZhCnsmoBz8lfGD4EQDgvbNrtrb6WupX8RcC1hs94FOL0eU86BCcyQiaAg5vZs%2BgNoITFg4befFsuLUo9uwx4n0TGMhmZGB8WIrHD0m2uiTnz52TWxfPSaG2IoPSkJF978jAQEVyuXyXdtOOGLE%2BrMQeRQUmgYHNMFdZNG0EAYGmO4CjZIK%2BWAh%2FjSAJd8tK4yvTwZM3LZOGTRzrKqf9e4Nv6yK%2FAQHghWoblhKACdOxG4J0%2Fgj41blWOSXTqnFuoI0wy8vmMx3%2Bmge2BkwHnH%2BY5Muzl%2B6IT8rf%2FBN59EIPHG1pZVuSWV2U1vK8DA%2BXZZx9uzg5Chtyn96WCunmwegTcz1U3ZG6tPHa5wwPzoSaMCT0VxjKrj5LrWGgEu2dpk5pN5MOnSq307f749zbmRTPgj%2BV62t5TLcQ%2FU%2FtEvxcZ4XIBJE6LyiDaSl0ldB5xI5m4pgedYSlLKYJRszGwTDO9gwVKgXmo4kTOj3GsSX1Wk2W5%2Bfl2pUrcv78eXnw4IGwjeTEyRPywQcfyMyumWB5Y0fwIBhHK4qgDAyDb%2Fpqeqy9FmS%2BgYV6D1ZMBusLLATSghllMtUqA9oqPUtZB9e0inxrD9CQ7ld84gtzGvdAWr6B2IogRwy8GAbeCmbTGKqEUete%2Fowxw4RTnUEECkcJIZ2FuhlHywsa0pk7oyftvCwLc%2BZPF9wXa5enpgJEhyMd0cMMNptCNw9DmnFOaGTyBC9ofskL9%2F%2Fd%2BEtDsPlnJly%2FqI9qlgnAHCkcDYEZi87O6qTHiKStKNvLffpdl4auurKc2%2BXMiN1t8TDHEUYIZ8P5acBsS461jafv335Phyd%2BBQNlHJvMTMnQB%2B9JRVry%2Ffffy63LP0ux1dCzL%2Ffv3y%2F5clmXerQAuo%2BTPhysFiABjMczAlJptUBsW3gYN4GFMaw7MUdLez%2B0nmj92Al45YQ6fca%2F%2FXp99nX2Ee%2FrBoP1%2BoTg4t3wkYwBHRsuhwlEnqbzKJbAR5AymaZ1cqI6ydGS8O6JnwcXoaDetGirsHjBpH51RdqryzJcyMtYuShDmKUyFbpMqjdtV%2FEvCpdl4tDZfX39tN8STASPTNIgUIGw9U8wTPopxLO0qUSq3QyUcSe75Lux%2BXz3MO7rYbIyPI4W2cnN37bDHci7fkFbC8aUdwhV8xpSI9Z35nPEo9wRiNL7YVBwEkO%2Fpp%2BiqQ86MK075%2FiaYADW3vZ%2BSquh%2B4HvP7gnly9dkgsXLsjc3Jzs3r1HmczTp0%2FJyOiIZPTopGagOzgz1egWnIrx45%2FCvB2Q%2BgbB4O0KyIZBu%2FuYoY0J510PrQlbJFjn%2FeLJ8G9pCdev9sGjdd2f8qkrXnyJGNgpGNjxzKYR%2BenmYurwK2FAYaTcaQdfn86kheklteDyqAtPJ8zL2Pr7%2BiKMyYWOWP9tM%2BXb%2FjHgd3wZPnz6tbrpYdftzZr76XS7ceFK9BjcprxsS6PVklp1TVZWV9XN%2B%2BDAgFRKJeGsKzMz9Mk83YYbF%2FHyX6wcJ4q9dMsXZCd7NahtoD11qXFJppMy67CREla8PJw7PYcEezyhQZgaHpbfvPuujJTLSqDduHxJqosLIrWP5MCBA7qfzsyfckagpUTJnd6jNLULDMhZB7ESi504ilq0nVlldogT6PUOgWHYN4LPhAuhPTqZGLO6c1uJigb8qX6lT01Df1f8JLyMRiQ1Z6GSg%2BXiT45H1dkYAUcc8kopkEllrUj8DtL7APH0IErtupRZEJ2X6stL0lxZlqFiQUZKRSljXgcsHUK%2FK2XPi9WqJ%2FC5Xw1DjuskudfY1qyuHhiwAXYsVvf6YHjWsFB5jaUBVk4Hs%2BuqYAHd%2BSUwvYlPhgLHlPVFRZt%2BMDabv8EGRz%2Fp%2Fk48poPhcDavWUdYT9TvGpN2CTjFUzWMZ6stywsLcvXqFTl37ke5evWqFItF%2Be1vPpQzZ84ow4mlhu4Bb7TnsD8AACAASURBVLmgV1T4y2DAUzZrjot%2FAdPq8CZi%2F%2FXAbKPCyvZnbym%2Fg1WMGLC7cNsLhDadOceaVVvXa%2BF5hQnNGqYT%2BDKzlJcQ7xEDbxYGdjyzac3hTFQ30edEozFYSAqz6qTGp2y%2BI9nm4jm9sMJ4OUOazocw0pAn2lKPs5Xdwsrzmcs1NQbj85Zj8CZLFHADP%2BGZTN6cTXCatV5e5kalJPkYDv3d7%2BlcMuYcQR3zZCTXzkq10ZAnc3Ny89Yt9ci3f98%2B2T0zI4VSyZZppMbpRtgIjC0Ip6Zq9qR5qZFlyFW%2F2LNWi3PRqK0vPV5XuBsnLxygHvz1vHqseO%2FGgFkNWBh4htnM5PMyNTYuxWPHpZTNyQ8%2F%2FiC3frkmzbU1ybXacvjwYQ2HKGAcYlrb%2F7L20qboDGRiejty5ytHdgQuSe%2FeJ3oaUfun94W3iagAD44rx51j3PYC8ubYsmFsb8qmq0YNM1nSmpmafbW8lIUKYx%2F0W072bSuw7WuAQ8wdUICn1WhKfXlFGmtrUinkZZBjT7JYMpgm%2B9lTktc6nfuLPSseOlhM5dEpghGSXJ1ggvRDV0gSsevJc%2BBu%2BVFHD7WorA%2BEbCa%2Frsy37Qs1SdeId2U9XYsVIiT9LczvAQW2NiGYQgtm6zKm4YZFu2NhQZ9qtlnr5uWHH36Qb777RmZnH8nMzIycPXNWjh0%2FJtPT01KpDKi2tN2CmQ0MjwrFzeKHrSf5jB9S4y21bdG7zQALjZbqwdZCgBlaOGipCfFWTCrh6W1%2FdBKePBGDn05pevwZY8bXjSRefIoYeBswsBEFtsPqbhNDN6NiSwBEBpMBv6wevtwbbgwOaTHv5O7EhTkUSrxKgjRfcJx4Id%2Fucl8OtQYrMAKz3YEn8aT6vPkneQGn56OmrIG5Y68m4V7e00uw%2FJI4ve%2FJFyUymcah4cPxFBxvMDc%2FJ41aXaYmJ%2FRQdcrFCyWtmM2%2FGgY%2BgcoIDKAOvaaHnPIv3O2npmld2ho6lAkpyDeRlZOj5ZouLz5vHgOQASzXeiB6Nifjo2Ny4ugxPfg802zL7Tt35KsvvtSNfocOHpShoWHtu7rE01xcqbZSsiKMI%2FuYitRFevLVzWTNKYQ1JfGTNrU37zmWZivHv8G4Xf9S7258EOKhDrWFOWnnb5bS%2F%2FpXT0Mulo8Td15OMrqSuC%2Fy5Bpr8rVLn9oizXpdamtreuRFhbMrC0Ul8l344LyIp3t1dzDwtMtg7x%2FL8eV38unFsqW3Enj2n7dKd9mMnd4cumNs%2F7deXMEkttzxy7qeS33Wp9AgFmEnDJRJCegLKXQ1YPpotmR1rSp379%2BX8z%2F9JBd%2Fvigrayty%2BPAROXv2rBw7dlxGR0ckny%2BoR1SaACy3mk0VwLIW53M5acGAMm%2FpvmEbA%2Fo3Nbdtf%2BxvAwhDl09aNenz3v%2BTb97bk5DuGhBubWFpQzzVgtqasdMENN31j28RAxtj4C1hNvszfMa4JchxjSTMDb%2BE%2BUri2DdbV5whIx3MWMKQ2T4KnXh8AUqy2PQTZXH1I1YdxvXfbcIjPMjnLA%2FeQ500IPwxHPgh5iZ5s0%2Bu0U1gcHjS6Z%2F%2B7BP3BpNzCAaPhsOM5AsFPe4E5weqGWahRbvQbOj%2BOzMaenqpW%2FHVl4z1eQG04cQID8OT74VK4hNng3pvGJ6kjk%2F9MQBG2UMHvmEgs7mcjI%2BNy4njx6VULMo333yj5mi1ak1qa1U5ffq0hquTqTCedI9T8BwN%2BeCtub7EdFvzlXf%2FpVvX2jrd4sTSFC8x%2FkMWb9jNRk4aF8l48ap0sKOkmb8pvjxK3zHSOyo9JXd%2F7mTw8g%2BsA62WrK6sqAMXzt2rlMpK7KOxeiVlPhPqjeq5cS9OsvRWsbv9NQI6yTXJx0ZG8m75JDE93%2FUh%2FuXNuDsLYdCyNcLr7PekhhaSeqcfYNrCHS2mnXelWZnvnqzKHUmBo7KlxSW58PPP8uVXX8udu3dlbGxUPnrvAzlx6qTs2bNbtZkq3CU%2FZTRDK%2Bi%2BUFv91M4IQDrOzPAyZHQCgo9%2B9MKb0RK%2FPpSKxr7FetsnHy3EjKiT0OTJe4XfTaWphJetGjSOStY3LjXJLT5FDOwsDLw1zOazms2ZNyZq%2F5EGhodv7jzINH%2BY1xpD6gwq8bjQzBGnUPDzIZ9Vcv%2FvCTx870xfXZEJNW90wNdQEw2L0L18EubTW5phTC9KXkeNG%2BZZ6uaMNN%2FT8bsAec4Xh8XKMkYTt%2B%2BUxQQNLouFgpoQEcfW8UBoMl9vISzPCXqInm6P9HM6N22dVMBG8VJR4uMzMUAf8bFIP3EBz9DQkJnOYnKdycjFixf1Tpzjx48L331M0s2yeBgN%2BwifXmi63bxNE%2BsGS2tx%2BJvu20%2FPd2d%2FdayFqSRVWcchs9r6eSrBp%2BfgSXvfPZz7076l4z3fM7IJ5vPFxUWp1%2BsyODgopVJJHbI8X07bKXbSQ8Fa8mbtYZDSLtZy%2BrcfepURstjpPLZTTTcHi9XTeqJ5ova6J%2BlBgCEBAa59tzBSm7MY29FHNN6JxdrMHIMvgkatJk%2FmFuSnCz%2FLf%2F33Z3LpyhU5euyY%2FPH3v5cTJ47L2Pi4CjFokWzLPM5ambrg6f5M5jqnM2BweccpkdXAzHd1rbSABPz4tCEGAk%2Ff5zvtCyK93YmirWqOo%2FqkID5CUP5pKktq%2BXibqBlE50PfXGJgxMBOxMBbxmy6yWxgcJpNZVzYaO9Eq08uEBe1Wk037CNpdAbHCFSfOUyKSFrCq9U1WVxc0jTDw2a%2BR%2FjzXpQFUW1lJswW%2BXhuTHtNvLQ2RVbX1qTRaMrAwKBqBn0B8mUonS49gWq4ZogJWVuq1ZrWGZhxVOB1hsDy543rAk4SvFg8g7YfCnTfFesoNVLHCm1pq6MFUUazFTTFMJ9Z9tIWCroXxsqgHMfExhC92i%2BU73D4c2%2BJvTDy3hvWmya%2Bb4wB72MZ03pn8FzMOGnpO%2BdsvvPOO%2FKnP%2F1Jz9y8cuWKfP7557K2tionTpyQyckpKRYLPUxmb5%2BldPcm1PvNiMfuNuxuz%2B63jWvy9n1xzDhO7d1DE3x4iN9tmCXzqKdPUmzNU5JvUIDrnOfMJneYzXK5LFm8ZO%2BQcZzCckCjhSAIUE%2BqPlGnvxIltYdzfR79WmRzsfqlfPVhtL0xiMn64qUmcBOLN49JDE2p2iqPBxOYC2KUtlRrdVlcWJR79%2B7LxYs%2Fy4ULP0t1bVX%2B19%2F9rZw9c0b27dsro6OjUiyWNDfWWaSrxpMEOqVe1%2F2xmUxBMgiA2aKhnRQzWgRuplVVCLQb6x%2BvQLxvAgP9MZa0qbW1UVT94lpM%2FmLpZAKCTrE%2BoYTes1Pmjk794kPEwCYw8BYxm0zcpo2sVqsqrV5ZWVEmk8keQpWJnn2bELCPHz%2BW%2B%2Ffv60IwOTmpRAZMJxfxdFFIIRhiZH5%2BQW7evKmeMPft2yfDw0OSU8JEdM8hDCxlE5cLAkp%2FaELz%2BUDIZFVzs7q6Kvy4nMghLhrMVqOhZqUww41mSx7Nzsri0rLM7NolY%2BMTki84oyhSzOfs%2BAfNybWCaCltD6bDAGyzs7NabzRAaIIIo54TE%2BNSLldUqo9k1etOWi5%2FtyISDah%2FD0WnbiGdSoFteyMTOMdUDA8NCcdXsNjyjFktczTwJtZKzgyksnyJR%2BDsrsNmM7N6WOz080bpNxNno7QxnI7ggp1AkwXGMenLjOO9e%2FfqGCYuHh6%2F%2FfY7PSsWhnN6ekr7Mt%2F86m77dBv5Pj4T%2BBDfy7W03RrODk3hGcd7h7HvJ3BKo8fbwOaMVBswMfirPvtLV%2Br0yws8J%2FM5beiwcGcORLOJNj2tHX%2BBQn6VJBvPueniwWE%2FPKbjoKUxTU6XDNEbMlDcemMdSyfd8HlzsTZM%2Fso%2BAJdKPrWEXihDVUPp2gn1WfuKpwj9RtcSjj1pNKVaXVWHdzeu31BG8%2F69%2BzJQKcnp0yfl9Ol3ZdcuzGbLUiwUVQuq80cAxeEB3fgpYEFUs1xYXV0PDefaQgEka4sAZrxtGgPgTXHXSeE9wO98CKL7dFAnfnhQrWaQwmiG3bnaIHlaBr0ZxveIgZ2DgR3LbEIo%2BA%2FC0okIGEmIh59%2F%2FlkPTobRPHnypDKIxnS0ZG1tTX755Rf54osv5NixY7pxf%2Ffu3QKz6RpH8oYAgXHkB1Fy7do1%2BfqrrwStZrPRkD179iiDRtxqrSazs4%2Fl9u3b6nkO75jsN1P35bm8TE1OqvYFxhKG9Natm0oo1%2Bs1dR4AA4a2cWlxURYX5qTdrGueyyurcvWXa%2FJ4bl4OHzkq%2B945oMQ001w%2Bl5Xx0REZGx1VuCnL6thtRkid0P7cuXNHLl%2B%2BrOXs2rVLGc979%2B4p8Y7zArzlkd4Jdb%2F3DgfqSzwuv6%2BPY999OuYNRnagMiCFQlHYE8WZnrnO3jrNbJNETW9pz343vDg0SfyN4CcG9Xw20ZbkFZ%2B2AgNBQBPW7FzOxjmCJCT87TZWCoMqsKB%2F0n4wnD%2F%2B%2BKOOUxhOxmWlUlGiTZswgGXtmfRZ3v07dyPyiEzhAYBUlfju8VPBb%2F1j99hK8Pb0sdUHbUnSPh9fJsiEBjZvWT60I%2B84Ypmfn9e%2BMzIyogLBp8H9MlBst7Tey9fNiqrtNGhheTbLam63%2BnkNjNXImgcXd%2BzWM7V7f9DjvwLjoa7KwjqHAx%2FyyeTYo9mU5eVluXf%2Fnlz75apc%2B%2BWaLMwv6P7Mo0eOyPHjJ2Rm124pF0sdU1tNq%2F0bTjKNqbAnNBVk5fpc0xVZY61rr1Ta%2BNgfA2DR8MaT49TvlkbjhHVgXS4B6ZY6tGF6nOgH%2B7oubQyIGHgLMLCjmE0nFpk2YAT59TJEMFYLCwt6Nt%2F169fV7A5G0s1eyYOFAg3lZ599pgQHpnm4IufyMhqNumoy7969q8wjJqgwsJjtkRdlHNi%2FXyoDA8qkMhfdv%2F9Azp3%2FSRlOPag5k1XnExA0LukslkpSUy3jYzl3%2FpyQ%2F507d%2BXDDz8UNKz3792Ta1cvqWt1zGmezC%2FIxZ8vy6PZx3Lz1m05eOioDA4NKayVckmOHDokp06e7ODBCGIjzNUDLIc6NFuysrKqmlz2umEqBuP38OFD%2BeKLz9UzHgz4b37zGwFXEOqdvSM6RTOJdl%2Fg6alEGUnSq2KQjpMvbaamzUz65NMVsbucrXzrJooTpmOjMnrjbxQvhr9KDBjzyZZpG5v0u6yOwUOHDnX6KSa19G2%2F6Me%2B%2F452dCdVjA%2F6IHm5JYT3Y97Jm7KIF%2BhMzzLen4KB3rHiON0oic1TKbqvb8T0BNI3wnME%2BhzWnSdz49zcnG4veNuYTZCn%2FTxFNEOIJ8yl4%2Bw50Lwto6brYUdyuXAJcFvswgtbW0zYbIjJZZkr8p39rcTFc%2FH84oLcvn1LmHNu3rwh1bU1XTdPHDsuzEnTUzNSKpd1%2FVPmtXetfMbEotCqqW3oq0GZRvnee%2F2%2BLdG9zYDy1rc7fz0kAdTxqbSIvySf9clSsh7ZsWedbNKdqROzJ3F8jRjY4RjYUcymEShmBgszyD5GtIEwnVwQOPWGmYuihUR7yTeYSUxqITKJjwaTdxi9xcUFqdWqQaMZPI%2By6b%2FRkAcP7suf%2F%2FylnDt%2FXhr1hqAFvHnjhhKxi%2FPzMjw0rPmNT0zIxOSkoIX85ZerMr%2BwoO%2Fstbz4889qvsqZWvVmUycq3J7DMA4ODsmTJ0%2Fkyy%2B%2FkJWVZdV8ch7X999%2BKwUOdM7nldm8fOWqPHw0K%2FMLSzL7ZEGGh0fUccDIyLCUSyVBmlooFmR1ra5muMYIGj7ACbBDUGFGi%2Bkw5mJcExMTipNvv%2F1GF1vwAiMI440G1jRHxPTZ1%2B%2BaXNP0EpXpGOlnSxHm%2BaBV0K0waprS1oPcdfM9M7pKF9cvCJ08XuKhF96XyCom%2FZUw4G3Gnb5tvrra2kcPHjyo455vCJcuXbqkYx5LBBhO78fMA4xpF3Y4o0l%2BXE5s4rqevIgXr%2BfDgLfTZlM9g%2BbuSxRuNm%2BP5%2B3r7%2Bk73%2BgTzMFYmzAv2p7NxAQ7Hf%2F1Pm%2F9fKj410k4qZm1oZHVSejOedJxH7bbIIzl4tgtmw%2FMjwICCNY%2B9Y0QztvO5TJSr1tfuXzlsly4eFHXUhzdHT16TE6dPCX732FrzYhtDdFlzOaW7nFhUixtzWcPAGNYe9Dfd13tiRNfuzGwbvSkkMij0pbdSbreOunXP1jirti8dCKu%2BxIDIgZ2IgZ2FLNphAPEoDFS2RzEp3lUZVZGCrm6sizXr1%2BTO3duqxkt35ns2aeIGR6MFGYuxkjZni0WGiSaxrSGIzkyeKRt6r7KR48eyurKqjoGwPNlPpdXV%2FmYpSLVPHDwkGRzeU5fkGKxLIePTMuf%2Fvqv5NGjR3Lj5g159HhWhkdGOnsi2ad48NAhaTQbslatyvfffyc3btyQsfFRwf3%2B0PCI1NZWtT7sCQVWJZLRCoZ9oMVSUQlp3YuayajmErOe%2Bfk5rQd11rgiKrVHiwkxDkwQVjCeaFLZV0L9OVJiZmZaTVvBD3tSnSl1fNsAgSFPTG3TgyY1fyt7yrv%2BFJfm4w%2Fann2p0hAp5HN6vAWxcIxgAnbTZKXzjc9vLwa6CTUb92DDeMS2CnswQWeMICxByHThwk8qTGJMI2hCw8kzP%2FKDmHQmpDd%2F%2BiJzhjkR6kcwJL18fdq3t53erJqbWS0ww2xiRsuciGCCvrJ92zXdH5N%2B%2BOK4T%2FBgeXj%2Bfn%2FxnLdjSl17wjpPG2eDGb3NDabdTMNtwoi6zi30E9bMn376Sc%2FPnGVNHx6Wd0%2BflvfOvicz09NSLOTtnGhsdYIDQPLT%2FuReZQEiNF26n%2Fl8lC5fn3uaoud1XfQYsEkMpBDpj3bn78ZjazNxEkbTc94kTDFaxMAbjIEdxWz65MwdDSULABoMZV7EJI9oK8%2Bd%2B1Hm5p7o5nyIB4gJzF6RYE%2FPTOtZV6Tjh3msEZ%2FWyk6U5vI52bN3j%2Fz2tx%2BpF9orV67K8WPHZf877%2Bi%2BQ%2FK7eOGiajqPHjkqu%2FbulbnFRZlfWpJdu3fLocNHlAEdHZ%2BQA622nDx5SqXmMKQscpjZ7N9%2FQD1rTk1NSnVtRTUxOM1pNxty9coV3duIt7tSqaxEEGZe4%2BNjMjg0rBLU%2FfvfkX373lGmFI3lV199LZcvX5JavWYmgGgI1Yy2IctLy6rJvXXrluYF7sbHxxUn4BIz2kuXLisRv7q6pqa04I5F0Al5MKSHTQuMomlBfWwwPaen6M572OeGqVKjiVOFqiwtLetiPDI8LANlzrVjP03YB7HNJILe57ye8b7dMIBwKKtjh36Khv%2FSzz%2BrhhNIYUARorBP2C%2FGuPdrwmhj0vIjnK5ovXk9sRD7g2Pxzbxb%2B5pGC6ECawBWLoTDbJbLdvTJ9m5nZlf6ZnrG9fZY32f9S%2Ffd06fvxNhs%2Bu7c3oQ32hReD%2BFqchavCU%2FBpQtV8%2Flih8HESR%2BO%2FKArMJvFWmqtuiYH9h%2BQk6dOytGjR2VifELXQ8WcNokxrp05xp2VMbfY4Zzr0PU8%2Fc1bbF0mMaAvBp6%2FRz8rxWbG37Py6AtqDIwYeGMxsKOYTW8F9jK2W7ZvE%2BYHjSYX2jscheAwBMbs3XfPyMlTp6RcKqtjnD%2F%2F%2Bc%2FSakJg1FRLCSHK4qO7VFRjCMHZFs6EJIy9i3hqxaPckyePpdGs656MPbv3yO1bt%2BT2zVtSyBdkbHRMpqampYUGtchClZMaJjdz82p6s3v3Hjly5KgUCiVlbldXV6RWW1M4BioVOXv2jGoUOQKEcp48mZMbN27K2NiYLK%2BsqPZ0ba0qTx4%2FVtPbldVVqdfqynjCKLNQNZttmZub132j1K%2BzrUAX2JbUqjVl9GAy0eDCLPu5hHj3RHNKfZeWltTklgWWuBDgxoBjqkw5TVUr4eCHcjdaJHXNRaMZBLnEY%2FGlPrdu31IHS%2B%2Fse0dKxYKWjd5TGXHdn5LsGvI2j%2FeIgV4MQBwy1goFzr0tqqMr%2BhnWAGgg2GNNn3v33XeVGfX%2BzrgnHn2Zvk0fN%2FNa%2BqgRCTovRHqhF%2BVv9Dv9hfalT3CxDQMhG1sy6BsI12wt2e4ND3xO8PZrks3C35vPZtP1K%2FPNCEubx1s%2FsDrzrHNHLhf25Jlgle0nMJjMJzCcaDPPvHtGjhw5ovMNvhmYT2gOZVthZFNro%2B3vYyeg9bmtwpK33Fblt1PzeTU92rG%2FUe4bhe9ULMd6RQyI7Dhmk0UBExX2WSCZVo1EDkc87Jf8RZ3%2BoMHE2c2nn34ip0%2BfCRpQHPxcVC0mpqcQGuzBuHf3nty9e0%2Fe2b9fSuznLLDYGDNLWRAfLDAQI2j%2BPnz%2FQ5mempJHDx%2FJ9WvXlCnF3BTzV%2BLj%2FGcVM9XHj%2BX2nTtqwrr7KF5k39H%2BiJaVfZ04GFhaWlSigbO4Dh8%2BpPXhzK56o2FazuFhyT%2BZ02Nbhmt1NXtFC1oZGJRCEca1KguLS3o8CodG%2F%2Bajj2R4ZEiWl5b0Tj3ZUwJci%2FMLqu357rvvlLH94x%2F%2FpHtEAQrGEuk%2BCyvaTkyFqRPMJvVOGE6W07YeTt1C44lZoktte0abTce2yNJOxnxmVLu5uLSozPL01Jq1o2o925JDuRm8szyNlOopKr6%2BtRgwM0CIRPolzAKeaJ15%2FOGHH%2BTcuXPat99%2F%2F331YFsoIGBi3mCcG8PJ%2BOCZdFw8W55vLWJ3TMVpR9rXLusvCBgQNKC1Yt6jLzDfmfDRtFLbv%2F23iqDdqnzejC7DGGf8uyk978m4R3iFcLWtQgishdRs9vx5XRuZW86cMUaTLSgIZzW%2FYCmhjKXORTqJeJfbWAn9kih7u1ruJZG15ckj9rccpTHDNxoDO47ZZC43YpDzjtGAZZU5w3nPt99%2Bq4sDjkFgmNjLxVmYHEmysLCoWkW0eGgh2W%2BJV9rzP52XgcEBNW%2F55JPfqckdmpFas6bHkLBfE20fjNfPFy%2FKV199JXOP5%2BT8Dz%2FIhfM%2FyYEDB9VElf0caDI5fwtLJPZ03Lh5U48%2FYd%2FY6OiIagTRvqJh%2Feabr9UBUalUlN9%2B%2FJGaAkIw%2F3juR7l5%2FYYeZ4KjocWlJdWWouWEGAJmTGvRAi4uLsvQ0IjuSxsaHpTDR47Ig0cP5MGjh7L%2F4H71cLtrZkaybVE37RDj4Anp7nvvvSd%2F%2BMMf1BwZz7xffvmlLrAwm3jU4%2B6X4RtiHPOjnDKbquH0CM%2B4w5hC4DE953M59X7bapj22HWYuJNvoWFS%2FekzMoyfIwZgL8PRFa7dh%2FDDwQvjzT0uM14RMjF%2B6feHDx%2FWPmyaS2Mqycd%2F5KGHqIf8HdHbn%2FlwSOO9FwO0He3rd%2Bs3LWU2mdsRqDHf0T9c092bR3zfORiAKWQtY6H2ce%2Fjm7kEbTdrInPHhQsXVDDBvPHxxx%2FL0aNHZGDAnOexXltfMmGGmeZm1PeA58faFzaY7xwExppEDEQMRAz0YGCHMZtM7tSQ4zKM6YS5m330SL777ltlmNiDg9QRogFnOJjXwWjCZKEJRDrJwe9oQYl77%2B5d%2Bed%2F%2FudwsHdDfv%2F7j2VyakLWVtfk%2BvUb8j%2F%2F87l8%2Fvn%2FyOXLV2R%2Bbl7%2B%2Ff%2F7d%2FnhL9%2FLowcP1KxG4cnmZGx6Wpro7zIZYT8m524%2BePBAzUVV6yltdSDgxAxMJvWAKeUwaIgeTEopd25%2BTk1n0dBC%2FI6Ojqkmc24el%2Bu3dS9oqVyRqams1oG9kCySSOnZV%2FJP%2F%2FRP8sP3f1Fi6pPf%2FU4JKZhDfhDdMMZofDhrE4n%2Bf%2F7nf2oa9m6CH%2BLxTNkGL4wmjoowP8S8yBhH7WtGtfd0O2qmS3FnB5AuyjAHgbAnb4sjto%2Bl7fuoLA6mSPGKGNgIAwnjQAyfF3T4qVAGR2AfffSRajs53geTWsY76SAcEdzwg8Ggb3Zfse914%2BPNf3Pin2nFhQn0ByxNnNmkPzC39TIgb37tYw3SGKAv0NYMe0yoaW%2F6BOsetAKO9L7%2B%2Bms5f%2F68ai9hMhHO7t69S%2F09sHZx2byRWEUQnvQzGFl3RGZx7JvNLR4vDVd8jhiIGIgYeFMxsKOYTacJMXPBKRAkImard%2B%2FdU2IS80wkj9VaVc%2FDvHr1Fzl27LgSEzBpEJZjY6O675GFAbPZ8bFxNQWF%2BfyHf%2FgHuX%2F%2FjvzhD5%2Bq9PLR7CNlGNEujo6OSqVc0f2cECgcX4LHVpgwnBFlCgUpVMrSZiFqi%2B63nNk1Ixd%2FuqCaldlHs4KWEUIXzev%2F%2BT%2F%2Fr1y4cF7%2B9V%2F%2FVXJ5Ozfw1MkTcuzYMbnw00%2FqfKhRryvMeK%2FNZHPSaLal2cYDZ0mmpmd0Hyhu19lXymKZy%2B2Sv%2F6rv5bFhXmBQf7Hf%2FxHNTl%2B%2F733ZGV5RR4%2BfKBMNx47YW4xn8UU6N%2F%2F%2Fd8F88K%2F%2F%2Fu%2Flz%2F%2B8Y8yMzOjizGdnkXRF0bwrgtoK3W%2B6QbMZmfABPNENJam4WzqnpZsoaBRlHFlnx2LP3vocDuv6ut49EQHh%2FGhLwbolxCN7BaA8KMvIXTxizGL2RtjHc09DCeWAX%2FzN3%2Bjlg%2BEMyfk82ZSa%2FOLaSu8z3te5N8b5t%2FifXtjwJgCm8uAlDk7lzPN5uLiovYh%2BgpMp7Vxr%2FBhe9cvQrd5DNAXWMPMttXMZjnuqFazI9M4Oom5Assn1urf%2Fe53escHBBcMqc8bllc3s9kLiclMfQ31e2%2Bs%2BB4xEDEQMfBmY2BHMZtO7EEgSsaIQjxRYgJ1%2BvS7qgE8cPCASqsv%2FHRBnQJhWstCQloIzz179irjSB4wOO%2B9%2F54cO3pcNYwXL16Q%2F%2FiP%2F5BsLqsmMzgBGBkekbNnz6rXVkw%2Bi3i15KgUnOfwXixJZWhYmpms3HlwX27dvaOL0d49e%2BXTTz6VlcUlNcn55utv5NNPP1XHRZj4DQyW5eHDKTXzRdsIfBBBXLdv35H%2F%2Bq%2F%2FUuZ0aHBImeomB85n88psojWdfPBQYTt14qQtftmMelI8cviQ%2FP3%2F%2Ft9SLhW1%2FjhLajYaMvfkiZrvIrVFw4vWFUaXhRMvjH%2F7t38nn3zyiTLQwOeXDDUL0QAAIABJREFU49zf0wts1x4Vj5C6I8P1%2BMpUZjOK%2B6PHjgmyYZh3CDytYFQmpTAXH58XA66xMgc%2FzA0cyG578RDgwJSizUdb8S%2F%2F8i%2Fa7w8cOKD7sTMZOxaJvsoF8dnvsr5sXxgXTkj2ixvDtg8GfA7z9qN9mY%2Fc0yjCBt%2BzyXxoF30gTkrbpxWfDYmPX4%2BZbncPo9350c7ER7uNwAFhNIwmQmfWR5hM9nljko%2FvA9OG275u0qo8VCeA9LOX4nfXYvIe%2B5JjJd4jBiIGdh4GdhSz6c3DIsJZl2g30YLhevyDD95XbcXY%2BJjgZIfDldFyfPbZZ%2BoA6NSpU3LixHE1E2XvohOLaPE%2B%2BPADPdJjcLAil69cUu0H%2BzbResIIXbt%2BTa5evSLFQkkqpbJq35o1M78ZGhqW4ydHZWR0TJZWVyT%2FMK%2FMKnCcPn1a7t25I99%2B86385fvvldnF2VA%2Bn5Vm0%2BIZw2Y1Q%2BLK4vd4dlbNe9%2FZt08mJiZM66cHzRdkda0q12%2FckEePHsiTJ7Pq0VZweJKxvZRjo6Ny%2BtQpXQz1SJPVVTn34zk1%2BcUsmLpDZCOpxZwW7eYHH3ygDpVsYa0E6b5ju%2FuueGOxTQXrIm%2BUdyo0efTv0PBohCm7EM4MzeE216yPETMrE%2BpEQpJDfIoYeBYGTGsAIxF4RjWvRZgxOTmhZuEIUdBMoNn%2F4osvdJwjUMLpFub29FP6Xqtl5rj9SiSOEatuWp4eCf1SxLDtggGdh9TkOqPbCdibh4WHO4FDIOHMJn3oKVPadqlShOMpGDANpgk80xYPNsZtbyZr4LVrv%2Bg2mdnZRzpP4O8BegHLJQSxzpjq2hcsfawveR%2FZWGOZXsvSz08BO36KGIgYiBh44zCww5hNpM3pX0ZNYHHwY4SkHQMCQ4fJ5p3bd%2BTcufN6riMmMSdOnFAtKJM%2BC4iZ0OXV5JW9ijBB%2Bw%2B8o2apMIsQHzBjnHn55y%2B%2FlEMHD8nw0LC0m23BxHV5eUWajZYUyhU5fAwTLAluz7PK1GE2e%2FzECbn08yW5efOGntfpJjwKA4wWeyCbSFvtGAYWMY5eoVx%2BHBXC2YEQRK18W1bXVmRlBacWRalVq9Js1gVmM5PJadnExSTs6JHDwuL53Xd%2FUUZzcWFB6z41NaUOgGAscYLAHk%2FHgy2qT%2B%2FjwN3RaG6KzjZc40FYjZcC7sGtJg9Ho3R0SeTfxco%2BHZ749e3FAH3Rib4EC65xJATTctNwjo2x5%2FiQRqO%2Fo%2BGH8YRx5B3rCPLj%2BWkX5fEzhtSeSRev7Y0BbzeD0gQGaLDQajFfmhktzGbiNIY0sW23d7v2g452MzohbVnD0V0wh6bRRMiAqSyWPzdu3JDlZbbKjOm5mTCb5m22rDRAvz5AmJVDns8e%2F5uJ068uMSxiIGIgYuBNwMCOYjYTjQWotwUFDSREZSbP5M%2Fiwr6thqwsL8nCAnsrc7qAfPjhh7Jvn3mpxHwKxgqGjWw43xIN4tTUhBw%2BfFCZxsGhQWUoIUgW5hf0XM%2BzZ87K1OSUlgOzefvWHd0HBlNInuxptH2JxvSWceIzOSmDgwNyd%2B6xOiOgQNYm%2B9kiRRmckYnXXBhImC0371HiFwYteHFdWV1TL7lobqmrMa8QT7gnaqvJ7Fp1Vb3YcgSKn6d57PgxNVtlvykMJ2cPIrldWVlWhvMvf%2FmL7t9000KYQSfQWChtsTSc6yKr52HaQpteajtMozYWFcXiOROYcIvJsg%2F%2BeXPCgOiZkIajDtN5vgkDLcL4ejCQJuKc%2BNP5oKcDYaKOlgJNJmMQ03WONsCsljwIh%2BGkX%2FplwhdjKAnzsrjDlGyCxvSs4v01Y4A28%2FajnyBoYM5m7saZFGa09JukD71mgGPxL4QB1kPWYb8QJtkaae3PuGcNRNiEp1nOzsRfAV7lmQNY%2F%2FD8bn2lZxLxTMPd%2B1NPcOeV77E%2FddARHyIGIgZ2MAZ2FLOZTO5mKsc7RJ86DGJPozJpDd1%2F8fU338iP586p5gJPcjCbEBUwUZhPkZb9njBoLAjkMzQ0KJjSusZjqbGo32D49uzeo85z9u19RxmnarWmx6ygMcRcVQmYcH5btbqmnmsXMgty%2F8F9O8stuNUnHgugltFumXfYx491PxneZ0eGhvUMUMxdOaIFEz%2B9AsO5urqmnmqLpVIgeI3ohTmt1Wvy5Mlj1aJyPhi%2FVrMhp0%2BfksOHDmu9Ia7xhAsuOBoGp0H%2F9%2F%2F%2Bq5ob41jp499%2BrObIEN6%2BUFJ%2Fxz1hPCtjH3Dn33xpTpZ6A513mHCP12g2pNVsSgGzNfJSqt04cDv8mhSe2w4enbFqW4oB71%2FpTL0P08XoxwMDFTl06LDOGT%2F%2B%2BKNqN7755hs1p0QAg1k9prfe50mfzsOFRM6ImtArYUTTZcfn7YUBbzOffxHyMW8y12IZ4%2FOat3G%2F%2FrS9ahShAQM%2BPo3RNGbT2462hsFkjaat8VWANhP%2FDA8ePFTGEk3m0aNH1Ts7%2BzPJh3O404KnF8W0w%2FGi6WO6iIGIgYiBNwEDO4rZ7Itw9li1W1KrYta6LHfu3Jb%2F%2FuwzdV1eq9Z03%2BTvf%2F97ZazK5ZIuTE5Adu5oBJu2wIiYu3K0bLA7uWxWz4bEaRDMLFJQNKKY4xTVSyz7LzlSpKnECgzs0tKyQMjev39Prl%2B7Jo8fP5ZdM9OqOWTxwd06jGGjbpL169eu6%2FEtnAF67OhRPTcUtUmtZsQQix7pYKrrtbotnqWSwkV5ELzERUrLETDffvetPHzwQMs78%2B4ZOfveezI8OKxaWBhtzh4FF5T36ad%2FUNhxpPTdd9%2BpcwQWZfasYI6ceGhMFnWIMWcHexdTcNbLbHq7NVp2PAtH1YCzibExdXKEoya%2FyI9%2F8YoY2EoM0K%2BMeGyrhhPiEgIUJuOXX67qeIUoheHkSCDCIVTT%2FVstF9S5CP3TtBac15eOs5Uwx7xeDQZoVxhNFzrS1jCcCBiMcYla61eD%2Ba3P1ddw2pSftV%2B38IcwLHhYH9lWg9ksaxzCVrbWHDx4UK0a6AOMZUzk1QchC128IgYiBiIGIgaeiYGEin9m1DcvAtoyCEQYxcXFBfUmx%2FlYX331tZpI4RDo00%2F%2FqGdkwTi5ZNsXqHq9oeaxtkC5BiNZsMAIyw2L2MOHD%2BXPX%2F1ZtaY4ucHD67Vr1%2FUsz5GxcWWe2DvJBTP5ZO6J3Lt3X9bWqmqac%2Bb0Kd0HArNKfvVaTVZWVmV5aVnNemDROI%2BTPaFLi4tSyOMhM6uaWD%2BnE6%2B6mAiryWwL2Ju6X5Nyqf8PP3wv%2F%2FWf%2Fym3bt9SL3o4%2FsED7%2B5du2VpcVk1rBBZaCXZA4rpGFJdGErKgkFmfynlYXIIQc43uww%2FrL%2BKR3DzHIuxajdbLTVbw3wROPJ4wh0YwGtQh3kNhcVbxMAWYwBmkyzN7J4jfyA2sXRgTF66dFmFMYxN5hT2cMOE0Nfp59rng5az2YTBtPDnGQNbXKGY3QthwLYcwGhiQsv8Zt5GTWjHWkJb84vXm4IBX7sTeBnHXNwRQuMUDLNZvM4y5mEwWfvYSsI6mBaq%2BniPfSDBZ3yKGIgYiBh4GgZ2NLOJ05lGvaGMy61bt%2BTzz78QNHRILY%2BfOC6ffPqpelrFZDSRWtsiBIOpCxKEJI560KfhrEc%2F6%2BbPDl4hPh8%2BfCRfffWVer5lsaLcR7Oz8uTJvBw8ckQ90LbrpG%2FLwEBZFzE8w8JFzUxNycH97%2BgZn%2Bwdy2Saala6Vl1TrSz7RYEXd%2Bt7du%2BWJ49nlTHF9JcFEcIY4uje%2Ffty6%2BZNdWbgRHIOM%2BJmUxbn5%2BXG9evKdB48cECPXUFqy17Pe%2Ffuyf17D1SyC4EFs8oFTjAd5mgIcMGCy14WysJxBnj0S81mgymsEti6v9K%2Fdt9N75PWcBo%2BCcdEiXqvLq%2FYPlcIeJCkdzOl7c4tvkUMbBUGzOyesQ8hiUDlwIH9qtViXGJ2zlmcjAX6OIQo2g76rB2p0i1geQ5Zy1ZVIObzEhgwISNnJZonUgRezK0wm1z2nQUgarReAs2vIantx%2FSCWd9YsxEms46xpiGERrOJ458TJ0%2FI8WPH9bxr9zbrQiPrA8a8Mu7F%2FKN71vEeMRAxEDEQMdAHAzua2YQ7hFGBgbp167buxcjlc3qMx28%2B%2Bo2cPHGys08T3LCgmBdJY7QwJ1XTmeDsw8zkYMTaHOPZ0Wig4RgdHZHJySmZnjIHQTBktXpdGvWmDAwMKtFSC%2BdlokU9dfKkhqGhHBoYkEqpqPm22VuaEd2vSL6Ysu6a2aXnepKmXq9JpVLW4xqowwfvf6BMIAslezqR0qJVHRkeluGhITUFpF7kdfjQIZkYH5f9B%2FbrYsrCyX40TIdgOHFCxGUMr5vFWlqYWogumHbyQ7PjZkXWrxJzQfJ91qWLt%2FKQxtT7Ik44Tp1ggjPZ7iNUIon3LKzG7y%2BKgXSf1T4YvM5WKgM6BskX026YTX7ERxjD%2BNS93XpsT161InzT%2Fh0EVC8KU0z362LA%2BkCi2cRBEFott3oxgaMJHn9dyGJpL4sB1lSWJcYld3wbPHr0SI8sO3%2F%2BJ92ryVhGgIvFDj4JXJtpYzmBwPsJIbbU%2BXhP4sSniIGIgYiBiIEEAzua2cS5DE5mYIomJifk7HtnldliQdm77x1l9tj%2FBxHJhWdaNBoQkWg7P%2FzwN3Lw4AHVcKhZHJECH8WCQ1xc4p88eVLKpbL83d%2F9nUxPTmt%2BSMVxMID53a49e2V61y4ZHB6WWqspE5OT%2BoN507Ml1STLHBhlczDIGYUNM77%2F56%2F%2FWo9c4WiWYqGoey1nZnYJ75MTk8pEAv%2FKyoqa21Iu0tnDR46oGeBApaKLJswhOGB1xMyXOmL6u7S8JI8fz6oDFKS4LLhoMmGQuYiHBBdY2acJ04lmh7p3L8K%2BjwnTZZwnoCVCS6vZPPMP%2BEQDq6bLAoz5Tv6Uo9mEzGiCTWb7zHJjhIgBBrX2v7Cvi%2F5Gv%2BfycY5joI8%2F%2Fq3OJZiTf%2F%2F99yrEUmuDIHghPuOCNCqQ0v7arVXhW%2Fe4ifjfThig6Zi%2FmE%2BxsGBO5Mgr5jNmnfXz3naCfufAspXjxBlN1i3WShM%2B31KnezgDQqhw9uxZtRxizYVe4CIuaXrXO8Yv%2FcQYTcP5VsK7c1ox1iRiIGIgYsAwkGkbZbRD8GFEnjnxaakpKtXDDLbRsP2ALBwsJkgtIR5YUGBwWJBgcLh4hxHDUcDk5LR6oISpLLKfUprSbjak2Wh2mEo0iixgBw8c0r2U5AFpwjmbj2YfS75QlBze7nCAU12TXKGgTkYy2YzkgyOhPNpT0mGq226piSoOgrhg2lR70mrL6sqK3Lh%2BTWYfPdS9psDFYskRJnNzcwoH9YBImpyakpHREdMQ4niozv7VhkIHMY32lf2RHKmCSSwM5vj4mEryMR8jH%2FZucgdvfoHTdLdJE89tHCi1mlpmPgfzvv5cQloJ7%2FMtyUhLHTiZA6a1WlUeP3ki9%2B7eFUygd%2B%2FapUfJVMolyekC31KjJWCnTSPD6S0S7y%2BDAevP5qWS%2BYDLhCz0VIhK26fNGHj8%2BIn88MMP8uc%2F%2F1nPqX333TPypz%2F9SQU7jBkjRG18wJiQT3p8aIbxz7bFAG3M3M92i3PnzqmG66%2F%2B6q90X70LI2EyaFPaN17bEwPp9QkIMZ1Fmzk7O6sWTgiLsNLhGBMcBMJsIlRgrePHPICpLf3Bx7G3N2F8571Y5Pxs6wdxnG%2FPvhChihiIGHj9GNihmk2TQuMYR81S8%2BYlNps1bR0LkS0cxq7AEPkRKSxKLDa7d%2B%2FW8yZhtjDrhGiEu4HFaec4ksOc8xSLJTW1wsSWMLzTkoYFaVAwQa1IO5uVpjJXoswVHJN5WM2oExz2VaoSJBwGD7OJVhbTVzsn1DQsmATnc8OqXTywf796jKWsSiWv5rLj4xNKGJsEPqNlwMIqAdyR0Oa0fnQ9iGP2nVFXeEkYWupuhDYSfhjThjpIIQ9fYN1scH33hQqjcsYIarl9NDkuEiC9tVRGYLwRAExOTKgJMPVHk4uTIGUGAiNuKdaXHEMiBl4UA0Yk4vTF5gXeGb%2F0O56zWZ8m20qc4pEWp0FffPGFOhXBay3xcSpi%2B%2FvsnEbgsfQJU2Jl8QWGNIHYy0q%2BJ9%2Fi06%2BLAdoCCxF%2BtCfzsM5BPdqsXxeqt7c0cM%2Bla%2BQmRYyMI0%2FHuoWmmmNN2HeNIIG9mpybiZM8xi3m0snal2gzCYNW8Pxsn6YJpqMg6e3tk7HmEQMRA8%2BHAaeini%2FVto6d1ndB5LlDh4w66cmImYW6WVRaKpnNsshkO9JMJRxhEsNi1%2FFWybsyQYYIGCUchLSbTTuWIyxOhVJGijBfqr0zSFrhWBBluFptgdHkdBKgdtozp9yoMWAwsFwsnFqzbE5Ng2EUCfOFsFA0Ta1nhGZQ4Q4OjtrKzNmiaYw2zGVbj2nx5nTil4WVBZoLPIEjCHEuvnl63n1B14%2BhBkYUJN%2FI18OoqTGYVl%2FFQ0hHvizumD5zhxqnHkqVa7kZybSVfbbi4t%2BIgS3CAP2ay%2B8%2BrvydO30dqwg%2FjxfhyDfffKt7OGvhGCL2e3FskKejlyPAsjEQBD9hoMGgEo8fz5Tp5W5RtWI2z4kBbwusPmA2ESSwDtAuXOk2e86sY%2FRNYqB3TeE9GT%2BeCSuHjVlC0oxokr6tVkrzOMe7cUMuXPhJrl79RYWoeGHnfG2ErW7FQ9uTlruuP531L1mxWi3Ga7LuWtkJHA5dvEcMRAxEDEQMJBjYYcwmk74vQsYg6V5LXYnc7JLFIjHthJnyxck0nBCHhAUkoc1MOCUL1LWFfByR9pxRBilEgYjUMy7tnRIhV4y5sgcYT2ed9Jtm6JxZt%2BfVNAzkkc0lTZeGQ0sjaS4jWa0EsNkvsfrqAO4VsGSpYKS2acKXPFS725UiIc4tmAwccemIqYytpIA7VAVJPGLxazVb0s7AuIvuaSWGfbN6JCniU8TA1mGAPu6Xjxl%2F5%2B5jgHGBh%2BgzZ85KqVSW%2F%2F7v%2F5YrV67qXj%2FM0WE40ZQQ3%2BcRI5jNvNYZFjo%2FcZyR6Vdmuvz4%2FOoxQDshaMOqgzsCBTSbznyg2aKb0FbxerUYsHXZGE1%2FTjOYlO7hPnYYb96GCHkwm71w4aJcvHhRfRMMDg7I4cNH1M8CFj0Ij5K0yXjs376M1aTdiWPlv1o8xNwjBiIGIgbedAwkHMubXpMO%2FCwGLBrG2m2GJuheWFhQEma0k23XQ7LgdAXzsolPGiXFxHoSC%2Fe3dTl3Arrh7QT3PPQyZs%2FON50BZWyunHQqnjcqp0%2B4MpoJAZ7khEbTmG5SKRzsZZW2oGB9MbiS3ONTxMCLYsD7HoIX9kVzfBDM4%2Beff657wdCIwaQQjhdTF9CQzolgvrswB%2BJYTfCDNcSLwhXTbQUGjNFEo4nQACGA7%2B93gUBH7LWZhWUrQHqL8kgYN5dAGqMJCkC3M5LJe%2BLJnPbxNmJ84UMBfwTnzv2ozCZtun%2F%2FOyogOnDAnP5hCo8QgXQcd%2BP5UpaPcw18yp%2FNxntKFvFTxEDEQMTAjsfADmQ2aTNYFBasXgan9%2F3Xb1%2BHzEt%2B%2FRA5JL%2Fu3TU%2BlOpEOM8QCtXVVd2rWszbXlT2txptF87cXNeuvy7ssbS3GwMQmBCoMJmYWeK9mTD2cOJ05Msvv9Rv7AlTx2LFQvDMbOno754HmjLTdDIOej08v914%2FrVrz5yERhNGBadrMCKYWKLdTJiKt3XGfrWtYYymCR59fHBPrxNpCBDQ2HdjTH0McV9cXFKz2b%2F85S9y6dLPqpnGbPb06dPqbR2z6O72xGw2p0IfyqDMKEtIYzs%2BRwxEDEQMvBwGdiizCVK2L1GwfSF7uc70PKlVeowRsS7sJpWGUFhaWpK7t%2B%2Bg7tEzS6empsyETakOEyD0EyM8T9kxbsTAy2AgTRjDdKLhxMkI4TzDcOKtljNvOSqIY1MwxeSCyEWryd2JacYCxHMmk%2BzhfBn4YtoXwwBtgrAL7TSaTbSatJtrzKzdN6%2F1ejEo3s5UNh5M8GhjwRg%2BGyMmnPExk8YQYVzEw9vs48eP5fLly8LxRI9mH%2BnYO3nylJq2s5YgHNK1J2hKPa1tt0nnHJ8jBiIGIgYiBrYKAzuY2dwqFMV8XhUG4B%2BdcWRPKoZMaBbm5udkbXlZCT0O1zYizyTYSlrAoW5jYcKrwlfMd%2FtgIK39gFDFZBZNJlowmMk7d%2B4o0QvE9N%2BpqUl1xuWMpoc7kW0jgX4d%2B%2FbrbGXXbCL4QnAAw2nzD%2B3ozuYiw%2Fkq28jxzRyfPFuJznDSPvy4iIOA4O7dO2oy%2B8svv6jQcu%2BevYLnaM6kZh3hmBLGLcysOw5EkGAMa2KS6wzsq6xjzDtiIGIgYuBtwkBkNt%2Bm1t7GdWX552Khx0HQWrWqZ5niUZejYGAy1R%2BknkcadcMBXfH2GjGgyvbQZ2EyOafv0KFD2ocxweSoBQ6NR1tWrx9RL7aY8PHNiWj6Oz97p1%2FHvv0am1Q1mmikaTNMoPEsjABABWOhwSMz8upayMcDjKQ%2FJ2MFxtKYS74jGEADTXvdvn1bLl68ILdu3VZNNKbtJ0%2Be1PNREQQx5rjcwZOPXcLQdPLuzOurq13MOWIgYiBi4O3EQGQ238523xa1DhZQ6gyIhR6iAgIDaXMuG843C5JrBdgTbAvoIxBvMwaSvZb0V2MQ6bcwnHijRYN57tw51XBeuHBBiWLCMOPjzmXEtD4pwevmmm8zXl9n3Zl%2FcCSDKT%2FMJppNzkmO16vHgM%2F9lMS4cAbTxpa9NzmsOqwHrBdoMzGbvXHzhlz46YJqNkdHx4T9mTjo2rVrl%2B65deg9TwQ6zsgy5vjxzcviW7wiBiIGIgYiBrYOA5HZ3DpcxpxeGANGREDg8cvlslKulPVcVFwCdV1ItvEW2BUYXyIGfj0MQJiaKR7n0Kq%2BvUMcQ6gODw%2Bp6R4QEffatWvKeBKXPYCY9KFpMaIawhcCG3M%2BI7R%2FvZrEktIYoK1gNtGUwcxwfI3vtU3Hi89bj4F%2BDB5hjBnGGusC7cMY4d21mVeuXJHLVy7L3JM5tRz48MMP1XR2bGysY0FAOr9szJlzIc8f7%2FPkzxikvH6wePp4jxiIGIgYiBh4fgxEZvP5cRZTbCEGYBozLPBh%2F00um1VivD1ixB6EgMZB2h3MoIzVjOzmFjZDzOo5MJAQqdozO%2BZ3TqRCtMKosFcM81qOWPjpp5%2Fk%2B%2B%2B%2FV2IWrcv09LQyMkZA%2BzFDsU8%2FRzNsaVTagR9mmXijhdnEEy17NuP16jDg%2Fb%2B3BJg%2BY%2FwQ5hijSVzd0z83L9evX9ezM2%2FevCnNZkNNZj%2F66CM1m6XNkrGYjCnCYFY55oS8%2FEo%2FW5wkjceJ94iBiIGIgYiBF8dAZDZfHHcx5RZgwBhI3Ygj%2BVxO90kNDQ5KNpPVd3eookQA7GZCI2xB6TGLiIHnxwB90faAJRpOJ1IhZv2CWeFsPxjOUqksmNN%2B9913aqaJqd8777wj7OHEfI%2F0XL2Er%2BcV768eAzCYMJtoN7loP5zKxGvrMED%2F7u7j7rAn0eozHtrtZEx46RxHw9mZeJvFCdDCwoJMTIzL0aPH5NSpU2o268IByjCzWMaUMZk%2BRhFgOgw27Cyuna%2BdGsBecLxHDEQMRAxEDLwUBiKz%2BVLoi4lfFAPKZIbEGTFzKb0rk5lXRlO9NhBHzWaN%2BEgT8y9adkwXMfCyGDDmkH7rRG03kWqELQzLgOzZs0eZUwjhH374Qc6fP69MDXH27dsnlUpZcjk3q7WRYWa16%2FN0uK18f4v3l8cAppoNPV8Tk0qECZjQIihYf9FG3W2zPk4McQw4Y8cdhh78crFdgn5OGN%2Fo027Gagynmc8Sn%2F2ZeHi2szMv6b7nAwcO6N7M%2Ffv3qzWMM5perq8VPha9zRImNJFcxvHkWIv3iIGIgYiBrcdAZDa3Hqcxx2dgIFnik4gcfSI5O%2BeOPTkQIPxgOPVTLif5HAQeLGkk9BLMxafXiQEjUvv3RzQqXDgFwlmJe8SEYIbh1P4tomcBouGEsXGi147Z6K4Z35xQxjezx%2B2OFd9eBANYVdZqdWVqYHxgXPjB%2FHRfaOZoV2OOur%2FFt34YoJ%2BaQy3fd2n4M0tW03S2WnyzPdA2TjJCGJrmlZVluXnzlnzzzTfq3RkhAN5mOdYEywEcOel2i86eZxt3xsACkb33g02%2FOle6UYQYHjEQMRAxEDHwUhiIzOZLoS8m3loMGCPpnj4hFpzZ1OMHWsFToWo6t7bkmFvEwKvCAAwiDCeHyr%2F%2F%2FvvKdH755ZeqpcE08JNPPpHdu3erJg1C203HXdvD3X8wP%2Fb9VUH7duYLfmkL9mtymQltcR1DbwwS5ztGZv95egp4M41mRjWaLogB767N5DsCmEajrswj%2BT969Eh%2B%2Bum8np%2BJCe3ExIScPXtWzWanp6ekWCzpeFgvFHge6GLciIGIgYiBiIFXiYHIbL5K7Ma8nwsDMJnVWk2WFheVAIHgq5TLalKbyYq01YmQmRk%2BS1r9XAXHyBEDrwADRkQn%2BzCz2aISy%2B%2B9957u1fy3f%2Fs3ZTjRaBKG9hPHQmjUnOE0rVCi6efdf68A5Lc2S5ge9mqurKxIJpvR9nFNdC9SjOE0AQBtEa%2FNYsAsV2AqvQ87o%2Bn9nW84AWo2a3qsyVdffSVff%2F2Vap3Z5%2FzBBx%2BoWbqdgVru5NMPgmc1DTDQ7vGKGIgYiBiIGHi1GIjM5qvFb8z9OTDAwq97c%2B7elXq9JrtmdsnM9LTkKxV1DKQEip6R1mva9hyFxKgRA68BA3ZUSlu1mpzFefz4cWVoPvvsM%2FVSu7i4qFpPzuiEyXFi3EF1DZB%2F8%2FB43xoMoFFj7llbW5V8Lq%2BaTRgg8E5b9F4WBKOy%2Fltv3PhuFikIVUxz2VBhIowm%2BCXM75jN4vjn9u3b8vXXX6vZLIzl6dOn9edenN3k3DWapF9%2FPbtt%2BrXt%2BnxiSMRAxEDEQMTAy2AgMpsvg72YdssxgGSbM9TQbg4PDavpVbPndE%2FfAAAgAElEQVTVFPZ0KoGH584tLzVmGDHwqjDgvZU9yEYQwzAODQ0Kjk0%2B%2FvhjZWYePnyozoPQ6sCIchYnzA4%2Fv4wB9bd430oMwKyg2YThzOdzKgjYiNnELNqYFG%2FbrYRk5%2BWVZgRdW5wOo8b0e7TKDx48UAaTo4IQwHB8EOPh4MGDMjk52RECpJnMpzGMT%2Fu28zAdaxQxEDEQMbA9MRCZze3ZLm8lVAinMaWF8IDwQ%2BLtF8QJpB13%2FkUiwjET79sVA9pX28ZkWt82ZpO%2BCyODUyAcnfCM06C7d%2B%2FKuXPntI8TDsMJUc3PGR%2FGRC44ytqu9X4T4aKtYDRXVlZ1vyBtA2NEePqi7Wzu8Xv6a3zeCAPgEYc%2FXN6XeSYcbSaMJWdmcqzJrVu3VMN86NAh8SOCMC%2BnPXw8GMNvpfW2kYXGvxEDEQMRAxED2wUDkdncLi0R4YDykLZqf9qSyWa7NJiQfN1kX0RYxMD2x4AR2d2HyMOsZLMQzm31QHvixAmtCHE53uHHH39UIhyNDtocnAtBZCOIiYT1q2lzmHicA6Fdg7HBw6lr4bpLZK9mciZk97f41g8D9HcbB%2BtncJwBzc7Oqjbz0qXLgoaf%2Fn7mzFnBpJxjgzA7dwbVmH3Hf9Qs98N3DIsYiBiIGNhuGIjM5nZrkR0Dz3rCYqOqmcbSpNwQE5xNiLEsRIdvl1IiA3aT%2F9Eb7UaojOGvBAPpvuwEbjqsX6EWz4ljTGghuNOaGVeawdgcOXJYvxMfzQ4aTnKACZrCfHCg0vHQGfcJ9sP308L6tZW3o6WjbbCmWF1dkeHhYTXXLBTWL4%2FeZi76or3i9WwMgCe0kW5KznYJNMlPnjyRS5d%2Blh9%2FPKfazZmZGTl58qSazvZqMxNBS8T5szEeY0QMRAxEDGwfDKxfTbcPbC8FCeTFuiWpH83RVUoqgid2s02NF7gc43kCI0RES2eGnuEtZKXEZpdOLinDJORk3CnMEvtrF2z%2ByT8m%2BSTREli6w5I3hzUd0v85XY49Y77KxV8LyahJK2Eeu%2FdZE%2BgfS2U5JLEzAb9kACE%2BUKnI3j17dK%2Fm8LCZTimhklHFpzTbLcloVrkONA4LxThB0p8IJKFBkMDV%2B%2BSwJfGcwEzyTL71pk4wQRzPKx3raWnT8XgmfW8%2Bz5M%2BnV%2BAJanMBrjoB3M6Hy%2F%2FWfE8jcdPMO81shz4m8RJ6uzpu%2B8OPqGaTwoMf0zH6U6NRiQd4i9evr97HAu3%2FLQ0LZU8%2BpeR5JPRTpp0ATvOx86MtWczw6RP0Wcx2zxy9IgeC8Fh93du35bz589Jo14XOXlCj0YplcpWga7CU5IXL97Bf%2Bod9RwRPNH6unsxCc5646TSezZeZldUfzGtYCeKB3tA%2Bt6bX%2FqbPztgOodYoGbZk6%2FXw5Nx77QPGGjD1DekVqsqw8nRmqVSsaPZ9DnF0lnmpOEJMB2MdP7%2BzPd%2BVUmD6F3F03SmDc08ANj56O2WzqHzcYPS0t97n60WaRiTZy%2BjT4cPlfYY6QGRzJNJWYZDYzgxm52fn1ehytWrV%2BXGjRtqNnvgwH55990zqtGE4Tfv42L79X0opcyYk9xt3jeQEg%2BzPrb6wZNOq8%2FeSZ7WmOsSpQISpKUCw2MHSfbuzZrGmX3pibg%2Bp%2B72fUFYvS3S0GjJ64pPVyr97IClE%2Fh3wjo1DBHT3wjy99551OYy6Kh%2BOTu%2BqHZ3DIdnc3cfuxTSeU4nDYV7l0gDk4YrVY106v7PXQmtv4YJuIOvfs3pMPT7li5I43UqkxS2Ll1AvfaBgEfdluSVTJJa9mkA0s9eeNKUHpJMjCEkbntKUPM2P%2B0oZtP7vd7DwLBJyUfY05raCSG1kbJ9OewzabLPxNgsHbgZpLMtdg0qc6SURigrzWwShwvzH5zb6ASr8QwWHhnwLIQwWVw6AZAuNUMQWxdNi6HldurUqaN%2BtHSB8LIsjBkk33QZXZNLmDF1jglo0txSMFj9M9JqJ7ApXIqXUB8Hgbui0Gdym72azZbCQGzDE0QBeLS5KQuzmcsq0V0qly23jIhuTwt1Mrz7UtQyNCkijVElke8LymTsHLyE0DDNkgLXd5UwOK3aFldrpoIFL9PiaDt1EZkWTvkQsQaSpUnKt%2FbVnmRdzOpo6DKwQp6hWYU6KLY0%2B5Cvf%2BykDg%2FESeVLNIfKYAjtFNLTh6iHhXqXgwHqzdjfU%2BU%2FZbFPJ%2Fe8kxw61ey0Oz30%2F2fvvb%2FsOI4837i%2BfTc8QICgBz1FSqM5O%2FvOzjn7ftz3P8%2B%2Bs29HoxElDY2GBCGCDt412ptr3%2Fl8I6Kq7kU3AJKgVgDuJRvlMiPDZ0RmVhY%2FcAFPr%2B%2F8577uBFBKUs61xplVY5o7NCrbGUJXhRclX6A5S7ldqe3AIVvP3jKsnkYrgyoOoyrXhFjqxchiNbjbNHrcqFut7j7B9Z7WanytUfjzfG52xgi4sYV2q2nXrl6zS5cuKhHCh5w8dcqazZY1WFJLo%2BKXB2iOe4U4IRWMSwR19DLVf7NotbT4HD6MT4HoPxXwUq7H2V4sfx9hh9i9BJdKVSgiMAWXASP%2Bo%2Bzkr6K3YUihk05nAQxFlTADZuBax%2B4PgjvRTuoB%2BOQs2%2F7%2BnmTB8lk2CcIfuUI6nW4btBs8KMlXuart8Ig2sshE88GiskDagZcL%2BEO3CemL7MP56rL284TPUbWCJw%2B2fJBtU8P5l74YKA6TZ%2FnHHb8Lv9xOS1tSuzwPm8tvaBb8ihn6%2FKwJs5m8m3np0iV9R5NPXL333vtKMl944QVbmJ83ybHJBlnux6U7wqigvmApz0SHfBrvSNM31BxG%2BLmi8GEnoZuiLfyuU5yUB3%2BjvtMcFyqYpR9sIPUA2PIk2El%2BdgV%2BQldFeZyeEk71GUpFP6zXTASvLPfQM%2FmwKIGohJTLHgNzuwUT5Bvl8ki%2Ff%2BCvdLIJL2mkuOPtdgrdkhzAE5ewPcpBDxysjdLmBMDxlI56305Z6UYt%2B2Qv5zDLe85DfEYSUcrP5eH6yjm9rOPqRHIPoSiGU32Hwb96Fk3mIBH30mqAQHXaL2AGDokK5cXSjBUUn4nzQiAxBs5w4HFOAWsCV8cYXH1XZ8oVuKRcAym1H7L3eKzUR%2BIW1S18Z%2FgFVuRYxI9pI%2FWG%2B1gRmhiETnFZ9OP%2BTLJArMmAssr07DniwDOVbI7LLRwpXqPiIRTA53VUwJjSAcpJ4BhH%2BY5UOlo6Ma%2FQJwGtsWmHf6JA9dOSo3Mj4PXOd2ijcADuRLBQN8xcUgSKchHaRIFAzH9upHWrawv%2BeF8rnK3wje%2BVeezjnbAcZAYE9bqBh%2B6pE%2FGt5t15eLLhz7z9aDYbdz8NXYz8s9EJHpINS6KTo%2B4DDiQckjwuhNToRGJ7e2cINyUS6oOfnJzKuUNqsTFHzTSr0%2Bv3PWFXQu489eALJtY0%2Bi0%2BhRPGiQKXIIVEn7bKX%2BqEy4D7rgoVHEI3gKm%2FqCwZK9d2Bw3UStdW8AEdycDNBxnKz7Q4zNQn53%2B2D0ZenqQeyPLZgUOUDcfvki6pkv44a7xDz05BscB4hwsO8FvqiUwlKOe7y7LKL29DZZFi0f7BHYdqlqz1mDyS%2Fgq2EknyNxCRjjEg4rilnGCC36M%2BMx3wRk2ILJdFCDEooVzZ8Yo3%2BgeaEU4FExei9JO78FVm7P%2FofnKj0AWPEhScEfSUPwA7cOet45n8rhE0R5KSnTHNyAbCsaCvLB1k581mo2HNesO%2B%2B%2F47u3jxYjRTMz79UOt0%2FDr0hAuXXShNUboMBnVL6AWOUUaKxjl8Fd35gKDWacIXAr8e4KDM5ee6LDYmb%2BU3qReci8Aj5S0%2FoiTKfWzB36JZ7he1w0DlHcdgenF0Mt9jTbqQcakzCfagIzgxONXtdrUDNss6G62mzczOhM8NOhNJ0eTIKSgGaNidToWC4wEFKe6D2s7yvrIjAFUKOihogwUJ03WUy2JQy92zalIKeK6HZR3VisDWIXh7yNH1BjotfIGgTGJSXAtq2KD8f%2FqtaM5RLdtOvcyEnncySTJJNvnECe8kv%2FXWW9p1lg2x%2BK6yBkYJwGtsjsUKFjFBuAIv%2FV%2FZSlqeB920RZ9Ztc6CAKm6623iKhw1uz1Um1Z3nRL8Cn%2BBkbpZbTv9jzsPODz%2Boyx%2F6H5Zjw9HO10qXdhJpW1HUDwQTOESvpFn6P4EfuMtc%2BXcUrvZvvrNgBNWpQECyZXEwqG43oXR61aJfQE5dGE0HEhPlTQW%2FRcZRkkjuOqSyvH%2BeX%2FQl1wbNUJRYgXin0g4VTVlVfp0d7uRUsGY4GNBI%2FXwMdpcrdzNm%2Be4OI6izU9sRB%2FjJPuzPHeAwSGvk7aIjopNgaNgCz4NMEnhAwKFy4gkLpp0PaCfgn%2FgLxwcC8FyMLHsPO3UEcsBmEAzyB%2FZYOgD%2Bs6SkJuY5XDx3zRMm4rl8JMaCKJsriDgnjy86AAmdq731wNXxSlDVxKhHv0mdOSkguzUm9VgHtzK%2Fj3xnh6fLw48s8kmdsVPgX98cgADqDNVFkYQRdzwcRpuizpxX65uzuEoiXDHgGPmP8rwy7byyq%2FDs5q5sSk49qCw6CwVuHoHycgixsofeKp9zsMxYPDcU0cgR4RbDlLUoNeTI8mRXVUIWHJE8h9CM0fCFDDQ0VV6ZrEnAk85wnAiAwIAYJLEBb8KJjjxTsPAO0w6fAVF8D95FbiKvuFQzkmOif4lvruGg6MT2tzYsEG%2Fp%2FenWGaYzgoQAU5H6qsXiSM08dPsZoUuak2IXvhSnlkMja2qN3K5K5mMCpTJDkTO3jwpBA%2BvEhjJmUvxDH8MTOGX%2FJHMvKOUrJJXCLYpDAreIiPBV1DsTh8wCsYCnuhU9%2BA3hEV2djGznkUlS%2Bmt48q%2F0oOY%2BWaXUy%2BTNeIYgRg8SP2cxIGSVVYD25Px0OcKyNQpdGAUgwN0YLIpxWDYQcyS0fGFotM%2BuqGZtho6GHRIvUrZRlepREQ60wjY2bEnLl49BmOcrw4FnAHvHTbnWJqSXY0mIPPGeDIBDgGP0m6H3okj%2FxxIKDXXFUt8Ai9kVasbAy3NhUUlnNzr9Xv27bffarfa%2FmBov%2FrVh3b8xAltLEQ7RZMxC%2Ba4Bu5gnUjlA1Hi%2F6hu0CiWTPJHPOAfb2lYcZ1g7G6VpIAHEXwETrLpsYGmwFa%2BJmgHbtiXnhbEcLua%2BAdvUx4yL2c4MnI79eROICowo1UOD%2FwoS110is2B9vb3NXM8MztrzVbTR%2B%2BT%2FAqiE%2BAdrtDxIE7yJriUXrp%2FeKBx3XCcy4SzLCW6gl4d5Efgcck7gvfo2hKaROUlxrEEBkrNXdE99OQnfSoPikSgROOBM9dj%2FIb7I8npgM9RyXZCTiR%2FW1tb%2BqwJm199demSBMqnf%2Fh%2BJoMri0uL%2Br4pAy7SHfEuLblEo1Bj0RO0BE0Q5oG091MU4VflBHi5X42nOrjVU9dqvKYBn90mxbcKnCged6L9sBv6cHAHDx2LUn5CXbUh6PE6SPT3eH4Ge2iv4F3gHhpeQHMcKB92UTx58MTRAa77brcsL5c4%2BpE%2Bycv4zDRX0Y8rUUrNKdsAD%2BqKp8kDHZ0v6uVCjtRGV8AZIou6FX1O2WpQsCI14FM%2BZQEPXaZhYOJn4CUGpvSc3wmXEjyWDGJGM6kRPnmRx8L2vZ3C%2FxfPSwEkd%2FJIG9kfQk9t6LO3IE5bfnS5ZJ9WxwDzJ0a570i6C704ENnQOVbeEa9FDEhMBf3g5VGRN6D7xFs5gAtMYjD6tyjPreQ0MCUH8Ze7BMQ5MO4z45TXcEp02EmOBlkGHgekziWZ0%2BPzw4GnJNlEjR%2F1c%2FdTLeW1SgeH6WhER96nWp5hnXRmXh7D9I7cyw1HHpTgKTRqqk6xHIFTUiVn5iNwGCYdcxoosLRUBQTT%2BnkejjIdSS7%2FxODrjECGP8tZB1yYnCWum%2BUMeu7BuYDhXCKhgAZgeLu0FJ1oei8FdO4Sc%2BkT6NFmwnB0nc4iGVM9L1Plt5%2BHFxfz4B0ZlzteHBw44pDAhuscUySBIPCBDwMSzc0t%2B%2FryZdvZ3rITx0%2FY2XNntcSW0W4tcavH8mSNfoMwbfknJUry4H%2FK2RMHd%2FV%2BL3lPXep4TuO4ibqoSjmNPMKGGG3nFom3O2GuVMpZAP%2BFTX1stsgddySUPGc0U0Fp4hYNihYBEFjJQ3IN8Dn0HEXAVb1JUQW4jlJBv3Qu9DGSWAWa6mAcW%2BdbCSta84NwdZh0GActVaRzgQKHlrWdF1xxnz%2BCPX4KXNFhv4znyQPKJr4%2BGICc4FkSmx1hthhg9LxWo9PMJZV17wQVbAf8QA9pwwf9gkcZfGHT2ZaOVFV17M1xCzDSH9lwJpY8hyLxxCuWNk4n7aBoi9kbfgpWsa26aZOs8%2BdfEr2NZtO%2B%2BPKi%2Ff7f%2F932u337x3%2F8Rztx8qSPNoe4kJ1UPXRH%2BlzM%2BnkiLbmJRsc6Nd2jOMdXAwpKXL0OOAm2mFtyWIMUkiP2XtPSXtgFjRnI0AozDAQ%2BTrsHXA7TbUf8QU6FHwtfhlx0P3RA2oFXAmgVJmJ2uKJKgalKOZFePDSvuOUJjWzZ%2FT6JJn%2BtVku8bzRb0h%2BvMQ6vhFKewUv950ZUqo14ElDCl5e1vFjhouKBRAirI8hPWy7qhYy5rpz6Y1e5B%2BjVQ%2BEGLd5HIRcw8P7BgZWUclZeUV%2ByDV%2BptmXLzESNrBE67Eh4WZJM6vBZE2Yy%2F%2FTnP9vVq1dsaXnZ3nrzbXvnnXfs7AsvaCY5W8o2aBrdYfbO7RFas1S2Uh69nvND9kRZ2USh5UXh8g7w3BDd0ulv0%2F95fT0vavrJpLzgE%2B2nP5LognuymERbFb11aCnxwBYExW04Biqymp7EBfDy76BBiglU3bTH0owoIXieHAuXSOh4Kpwl7zIxozg0lr8YDIrS8tV6mA7Jy2eSor6eR0paKKipNB9gVlzGwHopa5WQvYSfEF7OYXyv4jipbJngg7loSd2pJNiJtxIfJYK0736%2F5HNJO3gXfTt4A1O64aXhBM%2BrdcWjQFy%2BvCJjcS7sT7oSgwweTzh2Vf5SvoAXyHusEDhWRIEeURffrZgz%2BOA4lD4Ce6Kck6Fgxgc4RJ%2FLI7Sw0E351hoDb3W9UkazTrVT7j6EKM9XvLGCRzAkZ0cSssU%2F0Z%2BUpUSmx%2BeFA09Jsok4Ktb1gHSqZunnPmMzVCdYJn0xOyQnIE%2FlQUfA807EAxrqD7Rq1B3Sfr%2Bn0dm9vX3tDMlyNwKTTJbS6AClgA2HxgygZlMbpVNS2%2BDoTpl%2BhaAKh4HzKjtKHIMvu5FDCseFvTLDCDsaBIKMzI8GcgQ4Wpb2MkPljtKDiaIzUd8dTklLTDzQVfJXsLd0XNAEpq1myxPDItgfl0c6OkDA63qjpQRTIEUmUOh8wNWX47oDInEkGXV%2BwLfeYKCZ4P5wYFs7O%2Fb9dz%2FYjZu3rNvr2%2Fnz5z3h1NIqpx0E4UG%2Fl99wo30P3guS1DozU04bvIYnjhU8azm%2F5LRLTcslepkUktwjK8XYoicGJGK0nGYEV%2BR44KKkXWU9tIBulu65rBpOf3RcPioI1j4TRg34wDt6DT6Vock8aABH14HkMTKAPhIncKw3Y%2FaZkUvXNhE2GI6s33detdpt15emB0tKAsFdQBNfuOvBfKOGHsN3%2FzkOUU4zHT7AAm3O3MpgSeCMjYED05XolQZuNMJaCRR4LCJH1u%2F1dd6ut81qDauHxwIH0RyyJYhB50FOwXMEv5RDr7hfyKbSEeqegg7HOWlD5tJrbJDkK2SLHLhwNvm%2FjqovIQIdtxfXFZ7xU3IanGPgN5ePsVwWHohnqUfgV%2BP95Xl7%2BeVXjJm2zsyc%2Ff73%2F27%2F%2B3%2F%2Fq%2FTvN%2F%2FwG%2BP9NnwQP%2FcF0Bo6LlakHGhfBKidpDGPgaDzM%2Bu71CO5d74GewUsbcA5UdqiM8evfSYAfxOywddFRW8b%2FDxYdF57OxA45H5cwn%2F9FLF4kOf%2BTdUDfdqknLRVZ4JZSZxdFm4%2F6bdRDZbqb23v2u4uyWbHZufmffmmwMnBRPPSArcmF73zDMBcx684lZ4ljuVOrFlOR7EgkpUMQAFGtyOwbm9uU84vp9L1WTag9rPV4JV0rkTI7daXHTunkInP4lFT%2FHTKxtGD5wmGPkjg3VaZhRyNsM9kiZd1nIb6fubdu3ftq6%2B%2Bsk8%2F%2B0yfNzn%2F0nn753%2F%2BZ31flk2A6K%2Fo89Bf6W7OmMbeCNBdDAYVNDm%2FUy2cYuch5fM7tPIHibwjrivdl%2F8PuUVfkME8eIjfLgK32qjPfehzSuPf8HfgoWKa2XENc9wQZXI9%2FBF0BfxEUQIPWQCItlJu0gXFACGkiAdESwW3xBuYrv8%2BU0Uf4s%2FAucTb6fGWKZ%2F11DajHErYXAdLPP2sygNkSH1kpXazLxXMbDOS%2BbBUoNCn0rp4R7wV9lBtK2lKGoQlnRq%2FKO9lSvx5FOSMbQZW3nSawSwHDxyL4JvkgF1476mer9KvOnxvz8Xv3FBWBVr49MCBRC3vu0wYhPFBMvjF6xLgTz%2BlvgrdCLcjuxwxmON2QDnq5n2xgLoWA3DEYLxCxDvnodcsbaXdUFPpYuoaOt8w4lRnpsOVSIQz7UkNoCkGBUUPK%2FaGg4I%2FGkQo3u1nyUXJX9GGboz5Q9qb%2Fp4nDjxFyebDxILRh7GHgZOoMbKKovPInbIsJpJBh4exp%2FEULZDQEZSzVr3eUvmNnT27ev2G3bl7V58iYNZhaalpLZblEiTGBjgYb3aOY%2B90RhAELu4w5G3CWeKgwZcM0rGgwytGnp2EIsmR8TJboKUJdeGKQxFci1kgcQSeOF%2FyeeHQFIR7x%2BzO0B0nwZecE4mOEjicFPi5c2xOfFCe%2BzgylvhxJHjWy12UT8fo3bUcE0E25cALHzzCqxLgkjQP%2Bra3vye6%2BbYa31ojcWIZ4bfffW8Li0s2x8e9W23Vp00Qw6l22bWToHsYH%2F7OjrkiVDZ7oiWSPRyyd%2BSAitE4dKcS7KA%2F8Iugqq6lVZ7IpPy0GVGonm8kxfPYWIR2QU%2BJNPyhZTHLev2Bd8q896uxDA%2BA4YkCc%2FBTAjSybrenGaxRk3cewNgHJuAhZeXS6WwG6E9fyYd3dHRwdHoe0vCcOi4v72CpzXCCzyzSqZTtC7L0eiD7oEOCFsIO6Oe%2Fqi7Bq0G%2Fby0CR%2BmAFF3cp006bXWktMHS2RHvl5AZInlvG7jQpHeiEUuNwYkYHNEMh3faOWpMGu2Js2clKQO9X%2BJECTaM4J0i2K%2FNdWJZOHAU5IYKoGsUwvbBDX6hY8DFRhTswAOiE3iA6UsF4RZ24%2FKo1%2BN9HVrPTlyDSZTyQQ%2FhrYd1OOvBBfKUbQicytYbTTt27IT95jf%2FYHNzC%2Fav%2F%2Fo7%2B%2FjjP8pGf%2F2b3%2Bg7hJ1Ox4Z6Jy%2F1yOt7cICdlUmClEI%2BUtooOlwtwd2DFGqDhujLSCyCHx%2BwkXBc14MPyGoMd%2BQmsfjgE2ygRT964K1gCJnjb2WbyMcDH8oVfhmee0X5cXw5y5gbuexcsFUjGSdU8GPAlY8XgETRccN%2BKYM9bm%2FvaGaTBGhmhiX7OGIZp3QQ6Eofwhd7Q56wodfQj%2F5wlBZEgs0z%2BRq5OY%2BQk1fwOHWZOtBFG85yJ1hSEo%2BdvhyQYpaFO9TxQUG3IRp3Up3HupYjiH5Ks5k%2BKJj0IRVXPbftpA35oC%2FCF%2BlJN0NvpAI1H%2ByQX8nnLsu9vT27du2q%2Fcd%2FfGJffPGFdXtd%2B2%2F%2F%2FN%2Fso1%2F%2FWu8dz3Rmol9Je%2FdBMpc53JC5ikbHB9nRRgyeYavSyaAbXsSomnMm9E2gHLfku%2FQHoKETSFm%2BKRqS7stvOw5QLF8bfY1kGskbOKUvDNVVJeogR%2BpBkxalyiYY7OsbgVeh37I3pxkUwI9%2BCHz1Hwm0bAB5OGNA3ftqnz3mNvDke6nPtYp6AgitqTOuIw4L%2FFyuzg%2FBlZyzKTd81wHnedq5rDn6eXQlKaCs91LR%2FwDUwYge%2BBKqRGYUMgaQ81JiUQHXPYdcsxr2Hn0JOwe6frqM%2BNdxdLHyDmiSoXIO1BrWDL44n%2BkmVC90GKpRIzgIP3PAi3vQpP%2BjLPDhIv0CrgI4BS%2FVU7ocBE2uPXntg0nwSzZPPb065H0kPoHgCL%2FFKzvSPRdH2IAPbKotdUX4nbqW%2FqtY4EHfqTa0wsA3qdPgZup2JIS8WgYtSh5xBFKFXBXk%2FKDPhr6mNuxisNT7XnDADzNgSmvqK7VihH4nXnUhKSU%2BgIdhN0HO9PAcceAZSTaRGEbi7hWjINHjjptOOJQYYaqPGjJyWRiGJ0cEDHfA1GFkfVhr2KBWt4ENbY%2BAZL9ne72%2BDdkYiISn0dQzf6ksdpwMQ%2FekheQmnLqgeyKqANf9llDQuxJy%2Bu6E1Sk0GO31UUJg4AzSeeo6nBnQ1ck0WzL2fKkTHoSPV0Wu%2BfnMp%2FPLnVXQXDJKTkXOK7QDp5EdNB2cLy8UOKeq1pAT4o63415YTjscnpcOBxQBjEaSNUKGkx2oM2x3Oko2gLO0vGRvXHjT2u2O3Vtdtc2tbc1wzs15x%2Bl8oE2C5JjhyXd%2BICscvKiFPs36%2BcgfssY5KpxM%2BUsmrg%2FIQDOkBJDaldJHqqsBAgGvOsgICoAJ3tkJJs00rT91bL6xlDoUBXnZATnv4BmDHIwCEjho5Fezqf7uopZrS1aMZsasG0SAg6KdnHlVIUeB9oNGElHeDYR2%2BEdiBc7%2BOGdUCAC4n%2FKUloWullZCvyS9oHPBJrQJALBithpbEAYwFmDeKdabdOKKtNWxexDveihOyYa8Y2L21Ts6TzTBFVrgE7mdw%2FeEqqH24IPbjegKnaT8sB8jyrWGtVrxblh0%2BAR1oKRATwG8w3bdcvphiGwwUKVO%2FmQvrLyUmuVIMaaHdYf8U89IclttlRWufubLQcGBQQ4CW0a9tftsQzbA4Auzu599%2Frld%2BuvXsoUPP%2FyVnTv3orXbLeEGzSwzBx8FuhHYcb%2BQnIIlxBH3lJg7zxRrhD6AtxPs%2BhUNuERFl%2BsueMqOEIZsTuro7QqVjFoAACAASURBVKkJ%2FgkmJA%2FE68AItWs0RTN083NZuv457rotvdR799TXIFWW8ef8GyCkB9oUQ7PpHizx3OeUQNXtFTj73a7gzczOWWd2VroqXBwdEaRTkkjBSLtxn67WITPKk5Ag%2B6wOTqmPwhEYGfTJXQYuOZMOn6I%2BeuY65PymGXyMJ4i6UjtqQ8DdnqWfPM7gHvuMwVFu1jiPPhHfQVH%2FB6PgPHyhI%2B%2FPpDslHszKMHDEJ3pIovisCctmv%2F%2F%2Be%2Fvkk0%2Fs5s2btrKyYq%2B9%2Frq99957dvrMaWu12tJtmqvySS6iQMCRUaBd8wFF8En7VN9VJGDuZ8RteBl8xefkvYI0%2FDMBr8hz5jirS3nyMHUu%2B0gfhxKH3MerL8EfUA%2B%2BOsxsh%2FrCNSIADWQpc0m%2F7rxNGQuO5BoJowYbgcaAFvz28%2FxXIqnXNBhO3fzTc%2FVHpe8Ba3iLcgoOsLJOAd8bEG8iJpJ9SShOS1Bf1PWBIbSMJz74yGAA8QL0g1PBA5jMoJeQIbGhz2fGzpMafLxmUUM%2B8iciJgdV3X7BkgEkdIG%2BjKbFH5FUMinMR%2B2DSw4kukqXA6XyXSrsugJ%2B4MxgYKMRAwXgGozH7sS%2BwA1%2BQgu%2BhDaI%2B6BbPJAeyvBFq%2FBGX0L%2FgKMVOcEr5IMe8XOYnsi67vmgq8vZZUtZ8ZiBicprSCpT5UfRv7u9oa%2FyKYVShWRjVQAxHjygg5U%2BiGbXV%2Fmh8Lu83pGDIuAs3sSKIFbyeKzi9Lbq2Ly3A35pXyJ2%2Bs9zwYFnKNlEXh5Ao8z8UGiN7kQHFH5O9zG2UezQh2G5w4z66mtJNt3weyy1Go3018ep1hpKRlnyWWNJ5GigCUnaw2%2BRTGqMWrvByjcLH7CS89Usk7I2uWmMGyctJyRHH%2F16dFgEnwJcUOjtpIOX4eIQ8v0o4eEUUQYnUGdDE7CKTkwzCQSGCp6U7qrTTFggXG82hXzOWmoUXng6TGeykCpmTwg84D9tarmk4plY1ionEx0EHVExGxsxGvVIhsQnZhSZ1Tmm48qRe1pCS6CSzlQdjpAgWPVlPHLg4WhjkE64iNHapdJ5ixxoXx2EAmTvTqA%2FUlAPVhWIu3N3GZQBRo1IVstsPDGS2gkuDhYZeVnaRrZ08OigRp9TFxB%2B6CraRh3vGJ0nnox455PlKAMc12GB9Wv0NUYoNYrItfp4b9v1PIIxyqGHSiojAAOuRh6DXnQglkdRV%2FhThnMUXT%2FvfJE3S3dSB4Vh6Jo6F%2BBm8KykMzpPAg6NhJbhBZ0hSTyy9OCHxClHfenQsSMfllXZsN%2FklQew0On81BwVnaAyjwrqKYPwF9TTLJHwdvzgNbTyTDyPQMF5QPLscnLbcj1nqTh8oK70TIILeca59IFZVHCP2Y%2FkqOtwXkkppDNHjx21995%2F3%2BjkP%2FvsM7t8%2BbICfGa%2FWVLLJlroFkEcM7PCPWxBzbLDcz%2F4qNn68COi0VVZdIb%2FYIaZYIL2JGX5UU%2F6mSlOfVKd0O0MuKRHOVMecvdI130g1CmwysEOzb4yYh%2BrURgI8XQwZgaD0YjDWM0x0FJk8Sr0TPKRbrncZSEBFx1MHc774kns2M37mtDrS5ZnpHsM%2BvArAmKCLGV4oQtYoBI5sBBUt3u92uB%2BED8gfxV%2BAg8Av6q%2BmLpBgvQPPnkg6f6ZoA075Jd6hTblrD8tYw%2FAxUdr9kHBnpglGUqvw79AHB5ftqO6XIe%2ByczDNiv9FBsmZXJBac0wDvChfQ0UkmTu7OzYndu3tRKFpbNsCsSrD2%2B%2B%2BaaOR48d0%2BAJ1DO4KD%2BGn4zgGhzTR0LroO%2BrJdBpBhyZQYFW5zabi8HFvhIB6tJPetlW0OYl4T9OQ%2BtaNEjBmfvhZkNzjC49%2Bf6YZQ99EU4M4LSavmoHGwg%2BSqekI0DzhA%2B8BTP1Ime0Nbjis9Cyq97IWs2GNgSDA2mrgoN%2FU9LiOkQ%2FxcZhGaxLD%2FAx8EJ4%2Bgw%2B%2Fhw4KhuvklCWH%2FDk7%2BFFwIcJehWIBCeZGrOxo0Ffr3BQjx9%2BGN6K9oyWaBu4qusJGtftVkurcSiLP8DuwJOVHxzRHXgAXW2%2BZ6tXExyycGUWLHy6yhavfbQ8fkmfGytUWNGDXRSxRx19YTDP%2BxTnkb%2BeA3y0Bl6ga6If%2FyYRgpv3LazAGgzoD1lx5foCXUpwxRH%2FB9gMsrgLrWl1DzJgtUn2na4xAbff96Qs%2FDJ8ZSWO%2Bnx1NS5T2hRcydj7uiwru4k4gVeotFqs7%2F4evvJcMLOvArmwMcWssqGR7AuZttp8TisHm9yX0KfgYzXgjv4MBtYMuYpJ6LniXPqUvvEfOgTe%2FFr4C9mWexZ0F%2Fynv%2BeXA89YsilPEtL04EIBBrdlryyLTL%2FqBihHpGDPr70zw%2BB85oROkWVWPZb3jWq2PxjaXs9nODFo5jZJ4xi1w%2Bl5ruhOirZpz4%2B4OHcIGB3t5pIx7wgGmpFQR0TjcjxauCHHi5niDwvnH8srWLoIPAIiOdt4z5TgX8H9CKfgM5PQgnOhvEYto4Oknpw7O%2FGRJPZ9LX46LHDST8mMMwbnoT6cTkEBToxmRlLA8ph%2Bvyc%2B8loZPFAgyYhwdG44MznOCMhoYxRLV8GJNkhglpeXbX5%2BToEKTox3rACcM78whtmc%2FIlP0R731EY4W%2FwuZTUCSfDYIAAoOyLKw2PkA5%2F4o37%2BXFZ9XdJB4YSBBa%2FgrfdZ3qEjMYIVzSoS6MNHlhqTxEciSjv8gNvPJF1LVPrikzo4ymo00TtryiZO8JRr2gau65rvdMh4LNcKUqIjoD3JNZJz%2BAws4RnvfIJ3ylydcQXXbDdxgH7K0n6H2eUIQDSEHecqWydB8KCI5IWZOOkgBlJzGahcMJpzaKZ9%2FsBb96R%2BHqxIKgQe4K0OtqVlRwrCkAR1cvkOCUCfwJj3uKODDzukSeCjV%2FzxvivXdKIpV%2BEWM3g84w9eECSg51wzEAIfiqAuZI5tuT1H0hrBgGyW4ACaXAlcL5PWIiBmhrtuzVrdjh45ouAdXn4eCSc7qb7%2FwQf28kss7V8SXpT3FRT%2B3qv7BpZld4XrzMyMNdst8c2TjtDB4BHw9%2Fb2BIvvHiIzftqNOkb%2B4YnLcKCZLYJsPl0BX9jVEN4w4MSOusCjvAKTwcA67bbefYcx%2BCklkIOBZsYoh30jL0xvdmZWOoA8lcTWapLTXndf%2Bi1Z9fhEUl3JogfmEWiG3dMutuI6MLKZmY6xigKYLMHf2t62nd3dwn62d3et0e3K%2F8x0OqZ3hrHT0CvN5PUIsDx4BgeCy7nZ2Qh002fUbH%2B%2Fa%2Fv7%2B%2BI7tIEHejUzNyt9EWMVlMPzffELfcEP8%2Bu0Z7QjtwYM3V1YrzfQst8uusdqCMltYPNzs4UMMtjtdXt6PYHgnh%2F%2BCr%2FGO8GsHAB39XujoXjR63aFQ7%2Fbk8zQk8XFJevMRLKh2Yuh7e7t2e7Oju3t7drW5qbduX3LrvxwxW7cuCGYb771pr37zrt28uRJyW1za8tGW1vqK%2BkDkCt6iO2CP3jBG97Tll8hiO12JSf6gJn6rPCEBvwafNUgAXar5GAo%2FrMiphXvobsv61t3b09LeeEpwTk%2FBmfm5%2BclC%2FiNFvZ6fAZnR3qI3hKcE2QvzC%2BIt3pNRHo9tP3dXdvZ3ZNOwUNsDL0GJrrlabQPFO7u7tnu3q74io%2BBzsWFRVtZXra2NqOSi5Be7%2Bzs2t7ubuFXgMPybn1%2FVLN5npCgU%2BgsR5L91Ct8ADhk%2F4UR7WxtS8elJwwiDEfWaXdscWlJuoUvggfY8%2Bbmhm3tbMuvY7fi1eysLS4sSLdZdUBheIlM93b3NHiAzLi%2FtASusaeFEpKR7e33bHN72%2Fa7%2B8KTATnkzudukEP6UmDsbu%2FYzs62xyHhN%2BgDpAN8gxu%2FG0kgn89hkIM%2BCPpTrstLy9bRUm2XAja%2Beu%2BeeKU%2BMmwQvi4voi%2Fu35Dj%2Ft6erd5fk81wDQ9IXvG9hQzwK4OB7Wzv2PrGutsqvmA4lE5DV2c2fGHD9ZsZf%2FClHn4Ans8vLIgu%2FKa%2FzmOS%2Ffr6umxLsVgk8MIVfSGRjoQb38%2BqL%2BwA%2BwY2n25iNQE6AN%2FgLX4PG11f3zDsm3LQtri4YCvIYHbWE8uRyU7ur69LtthK%2Bg1oAq7iB60WwbftaSUDMsDPQBf4UQ58PX7xvgXZTMZTEtj0n%2BeCA09ZskmnGL1tRTw%2BduKdBQmdW6KPgGJQLBHiuLO3Zxsbm7aHUQQYRs5UJpb4qQXiVGYl6HwI%2FLV1%2B7bdW9uwtY1ta3XuW7szY4tzMzbbqtvS%2FIwtL8xbv99VsolBMTK0vrFtu12WF3kbjI6q01qY16gPbeDItra39JkP%2Bvx0LoyMLa2s2Nz8HG9SiVo5DMrSaZs7BZwbmxUdWTkSjsVH5%2FZ7XXUw%2Bzu79CFyLgChI8Jp84MvdJBsxMMSVeooGNISkoYcBuVHMUJGR7S9tWU729taZkIHB%2B8WFuYL5wbtlKOj5uPd29vbkgfLUuD5As59ZdkI4Agcqd%2Fd74omHBbBKTJBhp5kLij4b2tpYM22d3fkMOngkDifzsChHj92LAIHPknhzh3HThApPGOkeLbTsaNHj6hD0MxX3YPB%2B%2Btr6jQJBOiQ4RmdK04zAyJ4vru%2FZ6urq%2BqQhhEMMWhw%2FNhx0YUjxrnDx%2B2dHbu%2FtmZdyg36CvTBlZ1E6QhITChLe%2BqI1tfFV65JCpD9ubNnrUMAzwzAyNSprK2tKcigHEEvnSdBC0GdPtlAMMjS791du39%2FTbBUduDfLEVXjh49qkCaABZcNzc27d7qPSVK6Jk6rZkZO37iuC0tLqmTQGewBfi6tnZf9ehgKEvHcurECZuNDp4Qpbu3b2vra7axuamyBMbgeuzoUTt16pSPpkpfhqJnY33dgywFnP6uKjsRHzt%2BTEEMwTN8RP%2FFVwIXgpHBUAHTsWPHxQeNxkayuLa2bpvrG5qBoZNl1Alcjx8%2FriBHOkQH2%2B3a6v37tr65qTwZfqGbyJ9OloATnYBXdPB8lkcJxHCoI8kY38BcWV5xWZGECtdN0a9gIAYxkCftLy0uaok2E67IEZhbm1uCR%2FvoB%2FaHrPjwPYEc9kVwduLEcTt1%2BrRdu37d%2FvinP9nG5oaCkzcuvGHwAY8Bb8AVHSB46%2FX6SiBJME6dPCl9bdWgyweC0EGCnJ3dHfEDe0RPz734ovwWCQLyk71ubMgXEDwqOen2RPvZF854EseMmdW0PPXe6n3b3oGuroJNwj%2FoP6mBBN6%2F1niD7e3uy7bAmSQD3WLmA70meCSZtAgoNza3JC%2Fax9dyhJ%2BnT59WANdUQOwDCK6va0qK8AU4T%2FQaeaH%2Fe%2Ftd2erG1rYRZF2%2Fecvaq6vST2z%2FyFEPsghIwZ2Ec3tn14PXPU82UgfPvHDGbSv6HJIg7PXevXvCE79IoE%2BQf%2FqFM8IVVGUvvb6C3LX1deuKrz3pHb7txPGTnkTiM5Hr3p72D0DuzMBSnuT%2B3LkXxH%2FNlMQACr79%2Fv1VBcZKSvp96RCfHlkh2ZRm05%2F07f7auq3dvy89kd%2B0kXx2o9nWu%2FIkCOQllL13b9Vu3rhht27dtGtXr9rNG9elu9j2Rx9%2BaK%2B%2F8botL6%2FIZm7fvWN3V1eFKz6PgPjk8RN2tNFUoK%2B%2BbziynZ09u7%2B66slGD%2F%2FWt6XlRQ3kNJttDcBBW3d%2FX37oHnTt7Np%2Bb19yZSUMtsrgpHymWejgqomvzGDHIBI6yOsXHfX9npTs7O%2Fb3furHifs7Sn5w96giSBaszUaCBja2sam3b5zW%2F0GA5boAPZ%2F6vQpW66zVN93NGYQmrbhAUkn19jmmdOnPdFjUz86I6vZ7t6%2B5Eofw2APP9o9feqUVhox805%2Fg29CB2%2Ffvi3bxxfhm%2FAtZ5lZY9BD3wFnPGRoa5ubduvmLfkDeIovU9%2FOypemzwSyuJIN6e6t3bebt27ZPkujmd2q1dW%2FsdJJr0vIDuBrz9gAanX1vvwX%2FQA2wg7DmonWwDaDbyP599t37tjaxnoxoIRttdsz0lfNrMHXwdDWNzbszq3bsleu0RdiDAbzNKAHHlaXbNbur4tf0E%2FfRP%2FLChDiM%2FZ2wF8SS%2FAcmrBF%2BIQN4VPxF7w%2FrL5YCaz3RSz%2Fvh99HOUzcQJnfAt2gH3QD924cV32SCxCEkz%2FihzoE%2BiPGZDa299TUnjr5s1IDAeSK75tdm7Od2RGKPTxYdv3lRx7TEaSe%2BbMadktPhGaoIH4BrroY%2FHD4EqfRR%2BIrrQoF%2F32%2BsamXbt2TbZFOWDQD3RmZiWDVvAKH7W%2BuS64xDD0jQwkMos6uzCnbxGzfwOxGoNy7GNy9%2B499d3oJbxCZvC302krJh70ievAZPp7Xjnw1CWbo5GPXrnAsE6MSXOGnPosUqSkrtuaIlQHQ6J59fp1W1vfNI0Ia8mEj0bhlHA4JErMRKgDrjWsq2TT3%2BmhvgKhwch2d3ZthkRzrm0vnT1tSwskBO4YwXFra9N%2B%2BOGqra5vySkTKLHlOx0M7wW12iQaZr19DzB%2B%2BP4HjWoTyDGbR6d5vhnb8McsFMHi3burdvX6NWNUn4CDWbqzL5y1mbl5a5OUxIweHfDNG7fszq1bGq0licVRsqwJ56bRsXrDBr2BrW9s2dUb1%2BU4M4DGYbxUq9n84qKPZBGQ7xMM3jcc5tbWtnhB%2BydPnrJ6vamRROhUAkUwcveeRrnBk46JDugsyVO7LQfviSnOnc0krtuNmzflwElCSbZffuVl0TTT9GVtGp1cW5PDXL23qhE4HO4KgWiz4Q6%2B1dRmKSTOd1bv2Y3rNxSUEGCwmdOJo0d9%2BRKBLiOE9bqS7Ju3b9udu3c0qt3tdTUid%2B7sOc0%2BMEKJx%2BQ%2FAvErV64oIGK0vL%2FfVbIPLbNzs%2BIV9OPMCTC%2B%2B%2B47JTDwACdO4kK70EfHSEdEUA2vfrjyg5ae0WnQcRLgoAcKcng%2FgsBpv2u3bt0Sr8AFuZIE8N7e8pEVX%2FLI9PqwpgD66rWrRQBPx02n%2FdJLLyvInW2xEYoPeJAUXv7mGwWkzFRgTARjzGrM8h4bs0Do615PARZLONEVOiJoRwfn5%2BY0Ws5oJkkdCdbNm7fsytUrSgbQATrfV1991UdzZ%2Bc0usuMLgnklWvX7N7duwqcCYg0o9ZoeFLEzs9sBNUfaSQZGYAziQa%2Fo0ePWbPd0SZSbb6rGcHAnTt37eqVHzQL0e91JfszZ84oGJ2bmxX9yAqab966adfRQZL9Xk%2FLi%2FgG4PzigrVnWBZVV%2FDLAMr169eVbEA%2F8lugTLNli%2FMLsYSqLrvDZ0C%2FJ8dd4YVMsUXo04YNJGWMUN9blW6T9KEXlCFwzaWdChs0W9pX8MZAEQEj5b%2F%2F%2FgcFGCRCb71Vl%2BzQV%2Fh67fo1wWbWBn6RlBGMQ1dj1NIyXnwLo95Xr15Twknyhq6RkJ04ccrm5mKDHKsJBn6AJZPb21suA5ztyOzUyVM2M8MmYS4DdIBghGRLSWyvp4EmgrFjx49bp4O%2FyGRzz%2B7evqv2CbhIwKFvYWFRM2us0OCHzkPXjRs3NQODDAh0B6eGdvTYcZunUMzGQxcB5tVr12RbJATYHYHg0tKKtdusSPEZWmDwySUCeGZ7sQ1mHlg6xw61CohJNocEjwykrGuQBj9AIMWMDrMEmmln0w3KDka2ve2yxc8hAw2y1Wp2rHfCl8dqdp7dWwdGEn3nzj3N1kCXArb2jK0s93zQi6XJI5PPWt%2FcsLv3sJee7BAbJYlGUgzM8ANX5Li%2Bvik%2BMBPBu8sM%2BJ08dVqzKfQZDCLwugQzZasMZjHwl5srNVhNwmxMfNsxEjiSh4tfXdQus3fv3JZ9vnj%2BRXvvg%2Fft7XffkY2jFgwQEpSub22pb5XP6w9sYWHJlvoedDdJokl2GHjb2rINDRDFqhFWszDbqdVAPmMtm93f02zNxtameEByia%2Fe7%2B7ZzGxHO3jjs0jGd%2Ff3BXd%2Fzweo8FELDJTR1yuB9o0CCaAZjAZfdFA8aDaVHOqdc%2BGpKRoF28zYbRcze0ObmcV3s6IEc2Bjnxj81IAAG%2BDtK4HDVlROyz8xF18pBK4kefhK8AAKcPYZAIxBcPDlFSASVvmqLv7KE9hRrWddlh8Tx8iLa5GArvGzzNQyAOKJpa9ogq%2F8p30qNEzJSgtWcrH0WGZtIwZ6GByNP%2FAHL%2F7oGIAh%2FaCTku34agyecQs94DlyQ5YMxJG4a7AwdqHFZvlPAyXUow3Bk0F78hbvsGvQg2F4NgrTLuk%2BwMo77dp0qO6f63BYvvLF446OfLvkGqu8tNJKM7Dg6itWSJLwv1oZU1m55Ai5fwFf%2BjPiKfjAIAI%2FBjv0p%2BSc14bcF%2BJ3MpbAh3FNAo%2Feipci1neypf3ZmHUHV%2BppwFMD1CETVr40vX34n34Q30pZ6BLsWLFEkjq%2FMC%2BckQN%2FSkhZ4RKJJuJkj4r27IzNLy1ardko%2BvgWfSAryJouc2gF%2F1anY7MBF%2F4oDmAyQXEQrwSw%2F0VsAKZBQLFp%2Bs9zxoGnLNlM6eCBqj%2BUP35ygu6hUPbCiOQf6tZu4UQ6Vu%2BX7%2FhhdCSalCVQUAfEt5xwZnQKDAI1mnL%2BOEdGzRgNItnszJC0%2BDsidJh0hTgH2u7MdGy2O9DoKUlZGiHnWu8eS%2FEYDWT5EwECiQUjoiyxITmT%2B8UBxBIElr4wk9nstqzF%2Bw5yNox20n3g5%2Bta6sZIFKPHzEz0er5UimUlMzPeDm0pyOMdj1ZLTme%2Bx0wCbZra0Oxj8BC6cNzAmJ9fUDCWuIKPktdwqiSc0IgTZvkVdNDJUVe4x2Y%2B4jdLYFl%2Bp2U6ixoESHwYUdYAAB2fEoAuFNrc%2FLw6N0YW4Q%2FBMx2DZB0dG7O20EqwSiKKTJAPCT80uiP2UU8cNkElODIQoMS0RTC6ZM22j44iT36SDSN3kSSy7Bd8%2BKMdnDs4ckTPVo6sCEaXWWMFpEtKMoCDzOhf6LAI%2FpnBYjkLiSbBK4kp%2Bgpdar9W00wPNIArgSP6SrvM1lJWI7QxmkmnQ%2FBLp97tsoyP7zfOaOMldFZwWarcaIj%2BkydO2u7irjoXaFheXrI5EsLYiAFeo28MRJw%2BdVrlCHa4x%2BwLMgAXeMvkNG2wpO1U%2F7QGBjTy3GrZkSNHlXCjJ%2BDQtIbkD720peXXQ5bEzWkGiFFa6Ee3gQ%2BvlajMzCiBJzFAz9CX1AFkBd3IkMGQ7v6ulmizDJuZVfQt%2BSpb7bTtyJEVfZqHwA1cwZ%2FZdWwOGmkHuYivKyvCdUAQDK5zs%2BKLv6sSegVfkSsDBp2OAkPagq%2B0Dz0KzBS0YPMLdvLECS1tgtcMSjBjjR36MjfXLYImePXySy%2FbsaPH9BkJBiBIgi99dcl5ZSxRW9HADiPt2C42AP7glHYIPkqOajXxj0QY3CjLagTkxyBKyhW8WAKNzTGSDxwGfLjvMwroIHT5piT4hSPBKxJYkj10nxkvjgSNGX%2BwlEyrDjqdInDCf9EGn5PxJYwCLd0AVxJmcOWHrMAdued788iN1SQnjp2wxflFVeYeOggfFaTt72sZ79LSsr7pix3AF2igbXRIn%2BnR7JP7WNphMIYBA5JiJMM98JUPcHchW2CpGjMYDIBppqaOvi7IXkR76HbyBV6yYRErDAgQkTWJpNsLAbi%2FE4Z88R3YIDyA19iml3ME8MPoJjpPAMsgDo6AVRNa8kxyEat7qJd%2BCDroReUbWBY604mV8b4sm5mUO3fu2Pc%2F%2FKCBN%2FSQgczXXn%2FVXnnlFdcLLTLCDyLXo1Zvt5UwgRnJHnwFZ%2BTFPfwTts0AB3wnY0NfsWv6Evw0coFn2BllWI65sLwkn80zVs7Q7yIDrtEv%2FCL6Rjv4dhqCLmaX6Ztcr8AA%2F9rRzBB4UVb23un4YEe8%2FgBe9J%2B0xYwjCSQ2AL%2Fo49EJ6bbs2%2Fs3%2FBMJBf1A6iu2zexb9hkkOszcSTc7M74iJ3BFt8EpEzFwZUaOQTaWQwMTXSbJYBVAru5I40IvONfsF%2FYSfQH3BRdcIznGPzF9TR8DTPhIPDLb8WXf6CfpEX4AuTMYia6SmJFcY0fwF3niI%2FAvLXzxgg9ckxTh46FVr%2FjAZ2DW%2FL1g7HV0clTMgDLogw7BWzZ2c0XkXeqGLS9hA21PIFkeHnGH%2BiI%2BqyO9GkmuWiFB3xn2gozwY6KfPi54ja6xamRl5YgSSPw7ZTU4SIIoXnkskHJhcBIZsPqIPhadxTbpM0jc5cux45mO9AqYwEF2xEX5g9fY5fETJ2QfDAwBl%2FaJu8CVwQbkR1naYVCa9jMxRi6UJa5C5ritRqsp%2F4jvS%2F2jPH0ZvFIfm3S12xqMAld4RT%2BAdWhAtcMSXrct4in8BD9sGR3g1yaewmcoLuaOx%2BHY4vT3%2FHKgNsKb%2Ft3%2FQJE%2FlqPmWFsqbowK5cvgMgtKsySk%2FAQBHQcjzJvbWxo5JGl0wr1DkwOJ0UU4wijigISzxtK9od43uH37jrHUj7X7L5w6YfOzbZtvN%2BzI0rwdWZrzTxgUS%2B32bWNrx3a7OAtfn0%2FygXOh86eDg%2FWM8rFUoXxHgY7Qky8ZbIcOxkcOMXpmBxh97vICf4w844QJXjqxwyUdH3D1Ps22j1AjYjponBBw87MBOZrN6DMBTqoDTo1ywjWSIgJrZmB4pwH4OC34lkGWlkxoLxpfvqbZz51d4amOELp4pwhHLEfkdDHyTqC8s7frMBlZ63TkBOk8Gbnf2FjXSDPOMjtHcMWZd1otJWkzbCIRgS4jh8wkMGNVBBgs32LEUO9Vxcv%2B8dkULReJYBC40EWQT%2FLny%2BfcSIDLxhcs86MTxX%2BCk79%2FRPvMKDAqy%2FLKru3u7ninrSWULgM6COhTAqER7r5mqZkphKfIDxgEmpT1wMWDIUaEWYpF8kiHpR8BVZuyLM31QQdww%2FkzOq%2FlcAooPXikc%2BHPZ1g8ykP2zGYowGJYvkIXcs2ghTbBM2fAGa0mWCIhg1%2FwCn3FtuioaJ8AC%2Fln4ELnOjc74zNFKksAy3tl%2Fu6R0%2B9Bmt6ta3cEOHuJPgAAIABJREFUExywW3DVDEG8p0ZvSjKgGcBMYMIOCa5Iyum08Qq8bwQ9wEVu6f2gm9kPVgz0NdsQOgCvNDhBwutLGMEV%2FqMLvJSNvrjNsiyMGVBPVFiCv8dy9pjVpi0PlFvSF4IRgkeN%2BPEJjn1fEqrNU%2BigG04XegCu%2FOArfgBfxmw5AQPBG%2B%2FJ%2FfWvf9WsHPr9xhtv6I%2FBDnQBHUB2BArAQ%2F76hBCT4NoIhlmHQREMgyvBL7vhalQ9lrGjhZSHr8zoCtcIfNBTBrjYoCZxZUaMZarM6tM%2B%2BIMDyVPascJcltD1%2Blqii44reOdTNbwLjF5pcIQg15MSYKIDhQ1oRsFXV2i22FEQr7BDD3B9EBAbIdBFD1iGdvHLi8bOqcBjVg7eocf8CLjQbZJtn9l0GWJbA5bEBu%2FAK3ElyOKHGaHz3v6%2BEiPRH6tooAu5Upcfto%2Bc0EXxKvwQiZl8QMxqwERsSwlpJATps0igxdcI7ICDvlIW2FL4GEAkqCUIBkfqu832XAbotgJVHzyiffwVfFy9e8%2B%2BuXzZLn110W7dvKFk%2FsIbr9urr76iVwQWmeXIAUXNrtQVDPM6gW%2Bt5O9uEZQCF3mhE%2BgVtA9SV6WD%2BAEfhCVx9sTMl1syKIReaXZMxuU%2Bg36O4BkfjsYw40SSja1IX6ArZoXQq0yMuIlcJQP5YXjiiWXKADzTPyEveEuyLuYJZkOJtA%2FmumRJiHM2r8rrFpuzMFMX9qJ3t%2FVaADOTviwXmeBPxf8i2Qauxw5VXWEnVWREUl4M0MlefEYRfwWuwireMfbBMec%2FOogeMLOq%2Fj34L59FvxvLfZ0qLys7kA3AA6WM0ml4D%2B7qh7TvRd%2F2YgUC9p2xA34I2vhrI7d4%2FxgZgAs%2F%2FCn%2BFb3Wd7m1wZHD7g99Rhe64C1JMm07XfHpEs26%2BvuM4CgZRGyIXZOUSa%2BgN97RhC7Oq3ZILOL9q3Mgn2cZ6RY6UGdSIwaTY4k8cVbVr1EXXcLHo3%2FSq4hnwJH4wX2g2yYaKx%2BEXodtQy4xoHQFZ4O2OssEU75Fg99io3yVbCD0FRxomz94xg8d6ul756UPKmDiAwNXcNC2cfGetWgXCj6LLLgxSB7doWh0TKb%2FPo8ceIqSTcRTTTa5xug92SyP6fc9MFVATYdD8E3nQIej0dywSpmoB0BAxDkSwjN6rPC03rBub6h3eVhidu%2FeXa1zf%2BX8i7Y0z3sRZjNNEh6WdPg%2Bphge72kqaB06fmCKo8Ko%2BcO5pONzZ6VGw8H6bJNmE7R5jjtBLUMJ3Jl9xWkCnSAI2Lz3EX5IO%2FUBF%2BcixxYzo44DnbaaFwwcIR2i6A%2FPAo44Tc0AKnBX5OSVMjihbAQuBJgKsp0Md9oRCHkH6zwW7Ti2cIJ05iTjyIbzpJEAg3p0prz7yTK4bndfo3h6L2tu3ttmyQ6xvedHUgl4C7%2BRObTjuOn5cJD%2BV6hOLHcK%2FooHMY2sMKWso%2B4leIOOAJN7kmckV7Sa%2FJc%2BBp%2BgQz8B8TLqMAJPcCRgcqwdF4CTiPDMkxdP4NQRwWMF7UD1zSK4k%2FX9ruPu9ItVjoPqCRHZQVoBKMJ%2FngCH8xCv7lBZsCgTfCwAUssBFEM%2BGn0NPFXOB2M9JktZJWRHpwQXlOh2BACBWMhL1Ac%2BNOIyE%2F8DZvaxTk%2FwNPYZlu1RDrlJNg5PfiFw9mVwUif%2Fx1Vd0AVTOhd0BywnIDhK8IwOhr0mn5MXBVASKma34Sl0h%2Fol74UelYJHwGGMwW1GnkogGQBhyTa7gPJeDokMSdOFCxc0q8Y1%2FgCaCexgmesxknbwBFzSSydEN8sW%2FGZBO5dUDFkm3iqVuEaw6p4lgPIs7ifrE2YmnVFSh4J%2B8dif0Jbkg1mnuQY6WTdhyp%2FQXiwbg4%2FwgIED7IrlvZ9%2B%2Bpn4xmDFr3%2F9a3vt9dc0Kg8skgZ0BD%2FKOTOmopXAvvKuX7bn%2BLq0xTudOo%2F9rhOS5843t1zacTj8%2B%2BBv3I84D1QSIPzC34g%2BXWYrrv%2FIn5%2F0HgaKF%2B5jhGHAEa%2BARScRA50E%2F7xCcvvmLfvm66%2Ft%2B%2B%2B%2B0zu7p06dsAtvXLCXzp%2FXTDrJg69scF1T0sUnVmJXUsXEQoLmwxcKkcjO0zdIrjwvecGp22uonvSoMEzRA%2F%2BzjMvZFcMD3rR3YLp%2FC4YXdcSg%2BEc%2BMM6p4VJyu%2BE2tlK0Ua1YOUcC6v%2FyXvhB2Y5gCm3JrgqTc9XzvQclB%2ByVX7IkbQMbKH7BoxBvcdv7G7%2FMvlJ6EDhkwcSXttUjydfrM5IqknWzfB4TBXHW887oQ7yvFLyQl%2BgKX%2BT885kvT1BcRlUZQnABXw24TGm74EXckl%2Br0KTioROUpT3VC8RFbwwa5zPa5j48y3PhGXUOO0AX0ME2%2Bx%2Fqa3ly2KZokYxKKGrNRaubhV6VRcbPlJSWuImf4oXzCVDAlMyFkQPnqfMjdtVWjCGmCL7Hvh7%2Fut%2BPehmnVLCgrxKexb2IP%2BBllf%2ByERDyuKEoPj157jjwlCyjlYmECldVGXn56KVLjmfuUDByTIsjnoNSjPgx4oUj1siRFx%2Bro1F%2BarJxCTMpcjoDY4Madl5nuTrns6x%2FZ9lgjW8ietTD0s00KkbgGvoMcJlsqqHoIViGyY%2BZllwepCBMTkl9c2HMch7gqm8H876Gbxkk2qCX%2FlZ9rtMsslg6QbJCR1%2F8SidIWwLJDFajZnxwBIcKTFBLx5y1Ne6lmAGuclXprOFXFoy2gOUzRzgvd95ydVGOd070Ex44Rl%2BeNmoQTPsSEz4rwyjrGu9eXr2iAPrs6dPWQY7afdbpAaTYyWigtMSdKoEhVDJwwM%2Bv%2FCiGFcmVhKxNBwKADl6n6jwdZ3LlEZ9RAWYGHMIheKL7XlafLcjGw9mrw%2BFe6kLoQd7PQAGekrQJ%2B%2BjIqAaVY52fApjxHoxaTrUaEvVJP3f4JVzHNOlElm4z8MiheAkZkurl%2FQAkbnl976AdNrVoA%2BkHqboG9%2BIGIAK88JEilbjwMHWLYohUT9FTgYlvt9GWBnsERQ3LJgJFYCRP1H5xn%2FJlIh%2B1dSfPVbQEmzWTsgqfeZS88mJUE0%2FCBqJytli0Iz6HTSSvsmx5dGlAiw%2Fs%2BPuDIMCSwpdffllJEjNrvFP76aefaFb3%2Ffff10YYjLaTCICjEoqYlcvBL%2FErggOoAA%2FxTTx30qAn%2BaLzuKiegy%2F1JbcIlhMeD%2FK%2BjmGDojEDkyA420%2F6vbxfQcWQXChU1bViQlsTfzGUQRtoyi3%2FeZ%2BppffQt7c2NfvFqwz8MePEQBtloYuBMJJN7pGkomciO%2BSV%2BKXc5JcDWQ7cdx0Q5wtNEM%2BklSN3R5OA8jqOalONuM6H1hbyyBP6FpXNesk4HeOZ%2BgV%2Ft5yZPwJWDW5V9Fd9AZvk9Xt6h%2FKHH763zz%2F73K5fu6bZ%2FpdeOm8fvP%2BenT%2F%2FYvEOPvqFPrn8vV8g4edTPNmH8IyfekZdFEIs8RYAShUn4TJKXxJA3F%2BpZkCu%2BC3XafQEjiRfvFyyRb1TfAZNeIl5rktqg5qq4vW9XpyHPaTss3weKZtyCuycxqo%2FqlSmacpzS%2FzRNX1YzEhGPXAONL3fLup4y%2FWCB36dtDo%2Fge2s1TGRDVq83ZE2GUNvkVtRTu1XKsRp8Zyy2BlHNcoTSb7QrGDlmF8XvQHEbaUKcbw98XTiMZfATR5TI4tI9EUBMbboHVXmEF75s5TeBA7jl7Jp1jSJ7jEssG3Xfccj9Td1MfQskRXfSip0u7xUq9LXiG9pEe5mPOX6Rq0ESGW3L%2FktPomk8k6AqCvgA8svgJNqmZCo4XoHDPCnvD%2F1%2B1FXNFDay42xw5ud%2FvsccuApSTZdcfUvnkzai5LnX0ouDJdAJIMmLAbDjGv5P0HAVPwZXg%2BozBbKgPRNoOjQh2ZszcIfO3t1WNJTr1mLZI6%2FNDfZtBtejZfU02jDLP2J40nR6rXuhmWnI3U8S8MHnAJtoRwdT4UDStaAWg00omNK7pRHh5vYJBczuEoeyaFkcBgzoU5WiVc1cFeQBU5jM0YhpWyERqPD8g5mZKMQKfUJokn0wYFWdra2NJq%2Bfn%2FNzp07a0sLLBduGTt4ilcFUZLmAUMP2ekRcCTd7nzBQ%2Flo4UQdtyyVKCcfAnW1mDyS%2By3gFsgUjlp1Ug4Suv4pC8ZZlY90tvkrz%2FKOD5wkjqWeifEqlDFwVR48ANZYO%2Bhm8JmyDjM7wwwRynardRXQVvBEGIIfbQCLa8HMiwRV1dG4N4mb384OOStWjtF20Ua0R4uCFZ0q5%2FqFjefl5LFoX3zwwQ%2Fnx2TJwKlqryWl2ZQfE5fQL%2BAVrAjgqD4ziu6LvC2uQlrS8cQgquier3oimAeCBxuLi%2FP28ssv%2BQ7WjZqWhn7y6X8oUMWuzp59QasgtLojlv86GxOyIFUlJ8ocF7e3xEVBfMHzxDaf%2BjGhSga6SB2rDE6hN6EP4FLIC9jVi3HQKhhuYwxHcTgbjjoE3kP8Cv3CwH08Bsq3Qlnmvr5%2BX0tiWf7JBlqNBkmYL7kkcdILyAzx8AqHIkbHrextxpGT%2F6vcKnisEyeKf4u%2FwNefVCpOnOp5lSnV8yiL70g4eeSRc94b4r5KUZ8%2FdJnVGrHBnQPw6eNud18rS7799lv785%2F%2FbNeuXNE7lb%2F64H374L33tOEdg6Uk5LSi1TQxWJgJu%2FPaPzxfxWmCPOE0TtKEIKNCUWYMWNCWvjbLQqseHQyLYgWY4oS74%2BWzTYp4sSxc%2BstocvyggW5XGyBWoapfSXgJDklFId3SP%2BFzKmXKZxVc4zm4llqQ6DhQihRgxrDJct4nOr0OZbxOtX5ZZ%2Bxswo7zGXDAQu2XSOia9pI3ecx61WOlWvW2zg9%2BFryjxFiBspWyvy3vOXC%2FHqv2QKt%2BQ2WgO4UXoKp1ncZJmONtJt%2FhRvbjk02WMJ02wfWKUXQcpm4KN86i%2FRLI2D0k7ngWrm6i%2BbKin5X0qE8Yk30Vj7LeBMDp5XPCgaco2UyJpNJyrJ6XV5TkCTNb9ZGHbqg9fxgECYaWiJBzFE7OlwVozX8sHcFv8EdyOc9GFwvzVh%2F0bWmO5bM%2Bu%2Bh7%2FpV4yPzD4UQIqXTTccISfSxISzuTpDhW%2FUX1XHVBPAjIICurixMy8opjjYdVc8%2Fy1aNzx%2B8kFboCXuBaLZ%2FhIvcmccxymeQ4HMdAQfFYAzz1Z2yWxGZMeo9WgScOr6b37LY3N%2FWNtJXlJW2ewjuUbCqgIL0KD1APJKCJkR%2BFbyXRqXIrQSW%2F8ppj%2FiW06rO899CjKmSth5Z85MMCvzw5pMZBrU3e82sPKDSmGTPDgNRd6dRkrbJBr1m5Vnm%2FplYVRV2HrXF%2BUEf6ADxHpGggYQK30ENuVn6CLfjZEXuBiWKVGuWpyjAAMYF7WcLPVC6IcxsI26Tdwiii%2FSoXKrqX%2BFA%2Bg87xdqrcqz7J1QcEpb5UkSb5vABJK%2B%2Binjx53JjNZAn6559%2FphlOOMYSejaTYLka1ySgerctcB7H%2FbD2S3soaCjQyzteBgjuX7iPxKoWV1SSH4ELZe3y2aPPHsQTcqo%2BSAMp8W4Ry0Ghs9v1j6ZvbrCjLN%2B%2B62tjj1ablS%2B%2BUyOzmaYNQcDM39UbjHrOv3jP7mH4OdWU%2BGmUJewDaztzq9rlfupBdiSY4gg%2FcvUIOpAbJQkkzJM%2BkYjv2fXr17TE%2BNJf%2F6qNgN5680377T%2F8g77pik9Gl%2FDbkq%2F6S9dLJelhD%2FouY8DNPjHQLzgjGrPfDH0sEB6jMu4GUzgcRjLPolgJ6qCzHFB9CCyqPS68R7WZ%2BD4uvINQHrv3hPGHoRIB%2FqoyeJE8GGv77%2BwCniZ%2F%2Fay8%2Btug%2BqCPq2IgmT9KQSoUPA7Pgf84IB9ZJhkU8gduFfd8nEfRkhfUOcRGHuRIVpoenycOPIXJJuJJtc7zB0WmDlXOMt5jDMtJw9QsIXBkJJgDjpX3%2F9w0aIGlRYRlbAW9ONOx4ZEVW5ztaFeyuXZLSagS0sAoz8GP%2Bvw82KoGodyljXzi5fxfcEgMvVz1qS%2BDKF0oiTLFox8vXEO2rVYmOu7DktwS42gxgVQQKIPRvBlMzcsDjsAVCkVSn4XG62bnRuDCci5va%2BRLZ194QZsVsUMbG%2FE4zArGgNJPTwoPme3m05QLpIl35YPiTM%2BCk8kCjnmeBQ%2B6l89%2BqWNqRkHuIxqaxJni1XtVeM7vsAcVqpZ8REOHPE4IiW%2Bq9kGJ5iEgdLsKJ8%2BTkkxgkhYqUAZ6SBp%2Fzq9saxyK7k8%2BPCQxp1jiBk7FeQXkJKjKo4nTTLFJFnzmDZj4KRJLZpLYxIKNX%2FgO569%2B9YGW1f7nf%2F6nZjm7va799re%2F1edJtOGQGnbpyHfl%2B8GFlpA9hJ1VkJTPCczydgVUikZQHLoXzrJpoOWz8gklx68mWFC5LOtXbsap6zMXnvz4MsSRvgV36%2FYtu37tujZDur96X8tCSTBvXL%2BunUj53Ay7b2oDp4DH7EcuNy4RPBwDaOBpHjmrevwHax5EdVnKn5bXgpwNJM16fBCcKBCH1CKVzAQv%2Bjv1m%2FEtXXaa%2FeLLL%2B3bb7%2FRu%2FT%2F8Jvf2Ie%2F%2BpX2LJiLXc1ZIsvGM9TT%2B%2F28m8kGLryHT6KigVvXodR%2F0EgsOVbPefaYZBS8zfrjVAbcKssmC0xcHwYni%2Bn5I%2BBRZhIOVdL3Jazi%2BAh4RblHnUQc8LBij4N%2FUb8SV0zSU5T5Oz1xfGHsk2Lu4xNatJgnMQAbCyJ%2BNKDkfR4nAWQzk%2FcPuz4MTpavwntU2Yc%2BT0APLZStTo%2FPAwee4mQT8Rysydlh6l0RPnOkpVAVcVYcqb5ZxTV%2F2rE%2FYJKoDge8yWhNktB20xpLizaY9%2B23O3w7iJmgCCBjfx3NhApCgok19d7dpgV67%2FNg0J3PfSOHA%2BkDrgKETJTHS0WzQSzwxu%2Bow48AIzlCiYmc9IF6WTaGPHXp70ImzkWJYlaBthxuNcwqy3GGrPJXnNdq2j2QTVDYDbfT9o9fs8kJkJRglNW8U6nMGiW8SdoVeGYHVKlf5RC3E2fgVJ8l3IPu5bNf8ki7wi%2BOh7V1GH4PyrgKwSE%2FvExZfrKNyeuypA%2FeJLsf1HkvOdluwstjCS%2FKxw2eJ0%2ByDPcOq5dlHjwmhv7kUfWz3YRzUPnqvYTOvfzLujrif8ZuPHiRpoIvwbbwb75pmpf1wbK61Zp1fSbg3NmzRlJAYvlvv%2Fs3%2B%2FgPf1DK89FHH9mx48e00zIJKskqtub2Wu5MWcWgKrfEc%2Bw4KQRVTtkn9QjL7x1MbEKstvxzz%2F1bh6JzMLCd7S37f%2F%2Fn%2F7T%2F73%2F9r9gltqtvoPIu%2F9UrV%2Bybby7be%2B%2B%2Fb2%2B%2F9badPn0qPqVS7tYIhp6sVWgaQ7G8n%2BmlHzXtN%2BZngaV%2BR8xwBpa1OSuvOHfueLlC6%2FNSODh2D9UkksJIAqGD7ywDWN9PZCdSdpu9d88uXfqrffHlF7a6dl%2Bf0njttdc0W%2F7CmTO%2BI6Xk6DNf8M6bZ%2BdXBkE8%2BQRHZj6HbDZXMXCno8Qyr5MNomKMrjEGj10Udcfu%2BkVVZw94PHYru9SfC4%2F6CSOlx7XImaDJZT%2BGxs%2B7mIB%2FGLDE77Dn3M8yeXxY2cd9lvx43PI%2Fv1xy%2FudD%2BtEQJpt%2BTNlU20ne57H6rHqupn4C%2FCqM6nkV3qPartYbOxeQ6p2U%2Fk%2BGWAU2PX8KOfAUJpuprHk8mOsKnIqpDTpFd6BukxPTbAd0hEpo6OC17NaXqDU6LVJPb5DeaTTw9wtJgQK%2BNxlBlsp4aGK1CObodrK9Kgm8QxR%2F6vxx%2BHpeLeTJmSAKjCdzRSKb9iwM42LEfpj8vJQjX3Ymfh07zRYPM0zKGwUyHmrFcqniaQXP8pRWoQk6ysQ4W05Uk0YlmrGEkU8K7Gxva7tzPusCEGcli5992yUthE4SeZiBWdyDgvwv8YRvzHAUbceDvM5yms2pRCrjEihKHXLy40ofAuTQ20AH3zxScLLFyWuV0c1qrRJGlmfmXKw8tPXKg9D3yp0H8PBnGSRXS06cC9Y4bpRIvLJ0ljjofpbJeocPb1RLPiB56VrCqJYcO68uLUM3i4d%2BJn1POYWwHsC5rFTUrpZJGMXDCj%2F0jF1SG77DNhrB0nISKgRI4siP5ZF8W%2B7DD35l%2FW7P%2FvDxx%2FbnP%2F1Jny354Fcf2Isvntc7nG5bI6uzA1qF69hP5VIUgeMYnjRU0BIncSjKjT0vy4RbmIBYpfjh52miBfgDigtf3tfED7FxzXBoN2%2FcsE8%2F%2BcRW7636Z3n4dnK7bVd%2B%2BMF4N5Glo3zi6b%2F%2BX%2F9VSbtgVAzDV5843e6%2FsuHEhCO10H3XxDwiH%2Bokb%2FJYlq%2BwU1CqMDl32JJNnFdQK9pNjPzofk%2FvnlKYlSO8usCO6X1fVtywkZbNXrlyxf7yl78Yy2b5dt%2BLL56zd959115%2F7TV9py%2BTdj4NwQoUEk02a0Mnc%2FdvlmuzTFeUZ1IqROBH0hMY0pccoAHi3kTRcZoefpV8zePDSmf743wcr5Fw8jj%2BdPwq4VXvUk%2F3Kw%2B59zjwqnAedp7wOR72y%2FbyeGg5KfajSh1W%2B%2BD7QHsc3A6uXd59PKyytTyW9X%2FpM3oE4VgJM4XFw4ifQEr1H0M%2FkrpHwU94E808cPm48CYrVuFLDylQvamLKgPGHk6Cm14%2Fgxx4ypLNqik8KI1iZoz9z%2Fhsh5ybjyhnaVfxqtLnk0lPyFuESk9kJgrDil3L%2FH5ak5am0oeP2MHQN%2B8hGHBs819PXD2InGg%2FkjfHX9mZLFVxAYHJ2IY7Gbw7DG8n4DlxnrRCzljvmWVieWFGSZThUaWswAQsuJOUlJxShaLjKHCIIFwtxT9%2BSJwdAlfiSuKgz0N4cNLrdY2lbRsbG3b0yFGbWV5WUMOIOaPkfGtNmyHpfTWHRwDjGJUYco9gqPzBf4IuYVTePugMnj9GsbKIM6sgJ2BOXmdTVRwSBhBcN7LUpPzKoCxFk8di8GLSv5eg4ixbKx8Ao3r3MJzLGtWzsmaBS%2FVx4hPBdVl6opAux58%2BDF6WfFiZg1o46F5VFjwHpuA%2BBiOyXG4KkXilLUme1cS0isAE8hOX1ZLFeeoH7XCu77%2Fq%2FTqWnrtN8Z4hgb4CnjrfkGvoXed%2F%2Bqd%2F0izd7%2F71X%2B3zzz7zd%2FasbmfPndNOosx%2B8uH1qi45I4rmdYJdjeFaED2hSGhVFHTMqC4n6b4G%2FoqQuJ%2BFK809jqlSfAyfqF%2B9h4xdziO90%2Fri2bN2%2BtRJW19bs1GXz0P1bX9%2FaMM1Pm9Ss5Mnjtv6%2BprvQKtdW9kciHaAWlKTDXtbEON%2F5bWnVomLX4W%2FDTwLFhxy7fRRyt%2BL9GJeq4JJ1D74oP5Ja1uHLl%2Fxg%2FdS%2Be4ou38PbP3emn3z7bdKNL%2F55hu9vvD%2Bu%2B8o0Tx77qxeY4A8klMt4eZ9Vn0Wpm7aGyh0kk9gNRsd8U6vRPCNRH3uK3ADdfHpYFyrd5Nv1Xu%2FxHm2k8cn0YbInACU8B%2Bnb5mo%2BliXBfzHKv2wQgnpYWV%2B2jMgH8Sbx4X24zDL1n5crcfF5eByUOfxSPX5T8Hgces8LpVPGl6VPs6r8CdlnH2XS79achLK9PpZ5cBTlmxOqvS4WFKhxwLIItAYL%2FvoK3cabhbjo9EKOBSMRvggy6KMJ5QJm8Cl3Dt00vyyVLnrFwGjNpNWo7kEtSyX7SrICHutxsQenNFOhCEK8qNgFQznBTrRThWQAofJCmXGAJ%2Brs2BetcSXFh08eBDoTcIKl4NsYjlgfvNvb2%2FPbt66aXw3sN3u6JMOTZYwx8eEE5IvBfOrTF7zGcfEqbzn%2BD9WgBb8L%2Bs%2B6qzk8QQbo6IzoKqXKauCN6BXqZz38wjHCp6K%2F4%2FC6fGfl9g%2Ffp2fUvJJtfOk4EADPC95nHrzI6kLuVXxAmb1%2BkdCPKB4QqtoMJ8XajStXiPBDO2ITw5Bl2%2FS4hsBLS0u2gfvv6%2FA%2F49%2F%2FKNd%2FvprfWeTj7fzyZTFxcXSEUnTxo3WW%2Bfe%2BP1xRKvPqkmV1xabsPmopKOWhJTQOfP745APu%2FKaBz91e8Iv%2ByAg37FitvfUqZPaUZWkqr4X31OOb%2FKurKzY%2B%2B%2B9Zx%2B8966xAQ7buTFTJ2lWxuXAkdcIJI0JJJToF4lpPlSNpK6CcD73W%2BWVuBDlD6sbdaqsrkD2U%2F%2BmHgMQ%2FIoltKEvJKK3b9%2B2L774wi5%2BddHW19a1azE8eOXV1%2BzIkSPaOAn%2FCxZsrASOM52Z8Mn%2BaRj0nTLAVzv6HinLj71fKOiq%2BDgVnP7zN%2BdA1d8d3nghscOL%2FMQnvxzkgxD6W7aGr6E%2F8WmOSWx%2BSUyeNOwnCc%2F98CQ3ptfPGweewmTz0SJyg%2FfOmkCjWPb06KpRIhKkWsOXX9FBYn2KINMMlR1EQJltEeB5YqqE7xEdazX5yBmF8dm4KsLZ7uEBsTdXKVet%2FiPPnaKyUpKSxwyly%2BssS80y8VRAVqKUhfyo%2B84zIpkh%2Fw1HRgC8t7dv%2FUFfzts3M0kg7tCRa%2F4exOEwHgWMSeISEEeKZFPV%2Bw%2BcP1ahiVplncS51M3ymdBg4odgtnKbxH3quCdY%2BgQuqzx%2BAuAE4peAeZBiog%2F1OssYmX0rbc%2F9XibSNWu1Wra0tGRvvvmm8Pvqq6%2Fs5s2bSjjZ4IV38kg42eTF4QCrnMWkHVfFMouuqKazTe17vXEbSv9JsailBIlzh%2BsmWaZplZIO%2Byf8Cx2J82gw0PuEzAazIy%2FLi1k6y49yJJQk5K%2B89JKx4%2Br5F8%2Fb4vxCzBgHzgjVEVVXgH3yiS3%2FDE2JoFPktBX0ZkUdk4fJU68boEtAWbaoC8zgb3RHXKqedl2HfwdAiexCMoxVMuzKu7OzYzdu3rTPPv3ULn9zWUuqL1y4IB1hAGJpecmazVYkjPFFvWZL%2FMInuy8qBxOLDZTkpyJBL6gJHgq%2FPC8eTk%2F%2Bhhx4tG%2BayuenicP5lnZROIufBuwZqpX6lMdniLQpKY%2FNgWcy2YR6DF7Bhjzrj1Xy7NAjcUzvnEext4Q812CuAAAgAElEQVTpzsV57rMJB%2FGf8uOBQLWeB3iUKeFWoVSb9rJOY7VMnlfL5r1f4vhgO1X6nI4HyzgmHpd6aAQfeIeoNmCDiaH%2B%2Br2%2BdjQkHPNg2uUJD5VoFsHvj6TsYPb%2BSCA%2FtvjDeHE4Qg%2Fy7vCyPxajaflnhwOyn1qjkiQySJG64gMUzDqxwdbx48c1A0Xy%2BdXFr5Rs9PueiL362qu%2BkkCJBElEJGskVBisQHpywSmrEtS2WEnWU%2FpN564nmeVOjL4SBEAOOa%2FHvR5QEvtCSlXXkje1HvGgB1kAb8EoFktlB%2FquZrvdsjMkmyeOW7vFrLB%2FIqvTbtmpkyfs7bfetNdfe1Wzmnw6y99zdHiJs66iWQ5MGnrCCdZlgs9Ikego%2FhmWs8cFP0tcDz8b54bYXEk2nZ%2BeNGd6Daxq%2F5eDcyxt3d%2Ff16sKV6%2FyfuZ%2F2vXr121xadFeffVVu%2FDGG%2FbCC2c18KBBvkAKdaJdvqkpKkO%2FSLj5Lim%2FUudUImpOymeclig0PfzdcWAqp58mEviGzk%2F5dzD%2Fpnw5mC%2FP%2Ft1nNtlEdGXn92MF6TNKdKQP9xluOEVcd2gzj%2BOAxmexDgUVD346bY%2BC%2FLd5Dv4ZNGWLuGgFxe22AmNG1TNIQhDOZw9ws870OOXAlAPOAfcJ4505NkbSwR8DYXyHk4QzZ98ufnnRbt26pXfNWUnw0ksv2dGjR7SDrXa6ZbAnEksMVslbGC7taXBNmUhIgWdCgX8cF%2Bx6LFGLZFP3A91R8QpCmS7xnJ8294nzsYPwyFJjT4oL6PbdUQfCgncKV1aW7OiRFX0WhmWeJJ1HVlaUZL737rt27txZI%2FlkNpS3X331QSTGmkEMpIsvsuLLkl7nrLCK%2FiNL6wuuuih3Gy%2BpLVCeOKEC0BIK%2Fi9mE9WI%2B0OWyWopdQwA%2BLJZr5d9Bd8S3d3d1bLZb7751lhGzBJalg6%2F%2B%2B479vrrb2jWd3Z2tlw6XBkgRcypN45kDMYWuFVRT3yr96bnTxcHpjL8afKatNmfBmVaa8qBZ4kDz3Sy%2BfMElcnNz4NS1n644350wlqB9GMKl9X%2Brs7ghoIgBcI%2Bak7gxzcCjx07Zq12W7Ms%2Ba4QgS5k652jn0OJArSfA2Bad8qBp4MDmWT65yiGsRzSk5Ojx47aW403tbyW73DynnSv37Nud98uXHjDjh496rOWJBj5Lh47OZO8kXJq1pPprvJ7pnJLsbzd8yBP0Dgvkqqc5tSKVDdGT2C9rG%2Bekkaax8i3DmS7Qz%2FwUd4ckWjG7qhm2kGVhHN5adHu3mGZaN3Onz9rH374gb399gU7emRZs3UjdhtXtp6Agh4lnPgv2saTsZVczGIykVrxz%2F60kitCSvJAdb1f8H%2BznTxyN9tIXnDPSyOJMvkDN%2BeyJ9ie0Db4ULT5e5UbG5t27do1%2B%2Frrr%2B3777833o9n%2BTRLq0mwjx49ZjMzM5K7xgzUjLeVGI0fH%2FYsSz5OmSw7PU458KxwYKr3z4okp3Q8GQ5Mk80nw8enFoqCxkpw9H%2BKEFBo1Bs2Mztrx0%2Bc0DKu2dk5q7MxRSSaBFnVkOun4ZovOR1Smz4iZiQOKTG9PeXAU8MBNoDR7rT6JEo5w8kyWgZ1GMxhh%2BfPPvvcbt68YX%2F5y%2BeaCXz77be1OQyJmAaFlBxiHJ5gehJk%2BkYnzPCNYfShYueNyvseqr6PqgdfRQimbCaX3pK4eTWZnoy8SE8jtTqA5Q8so03vUCmriVaSMt%2BhlyeN%2BkgJ5ZkzJ%2BzOnZvWbrXsjTdeU7L54rkXrN1mYxtg5YAjyWqmdXzmqma%2Bvw4DYNDMs0j0aACyIChczZCEPenluWgNfuREcAVlP%2BW54zB%2BLAAIEN9I9Rlnf92Apylv5Ibv7Ha7tra2ps%2B6fPnll5rJ5n3Vt9562z766EM7o29nNqUHtOWJZgjkAbymN6YcmHJgyoEpB6Yc%2BHEcmCabP45fz1zpXGL1f5owj5l89pJlXJ12R4ESu9RqtVqx7LYaBP4ErDOqfVjVaZz1MO5Mnz1VHIilrnxeaIh95bV%2FHopNgV555RXN7n3xRcuuXr1qn376qcq99957%2BuQFyQv1vK4fzdiUyBmB7ZJQavdt7FRpkuYrNffmyaaXZTaQxMvrkqBReujJWCRsmbjFXOEhySb1%2BOVx8tyf%2Br%2FsoMqfl23Uh3byxBE7d%2FaU3bh%2BRUto333ngr32you2tDRnbD7LhktOs6%2B6cDjpGGrWgE7xBJjQysZKzHBS2TcvI8lUi8qgM1mNXDNzziqaD5zTHhD8CLfyjk74bujAl8%2F6rq9MY8ass3bgHdn29o7duXPHLl%2F%2B2i5dumTr6%2BuatX7jjQv21ltvaaMkBh4YVGDAQK2RHKdwH8BpemPKgSkHphyYcmDKgR%2FHgWmy%2BeP49dSU%2FnuZsXx8hnmQBN4ETOwOycYlHrJ68MMzpwuoGfg9fguPVfIXAvtYbU8LTTnwhDmQSQMbb5GQNPiWJhYmOzO9m8kutew%2Bis2xKcyVK2wc8xfr9%2FvaNIbPX7C5ELOgnmT6jF%2FCVkKlVI5ky5MzDR7xDUdSSSUxMVMZ9q1l8UpFSQJ95pEjG%2FLoHU3Z4YQxekPjHPJ1t%2FIZ%2FmCiEJd8T5KEOXxGo9a3U8eX7eVzp%2B3OjVOi%2FYN3L9jJEyvW4lOj9UGZYZKgZ4vBM9EtmiCwwTpj%2FY3YvZykk82alHx6qqgENFov99AuUU74eVRzmhXl01DZuJ9UqUOGmtkUz10moEji2O8P9a3ia1ev2deXfdlsr9uzl19%2BtVg2u7y8Eu%2Fm%2BvvzwErastXpccqBKQemHJhyYMqBn8uBabL5czn4d1o%2FA8G%2FU%2FQeQAt82dGR2ZfhgBTT16Bpl1qNsvs9D7mKCOwBOI9142dWf6w2poWmHPg74IASEm0eQ7LZVMKpjWQCN56TnCwvL1u7%2FbqxdH12bs54j%2FPffv9vtrm1Ze%2B887adPHHSZmZnrMb7iiQ0tbqSUxJYrT6I1bU8G8U3HTn32b1MmpT5RUIZs42jvjVGfatZ32zYN%2BP9Sirqh6GmseYxHo0dKJ9%2FYw8Ea9RnGSxJpKd6jcHAji607cLLL9hg94K98uqr9tr507bQqVttsGt8j1M4jIax1aym%2BmzU7%2Bl%2BrdnQ9rPCiMSy3jars5lZU4mmGecknswUknw6%2FQ2RVcGT00jEE2v46z8VFlnFrSwET7TxEb7SZ2BJ6xmcYxaaP2Ywv%2Fnmsn311SW7ceOG3s195913lGieOHHS5ufnlGjid9EB1wNvu%2Fpv0eT0ZMqBKQemHJhyYMqBn8iBabL5Exk3rfbLcIA4k3eMmFVpNdsKiBTQ0hzvN8VHwn%2BZ1qdQpxx4djjgAzgkhb5LDEcSTWyLX76PSTlmNVutJX17kvf5sME%2FfPwH%2B8Mf%2FqDvU7Jb6ZkzL9jc%2FJyud%2Ff3BKPV4l2%2FljVYhkl6xaBRDA6xMdGAmcomiRdpI6nXIP761hj2rdbfM%2Bvt2LC3azbqaZaTb4n4igavRUM%2BvxjX5H5FEhpJWZFs5rXQ82SN5HdEDkli5efztZG9%2F%2Fo5O3NkTon2kY6Z7azaYI%2BE1GcJlXAyKwr%2FmMTs7Xui3PT3NEd8w7neMmvNWq01Y9bsmNXbVquRMLesZjGLLFSAC26xGHYMTehiDpgjDzy55Uq%2FmCEuL%2BGkl%2B0PoMp38ebbmfxtbm7aF198YZ9%2F%2Frltb2%2FbsWPH7c03Lxjv4bLxk7ejPLdczhwyKxrMxqbHKQemHJhyYMqBKQd%2BJgemyebPZOC0%2BhPigGZERrbH1vx37ujIJxr8w%2BsRJMa7REUQ9oSanoKZcuBZ5YAvneV9Qn9PUrON8Q5mSfNI37Yl3yB5PH3mtP2Xf%2Fov%2Bqbix3%2F82D759BMlmI1my15on7XV1VX78suLtr29ZadPnbJXXnlVn0thaQIJpyebJGzs5jo09trBZpVoMpM57Fl92DXr7dlgZ9N6m%2Fdsb%2FOeDbo7ZqO%2Bf3KEhFN5l79H6DOEQPFErIq7J3CevXnp8ilnOVtIos2sK0k2iXerVrMzC3Ub9tZt%2Fep926jV9UxNCGNmDvtKyDxJHRSb6AyGA7NGy5qdOWvNL1tnYcVac4vWmFmwWmvWrD5jZj7jadYsUklw9XSz6sUiwcxEU8ekwWeSQccpLNJRzdRCi3CrmRJNdpn97LPPjI2ASPbfeOMN%2B%2Bijj7RUeHYWnHyprHJLUlzpgg88FBPK2fT0OOXAlANTDkw5MOXAE%2BDANNl8AkycgngyHCAgZjv%2BO7dv28bmhrVbbVteXLZRqx3BMgFaBmtPps0plCkHnmUOkEBgV5lU8M5mp9OO2a2RkTTxjASRnVVJTnk%2F89Tp0%2Fbf%2F%2B%2F%2Fbssry%2Fa73%2F3OLv31r1ZvNu3u6qpdvPiV%2Fcu%2F%2FIttbW3Zrz%2F6yP6f%2FzFT7FxLRqR3%2F8yMb1oyYzrkEyLDgdVZLtvbteH%2BlnW3N6y7tWb7m%2Fdtb%2B227a7dse7uhg37%2B%2F5dzFgOyiY8JGc%2Bk5fHlBjpF5msH%2FP1zfGE0xNUlv3yY8mvVkrE%2B47sds1srH7MVCrJdJ5pJ99%2B30bDgf7Emxl4NzS%2BSapkc3bB2vMrNrN8zGaXjtrs0jGbWTpmrdllq7fnrdaYVTktsQ3YtDVkI6GRt%2BYzwggq8PARAV3qbVZfNauE1dP2qFer6RNRg17PNtY37PLly%2Fbxxx%2FbxYsXjfdwf%2Fvb39r7779vZ8%2Byw25HySjJafn%2Brc9y56dYCj44N6b%2FTjkw5cCUA1MOTDnwRDgwTTafCBunQH4uBxQu5gYVZtbd7yo4IhAmoMydEonDFJJFXPZz253Wn3LgWeaAlrXWG9Zu%2BydMPKGI2TLNcmkNZpFwaQY0PmUyNzdn7777rvV7Pfvk00%2Ftk08%2BsX%2F7%2Fb%2FrPcBLl77S0tn5uTn76MMP7fXXX9esKGapNrTRT9%2Fqo57VB%2FtmfWYyd623s247q7dt894t2127Z%2F2ddbO9Tat1t6ze34v3N5Uh25AlrySalYTTk86UWCSbmvPzlJQn467Bk2jdZWYTvDLxpGxdGPsgFslfJp4BR5sX6fuiAxv1R9bY9eWwHT5%2F0m8qOe7ubNne%2FXu2Mbtgc0tHbfHISVs4ckpJZ2N%2BxRqdeas3OjaMjYOGxrudTS0qJqPU2%2Bi1kfliZ96B5V3RQSSb8d4ru8uKD1DIjr7%2Bfvv%2B3r7dvX1bCSabOm1srNsHH%2FC90Lft%2FPkXtYSW9zOhmc2fSDb5yx9LoPmN0V3hQZabHqccmHJgyoEpB6Yc%2BKkcmCabP5Vz03pPmAPMsviMAe%2BU9fp932lRgU8EgdN1Xk%2BY51NwzzIHfOmsf%2Bokz51eEiwSNZKM%2BI6mmZZdYnv6hiQbANUbtry0pA10bty8aZcvf2NffHnRrl27pqSGT2Zcu3ZVG9G8%2FfZbNtM5ay02zwGuks19qw32rNbdscHOhu1t3LPt1Vu2vXrbdtdXrb%2B9rmfNwZ51Rl1rsDPPiARV6ZcngJ5aFbObY8lmzGgq%2BUp6nCzhkP9kgq11uZXnTCT6EtuYC9UzbnrC6mkoiZ12DNKmPNowVwQyO9mwPn%2BNfRs0uzbq79v%2B3o4NNtesu3bPFo%2BfsYXjZ6y1fNxqLK9ttG1Ya2kmlhlLmoOePps0ccXMMseB78oLHiTH%2BsRKM7CJmeper287W1t2%2Fdo1u4hMrl7RLPLbb7%2BjT5qcP3%2FeFhYWNIvtOxAzo8ssbplo4k6ZreWHfkx%2FzxYHUqbVgYRni8IpNVMOTDnwtHBgmmw%2BLZJ6DvAk7CHAnZmZMWZVWEbrHSWBkCeckXs%2BB9yYkjjlwM%2FjQDXIrJ4DFTt6IL9QPsMSTW03q%2BW1DAAN%2BgNtNHP9%2BjX7%2FrvvbHNzS8tvuX%2F71i378ssv7L133rZTx49Ya37WV7Wy%2Bc%2Boa7Xejg2279v%2B%2Fdu2dee6bd69br3NNSWZ7e6u1fv71hruW6c2sKYNbMSSW81oyuSVkGH7Pm%2FJLGfyhKyL85zR9GSpeJzFOA5zcayKV5%2Bwra6uHVTW5shqCmVhWvTqGFR4FhsO9WsNG9rQRuykPRhZb7Cv5cAbW2s23NvSe6kLw541V05YbXbJ6srFmaUk6aMBkn3gevIpoSQa2swo3rVlWbGZ9Qcj2%2B%2Fu2%2Fr9Ncniyy%2B%2BtNV79%2BzY0aP6TM2LL75op0%2BfNr6fynupnkwyozs%2BeznOBH%2BWycnks%2Bn108YB%2F6auBiq02zR6UA4yPG3UTPGdcmDKgaefA9Nk8%2BmX4TNDAe9P8dmFkydPKuFcXFpUJ8k7YIz4TwbMzwzhU0KmHPibc4DBGx%2FEoWnNfFpNS2O5qyWbQ7P1tXX7%2F9l782dJkuNM7MuMPOp8V99zAgMSIAHuUuLKdldaUWb6Rabf9PdKa%2FuLzETRKIIgQOIgiIOYmR5Md7%2BzzrxT9rlHVGZVv9f9%2Bpp53R31rF5mRsbh4RGZ5V%2B4h%2FuvfvVL%2FNPPfobf%2F%2F7fJKRGVVYWJxmcnZ3jV7%2F4JX7xg3%2FCn373E4wHDxAYoqcSaAo05QrZxRMsnnyJ5eOHKC%2BeICzXSNoaht5n2xymLpAENUxgwaagSKfD7AFNUfVZjGbzWMSJYIOcFXQ6dipuI9i0CG77tjiBdUl6ZD5%2BW3Fs1AezUodk0jzUTlLnWbclrV5Rc08q0XBDq%2BE1MoZy4d7OtsY0DGQPa0CfQYZOfYyESWEdBJw8yL5aXtFEtqZH3kacAFEbWRPc1hXmixW%2B%2Fvpr%2FP53v8Nvf%2FMbXJyf46MPP8Jf%2Fvt%2Fj08%2F%2FdRqM1MxmeWY0ikSx1nfnWyr%2B%2By%2BT3ntAWfHn7ftzI0dj%2BIJuubz1CKO1brhbeuPp9dzwHPg3eGAB5vvzljekJ6ooPbixKgXy0Gagl5oaQJGpxaMjScCk6HwaYUlCnzbctOLN%2BdLeA689xy45FmV58p6lDUGq%2FUKD7%2F6Co8ePxHnXcR4fRdd6%2FUaX37xBX7605%2FgL%2F78T3H7aIq9yUjMYVHnKJfnWJ1%2BjeXxVyhmjxHmcyRthTSgl9oSQVMI6IxlzyI90Ooebe6V7D4OcDpo2d3ZgEHZy80Xg0LGfg59b7gXhjvaHBakulIO4vKu1TVavaqm6IuHLn10L2VIVz9tLd58UeWiZw0Dg9o0qPILZGcEjEAyHCBKUzGVBWjOGiEM6KWWDpTI1ACMB0rHQ8vZBYp8DS62MdQM96s3VY2L8xl%2B94fP8etf%2F1p4TnD6gz%2F7M%2Fy7H%2F0FPvzwQ0wmY%2BvoKRCwQaBBAMkvFVv9xYU%2Bf%2FrnuwC0f8%2Bfv10c0LF0M%2Fvtot1T6zngOfBuccCDzXdrPL%2Fl3lAE44%2BbO15FjgqPKih24qGUDEMJHk9nFjY2%2FBawlNVbClBXVe3TPQc8B16aA3y%2BBKSII5lAYlB%2B77PPRJtGp13j0ReYzWbI8hxFnqMsCpxfnOPXv%2FoVfv5PP8OffPohhuYeYtOgWc%2BxPn2M1dkjVItjAZpRs0YkGsAaQV0hbGrQEDVyz7TYycvGxJ7NKruj0E%2FMaHfkZ3tH%2Bnzpe4Gga%2BtuPxehM6u3x0vhqra%2FeenInlJ9LbEm7jUV%2BMlwLU0D7pGMQ6Cs6V27QX4eYn06RTqeSEzSIEwRmoEF7WxQNZCMbXr6%2BBH%2B%2BWf%2FiHy9xp%2F%2F8M%2Fw4ccfSwia0%2FML%2FOZ3v8evf%2FNbnJ2fYzKd4DuffArulX1w%2F4FoMqWL5JPVbG2bTpJSvecBpXLqXfvvxpVHd979Hr9rvfX98RzwHHibOODB5ts0Wm8FrRRqrgacFPuc6GelPJXhuLJvhUhxZBG2aOtKwzLY%2FSYCNMWclozoC4xvBWM8kZ4DN5YDFE4d0BQTzraVPX%2F7e1P86Ec%2FBJ0BffjgA3z%2B%2BRf48ssv8MUXXwoAPT8%2FR1MVePToEX7x83%2FGv%2Fuz7%2BFgkuBwOkC%2BvMDi9BHyi2O02QymXiGiJlP2c9KMtoWhRtPum9T3gXuy3XvEIUt9a%2Bg7wLFR3wH6X%2FO9%2BFvB1i8vnxYtTU5d9RbgkiLRszpSSKiAYr7puvLUclJX2RJMc58oo5s0jB18jsXxQyTjKcbpGCadSo2iaZQQLIyRWeH8fIaf%2FONP8d%2F%2Br%2F8TFfdlzs7xF8sVojjG5w8f4suv%2FiiO0z54cA%2Ff%2Bc538fHHH%2BHo8AhRHCnNdGwUBmqCK3v11PkTQec2ANl08Bs6cYzrOPtqDbv6WMvrqvPVKLpppTuw6flz08bG0%2BM58D5ywIPN93HU33if%2BQNHgWD7h05FhH5aIM5EnMAmsfAC7k1qwH1hNBOjkwsKdlrWCYL9Ot54Z3wDngPvBwfsY0VAxz2QNGmNjcHdO3cwHo7w2Xe%2Bi%2BOTE3z%2Bhz%2FgX379a%2Fzud7%2FHHx8%2BxMnxY6wXF%2Fj88z%2FgV7%2F6Bb738X0cJLeQXZxiefIE5fICcaFAk1pNagJFmxkChqCNkT7ok2jzxnALUs6CgU%2B%2Fe3vocXtAXL7t1KuvLqvDNd7d0%2B2XjikagoXvNH0LUXvkWtAyaqpqF80YVzQoBYwWRY3VxRNEpweIGYdzcoRgUOleSglh0mC1XuOLL7%2FE3%2F3d38m3LnOsVkucn19gNJ3gfDZDOhjiO9%2F9DJ997zM8ePAA48lE34%2BiubX78uy70tFGB0EObDpqv9ljx09pl5cbvr0MJTv1vUwVvozngOeA54DnwDfKAQ82v1F2v0%2BNXV%2BikJyUjmj%2BVVHwWiFbr8VJEM1pu1Va9ZroBKn3iZu%2BrzeBA88SdC%2Bb78%2FK%2F6r9uay9V6xTnNAGCHrPHJ%2B9NEmQHqViUktPp598%2FDF%2B8IMfiGbzi8%2B%2FwO9%2B%2B6%2F43W9%2BiXxxLsBzOT9HuZ8I2GQaQ5%2BEsjdTgWYUqKdXKjRlGYldEVbxH5eeOr4R2HU97dK7nupdtwzVpb%2FYGctry7Y%2Bvo4ssJS6LRFdO6SFiRrzkqcCnLm%2Fkua0NjYnI5aYNkCRr5DPz5EvLpAcrGFGFQLTiOddevU9Pj7GL37xC%2Fzsn%2F5Z9shWRYY8zzBbzPHxJ5%2Fgo08%2Bwff%2F9E%2Fw5z%2F8Ee7evYd0QFNcLsTR2RBDpWhoE%2B5vpwMi7vOUxbse957Pkcv4%2B%2FxSdvBsRsuoq4o9dft5be4WUJ5fVb1P9xzwHPAc8By4eRzwYPPmjcn7SZHsM2qwWtHb4h8xm8%2Fx4P59AZwUnMQMjJ4aw77w%2BX6yyvf62%2BCAE4rdsU%2BDE4B3BWPmuSx%2Fv%2BzLnD%2BrvevWt02XM0%2Bl51MXe7GxIUgU%2FKmzGTrwGt2%2Fj%2Fv37uP7f%2Fp92T%2F41cPP8Yff%2FQsef%2FUH3DsYYTpKUKznAqzoNIfaTOsKByHjbxKmcY9k3aAWT9N8punBxu7VJNeElUxn65fxlf2Uml5VVSYMU6DJkCTqmKgPNLc5xeyWImt6q0PsaGQftA6mcC9nFISICD6LHMVyjmq1gBnnQEjNZ4j1aoU%2F%2FOHf8Ld%2F%2B7f49b%2F8C%2FI8ly0Ejx4%2Flpame%2Fv4H%2F%2FLx%2FjRj36E%2Bw8eII4Tjb0p%2B2oJNgWy675RAb8EnrThJQblftDmGtpN10t3fNF5xHLssTv2yzve9NOUj89%2BPp5V32Xt7Nbvrz0HPAc8BzwHbgIHPNi8CaPwntPgxBsKRfRueXJygrOzM%2FFIe%2BvWLXX%2F%2F1pEyvec0b77L8kBN0N57J9fJUQ7IXk3%2F%2FOad3Vflq%2Ff1nXOWcez6uvacHuluaDDc3fNowOctCaIRGOmZu1Eg4PhEPcHA9y%2BfYg%2F%2B%2F53kS9OEbVrTE2D9aMvUK7nMHWOuGUMzQYRgaWYfIrtqNQt%2BDLgnkLLKzn2ade%2BSk823bH9F80oz%2Fv86Pr14mdsQIEbj5cva2meLW%2B5pEPMjsly3rehRgisJcRLqzFEi0zAZrmcI95bI4gL0MSW3nx%2F%2FON%2FwI%2F%2F%2Fu9Fq5maAFEYoipLXFyc4%2Fj4CeazmYQ%2BkTFle2Le0W7GR%2BhleBWOIcOdsCeM%2FWk3m6qX377jGMedDVPtfOlfX5bHpfWProwbB3dkHp7v3u%2BVtfzqpci2ia6clncLDl1Nl4%2FOVj035kLjnDpydOzclT96DngOeA68%2BxzwYPPdH%2BOb3UO1nhUaRbsg5me6Gk%2FwqWEBeg45KG2IkHmzu%2BWpe1c44MRbHt1X%2B%2BYE%2BK6ndnJ2CfZsu9xTtyXhOnkoePeF992aeI8fd7SXzzy4vOogiGWdlpPVqKkmtZG6j1MiS7bcXUmdnaAecVATRxNMhgGCaolgeYYqX4sGD%2FkKpikQCehimBBbl%2Bjs%2Bs%2By9l%2B1qB3BTNWPPvTU4vXN6B0Icble7ah7yJUjbo9mn5uWV32A5NhnuU7aHE2y97WpEYUBTNsgL9bIl3MUqwUGxRrIMzx5PMc%2F%2FP3%2Fh%2F%2F3b%2F4ffPXHr8SbbU2%2BixVHKHs5f%2FnLX%2BKDjz7C93%2FwAwkLFcWJAlqOgCwQENyy5%2BSWOibiJb%2FWt5oF86rpVB51nO16qGPQ8XD3urtz%2BZm2v31vt52OYTxzJsCujPSDKFk%2BkmOLn5va7CToanM1vPmjjKvlO1t7HnjkdNF3BfNq31wdb55a34LngOeA58C3zwEPNr%2F9MfAUWHMv%2Fmg7h0C670nVLE74paBhRdxOPvLc8xx4Yxxwoi2P7quNuTlprywFTvRlXnfOWzzn19Vnsz916JfZvblbZ%2F%2B%2Bq9flccd%2BnsvOu%2Fa0P64ekmshE81dRduopqFoN09g1yMxcw8FmNILa12XqLIV2iKDoZOvpoVBK95nw008TKVHW9zAsx0edfRp7m2geVmPXiVNwTNr6Gk3d0kQgvnPUq4HO8IK%2FkTLqdUICKSWMjUGRdOgyNYoshXqosC6Ose%2F%2Fvo3%2BMlP%2FgG%2F%2Bc1vxCGQMSFMCKRpIvsyTWQwGo2kfm4xWK8zDEdjmNgI2BfyLPASmojJhcfKic0tubTEbuYhr1lD%2F6jlbGl7scuEfp7rn7vWWcJxuCvt7vbb6kyoedfl6Mp8O2fb4FK1lttpT9Ol9%2Ft9ezqPT3lzHHDvNz8Ob47HvmbPgWdxwIPNZ3HH33tjHBDlwEbU0dh%2B3Gc0HA5xsH8g8fu4P0z2HlHQcAIUF4b9b%2FYbG%2F0kTXAAACAASURBVBdf8S4HVMxVjZsVd7ekXnfhJqW7dsKxS2e9%2FXPXjst%2F2T2Xh0eXbzeN6f17PGdd%2FbR%2BGXdOaOXa1DrEsoC3JZlpBJj6bRnSw2ntnCnspjxbU%2B%2B1YLiiskCZr9FWJWLQhJROchiPklU7urTNTXNCVpd2Oa8c7W%2Fi6HjmeKLccdRuWnS37Q13yfs853dThmtl%2FKOFBmogaBA03KvaosgyfH2xwE%2F%2F8af4%2Bc%2F%2FGfPZhbz7xoNUYnSO0gT37t%2FHx598LA6C%2FvyHP8Sn3%2FlUQtDQW3doGlVbsrE%2BEdrihlx30o210tRR6Spwx66EnrleufTrHDcceEZm5ZT8F%2Fr1%2BhkFbuAt%2Fd16HtDsE%2F4iefvl%2FPmrc0AB55tdsHp1Kn0NngPvJgc82Hw3x%2FWt6BUFMSfS8YeAjknG4zHo8ZIr%2B%2FsHBxLQnKKLeq5U8zKRTd6KHnoi3wUOKJDiLHRC9O4MvOyasEo186%2BfB44OV%2FOuoL573%2BVzR5ffmV9quvSCmkwpzn9c4eGRgJPHfj95rtd8hkXfadVobV2jLnKgKmHES6vuaWQdUsKuNEkzAmDZvm3PkthvyVH95o9dqzxzPRY6n6JrO6%2FcdknuyDoaSGzMylRArH2sygIn9D776y%2Fx05%2F%2BBE8eP8b%2B%2Fp689z796CMc7e9jMh7igw%2Fu47PPPhOQeefuPYzGY0gMYkNud9x3fHHaGyFc%2F%2BktGZeuF5fPS9bo8vQ64Cp%2FoWO%2Frl7BbTWr3CD40tbYNs9ete1eezfklCa0nPJq0vzu9e%2BGsPlKMvhcNE0tY0AHzv7jOeA58M1zwIPNb57nvkVygEKsW%2Fm3aksRN4IAk%2BkEcRzJKj6FEWoG2tDo%2FiTLPf%2BT7afRN8kBEcNl0vHfBiH1SLDpktLNTmcg2gnyvSIvcroR1J1Q7gq7toRCl9gDDr2kzWmffn0OlT7WoRQLIBHw0fWgAwOdflKgAjEpvUS7vXYUrpsKaGsE9O4qX9cO2UeaWa8eRWMqoFb7YF8N3zrsEOqsRQVpFBJl9HX%2F6IadOiN6l6o9cT1kPYbxLtEK8CzLHPl6iSxb4%2BjwAP%2Fhr%2F577N%2B%2Bh%2B9%2B9zN8%2F3vfw8cffoC9yRiDQYzRaIjBYIg4SRCEqhsOJKCnk5rJV9LDVpSfJLQ%2FGySV%2F9yH3ms384mJrqzL4I62UL8yd%2Bu5x36DHb%2F6fNzQa%2BvqZpWrvF%2BHS7tJRx3nLVZa8ghwOi0m8%2FWvn7%2FP8yb18m2nhWMhIsZlA%2FW2d87T7znwlnDAg823ZKDePTJVehMlB1e3wxB1XaNiMPQwxGA4spqhTkwXUdiZ0950OeTdG7D3tEcUgfuTzZ4%2FJbgwvQ%2FiyC4nZL%2BUtP40v6XpPi39LLvp8rT0M9hz0qh0iSZMnielT58vR6s98mC1TwHLqaug3pEptt98mAk06xIg2KTpKM1v5Su1dyyReqRySesTalP7Sd%2FaOXvcp2eby7zjPu6Opul7TXkTR0ZNkOsKaErEJsD%2B7SP8p6MP8OkP%2FxJZmyAZ72Nvbx%2F70z0c7E2RxAZNU%2BqeT2MErMrCG%2BcdQT0X4dxY2D2zSgnb73%2B796ejdGs6y4WjfZOjO2FVz7jdZXz2maNImWkr3Kw%2FOFiu%2FNIGXaPu%2BOz6v427CiYvp68DmtRoOodH3waV726b9OtAmYH8FV8PV3SV9zke%2FTG5IqtP9hzwHHhDHPBg8w0x1lf7bA444UPW4K3KgAIag5ITeEo8TYlXty3qP7tWf9dz4HVygILktrSts%2FEyAZNpDlwqDc5ckWBr%2B8M6X%2BJjwd71Sl5GI0tas0UBma5%2FuzV2T6fUQg%2BwgjgYu5Gufvobpy3k4bPa1mirAnW%2BQlPnCMIaNKkVM1xrntv1vNOd7rZ%2B066FS26RS4jr85Zjq9f9vrk%2B8I7CwgYh92y2FZoqRxIF%2BOj2fdxN9pAHKVozQBQPEBmDJI4Rhi3qiuayLNcJyhyHTTsCPHnPjQdDofRbdufPOvb74vK5StzRpb%2FIsV8v6yHdDnTZe5sDY4W6tpjo5ptrr1%2BXS%2FNHz4EWVVUiiiIBnM8Ck8%2B65%2FnoOeA58OY54MHmm%2Bexb%2BEZHBB5icIazY5oiteGqKpKTGejKBThy%2F1QiMihssgzavS3PAdeJwecoKsCs4MOT7fg8u3eYTknSPOeO3fH3fxXXffr759flZ%2Fpl%2Bdjyw6eaA7736njpEqmMWefThqCKnRyrSr0qYG2BOocdbbAen6GslwLuEJQizdbMWUT%2B9jtOl0rWp%2B7UnpcGzfheDVFvLN7l9eObzwy3EsDE7RiuVFmS%2BSrOQZBjfEoRRwMUYUJQmNNZUPyuUVglNusS7EYFzN229ttu8%2BtZ93r5%2Bufu%2FHp09%2B%2Ff51z1%2F9%2B%2B%2B7cHZVDuoihdepCjkLNXZ5KqV64ketQ4fO82xzgIkscJ15j%2BW4Ps%2B%2FdO8IBDzbfkYF827tBGYrmLgSai%2Fkc62yNvekE08lk82NCAUxdY7ztvfX0v30cYPxJWqBS7O0E5mf1w%2BUSxb3b8LcFQp5Veveezv7d1KuvXetP53A9kKNoS5mH4MKZAfOOvZZq9JwxLgX%2BSBrLqKdatNyfSYdASxSrMyzmxyiLJSJq8qxzIQddLqXGNrVpUzJtGnm6yI1KIZ2O1n4vFUbpYhrfWwo2DWo0%2BQr54gLVao5otI8wjhCKz15y1%2FKYdQaROEYT02ThI9tRk0AFnWREv02LRbeTrsGtqwq4dHd8VlXM43jhzl05x59dam19G429aru73NvtSbo8fx3Ht3P4q%2FeJA1yEplbTfzwHPAduPgf8k3rzx%2Bi9orAsChwfH%2BP8%2FBztBw8wHAwQ2x8Uakco3jLC3Ea%2Be6%2B44zv7TXNAxWXV3ykuU1HYidGOHicg88ivaKZEHaX6GtVM7ZZypa93pJMRV%2FsVYrtUJDDHEbRbtSVBQZC76TbP9eizIFQApmBQBzSpE7UhH2RPJq0QMgT1Gk0xQ7Y4xopgM58jaovNvk3l4C7Vlkh72Gi2lIEO7joi36qjdIGmt1xECwg2a0SoULcFqmKFenmOanEKTA8RJSOEhvFMGV6Ge1wJ0TmKhKgcctZmmSTvPgWyyhA7FjS11Ulmc%2FbG8pU559q%2BqiI3L7v7roSjgkc5dwk2a5fmHOioKfD2%2FHy6Xqa4Nrq7%2FsxzwHPAc8Bz4CZywIPNmzgq7ylNBJNlVWG%2BWODs%2FByHhwegEwCmi7xFYUpO3lMG%2BW5%2FoxxwArIIxL155%2BRlK9tvaFIjU15a2CQZHDCz2URC5r%2BXEJWFIHp31TY2DcuJo4oXTkO5nWP7SuGfKlxdWbs3UC4VXFJ7wN4oANK6Vf9Uo21KhE2Opl4BxQXy2ROsLh6hWp8D5RJBkyOgR9qW0EmIF0c5%2Bs%2FS%2BVRfmFM3SJI2lnoJTm139Ru%2FUn46ugkCOTeitkRFU%2BNigWp5ivziCQb7R4hHE4RxiqYN0TRAQ%2F8%2FUoKllE%2Bt7MvsuMFxkVGRd6L1lCuZNyVeoNcbSm0ZrcM2%2Fvx6Ns%2BGq6crwr5z3YK0sjcEz0qyXTDceApluqVddlXou%2F7pGrXuq9K7lv2Z54DngOeA58BN4YAHmzdlJDwdYi5LeaOuKvkSaIrc6YQZd%2FS88hx4wxyg2GtF7q2WXJoIxlY4dhkUhLkcFiRJRQqgnD5KHLpsslFs3ly4qi49sn7Jucm%2BObGQzF2746XVSCJrUriy2zzpoXdoggG7s7NXnZxKaJMSAZ0ANRnCcoV6fo7s5BHKsycw%2BRJxWyFpK0RNDUOwyQUjrdky5nLaek1JhrcXVHQ9YR%2FISfKBgLMsM9SrGdbnT5BMDxGkYxiax8ZjSHSTVr3NUsepQN%2FNkD43XP3K1w2zmEwAd805pYPBQv26d8%2F715eMm%2BBC5nE0aR4%2BI5Ii1fNfR6v0TJN6FXKxo3fZO70iuZfjmzl1gLjfmvMp0E%2Fz554DngOeA54DHQc82Ox44c9uAAfohVZcxT8lXaioLv%2BfuncDCPckvDMceEoG3u2Zy%2BA0MU6IFu%2FJmlkEUJGcnck3Aaf7cAK7rxPRu7su11NHiZ%2FoGudd9yC4su76qZKXJoiWSepw0ITeZklvABOE4gXVFXRgUUKZ0BlQlSFsMhgCzvUc5ekTrL9%2BiOr0CZJsiaQh2CS4qhFtgOamNneiR1Vk2u5oXzrubGd9G684DUSr1zTgns0oIOBco1icYXHyNZAMMQwMognffdwkEGpMz8CIttMNsxvlp3mgdwjlyLcX2VesdV3GbZfG4%2FM%2B%2FbnNvJZS8UDMcwcyeXQm21qnAjXXhjpCUsDJNIGkdoZ2s%2F151Pj7ngOeA54DngM3iwMebN6s8XinqVHxYbuLIoo4oT0IkCQp9g8OUBQFBoMBQqPaFRFAmNnJ7tvV%2BCvPgdfCARWN%2Bb%2F%2FsWapm7mnuVSI1ry6y46CtNt7RsFfNVSctP0a5Vzka57R8RCFbNmd12%2F0knMK3yzzVG07eZ3wvpPcu3Q1EFu6loWGVlzQCMUEAiGB4EZTxlL0PJsB7RphtRKgWZz8EYuv%2Fg3Zo4cwi3OkTY40qGAYM7dtNgEvHOTokbHVlc2W1B6MvqwnjvateuzFZfkvy%2Fd02mW1XlUb8%2Fbv7V53tTMXZwK1lGhqOY9CIybIFbWbBJsmRijgntrPFkFSI4yGAOggiLs9df4oVHM1KrCUltROVRYKGPrkMu1bR9FVZ7t9uIwfl5VVbWSn3bPlZDB5rqOuVOs9kstXvoJKy8ptDLrVEEuxvK3Zcp4p7%2FbHjWPH23e7v753ngOeA%2B8uBzzYfHfH9kb2rC80kEAKHY0I2xQ%2BAgwGKe7evYs0SbC%2Fv2e9zVHMoOCugosTPm5kBz1Rby0HVJh1Iq079mBFl7QFNYKAgIrSszX7FrG4J1GLOaqTlrdbccxS5z%2Fu6qojy%2FaIuDTbVUL40%2BmqN1IIIyC2DxCkO9bpjN1zKTRyD2a9Bso5muU58pOvMX%2F4O8y%2F%2BA0wf4IJcgzCGmFdIWiqDaDQJ1cVp7tk92DTxskN8zxNsYMuO1wQunXfIrlzWbndNt0183Yc7c76NLkaFei7kl1epmzfc3n0SFAVCMLSWKSG86Sp0BYrFBfHWHNPJ4FoVWBwmMFMbyEYVjDRAG0QCUBV%2FnGWuQUMa%2BLM3pIU91Vitgl47tV2X7S%2F7BHTt7m5AYi9OmVRRfJZIuiF2L6rmY01OH52%2FNY2dS%2BqzbRpTnNtLm33HCXkhcJvl9Ij5g2f8jfKgUDp22UMuQYNrEOLXt4HbiGRbSRkjW2DR%2Fe9RhM%2Bi%2BeA54DnwI3hgAebN2Yo3lNCxGovkLia8uMahJhMxhLYPI4ju4%2BTP8w9EaMvhbynbPPdfhMccJ49t%2Bt2QGJLLOxpOSn4EnCqxE8goRpOEbMpKIbWLJLaS1vO1blJ2G7SXm21aOu%2FNGMvkWV2y7lrd%2BzAETGQXtF5S422JUi0Tn24Z9pBMXn%2BGqAuUa9nKC%2BeID99hPWjL7H84x%2FQnD%2FGuM0wSRrRaFYlPdG2CI1B0zUr5qEKM5Rkd0vBSP9Or0u9U%2BZ3j38%2Ft9Mdu%2Fp6RTb82M7vcmiqu8fyXR39VE13Ka50d3zGnZ7WjrjYkC8Em8hR1zXKsxKLMkO7XgDFCsO6QFjnwGCEIEpgwgiymTPgz3UIegiW%2FbRhhDYwWxSTypb7bV%2F60y%2FbzVJX3TZ%2FbOoGcJEHnDN8BrhPl0DJgmPe4jdg8CptQy43Kk7rnEpgpDoVcm26EWF%2B%2FUjJbxVwOkpe5KgAU%2FtelqX8tjF0hwOT%2FbqYl7%2BHHSB1%2B1n749Mv8WrnfQDNmi6j6dVa8KU9BzwH3mcOeLD5Po%2F%2BDeg7BQ8KJEHYoi4b1DS9C0IkSSIryHXNH1y7ds7fWZUzbgDlnoR3jwNO27Dds0403k7nlYAcgsi2ViGbx5rXlLSZwSINcXbFNBWZHTjaqP4cqNtAnZcRKqXBHpG7dXTXmzM5IU0E2jWaplQvs3UFVIyfqYCzJcgsNWxHdnGM%2BZOvkJ88QntxArM8xwg5JlGLmHVUJZqqEidDrSEY4mfT4lMgQe8oDTxXDtliTx3cXacrtZq9TT53X9t09W1SLRlueJQuOy6bTCzrLmwBW7%2Brb9Pc1okrw1o5wroHkamyVBYY2Y8udbQ14oZhPgjuS7TzAlmdw9C7Lx0s7d%2BGmewhTIcI4iGCZIAgSiXwk8yZwCAwiXz7vBVydAVhi7LrXWz3VXnQ9WlTB5m3%2B5GiTLcLFA0XLkhupMBYlP6MEWr0WrR01NRy%2FKilZS%2Bc1tY9Hbv09Bsldx1s7ae%2FmXMHxl4FhPXLKpC8un%2FMa4yR3z4CTpmvFtT3Qevr6m2fttdVp6%2FHc8BzwHPAccCDTccJf%2FxWOKBiiwplGwLsrysP8rWCaicgbnL6E8%2BB18YBFV0vEaSvaEH0PjSHE0DGvYw10NB5Do%2B8ruS6qQngGI%2BSAjjTnebTVWzb3MiePNkFUS7v846bSrYAnpbq32OKXks%2FxPkQATNpr1DTDLZiaJMabVWizjOs10usljOs5yfIL06A5QxpuUbaFhgYOr%2Bp0NQVqrZBEwYIuN9auuFAgeuTA%2FVX8%2Fq5d8j3rgvSPZaxqbZnrtdam953aVq4X8YtDDBtm1P9FG2BKe7TnbNUHwJpfwm%2FRKNnQhgQbDHdzpdWdmairmq0qwrrKsN6fo5k7wjp3iHi8RRmOEaYThDEA9nfGdCJEDWGIbViu5pNhYiOtlc69pigYEtmim2g32un5mcaw9zYD8F1FIt2NgxjBGEi9IM00%2B2u6wd1vaKtZTmdM7sj4Kp8V45cTOXnKpBHJ3nboJLPzIaz7wobfD88BzwH3hMOeLD5ngz0je2m7NdU80VKKfxBLYsCNDNKkhhpEm9%2BZDdr2f4398YO5%2FtBGIVqFaxln6Y4zSGwLIAyR5tnaOS7RJ3NUWULVEWGpipQ16WYGDpNifLLCu4C%2BNzkdsDsVTjq6urX4dL6Rz5ZNKNtRNNGbSYd%2B2ioDprOVkJ%2Flq%2BwXi1Q5gsE5RpJXUqIE2NjadZtjZpAMwjQEGSEoTWhpc6K%2Bz9Jh9X4CigjMLN9tzBNI3IGNhQnaeSXeTQfYasrI8L45q5qxzqQwrqtlq3XfVeLAr6ufgchxZOrAFkFjY5LCqIcre5oKdnEImXrsntXtXQCvVrUzC4OgIzwRBcbCM61%2F5HwvUVVVijKNcrVHOXiDNnFFPF4gjAdi3azIVgLInGaFrr9ewRnjhzpp%2FJXk7Zu9Lhw%2FVNXA4%2FuXFWWvTpIix0j5aia%2BRJomjhFnI4Rjwia9xAOxlZLa4FnGFttv3LD1dof9W4M3N23%2Fyge15%2FTjT647J8%2Fp5i%2F7TngOeA5cOM44MHmjRuS942gjQgjoJJ7mM7Oz7FczHF0eIj4YJ%2FyVeeUgRqT941Fvr%2FfAAe2xOlntOfyUaiv0TYFgrYA6kz22zWrBar5DNnFOYrZCcrVGer1HFWxQk0g2hCUKsjoGtFnQPVGKq5LyitPdK23a8dVqG0QH%2BjTxOsWNXdtWmdAhG4U%2Fw0IPFXbWdWMrVkIyIwYwgMtIu4rI1QNgErOQjTUyoRWQ0XnN5s9iw7AtQgFeaqGV1tXuNIE6gRHfNjaOJ9Sf48uolb13svydNhCS0y258wxqR%2BzGuSepo2Uqisn3TdIAV4c91jTZr3PBS8dn5C0i0se8kDHnfd4pjSTa9q%2BcEG0jD3QGwTCT%2BqLaSoa8luzLLXhALdWRqEC66al595a1y4Yi7PKUBULNKsB2jhFjRgKT6nVVBrZkgPwpIcf4ZWc7Y693r%2F%2Bfx0PdvR6NbFPOr5CIEKEhmBzgIhgc7yPeO82koPbSKcHMOMpgnQI0OuuKGeFK8Jtu2liQyo5vvvWd2OwyfSGT7iwwS9Bogd%2Bb5jZvnrPAc%2BBd44DHmy%2Bc0P6dnTICZiqYeCPeECfEqiqEqenpzg9ORFPtNPpRLzVMr%2F%2FkX87xvZtpFKwhBOrd83V9OamWyL8BjSLJXjMEDQZkM9RzU9RnB0jOznF%2BuQYxewYyGcIqjVaxqOsS4Q98KMAgWJzX5xXoXvT2AufuLp262VFHSTRcwu2BKJY8GPbk%2BdNoJmCzQC1gM%2FUAjECC34ogBMg1iYS0FdTjUfzWUPTyBZtXQtgU5%2Bq1DTyq3VJREkBiAonCO0IBivEmxx8P0hbAjY7bSB5Jm2zRukqQYACAa2F%2FSHQ5WZBBh4JBAxXsneQ8Sw1rAhhp9QlVLFtoitthxpHgmqBpgGdJik4ZkdlW6TQTlgbomoJzenIJ5Itu%2BylACS%2B1yyvwpahZOg4h2BbY5kaGRJSp9rkVPanE8jXYsrc5jmaMpYwKKo1JTXaL51LClwtNLQjKSNjR%2FJlDxbE78zOy2vTubaZXWQTKQkitGGMMhqgjMcIJ08QH9zF8Ba%2FdxDtHyEcqdOsxringLUIjLYJXBFh73S%2BufZ3wadLf96Rc%2BZZn6t%2BY1iOC6H8cC%2Bl%2F3gOeA54DngOXJ8DHmxen1c%2B5xvgAIWG7ge%2BRVVVyLIMi%2BUCeUZvjY0Ilcwj3zdAg6%2FSc4AcEJFZhNFOILVYwN7lFWFEhbYt0NZrtNUKVTFHOTvG6tGXyJ78EdXpGZrZDEG%2BgGnWMG2JkPs3JWIidWCutT7f2abe6Y79%2B88772i2PdECVmsnFxvHMWxHnjzRDPJM4A7NX9lTMYtkDgIjwj9GeuQdhVAESgQEBGZVG6IOYzQmQVm3qIgzowSxdfBV5fSsWgs4IziiJritCZZaxCGQSFuWI22INohRtTEKavKCWD35ip8ZgjN1IEazXtLSmEBMdqnVpNdbfoXOlhrYHGGjIUWEny1NemPUsl8wlr2DLdMa1ZISELIPbZRY%2BMn9pyXqJkfYlmDNsu%2BWQJMmx6JUDaW%2BChGqIAEYqiSMUdQt6qZBaCIkKeuj8zOaUNtwMC0BYwMCTYVVOieYj2kRQ%2BkIoKW2mW3RT3CNhvyhxnCjbeXY2LIb0183e%2Frz4Xlz5%2Bn7LC3YmtQ%2FB6BpaSlhZzABu%2FQGLQq0ZY46y3Tf72qOYnmKMrvAoPgAydFdRJMaSMcQtS%2BsEyT21WlK2YB7NDbdUnPh7sbTfdhNYX3UiO92RzXF%2Bkzslulfd%2Fn6qf7cc8BzwHPAc%2BB5HPBg83kc8vffGAf4807ZgSBSBQAKo40IZQSdFLKYR%2FcniX5hI3O8MaJ8xe8dB1RMpiDK%2BSj%2FNjzgPTGMlEzUkHFO0ksrwUyOupxjdfY15l9%2FjvWjL9CeHSNaLBFla8RNiQjUZio42gA2EZy11U1DciI37BnPu%2BvtfP0r1sOPO7pzV38vXdVxtt5LwKaFlASe%2BlGNG7WaBJ0KSalfo87PCNCsCHeCFI0ZoBCwGmI4miKZTsVENVssBGhUAhC5X5VALxLeiQMl0R4qLQzjwXobk6I2Q9QmRWtixHGCZJAiiULUVY58uURVlgI0wzTBYDxGJOBWwWxdrlCtZsjXFwhKNZylU50wHiId7SMZTMSKIl9lKPMCDcEwd1kOp0j3DiTGL6oMxeIc%2BeIMVGi1dGZDvjTU2OksaAKCzBhNNJT9iNFwHwSe2SoXbeZgMpEwTnQGtFpcoFgt0FhTavKzlqg4Vp%2Fb1jDc88uwJ42aL3NCBjXzWcdNMhNpjuvK8EjKO%2B2m1QnuzAc7nNc%2BuPHnrGLt1%2F1oTiktIU4UsbaNmmiXeY2izlHWayzqDFm5xqDKMEKFJGwQxAScLE3Nob7vZV5vESCjoAQxXRZTOnqvolSBJp9xfc6fzudCizx9hynUZqoJ7eX3farngOeA54DnwNUc8GDzat74Oy%2FNgS3p4IpaOsMoCgD80AzOREbMZxlj0xiGRLGhUaxpo6v5%2BeLFFc36ZM%2BBSzjAeaU6K4rXO7OrtaacItQTeZQIBBiskc3PcP7Hz3H%2B8PfAxTEG%2BRJRlSNpCySodB8e9zxSKyjB7u3%2BYxGS3WwmQa5N3SSnVy7tEoI3Sf063Ln2RrO4NHbQ1cejAjwNO6HXBCoKKR10ZVmmqGZTxH8LWAlz6tagDCIUbYy6TVBTozkYIz26g8nhLZjQIJ4vsJ5zz2omZschCoRtDuQEoTM0xQpNU4tGjzQ19HcTJzDjAwTpHpooQZSOMNzfw3CYSj24OEebreXdkIzGmBweIkpjMLYnzZWrjAsAj1GfBahXcwnhQoicDqeY3vkAk4PbAgjXj09QNks0YSXmr%2Bn0Fob3PsJwPJZ9tkUQI8tLmMCgNQR%2BhYR1EcASGNVqhgnM8ACT2w8wOriLvAmwOL0QBg7v3sFkf088EwcXp%2BC3ydfiKIpg05gAJmytJrNAS0dSi3O0xWpj%2Fmv43pP3o8BhGTfugaXRLkGnjpwukOg5udgf%2F81EudYJ69A9l3L2AkDTVc%2B2ObdIk5owc9GQgFu0itzzWrRYX1RY1gUyemmOQoRxhJgANaITJTpCohadvdTn0hGiPwNPPaGu8Wsc2S%2FWqh%2F7s%2BIun3nsLHCemc3f9BzwHPAc8BzY4YAHmzsM8ZevygH3Q%2B6Ol9fnBHvRJtnVZv6Yp2mKo8MDEUDH47EIrE44EMGDgj%2BrVFno8sp9qufAq3BAHNBoBSo2q34nkFiZGs4EdS6AZH36GLNHD7E6eYRBsaRBJUxbWI0mY8YqWBPBW%2FREljALIHilTwr%2Fd5Naz579DF3eRXlKulubKrq6u5tsstPk8pQggUWow6UGT0CyGtdKMSaxRw3BVpigNgkyxCiaCPF4D9M79zG99yEGe4cI6Tl1L4ehJrLIgCaHQQHTrGQ%2F6%2FLkIYqqkLieEUOsBPRkGwODFMNbtxHtP0AdjRAmQ6R7e4hHAxh68z28QJRnYmIbj0YYjCeqEStp8lohKeZo06HolPPGoFqvpE9BOkVwdA%2FBnQ%2FQnM5QzUqUJU1pKwnRgektmFsfwOxNUc%2FOUC0zVOtcHEBVQY06X6MqclRljZZ7M7knMR5isn8f8Z3vILl1TwB9Gp%2FJPtbh%2FQcwo6EArdHkDuK9C1TrBapsJfMiGcSIYi5kFAjKa5oiIAAAIABJREFUFZrZE8yrAmWxtno9jo3OPWc6yxEi2OTCAI%2F8uJHl0Z13Cwua57r%2FHZhjfla%2F0WteG5U5CpRu%2FuczwFnFOxEMaprY5hWyukRO0Eyt9WiMKBogDFMEAQ20OR%2FYetcrBXuu%2Fuv2qMvX7xt716%2Fv2t3rqvNnngOeA54DngPX5IAHm9dklM92HQ5Y6ceKz88tIXKuM23ij38o4U7u3LmDwXCAyXgimk7WQ22CwMyXlzWeS47P8H5yQGetuPi04rU6gBGsZbeG6bSjhkZDnLQMA3J2jIuvv0J%2BfoKoWIsmM6JH0ZrOgyrr1bSRo4juUqFVHPVYzbrdk%2BOSX26a79bC2vo1uXN3dK25owWefNbE66rs4LSAU%2BsiAJBdnEGEJkrRRkPxlFpFA0wP7%2BPooz%2FB6OguwjgVD6zRoMFoShesZGSFsF4jyM4RRBGWq7mYu1JL3NbcI1mjjQPEgyGGh3cwvPcJmnRP9kJGgxGQxKIpHkxvIakKjV0ZxWLiWlYV8naFKKgxGEwwMQPUVYDVqkJZ0EkPEJsJ6sEhMLqFZhWiiC%2BQGfHBi2QwRLh3C%2BH%2BLWAykX2loPfUIEQaNggJcrM1UJVo8gJZUSOvgGg0RXT7EyR3P0U72UdbtRjFB4jSAdL9AxnXpixhkn1E4yOUjFM6u5D4q9FkiHhogGoFkCeM0Ro%2FFodDDZ0JcV7YSUitMseSlwo07bUbOt7l8Ls9sFcNcS%2F%2FladSz85da32yk%2FrMS0uOBZqqoWU8zbDhvtQQYdWiWJ5jcfII6XgPSTqGiUYCNhEScLLX9DLcgc5X6RaJJcDsQCdrU7Na7t11gFNB6DO75m96DngOeA54DrwABzzYfAFm%2BazX4cBlAu9l5fRHX71askyLplHnDYPRUByMRHT80Q9u%2FaqSxmVk%2BLT3ngMqcjo2bHQ5FqfZSUdTQBdPk6aaqxkWTx5h9vVXwGqOsQEGDRBWCjSd5n4L60kTl0nyvOEmtz4%2F132KHNXPP7r69eiuFAQr2nU9V92mPpPUNioUJmDjck%2Bg5qN2vyL3VUbDKcaHd3Hnk%2B9h7%2F4nookssgoF0VhrEKcEVQOEUQtUS7TzQDWHyQh1MkJIsNnWqATQRAjowTSIYIIYYaxxJut4gIYebpsKBeFvS3tbApZYgGteFTi7mEsImtv7Q4wHR0hGK7ThE7BEYLgXdII2HANmDCQN6ngPa2SoudNyuI%2F44DbMeA9IEpjpASYgLr2FqK3QUjMrmzdbzOcLLB4foyxajG7fx%2Bjep4gOH4hzoTovkQy5j5Ta1gjZei3ufNJkDBNP0DYxsmWNdTbDalEiLQnAc4Q5TYtr0BVRQ4dLNnap8l7HQrlPUMkzphF22vF8%2FRPm%2BVPqGjn0OVALblLK8WvqFlGUYEgPxnWB4uIE88djDIcEnFOEDIcC64FXQuGwl66DjgtsnDV2M%2FkqcnSfpuWhs0qWzPqbw98dfqOIWze8p9mr%2BOjTPQc8BzwHXpYDHmy%2BLOd8uVfigBWRRFjgSjLlTLqWp6ViZCKYmMKG29%2FmhIrnCxavRJQv%2FN5ywM1HwTtWxSHirZjUUmSm8ag6BuKeumpxgfXpE5QXJ0iqHMOEMSdVq0lxlfuNNeRGz0yV3HXqE%2BG0tipi8Gud2ldU5kzQNwK6E%2BCtzC6XarjYgRyesT796l5NeqHl%2FsoI8WiC8Z0HOPjoM%2Bzd%2BwjhYIK6CZBVJRbrQgDhMEwwSUOEDBUSphJbMUgniCaHSIqVAE1qlthEmE5gkglqJCjKAEEZiJdZExJ8Gnk%2FrHOgzFuYMEAcca%2FfAAGDhdSpOPzJc4NBGiE0UwyHt1BmrYDN8fQO4sEBYEaIhiEG%2B3eQFAxpUWJwcIT08BbCwUB97qZDjONItdI09SXYpFa3qrEKn6BdVhjsDXDwwacYHNxFFabIS6BsYvHGS%2FqplaOX2iBOZR9q3ZSokxpNusZqvsLx8bloNU27QtIskOQXCAu6GJLophsXOd1DqeOlo8v%2FvNY9vl2em3VGCoVKetmNDGqOc13K2A0Qyz7O1Xop1gHZwQkm%2B7cRpVOdJ%2BIYiY6ZCFadbtf1T7ngrp51dJpKp5wlsHRhTFiOzuh4zXwebD6Lk%2F6e54DngOfAy3HAg82X45sv9Zo44AQBVic%2F9uIQqHO3zzQrUr2mFn01ngOXc0B1Jiq8i5AspqSclw1axlkk2KxzNNkcxewU9fwccZFjFNYYUCtflfIl0BShlWE1qBiUD4VjtkDhm7V3H2mru3xjZ9q2o0Gbuezp2qZO8znASaGfe%2B64Z5P77Mb3HmD8wadIbt1BmI6AKGZkGJg4RTLkfkgiyEi0e%2BJl1CQIkhEG%2B7dxiBJ5bLBoauQlPd4apOMj7B3ex%2FDoAYKDu2iSPTThAIFJYbgIZRqMRgHqeIgojEX7SdPMKATu3jaoyzWGhvExc0SjA9y5%2BxGSMKETWezd%2FgA0wYUZIE4NDu4%2BELBccbFgb4QBY%2FqaANlqhWK5QlsVMFGIoK0RBQFocdGG1IgOEU8PMKAmbnKAoglRzNfIK4LaGAMzAON5RgTjaSQgtaCJMJ0SR0MkkyOkeYn5eo1svUTUtqiaFlXRIK44S3SHJk2W%2BdHx0P86ejomN%2Fl%2Fn2alk0AuFGdIRVUjqApZVByYEFXdol0tUM0vUC%2FnaMcZgniklgTiWIvLN8oL1kXNrny6JL1%2Bxn%2F3O0MtJ4Elw9CE9FAcMjar%2Fva4PM%2Boxt%2FyHPAc8BzwHHgJDniw%2BRJM80VeMweo1AjUvTw1m2sKYVmGwWCA4YBaC36cCPwCEsZrJtNX925yQPa62Smms6sz2rOucqzLnFqc3NDbaTk%2FA9YLDNoSo7ZBInsOS9QtnQIprFQTwg4kdCDz6TnMFDfD3wSXXR8vb5ktap%2B3QUI%2FN8%2F1mnmCMEQ6GGIy3cNgugcMBgC1ucwTUBsZiXYR3JsnWqkAdUlPvrWETolG%2BzBRANMCq7NzNGaNQOJsDhGaoezdozllawZoggQtaHIJMXdkPgLNkN5KmwBVxZiWBoNkSLMIGHq7LaiFDmFChk4ZIIgjDMd7MCnpjGCSEKN9g8F4iIZxUOMAkQnEOc9qdoaz42Os5ws0NItuG%2BztTXH%2F%2FgNEcYq6DVFULZq8RLxcwZTkB8OzjJAORojTVPYkqnmmauWKopL%2BD%2BMEw%2Bm%2B7ucNW%2BTLEWKskNRLBIsU2ddrNPlCHAwRRCvPebxqdshovIkp82p10ulbDyZzDzD7wFkmels6Z64ZFihE1UYoiwz1ciZ7WhkOJRBkvlmpsTNP55%2B90B%2BNF6TSmdQSZNJslke3VYMLRG8ScLJtft5kGy%2FIDp%2Fdc8BzwHPgG%2BGAB5vfCJt9I5dxQMUP%2FQHW%2By2KosTjJ09wfn6Oe3fvIoljMZVzgq4s9luZ47I6fZrnwMtwgLKwzET%2Bs%2FNLhWX%2Bp2ZTzWjbtkJT0EvpAkG%2BQtpUSOgiJ6D3zBY1taFNpbERbWgKqY%2BCptVU7dInzakV6e6t13q9%2Fdjoc%2Bc0lptOs0UBBszt4MJ2SV4RNDR1hWy9gslW4omWaJBeZ9frEnnOCJwR0mQgcTLpWCcTb64ZTFgjTWgCO0YwmKIOB6hAgGaQlwEWiwLtbInErGDGQ4QpnQ0BRZ5jtVqgbQuEIdtnHyLEyRBxCNFIVsUao6RFUucS13J2doL1cobRdA8N915yLyR9ztALLMFPy9AjVL7yvICpSUmFAYFgU2J2cY7VcoWmrHC4f4iQWtoWyLMCs9kaRd5gb%2F8W9vaPMKFX1TRBYLTuins8qaWUxYdWQDdBcULNdzhFHLVoyzEMMkTVDNVJiydnX8ueVIVlymnOH9Xm6Zg9NSl0qJ5KvkkJBFoVnSvRUZM46aEFQYOyKpFwplUFGmo31wT4BQPrKMAW3rln8vXodQkqCTDF1J165JCLJP7jOeA54DngOfCmOODB5pvirK%2F3hTnAfVtFkePs7AxPHj%2FCaDjE0eHhph6KGlb82qT5E8%2BB18mBTm6nYO%2FCfxCJ6jWaWmItVlmGpiiQNA0CasYYi5LOdMIWlYAajQ8rII7FN0IzW7CfHsDspbq7b%2FDIvuiTpPClczTDZA1tortUt4kgBGoQEow2FbLFHPmTr1FGKfbToSwM5csCT74%2BxmKRYZDy%2Bb2FmECvqbG8OMf52ZnElrx9tIfpNBVHMC1iVFUoLG6CBvm6QLQuYMYVQnpd4kesm2vUTS6xNBEBRVmJltGkEYLYYDVfIFtewCBBFJTI1hc4Of0jivUSTVAhno9g9saI0xBNWWNxeoJsNUMSBxiOU0R2n%2FgkNhjcOsR0MEAaRXhY%2FFH2avLtI7FGOTPYn%2FlMzKQnkwnSJEQctiizJVqaGKcDGJMgMiFaE6BtDJqgFXNf8lDibIZ0tBsjppXoOkPLuMKy6qGjov%2FZdTc7do%2Fd6Mj86gp0N27ImSzZ0JSYMUID8sqIwynOC2o3g7BGlWfIs7WYuNLwmh%2F2WBS8ctVpOrVbOof1%2FPn%2FqVF0msxvWrvotJryTpF1JzeWz6fb5%2FAc8BzwHHjbOeDB5ts%2Bgu8E%2FSJSiOKHgLMsC%2BR5gbIsxWyuaakVEOWGdVaiQsg70XXfiRvIAQq67mtxpgi%2BgTiooTloWZRoGwKvAC0dWzG%2BJvd1BpyrNj6Fm610zMPq%2BvLltwY0%2B%2BxWYV3FetKnoHqjVbPPHEuIFlBc50jgE4TU3hYrlLMzNEmK9GAfyXiEMstwcfw1Tk8uMJ3sYRSFmKTUBrbIlnOcHj%2BW53yYRhiPYoFvBGVsoa5q2fIZGYPhIMVgmCJIItEUErAxLuU4GNK%2FDKhhrpoSFc2Xw0JMY%2BMhASv3SYrXF9QtY2Iuka1nQFgjHEQYHEwQDyKUyzXOH32B2dkxBqnBeEJwGInZ7WA8xWAyxcH%2BnuwrXCyWqGvVAXO8TQCksQH7MBxEGA8TOadn1flsAQQG%2BwdHAqho8kuT0EhiiNYI20YWK6htzdczjFMgThpU2QKr%2BTmqPLfTxE6YLW24jld%2FBPvnAsr6c6x%2F81s%2BF8qlL6pN5lTjnJItmbzZUlPdoLZmy8ptt7zoiN%2FMVJew81D1kq843QWZnJe7aVcUfaVktkFgXdeN7Of%2BJtp8JYJ9Yc8BzwHPgdfIAQ82XyMzfVUvwwEnHbmjjbspgq0KFxTw5EOBRAzTXKy0l2nPl%2FEcuIwDbv7173VpKvyKn1l1dkPTO4bl4dwk4KQzoEDjU8oeMJGf1TZXayHg7IRlV7M79lv9ps47atgidU%2BaorEdO8oUaCpVPCdgMmED09Yoqxzleil77dpshaCkq9g12nyJOjJiHknzWpq8FiXjU%2BbSSlaWqCXUkTpfCulHh%2BDc0HySmyBLBKYRjZeYvxKCmRBhkiCvcmRZjsViLt5NGZM3CIYYjQYYJSFSlKjmC9RVqf1qGwlBslosUTLECL2PFjnK1Qr5coFqWSGbSc8QJSmmB4fYb1qM9vYxHA4wnU6xzhjXk5iogQkCpEmM%2Fb0pDg4OcbBPk1iDPM%2BxXi5kXyftRcX0lQiQCm95czWyMJFnK8xn58hXF4imCQYIhY7Z%2BRmKfI2YU6qxQEsQJDXPOpeEiN4E2R7D3bu9jC91ulv7i1TydFk%2BMjSjbesGNDHWHJGoLgnKw4B7JvmM0UGS9t%2BBTrasGl6W4rebny9C1W7ebxL0cQ8vPd%2ByTW%2B6uzsS%2FtpzwHPgXeaAB5vv8ui%2BFX2j0OCEB8ZfMxiNKDiOkCQxjOynUcFChGEK7HL5eoSNt4JFnsg3ywGnwVPpt9cW55j9tgpGxKNqGAMmQUtTQM7PVh3VUAMvIjK1GHSQQsDB2qwWZ3fG7l73Gn7jp66r7snTBh3ctET3qHCaKAJmQh8jjl54TlBVAzU99Rbi9CXiHlY0iKzZaBgGKOsWJfddiqulBgVq1DQ7DhhbskAdFuJptmpXyMs5imKOQbOGCSbiHEhCrQQGVRChqAMs1yUWy0z2jU7pcKcNMGDMziRFky2Q5zWW65y4EmgjMWNlSJa2IfURmpoer6l1DFEVFcp1SQ9liKiFXqwQJEsYOvwZjjGaTNEGa7uowFjADLsSIk0STMYTDMcThJFBs1yLZi40iYKqJhTvtJwEoWi9Gd6pEmc49EJLYDqWWKMJqrJEvtbyqQVaCq8s0JSxcKOmM4dXLsUN1eubU5fV7lq5znGXMrUQ4NoM8XPV1KIB5jPU8vmhKS1jq9JbcWC9F3NvZ48X3e8E22dPX19vr9OjV83DeUPtJrXv%2FuM54DngOfA%2BccC%2F9d6n0b5RfXWCQieUcMU3SVIcHR2KBmE6mYrHQF19psbTdcCVddf%2B6DnwujnAOcYJR5CpZ7LOwXiPcQqTDNCYCFUZoGVwesIvAi7Zm0mJulHpegsOqG7mdVP6svV10LKjq0vTWskF97Q5wV%2FSrKVwaNd%2BxOOsgAOB47JXkWCMC0bU%2FJZNhbKtURObE3CSRaLEalC1JWqaIZsWTVugKJcoqzWapoBhHBWGnhE3TdCwKyFjaKYIw0TCheRrArgWSRQLUCmrJRarCotVjaI24tGWHmjp2bYNUonhyNAa6Wgfw7zAum0lbied%2FxAo1kGEZVYCsxX2wyFMPIBJGtW6iXchWlYYRFGAOI5FI0fPtxxymgKHMUEFPedSR8f9iOQhO85O03SUGk6a01ZiOhqIFlTTVSPK%2FNSEq9a8G4Hnj7S%2BIvX%2F83M%2FP4cb%2B%2BfnvCyH0sE65EweIGsJIKAzQCuLiRFa8j5KYKIUARdzbPiXbmb26381qvo1fbPnnDdvK%2B3fLKd8a54DngPvFgc82Hy3xvOt7o2CzRhHR0dI0xSj4QgmokRKiVf3vYnV4lvdS0%2F828EB1VKqlKyAkwJwEEaIkhHi4QRtlKJoQ9ShQWxitOJBk%2Fs2FSx0ovbN7jHFXycC80gASTAofWdfLKDUo8tN8ER3OaodZCgUUCPVFpC4l3GC0XiMdDhCYGhE2jI7Iu7BDCH7Jk0cUhkK7nilY6CAG7NpZ8n9jU0Fxr9kPEaCRAtXJDZiEqcIx1O0VYNFdYGqAPI1PdxSC1hjldVYZg3KNoYZTBFGqrWMR3sS47M1KZKxweG9VsIrzU5i8VhrkgjpZArEQ3x9fIYf%2F%2Fy3uP%2FgA3z4wYeIDEFqbGOGGjHf5f67xWKFOJljOJrKfk8TUTNnGAsFDc0lOfTkZ9uoqXUbCDiNowhxFEuIFHE6xG7bvb0CsDZ40fH76Tnkhqh%2FR4pxoF7D5zVVI5SwLi4YyB5WAZh0qWVQM24ruRQl8kwlwwlCeZaMAvTNzHw9fXoNbHnpKmg668KtvHQlvqDngOeA58BbyIH3HmzStMV9%2FKqj48TLHMnHjpfXq2FbXHJjQaBJjYFb1WY6c%2FKfS7te%2FT6X58ALcMBK1068Vy0fZ5xqsuj4hfEUDT2vjqcI0zGK%2BSnytpG4j5H4cS0lTAo1WHyfSF0v%2Bli8AMmvnFUeQUegfc42gLPbc6pAyPJCTB4JBowAToJw0DxVolWEMNEA42mK6f4hBqMhQjrTGcY42J%2BII6WmrZGmiSwg1bLXNRBgVjV0rhSgDUKUdYXlcoEwOIcZBYiGIYI0kv2SsQllb2UZp1iC2mWgKlsw0gj3xeVFLZrnwzv3EEzHKPMVAmMwvX1HY4LGKWKCm5ixQLlQ0KLIJ4j43hlOUAUJfvPwFP%2F33%2FwYafoL%2FM9%2F%2FV%2Fwp599F9M9OiAKxUQ6ywtwD2iR0VFUiDt3YkTJQBbIWhOLWa2JI2GNhVmoueG8DQSUpskQ7SBHnFAbK4PQoXpdW7N7Pu1Cm%2Bxi1Cwcc1vikuF3Y3nJrRdMYk1s53V9%2BHixvoBAPOTTYlC2AcQlUpQiHk2RjLg4MJB7sjohvLmMisvSXhelb6Yegs0gcOP9ZtrwtXoOeA54DtxEDrz3YPN1DIoDSVfVdR0QK4BKflivquXl0h1t16HhZVpw9buyL9sFZ76nfGAMNOt0hXvfZEHAOwVyPPbH188BepF1Vn6qgbGCvSxwqPOS0O7VDJMhkskBkukBsosT5NVC9ihS68mwFgou3LwlrTdZMO7AidPfOu5Sw6keai1IUKig%2FRETT2p61aFLVTWgl15q9vaObsGYGPuHhyDgIm9HcYR7B1NMhgmKusJgmIgWk%2BW4hxJBgppuZkPGQIzUWQyxLr2TViWCpkTIPaE0TKUWNAKqhJ5gB2J6qQtUEfKiEM3pZG%2BC8cEQQbFEtpiJhcT46DbivQkCBtaUdhnkpUUSU8s4hklSgPs%2BwwFMPEZZRyjzBr%2F%2F%2FBGqOtBwJrcOxDMtzWWzLBNAKI6I6ASpqeQrTqMYIobBP%2Bm6tqXXYu7vjVA1BWq2TdAZ0WyXWtCGul3UDKtDW1wLLPVIJnARwH07wKnTqje3HJq7qfON%2B55pXsw9zdRoBgZlY1AGEaJ0KLFao%2BGU8WBkn67qhUU37KakPbo%2Bu%2BPO7Rt6KYtPL%2FsDeUP75MnyHPAc8By4Dgfea7C5C5QU6Lz4D9irA7lO4LvOoL1IHkfby%2FbteW25%2Brt8L9kXkalUG0RaGfaE%2B8AYgJu%2Fz%2FIVDdMNl907Rvizt4YDOmcVcKp2T7AUkzdadYICBgmkZnOMdHyA0f4drM9PUC%2B5HxHinbVtAoRErfR9Yx8FJ1%2B%2B%2BJvlzTBw84RuCFRalT4F3bKnUrv%2FtL2CKDz1WY3jBG2cioOXqoU41Lk12pMwIowxSa%2BvVb4WB0I0ITxIGetjhIDm8U2BIogxGu6hHR%2BiXa8FlKXJCOPhGOO9PQSjKQLGMjHkaS7mqYJvTYtoOsCIsTEZ13JoEIUVqrDEIG1BE90BcXAQoso0NmiIAkG1QpM1KJZLVKsF8tmZhCARE954iDbO0SZTzBcZ4nSMv%2FjL%2Fw4P7t%2FH5%2F%2F2Wwx%2F%2BwcFp0ThBJB0gkQ6QiKoQuKDrpYzmSNFto90PCZpAiAJFvk%2Bo1%2BcLC8ltBOdLcn7k3iKmJTGxi0dyOhX4nEK9xUU0xkTs9rssqyhM4QjJ5P1DUyYV521blYRX1MrHIKOmipjUHLPrWF4mz2ke7eQ7B3B0NSZYJN7YGlWfGXzV954AzzwVXoOeA54DngOvAoH3luwuQs0HROvSn8aVLkSr%2BP4rB%2FV69fvhMjdn2GXvtu319sn18r16VUBSfM7WmgGt1qtsFwuMR6NEY05Rek5koIZ8%2B727kXa83k9B67igBPWdR5zlsmZ%2FFNzWDoBohktohGi0R5Gh7eRze9gXa9R5hXCKkDUQL40MuWcdrN193gVFc9KV8qeleP591wd4qtGn6yukDVzJEoWHCoASG9bv7PaH3pXpSkr9x0OB4gP9jGYThAlCcx4hChK0ZYlysUcq9NjLE6fSFzO4XiM4f4BotEEAcOVmFD3Zd95gBVaLI6PlY9tiIgeX%2BsSLYEqne4kJYIoFvBfFTnduyIWbVgMIriqvEBZ0Zy5wWRQi4dcU2Yoygvk8ydoyhIo54guGAu0wPzsDMvzM5TrOYNyIhkOUJoRMjNFOLqF5Xwh%2B0Pv3%2F8Q%2F%2FE%2F%2F2cJVfH1V5%2FDoMH9W1PxKFvlK5RBg2J9gTIfoaZX1YoecmuU2QJNMZYYm9k6E4iYRAki7lc1Aeo4hAlixDHnFGMvhohC3duqIFMBZv%2BcGFe%2B3YjJO1HHlP%2Fd6PYyvNKpm7WvVInoZAnNW5OALp9yegBuE5QMUhONEU2OMDi8i2R6C0FCU%2BsINb0Fh62sMVwNOF%2BNLl%2Fac8BzwHPAc%2BCb4cB7BTa3wZb7Yb7eD6ozsbtqBVksPWXMtutzIOpZw6lASsv1z1lmm%2BbLahGjPxFsN3l3fp2Zw93jLW2pT6fjRb%2F%2B%2Fv1%2Bev%2F89Qs4jFX36NEjnJyc4oMHDzBIh4gM92%2BKnCnilFB2HfL6pPpzz4HncqA%2FnzugyGKiZaFOiQEhoxThgMDpFsZHd1CuzlDTg6o4eaHlJOPoGVpHqldaqYDI7gUn7SWPJUGiq07PXu6%2F6ymPBJZy3AIrTHQvCz26d5wATYKk2CAaJhgdTBDtjQHroAfVGtnZGWaPvsbi%2BBHW509gqgLZcIicsSv3D%2BUbE6CyjskYSXGAdrbAbHmBerXC%2BuwE5ToTB0wm1diX6XSKuqlw9vgRAhPg6P6HCIcTNHmB2ZNjifl5cDRFOk4AOipanqM%2Be4Ti5CtkyyXWTxLxYEtPsMVyhXI5l3AtcRwiKAdYtQkWZoWkMWiqDJGhd%2BwEDz74EH%2F1P%2Fwn%2FOzHAb76w79idf4E05TKzDUa06AtM4R1jigaYGhaVG2NqC7QrmZgPFG%2By6iPvHV4C4M4xTgOMBgloqGMgxqgI6QyR9SUNKYVDTlhZ4BazLKdCa1oNTkUm%2FHqj70b0X7aq5y%2F4Fx9RlO0FWgYKmhwgMqMkDeBmM7W0RAY7iE5eoDhrY8QT%2B8AZoSqMeD%2BXWqNd38Pn9GMv%2BU54DngOeA5cEM58B6BTf4YK3hjrCt%2BRPMQcNM%2Bf1j1vtxw%2F0Sysz%2B6TsiTPYTqit%2BJow7I6ZEZbWar3dC2XHvuntJS19zrw5Vt9bpaVaUIqtQa8ONodSQ9dbS0q%2FEf73b1S17G9rLxvdhFxrwztEPbZHP9dkdXh%2BOX0u3a1T525q4Mcu4%2BTjB4XsBqNq0QWcngNWtpGprPVriYzXB8fIy96RTlUSnx7DhGdFYp3XUysGvYHz0HXgMH3BOwea43ddqHRSafAfhsJgNE0z1M79xDnZ1jljM2JB3aGCSGnllpElmgofdRme18QvVvU%2B3WiWudiarJd%2BBuk42aRgs0%2Brk39697Yvenuux89uQZtB6fZXGKNNBZT%2B9I5z0CQOX55f7CAm2dA3UGlEvUZY68fIwiyzE%2FOcX85BjNaoYgX4pX2WoVYrU4QXE%2BRj49wPjwEOl0Ilq9djlDu5oD%2BQptXWJZ5Sj4PmhaUCOaFPcQl3uoygKLr74AnQwN6pk4lKHm8Pjhl8jWKzR3j3BwOBUNZ7O8wPrJI5THT9CsMzHhlJAlgcGgaTGqS5i2YqhPFNkabZ2gSQMEzQHory7uAAAgAElEQVRMUIBAMAxbBCbCR9%2F5nuzZ%2FElQ41f%2F%2BDcw1RwPbu1jL40QtpUARr73kqBGHABxuUR%2BvMTp6RlOTo6Vv6dH2JtMkcQhYtMgjhqEZYkmm6E%2BP0GYr5GiAbd6hjVH2H3t69qOP0dF5sjmV2t3Nuxeu5F%2B%2BuhyujmvOex839TfXT9dw26K1ijzRsrTK69BOJgi%2Bs6PEB19isR6oW3DGGEyQjq9hdHebUTDA7TRACEMTMNYptxC8SJt79Lirz0HPAc8BzwHbgIH3iqwyZ%2Bx7sfxMvZ1kIt3CYQIYFhKf7QCAXYMrE2hjcKBCBP294xe8rSc7lviubix53YhxkbjSrNk6WsKCYJcOSktdWtZFQ61fQVKToCU%2Blp6UFTg6wArwZYxCuBIs0tnfe7DNJanhkE0KHS40NDBBFfDAwkhwL648gI2RetCYzgKwpRa1CFFx1HLWfKCArJ4znP9cvxTgEy%2BCj8lUoGjXwdH%2BWxrpfAqpoTb48ImnHDDFkSBwuZJFoMXUMisKlSMRddzEMT7WtZxwh89B14vB%2BQpEKHePg86LeWZ0Xt8vgg4EwTDCQa372O%2FzgVoLRlHcn2BvC1QM6ZHSy0V405aI1SJTcn3RWc271rR59xd8ZnQZ4%2B901T%2B1xcVn5cup0u9nA9uW2Z31y3zuPp4zfiVWqP%2BJ9DkApB6hnUrPHyK%2Ba7jnsKqzFAznMdFC0OAJY6SgMUqwyrLURUFwjJHUldI2pJ%2BR9kI2myNOrvAcvYEzcUEmO4hSSKs5zPkp2cwdQ1Tx6gLerel8SVx%2BwiVyZCvh6jqEtH8FGVFQDpHEafI8hzl%2BTmqbIXZ4iHM%2FgSD2IjGsbg4R7BcCrgk7XxfSlCNthWQGHB%2FZN2ibgzidoC4HiJqVojaFYJmCTQZQjoUCmLc%2F%2BgT%2FMf%2F6X9BMXuCH%2F%2FNf0U%2BP8NkkCJfLXF%2Beizay2xdIOLC4fIMZZZhdnqMerUUbeTs5EuUaYphGmGYhhikNJ2tURdLlLMTmGJBj0hiFizj4H5XZA7ooqG%2B%2F3hXISc17vzIf%2F6TgjqK3Zh3Z1rvzrVcujmpLUiN8jvBpRKX5sp1v4%2FaoGvP2WHbUC9tgCZkpFR66t3D6NMfIf2T%2FwAw1qmASNbLZ4nXNJFmEBg6hwoFbDKP%2FiazfteGo8EfPQc8BzwHPAfeFg68dWCT4EMXOx1cUVaLyESByQISgkxqBSt6M%2BT%2BH2PkyxVxXvNb1TXaspU8BEWDwUCEEVajwh9%2FDBkfrUElALVGFIUIxVOqAiERYJjG%2FTYUNqsGNAVlHUPGiTQUzhSsFkUu90gxQ3vw4%2BhiewIgJQZZIA5yCESZTtokeLgAQAWgRUGtSSMeDenVkJSyP%2FyEJhJvriIrMIFsEfCpgiXpKMpC%2BGjEaQOFx0LKk54kThAnKUzIuHlSpfDFAWQnYLBN5RPz8EqvK0YzZ4oId3ac5LYTGJimKhr2jRqUxkrFTsOp7VrgzH6z%2Fr75mDYn7fh%2FngOvxgGZyVKFyu5unvYWWfQh0mb4YBk%2Bc0OxaUxvfYCDppFnJjv9o4ZDyRYImgBRW3IHGow4lNG9kHzmREtoRWg%2Blfpk6n82tXmR8dTNe3m3WZChlMj%2Fyx4FlybvStcdW617fjdV8H3IZgRg6l2u0YlXVXlvcOGK%2BwXp%2FEhL0dwzqDO0yxJZvkRuElRtAHppjegoKFSNbtjWiLkI1pR8OUi%2F%2BJYqsyWacoZ8fYYmjlDlGcJszaAqCFuGOAnpo1YsHoL1CkU1QzuLhE9hkSEh0K0WKOnVtCoxyAsBtvFqhaaao6R2ualhihLDppL3DekPmko0zeQiTVVFA833MVoMggoFcsT1CqZZI2zobZZ0y1tJiDm8fQ9%2F%2Fb%2F%2BbwjKJX7%2BD3%2BLr79%2BjCnNg1dr1GWJ9XKBJAywPx7ANCWC1RxpnsOAwNIgWnPvYouSUWMMHReRGxWaqkBQrNDUFSoukvI9LqF29N2uWmX%2BkHBg%2BgOq42HfkHLB0dTx385ncalOLzv33HvbzQX1AMthIsznwqSCTVejNsAWHODkM8J29Cu%2FOfwtk9ipIai9LIMUVTjB0OwhjQ8VbFoKpT4bl1TnvCwv0Cmx%2Fbi63bU%2Feg54DngOeA68bRx4q8CmMNdJUZsfy47l8tNqf4gJNFWDqdpNlQ%2F72j51RHNyfILZbIbRaIT79x9gwqDerJsx37gqWxWiHeVvr2r79B5BloBQCVcOWc2uygqz2RwPH34F4q1PP%2F0UU9YXAGVZiDkV9yPyc%2FfuXQGXw%2BEQe3t74myD4DKil0ZAQOkZ9z3NZhiPx7hz5w6Y14HS9XqNh199JeUODw8x3ZsK8BSYR4BqQaoKASpSkDV5kePk5InQcuvoCJPJBEWe4fjkCS5mF%2BKU5969%2B5iM98RsjMIHQSb3DwnYpEt%2FmuKKVlVI3RoJVSS3kCDv7rYIFjI6NoXn%2FYG0AlRAC8UY48kEe%2FsHGAyHAsYJSOXTLZxvavYnngOviwMqUPfnqZujslojU5bPELWODHMCJAgIIkcHGN4BojhBMhxjcfJItF5ttkBNAME9eTXDd4iuULR1TuInAGCLrRPY5dFgu65tPdUUtRR4Vn9dqS2NpkvcFNQ%2BKmzVtoWG0LmjIU0a%2B9K%2BOYRmgR8WeEm%2FCdjqEk1dIsRaaqdjnzikISRBUit9NrQK4dYF8oqAixYlTYmq4Ds6Q8CFN777aNJKbRbzctGNQEe0zHwhZigL1b4ZAcctQGc8hERNI%2BCT3aRj2Hado6bZPa%2B50Mh3odPPyXuRveI7kqV1bGM0GAUt6rZCU2TSHk1ZxRJEkA9jZrYSW%2FXoo%2B%2Fir%2F%2F3%2FwNJkuLffv6PePjFV7hzMMEoMQBBNOuoE0RBjbTMhAexiRARVDHYZlWDtrsS7oSgncBT%2BtlKSJA2iFBJH5mo%2B3%2B5qMnfIHkV2t84N6w87i69urHdDLnMMb3S0bfzztbl8uklFzR5XwGnPhfaCvPZpQmhmVfalgWdnHhcQOSeB%2FLNpGi4N3N0iDbmbyEXaBLXXO9oV4n78949JL1c%2FtRzwHPAc8Bz4O3jwNsHNp%2FDY%2FcD7FZeRaNHCYQ%2FiSJbcEW2QZ7lePjll%2FjpT3%2BKL774Ah%2FQCcRf%2FRXu3%2F9ANHJFwRVtNhb8%2F%2By9Z5McSbItdkqrrq7WChoYoCFG7cysePe%2B94zGZ%2FzCD%2BRnvr%2FH77RrpBl5Sbtq94odtaMAzEBroBut0FqUpJ3jEZlZ1dXV1RCzA0z2TCEzQ3h4eGZG%2Bgn38EChWECB%2B7nRoinLqK3ZpGWRAJHAj0CT1sbHj5%2Fgh%2B%2Bvot5oCTBOTU1pA3PLe4QbN24o%2FfTp09jc3MTY2ChmZy8KTNKqSGWMoI4RWR89eoT79%2B8LmBJwerBJwLmysoLP%2F%2FxnFEslXL58GflCHulMRiBTgJSurvruh2oI93FbXVvF9evXcff2bVy5chkzM9NYW1vDjZs%2F4smTJxgdGcWlS%2B9jcnIaw8OjyOXy2NnewfY2IypKJUWG%2B9uViiiVCAYjEtcaL2njUn4MJFKJ8OpNt5vnZ8mptHAvuwxGRoaRSiYxSADt1rJ2qxmnxRJ4fRLgc2zPbqjvdnlupe0TBKVAUMDotIygyb0hc5kcUoUyUgMj2FlbQX1rVb%2Fa9gYa1V0063UBDxuIyLlX2%2F2Z741T7OWCbml6l%2BXG6q590S5HvZF897vkRZM8IGEvudUJh0ftgcixUu%2ByIT2Wk32LILBeA7jnZaKBtOKGNhWhlRZMWm9pe0zIglhT%2B%2Fbqs4WGwAl5opWulaSXcVM%2FejUQ1mScNYtWU4JT84wgwqIHrpXlKMGJLv7ZsgHGCJYzpnWYs3wClwbMraSbfHPAyOQSAUm20yfyiSbqrTp2dndR29pFi3u50L5K4bCSrH0JIFvC8MkL%2BOS%2FNpGqN%2FHox2%2FR2FzFzGgZA9kEMqgjVd1DOtFEBg0kEy1kEuSzoeBB%2FP5oslITlVycYU3UKckUt3JJ2xYhlJNAJtcumu2SgZF4P%2FivgLk3VwY3ljzz1%2FHX8TD4EjpGAGeQzj0xo88BBaBn374n9n0VIkVCkbA4kaLPpcpx%2BQnXuiYzeSRyZaSGppDMDWibGrOYOv7YYAdvlhNw0tERf3lgRV%2FgrTtqUleuw10F8tb1J2Y4lkAsgVgCXgLvFNi0j50N1LRCSgvR7LZTThqcSW%2BAQHJhYQE%2F%2FPAD%2Fumf%2Fgl37tzF6TNnsLW1LdDJD%2FsOA0o0WqhUKpidncX0zJSsiFQUCNr4R8vm1uYmHj16jIcPH6LRaOLBg4f4%2FvsfwM3KCeIINsvlAeTzOQW9uXnzprb14Ifl2bOncrXlOs1PP%2F1UbYlvQMB1bm5O4HR3dwcXL16UcsF6e7u7AspffvEFpqenFbW1XjshfrRG1QUASabMOivQR0NAtYb5Z3P45i9%2Fwa2bNzBUGZTb1qPHj%2FDlV1%2Fi4YOHAnrPny%2FhzJn3cP78BYyPTWBhYQl37t5FvVZDKp1UmTNnTuP48WMoFLJOB5H6I71B1k330Tzss6kZ9Ka5NXM2nIGRKpUhFPIFBQZSMCP%2FtMbHWAJvVAKRpzVyyibbL6mIcyUmLfi0PKUBRkxOZZHOlFAqDCNb2UBtaxV7myuobq6hsccANDW06OruLGpSp51Fy6vWzlwUtGgTNtZp8kDIsZ8fy%2Ff%2FskTP%2BR1XMNon4inGpOHaTQY18hZXQQ4BvToa1R3Ud7bRqu8gxeBAzbrWGCbApQrcbqQpwEn3VQI1jmX2%2FrbQ4JikXhGUNCEvV03eEdKYtwStiFpfzuUDHBNonUzRG4U55ItwOOxbUpZSA6McF5u0GnItu4KJmWWTHh4EdiYQckCAxDaJiZzUuZY20dJ2K3T53a3W0Nitgd3TR8QLgxNrrNg0q%2FbEiffw8X%2F9b0i1arj37Z%2Bx3KpicGYEBUabRQNZrlYkCCdYp0xopXT9Yt8a5IXLLxJAleMzlzRwax3uPZnOa3%2FRZCanZRFcJ0wAx77xmZCl04E%2FY8r6YvfU9St6g90958HlRlKipyEFP%2BGg8gEIcjKQGPmPZnDDo6onDGim00im80jlBpAdnNR2QW1A0%2FFyAJs9OCVHrOWPUf7fznM%2Bv5yQ1hY46Yzu8dvZk5jrWAKxBGIJ7JfAOwQ2%2BRG0zyg%2FQ1RyNIPOT1LTAvFwQK%2FVanjxYgU%2F%2Fngd3373HR4%2BeiQr4uLioqyct27dFtBcXV1TZNT33jsvN9aR0WFksxYdj9Y2gk4GsNnc3MLdu3fw588%2F13d3cXFJ4JVgk0oSXVXp4jo5OSm33o2NDSk%2FIyMjAqO0XnKtKC2d5bK58JJPrjXl2k9aP2k5NZdgRmtlKP1l3L1zB08eP1aXHz96JKsnrZwWDIibmmdQKg1gZHhYbrq0vK6%2BWFW9u7fvKGLk7s4OHty%2Fjx9%2F%2BgmPHj6WHAiy5%2BYW8eghXYFpRchhfv45rl29jq3tLeRyGZw8eQKDgxWMj4%2Fp2iwNpjL4SXKb%2F6aq6hV1ntn98Sn2OPo0ZlvpXC4noMn7pj8pi5ww0Hy6ZvX3P8pxSiyB1yuBKNDzlO35JvTxBi9aOOlFkEEik0UiVUAiU0a2NIx0ZRTZ3Qk0FGG1KldRBg2y59xMj%2FaE%2B%2FVvXu32R9%2BqHZlq71V7eueVartXpzPPX1sLvh07EjYwOJeAnurLtgU0auCeknvbG9jbXEN1d90iqLJfNYJo1jeX0yTq2uOy1eA6yZSBSvEtaG7LACgDWSidu6YAIcGfczMmOb3uWuyucV3LGNSMLV8g1tAWM7T%2BsT7HioZ3UyYYYwvshPWBVfnr%2FmcAlHto0jKroE4MVkPzq7ObEniRgB%2FXwD4nMhg%2FO4vfcJ%2FM6jYeXfsKC88XUZweRiabQLbVQrpRdwDcLbcUR2lFaCVnlBLXnVaRRINWzVwRmUIZ2eIQcgNDyJXKSOUKSHAyg4BToJMutQSd5mpsfTrkhnfveFuqsKtLETVOhHipqf9OgjzXi%2BCeWwJOuf2aHFklmTJwTA8AJHNI5SpI5wf23YVom23MHHpBDg%2B%2Bo4dW%2F4UV4DNMsJnJpLWU5HWxR7oW0d4H%2FXt3ZPa6ZBTTiSUQS%2BDNS%2BAdApteEQg%2FuvoY8%2FvHOeSWATWug6Qb6eeff4Enj5%2Fg%2BLHj%2BN1vf4fByiBSqTTW1zbkonrv3j1ZOo%2FNHEO1VgsC9qTSCaRTSTQaFliIW5UQHI2NjaFebyjIDtd%2FVqt1EFBOTU8LrHJt5OYmNxBn4KACTpw4oXoEk3SZ3draclbXqtrih4eA0%2F4s2iwtiwSIc8%2Be4dbNm3JvfT4%2Fj6%2B%2F%2BgrkN5vLybWMIDiTzcpK%2B5vf%2FAYXL85iY21dda5duybF7MrlK7J03r5zG3fu3FEzJ0%2BeFgC%2BdesOmo0kZmcv49JFYHx8QpZVgl9%2BDCcmxtU3WnRoSeUaTs6028efIJv3wP9CxcTSXJd4YB2vM0S1Dn%2FurCHBHVV6cBUhFJ%2FGEnjzErAn2pS1pqKy0ibnABmxByNqJptIpJjWQCJbkjUnw0AxApnOChS8G9FnOaoERs%2FfUL%2Fkfhlth%2Bd8V%2BlP6wLRkE%2B%2By42q1p7Wd7ZQ21nH7uYydtYWFQipvrGG6vYamjWCaALNhECgWUQbQuTEJQZaHPxr2pruEMxzXT3HDcqQ24LY4kTVY7AcE7wEQZDFSyvLiUQL4EagSfDJ%2Bn4k0rp11op00%2FVS45NNHBgtgiVSNsBJIEtrpwd0EQKkp9tGzxne7wSGT5zGJ%2F%2FD%2F4hkdQNPb3yLpXQDAxMVJFNNrdWlBVaB2BQ0KYmas9I2Ejy3PSdbubyBzMERbQOSL48iOzCM7EAFyXwBSLItrhvltlVkLgo0%2FTNill9%2F9VqO6rpZj0VPY3AHZd0o17a3dCpCOlCvM9IvgyLl0Url2m9GB5lf8yXfBXr1vIllI%2FxG87ZRB%2BJf%2BN79miUe9z2WQCyBn1MC7xTY7BScn9UjCKR1kK6z169fw5%2F%2B9K%2F4%2FofvkcvmMHtxFp9%2B8qmsinRnpaWRVs7d3T1ZR48dO6aPwObGBrj5d5FRBpMpAcOt7W0F8OEH4r1z52QRTafSePp0Dnu7VUxPTeHMmTNas7m3t4vnz%2BexuroqkDk%2FPy926aZLPulya2AuI%2BDJa1pBmUbeGXiI1%2BTjwf0HuHvnLirlsvhucG%2FK1VUF5eGWIZtbW9ir1sDgR6Mjw5iZmsKzp0%2Fx3bff4NkTAuxjeP%2FKFa1VffTwEZ7PL6AyPORc3kwdY9%2Fm5ubV7sWLl3D8%2BEnnMshIumkU8jltyM4Pl328TAlkp6S2Ofc1feTC%2BfG2W2Rrl7zyJhVSimGtWkWtWkOGEYQzFkxCXDnLQjd9p41wfBFL4A1IQHo3lWiPXpK0qLngLoZAbBWmm2xJJjNIIYt0q6HIp6zpLUIOsYRciri%2FtHfQX0WPpi5GU17u3JxAXKMi6ttkFFeCTdJlhoHIVL6MVIlbmYwitz2MfGUI1bVl7L5YwM5SBrW1RezuMdJrAzlFXmVEWVvrSR3Xw2yzgJG0bZ9k7zLHEOfuag0HbqKUNd1zOUZqrOG1rHoJeXEoYjeBKnGxi%2FJrPfGS4tHOle6TXdclPabxmjzx7jqX4ACsehF7LKfySay%2FWMGL%2BYeoby0jubGooGaPGi2Np8cqBSTyFF9dLrp006W5tkWQ2GwpAFA1AJolZMtDKIxMoDw6hfzgOFLFChL5ASSyRdsahEAzwZ8BcQObZtX17Fk%2FfQfD1APP3Hh6YL5%2FznnsNeh61E4569wsnoyOvtdqoMb708zY%2FpkBzYNb%2FTXm0OWcHk78e51gkLT8nt3%2BPfg1yjfucyyBWAJ%2FXQm882CT6yh393bxbO4Zvv3mG%2Fz7v%2F8Hvv76awFKrnckgCO4JAikhfHBg0e4d%2B%2B%2BXFWHh0fkJnvn9m1sbW3gzJmTOHHiGDLpggJbbG9uaO0k12vyE7%2B2uqZItDvbW0gnM472gj4eBI8PHz7As2fPtJbpyy%2B%2FxOjoKHZ3LfAOgbACDdVrWst569YtrQNdWlrSx%2BKnn35ClcBze0frOJn%2B%2B9%2F9DmfPnsXwyIgCBJEH7jn3bG5O60jperu%2BtoatzQ0sLixgfu4ZSsUiTp44IRC7uvpCbrp8BPlRIpClDGiRzaTzCnZ048ZN0JWYHyxtv5Kiay1%2FNgvr4%2FcYsHd7wcm1zc%2Bkmk2jU8eQShT%2BE7wF3DqBEXjX19YxXKkgM2iPqJzwGHgkqiQGteKTWAI%2FnwT0CPIZZ5OyvjPFrvmcWjwZoR%2B5kjLqqHKd9exwUND9IfdLB%2FvpqXjbV9DoBtT5PrGMK8w1hXpb%2BZLRPOgiyCaSdSCVRYLBXlBEJpdHulhCfmAI%2BWIF6VQea%2FL0aGCv7gL2yI%2FV%2Bk0gyZb4H5vSOxyxspAHjj8Ku8a1l5RX00AV6yj6LMtzb0xug%2BRdNrlGU1vKGFHSFS214sYd3RnrpACpl0lEQCYPA8bcDkVrQbn2U%2BDTCrLuFif81tZQzOcwMFjGze%2B%2Bw5%2F%2Fn79Da2sJRWwhW1vD1tICikM5JLngkw%2BCA8p%2B4KKViZFm6T7bSGWB%2FAAylTEUR6cwMDaFwsgkUqVhIFNyIDMrq2ZLYJOhkBzYdM%2BfDNSuTxbR2Poa6Z7vcecQrHTeJpOaL2bSsFSzdHejFZTmZGNA2ZY58D4Jl4tVt7VLk%2FfXRYDyleNjmwR8vIa2xNdwEYLXzsmJ10A8JhFLIJZALIE%2BJPBOg032nwMt1ys%2BfPAAn3%2FxBW7dviVgSRdVuq7ev3cfG%2BsbcuMi2HvxYhVcr0mgOVgexM1bt3H37l1MT09i6%2FefoVwuoZDPas1mo17H7s4W1tZW1QaBJIMNUWkbPz4m%2FWJrc0vWDgYSIrCkpdJHmiV%2F2WxWrjNci8lZeuYR4H311VcgwCSoJBDmh4iAkVY%2FrhEtFgs4feY0LszOYmp6Ctz%2BhPttkg75Zb8ZYIj7tmUzaQyUCjhx%2FLhZJFNJ%2FOlPf8TKygsw%2BNDk1AROnjqlaLaF5RVkc0UkEmk8n1%2FE1atXcfbcObXPbVky6RRKA0WMj41hZGwYKSpMcgszlYR80mJp60S4ZstpgB0Po%2Bk4%2FJeqCq0J%2FBBya5aqLLK0%2FFLBGygNgM5XzDTFKlSGOkjGl7EEXloCgiYOAHUl4jRue255YRFU9UwK%2FLCWPZvEaQYuzKHTggkx15RxQS7nIm5t9fdM91L6SSeaHz23NsRUcMp8gjMPyfgWKjgQ3eIZiEZ%2BpLRQMYwNtzFpIKGo3gSeaQWASTP4C9eocifRWgMbtTrqW0C1sYMUGJWV23sQbHirpDVPKXhmOUmlFz9B91tG%2BTUrpvaOYvRdWjEdSFUlF2VbazTJq8aFcIzRWBIBP16ynorBXS8Lk5Ip47Sgmhsto%2Br69ZsEnGy3urONG1d%2FwNVvv8PxYzP47A%2B%2FB5cw3PzpJwxlqjg%2BlEY528TY9BhmhvLIp7lfKAMhWXAjWiIZWbbWottsCk3KjkB9cBSF8RmUJ08iPzKBZHEQoDUzmTfXWUamJUhzlk27X9ZfcS%2Fk7uVKTpnqQF9wt%2B3JtN5GEllSYNHLw44qpyXFXnr2sIRXdqZ%2F1b7P8W1bG1xykqO3cYquzq2Iha2dh4OvSLcb1wfXeJty9OxLtF5%2Bb577EHi%2B%2BbbiFmIJxBKIJeAl8E6DTQ6sqXQK2WxGQXLeO%2FcexkbHcHvytgAiLXi0DI6Nj2srFIK6zc1tFItlRWFNptICoozcuvrihcAerYT12rACUAyWB3D%2B%2FDkF4eHaS%2BIqBu6hxfS%2F%2FO1%2FxvGTp1EoWNAe1rt7745AIEHu73%2F%2Fe1k2acXjGs5Lly7JjYY8c%2F0naRBw0SLKwEH8kT8G9Nne2Zb7L9dazs3P4cOPPtK60%2FGhir7NDEiUzzGiXUtgj3yeO3sWlXJJND7%2F%2FM%2F46acfte3JQLmkID%2BNZg2NKt2Nt1GtNWTZpOVzbu65ADBdkTlfnc2mcezYDD799BN8%2BtknAqppBYMw9zZ%2BQLlmlEqW6SFUjLopDN79lo%2BiUxYVzKCprQc21texs7uDZqNhqqPcda2of3jjYyyB1yEBqchapmhRWL2C61VAHkOQYi6bsjLqsbU6iuAqxTgsrTNnemIbhC0ENJ5%2Bt7eiV39YXjx1qWhJBjUMWPWiZHkELl75JFvil1ZIvWu2r6Nsky0GREoqoqw2hdQrnUAym0WinEU%2BkUKl1QIn3zae1rCz25RhVKsTZc21dZdOFCYDMWygk1yLZ%2F%2BOB%2FDSoBXHVRY3YOotriZLq2m8y57Ggm44CXvp5CbhMdWk5SVkUmNPWY5H8u%2B2dOFdSzRx68er%2BJf%2F%2B%2F%2FEvbt3cW9sHJWRIX07Ll26jO2Fezg%2BUzHAmdxFOV1HtrXLvV3ArUrYGqPx1hh1FgnsJdKoZYtIDgyjOH4CpalTyI1OITkwBGRCkElZE%2BhznxgG2mE0Wrni%2BqeR1k3XJ981DbWyyPre2dHn%2B94HVlASUGZYIhiuWxYrgM%2BGogLTBVgysrL812NdPdbWVJDGE3q%2ByPtFEX9dgb4OpO5uZsf9suohv32R%2BwUW4nvmAeebZM%2B34d%2F1N9lWTDuWQCyBWALdJPDOg01%2Bp7gW4tLlyzh1%2BrQisv7zv%2FyzZqUZpOcPf%2Fi91lWurW%2Fg7p17uH%2F%2FEaanZ%2FDbz36vTbtpTfz%2F%2Ft%2B%2Fx6NH91HM043MuXISGDXq2NvZxtrqElbX1rG7vQlGYazu7grUFQpLyGQ3FbiHe1LOzMxgaXlJgX%2F%2B5m%2F%2BRsdvvvlGM74nT54Un4ODgxb9dmREIJT7a54%2Ffx4sT5DKvTQZFOPK5UuyTn7%2Bxed48OCBtmD5wx%2F%2BgKHhYVk%2FWYYBMxjMKJfNYnCghHw2LVfeW7duYnh4CB9%2B%2BIHqLq0sYXlpEbt7Vcw%2FX0AymUOlMiIrLD9QDN6xvkEX4SfIF%2FPI5jPY2dvRFjD6kFFfkaLIsqZAMhqhXN6YrievXcHr9jDyXpFvAkxanmnpZXRdr3KIkr%2FoSiBOjCVwNAnwcaKirKM7d9p35GC5Bhv8uWUpUkwAACAASURBVIMscmfkNhvMlfrtrEt2bv8GpKSq64kmGXsx%2BmY4BAGsYq0FlUlPBB386oO259cXJXBgUByjJIIBecIvgrlWi4CH27wkkEpmZAVNlBIojtP6t4PtjXXUGjXs1SGrI91IWYPeDloDGXRCXXBtORBOYOqa9TzJo8FzIUTjBOfQTVCOvY%2BkeTpW1cYQnuusPdPxYA1zvWayVUeyVUMae0hW13H3m3%2FDv%2Fzd32Hp3l2M5XNYnX%2BIx7d%2FxP%2F8v%2F4vWPztp%2Fj3%2F4uTl2uYLleQzaeRZYCoGhszl2C6BzdaCVTRRDWZQS2dQ6NQRqYygcLESWRHj6GRH0QrVUQqTbdZByrp5iwwyF4SmBBc8j74qQ975iQDTRaY%2FBhF15fwooseSZLjtiTJ8dlOVETpDLqkyZcmGnWzNGdpoVUQOKMUlTtTPOj07TDfJOrKd1bwBXsePZWDKh%2BU3pPoLyrz5wCAP0cbvyihxszEEogl8IuTwDsNNiltflITyaTcMWlBpBsrB18CIQszznDyCQGclZUVEIjxA%2Fu73%2F5BgX24TpHrFfmjlZT1%2BKObF11Q7929g3%2F91z9pf00G8aFLGa2g%2F%2FHv%2F4ZCsYxMtoChoSGcOXsatCLyg013Xbq40orIKLLj4%2BMKe86ItQw2xB8j3LIerZxc23n8%2BHHtw3nq1ClUq3sYGx3B5OQE%2FvEf%2FwHfffcd%2Fv0%2F%2Fg3DI0OykDabdddHBUuU0kML6vUfr%2BGPf%2FwXrQX98MMPZT1debEil7nBoYq2esnlCygUBjA4OIL5uUVMTk3jv%2F9v%2Fx3ci%2FMf%2FuEfMDBYwn%2F6T7%2FHxx9%2FhKmpydA1yiupms1OSdOQDuMU4H6efJb3W7cIvArYm%2FVFyo%2FbEYG0OpWbfujHZWIJdEpA6qyUbz6yofLqFWVL8VcRfOiAjdViKar35kJu5%2Fb0W3sRujoNr6P8hK1EU9spCEQ4GmTBU%2BL70HYd5OynJbARSQ7adcQcebOaiSjRuIET23uR1jZrL5XIIpVpIVGoIz88iYHxFWxUt1HdqCJVryFliz9tGypZOX3DQasuwfckeheYxXSbDXBnumZ%2FDSSxiKPljp6SEaaQom35c38MSglOM8BRqrWHXGsH6Z0lzH%2F%2FJzz%2B5k%2FYuP8AH546iVQ2i%2FtzG3h%2B%2B1s8fXgRM6eOY%2BbEcWzO38XmZhpT2r6KfdAKVL9aV3to1pNp1FM5tBileGAYA6PTKI5MIVUcQj2ZRyORRYL7bHKCj5ue0qjKp1IdCnulSTdZex0YVRfYH5sIlWwot%2FYuWkcDMibnbkCEOdraq1bXN4Fl%2BK0MqhqlQ%2F89avnuBF8Ple6049RYArEEYgnEEvg5JPDOgk3O0OpDSj1Fob8NYFqo%2FJb2ActkDUj62Xyul%2BSaTUZi5XeaehaBJdcq2r5hoRtRMp3G6MgoLl%2B%2BhNUXKwKP%2FEB%2F%2BOH7GB4eQ7XexODgMMbGpxTAZ3xsVDP%2BL1ZfKFgRt19hAB%2BusWREWgJhrt8UyHIR5Px6TqYR7BJ8cluVRqOGTJoRYfOoVnelTK2%2BWAUj3vJHq6Ctm2zKOri7sw1ucfL3f%2F%2F3%2BOLzL5DL50DQSiBLq%2Bc6LYiNhgIA0V2XazY9GJ8YH8d759%2BTVWNgoIjyQAljY6MYGRlGNse1q1TmzHopmUk5oopkCuJRNBT2k%2FwMDw1pH1C6AxPs80%2BTBjyRBfXneDXiNn4tEqA663%2Ft%2BjlTfQjS%2FdII1WBfyyKsUln3bwTda%2FnnS%2Byn0p7Ss1zYoFXidbRCBFRFk9tbsOi5Ps0gpLuSR2XomungpYPRJgfrj7l1yi1Y6yq55WQR2fIIBkYmFaV2e2sVdeyCW8SwDv%2FT6MnxostfwIfrk%2B%2Bq0l0VpfkMB6zC8SVK16FwJkkm0Tw2ftC1gcR0aw%2BVbB3DqW3M%2FfBHrYf%2F%2BPg4JseaaNJkuQdcv%2FMX3PhyGv%2Flv%2F1PuHDxPL6du4mNzXW0GgWVsbWe9vRIBok0GomMAGUjlUc6O4BceQSZ0pC2yEmkcmhyXSZXxzbNosgPUJJwPckJU%2FeQOtmxW14e6qaybSz2PQxEFZG3exzd8%2Bkn7cKSAqqM6ptMykuF3yd6q2icj9CJT2MJxBKIJRBLIJZAvxJ4R8EmVRT7QPIjSTdQHu2cR1ufo33UuNVjqyWLJ9dd0vLJD202k9HHPKxj4JXA09YoNgX2JicmMTU1JfBXKpZw5sxp5PIlPF9Y1jpLbn3CAD4DpSJerK1ioFRSoKC%2F%2FOUvsmDStZY%2Fgkn7wJvCynO6kZKfamTPzXye4XJyaNRqcrc9ffq03GvpSkv%2Bnz9%2Fbu6nzYaAK8H15tamrJm3b9%2FG8soyTp86jVKpiHyeADeniLuLy0va0H19cwuZTAEFRknM5DHELVG06MYsjLQSy0U2RSuOKW1eVRGopxrD4CJUfnSwe%2BHL9HowCTYJsEfHxpBJZ1AZHBTQF9T0SqoR7UUmzoslcCQJ8Nnkj9tTOC9wXcuq1JVS9Gn2qr4vaBYjAzTcf9avy4rW8WX7O4Y120GS0sPMiAWsNzhgFU%2FJH%2B21skkiAkNL57%2F82TpGunRqMkx2O64nDN06kawjmS8jVxlFrjyM3dXnaNS30WjVkVKQIYOmh%2FVY7QYMhp1Tkrv0XNlRNbqTVXmf749h0Q7qrq%2B0bNYxMZjFRxdmsLG1jcFyGWMjJWQyVdTRQH0wgcdYx4sHV7G7eAGVQgL5FC2RNa3TbLK%2FGq849lGWinGr9ZfNRAbNRBZI5e2XyKKl65y2NaE9lE8jAzTRLZjhhQjTA%2B5JVwDapjP8nQz7EvYvWJcZJvV1pnucsC2ums2svid8PtR0t4b6ohoXiiUQSyCWQCyBX6sE3kmwyY8it9BoNBtu70gDlPyIEjgRMEUxC0EdrZkbG5tSOOjCKmsmNxBn4IuGgdWwvrkvUZXgzO8LBg9aXFQAxSdPnqBWb2F%2BfhFzI4vY3q3h%2BMKMguoUigUMVirigcCPVsT3339fVkbxJaYM1LJd0ibQJOAkkKQrLMEmLZrsG%2FP39qoqw7WgBJwE1lz3yT7J9U3RFAG66F44f0FlaS3UPqKplNre3tnCvfv3MPfkKdbWNzE6OoHhoTGcPn0WZ8%2BccZub27525ItsUhb809Ep1LYxewLpZMopW04zMf2p9zsmtzxKFLLe5ui%2BzHtFxZaWaU4aaOI%2BnL3vTTDOjSXQvwQ80PQwi2iTT6%2B%2F9hDSUv0DHT1G27LSzCUY0DtiF9FCXc976vLKbCdk5aO1LD86vnVtqGtilLZeSANgGkO4atM8O7h20NYS8tqByGQOSOeRKQyiWBnB9nIZ9Z01NBpVAS6TGxslr9F2QkaYGuSyAyoW7ZuVZbJ%2BzpJro4bl7S8d0u88E3mXyP7QhZ%2FBgNLJBirFNMqlUbRao4LWiRY3K6mjyeiwxQTePzGMuaUH%2BOf%2F439HOtHCQKqOsfKA9hnVvqDkkA3oRpArCzlUayawvVvHztoWEsvrQHkP%2BSzzGXWWVmDuyQr7%2FnD0c7eh2bQnUTy7IVDsapKEnbDehP3ntaV19jt63QtAprjeP5fVN4WTn65D0erxeSyBWAKxBGIJxBI4VALvFNjUPHJgwWxqO5JEhp9fU%2Fj4wSSo05YltBhqu5GW9qZceL6AhYXnUncINLk3J9epEFxRATBg56yMdDlNJZFO0Q03g2KphOPHT8gyuLm5hfnnS1hYWMbmFq2k3G9zXW6o586dw%2BjIiCySBIOMhvvee%2Be0ZpPrOAlyaXWley1BJrdK2dzcUFAfboXCdZ60gtIld3GR%2B2bO4cGD%2B9oK5enTpygNlKTYUkmggqvgOi0Db4x2S3A7WBnE%2Ffv3pUAQxNJ9l9u8DCwu6GEhsKZ1cXCwLMsi%2BSSY5hYE5oLsosNG9BhKWBYhB0QPfeq6FOC903rNZkv3KMOZf7dOTFPqvo7ur61N8knxMZbAq0nAKeoJrbrsrqJrQsWr7zamGJBgXQMFxoOHpU7tpzbPv8j7Ygmv8q8n5hDxS5ByPQjBXYSGJpR0zXbsF5R3GCoEj9xMkYgnra06ktk8cgODyBZKqHHSqUGQ5IEjiTq5HCAQthZYVgPAGWHOc%2BTIeEl4Aat%2BV6Tt23W0%2FH3hpRtnWM2q0rrJbVAc3yzrvGG4NctgOo3ZqSGkWyt4On8XqUIeJ8aHMVEpItWqGTgN%2BsF2TQayDzNQUL2J9eUXmNu5gZHtBI69l8LQRAaZfF6yoryScj02XhMJmxwVGKbcnGXT%2BuwsnG19DqXSLrnuVzaB2CEfV5TfS%2F7iv1gCsQRiCcQSiCXwshJ4h8AmXcdCMRBs2WwsY%2Fk4tzJGW6SLbDaLbCYr9ySCvGdPn%2BHatauyDJZKZWxubOD7777DxPgEtrd3tOaTQJABgkSr2QL3HKc7aXmwAoa%2FZ%2FrubhXra5uo1X%2FA6uomCoWi1mOWBwYEJBk%2B3gBVU5ZGRqAdH58QmCMAvHDhgjqwvLyMW7duiZ%2BnT5%2Fh0aPH2hOTYPWDD97HwkIFX3%2F5JebnLcgQlQG667I%2BI9dy7enc3LyCEbGvhXwBAwNl8fDwwUPt3emDJS0vr4D7gxLIvlhdlXWXgZIqlWVtAVMolgRGtd8dlTGCTuln5p7MtnV9gPIY3pH%2Bzkyx4nohH73S2kxSx6Ly16ZU9UczLhVL4HAJUMXnk2xrE%2B1xthQDC8QM%2FjpKjUq6TWZZrl0zuk4IO91zGxmfohT6P48Q0HvQHSCQ3sE51hopOU4PKOu5D%2B2GniaPwjv%2BnVRfCYg0KCKVzSGZzmgPRwYU0jurxYKeAnmI9KWrAFxZ577p%2B8RavqYdoymub9EPQVfaYaJaaYuYTWBJrxBaMunC6sCcbxRN5FBHIp3EleMjmD0%2BofvMlQOpRFMuuAwyJMdXN1ZJXmyyBWSyOQwWK9irZTG3%2FAKP1q5ifqOOk%2B%2FtYWJ6GoODA8imU6hzHT09c%2BSNQ0Cv9R76fujJkliNN7LW%2FmQGzIYdPeSsF%2BA8pGqcHUsglkAsgVgCsQR6SuDtA5v2Ze3SKX54%2FUfWXD0JkPwfP6a00nFt5KlTpwX2CLgINGkV%2FOGHq3JXnZqaxosXK%2FjHf%2FxHDJYHMVAug26mtEJOTEygUCyqFVoAZSHd3ZP7bGmgjGRqD7u7dW1hQlfVanUP62trcolaWlqSdkd3W54LpLVa2NjYCMCmWTZbuHv3Ln788UdFqiUY5tYt%2FNEVlmssl5eWlDcwwDWiZzE5OYkTJ44LcOYLedy6eQs7O7tIJlOuThYpRtRNZcQ7gXEqlREAHRkdVZ9qtTp2d3YVfZBAj4GIxsfHMM4gQvmsLK20mJJv7qHJv0C6TrmTu2CY6kXf59HWt1ExpRV5Z3tbwYLS%2BYKUWClsXsEKGu6TdFwslkBfEggBVljcRhWOH5brHz4e%2FXhjZfj8u7MQaKo40329kPKRzxwJ32oIA0NKVqR3W74%2Ba%2FVfkq2xZsu2NHErOQk6SUN06N7AnqbS2lyRljyrEfJnMotyEM3rfh7Qj2R7XsJ7EMncd2p8dCaTrnHMI%2B%2BuS6GHBn8B91xOwTW93P6DVuwGUvWq9hdNprOqaXSasoDSYZZ7HFMWlIGnlUi2tE9xaXgE%2BfwoGgN7uLe4hQcPH2FhYxcnV1Zx7txpTIyOIJumJ4kJN5FoapJU42vLlnSwLwG%2FLj6B0nQjeHaYjIOCgVj4jPs%2FG8v99f6yvlx8jCUQSyCWQCyBWAKHSeCtApv85OmzZ9%2Fxtr4pnTPJEaWQ304flbVJ99Sa7d%2FIrUQIaJaXl7TVCbcf4ZrIc%2BfO4vz5WSkWDx48VD5bpHWQ24zU6nXs7O7I7TabScvN9fnCIm7euo07d%2B6o3s7OHtY3NjUzXatVBVSTqwnUG1U8fvxI1kPul8n9M%2BmeyrWbvCbg%2FeSTTwTmCEAJjLklCoEkj2fPngWDAZH3%2BblnmJ2dxalTJ3Hs2HGUywNyh6WbLN1uFxYWRJvW28HBisAa11k1FCyphXqds%2BZNlAYGZJ0dHh5FsTSg9aTlyjAIQLnuk2Dz5KkTGB0dwaNHDzXTTgBPhYs%2FuxtOTeO186gLb0yXG2V3MCzi1SIHJNFoYWN9HUuLi3I5ztMKnbCItL7FtsrxRSyB1yYBPmEecIZETeW2p689l2nhn6xDhADOmKccVXbl2ouHFV%2FizMBWe2RZrjuMQKaXoBpl0HptAEQ7bIJrEe2dN5ij0vxHIIXl3Y%2BAjOviGUSs7jYBSRAkdYefUUY9KBdW8%2BN95BgtaxxGU%2Bw82gvyK5kEzLryDlhZWddXZbXXZn2zdRvg5LjJfmZSlpNo7pkF1wFVPQOOebZru5PygSBQbQGpJIqlAoamZlCYKSEzv44bD59rf%2BO1jU19L86fO43JsREMcF%2FnJKPTumi0EjUnUl3PyepBQlBfDsrs7KOTSeRg992XC%2BkYCI0UjE9jCcQSiCUQSyCWwCESeOvApsIUBG5P7b3Tp1GbXttMcCqVlkWOW4FwHSQD7Dx%2B%2FFhrM3nk7%2FnCPJqNJmZnL%2BC3v%2F29AB1RE8Hd3Tt3cfPmLSwuLSqs%2Fe7eNuqNmpTJqclJ1BqM9LqNpeUXWFpaQS6Xl95FhYTrPicmJ%2BTWyjrzz59jaXlZDB87NqOytHDeuHFD%2B24S0BKAchsUuvpOT0%2B7tZODqFQGMTIyKlBJa%2BXI8DCOHTsGuufSNZegdW5%2BHg8fP8bK8jKu%2F%2FgTlpZXFNxnaGREig7BNvmiGy%2BVFwYWYkAkus6urq4jm81jdvayLLj1elNy82tEGbn23r274LYtlaGylMaWIi7S3SzlgKcpvqaeUDkxtVfWAbsxEZXRtHErZfeQpflXr9e0lcyzp0%2BRTiYxXKkAWV8mtD9YSvxvLIHXJQF7%2FjRj0qbBM53PK9vxUMjOe7XMZ9tTDFX1XjWOkmc8ecCpmgKa1uZR2vM8Wk13pXXRpE5gZT%2B6dJpYWrZ%2BW2FsjA9GUJX1zqFsecwyuFcqjZbWekdoBSAvKksj7VMUfMjJz%2FPHY1t%2FXX63vqqOJsOiMvWUfJpR9Fc8BiW0z4itQ%2FepTKIkCLj5DdKyAlYKLKC6kIjMImr8NnhfaKFMUh4E4QkkM2kUBsvIl2eQGUsgXZkEbt3Dk2fPcP36j1hbWcbs%2BbM4e%2BokKuUBW3%2FvnkmTAS2eLXRGm4122SZa6cFsEYSj%2FfR9ak8z%2Fv2SE1s2EUhkf9E4JZZALIFYArEEYgn0KYG3CmyyTwfNrNpn0RQIKi0JftwTSe05SXTItZcEjn%2F607%2FI8kdLJoHa5MQELl%2B%2BjCtXPpAbaqUypKA%2FtHJyjeSZs2dx9eo13L59C9wb88XqMoqFPMZGRsH1ncdPnAISKZw7d17gkK6oxeLXyOXvYXb2Ej76%2BGNtO0IwSBdU0vzd734LAuGvv%2F5aazNp2fzggw%2FkpktLJoMAERjSdZautQxUxPKcbabFk6B05tgx7O7s4OmzJ7h67Zpora2tyRWYoHpoqIKxiQmBVFoY6OsrawO3LkkmUavX8OjxY9y7dx%2FPns1hfHxKvBJk09X3%2BvWfMDf3DN9%2Fn8Lc3FP88Y9%2FlKX3zOlTpmxKyXIqqp9ppw5Evdwpq1TQtI4rqnk75zSv8JiyaIE42OdatSoX2q3NDVT3djURYM%2Byi0wS6z99vtpxsf4lYOOGnkk%2BwNLUrTZzOObYJJfDWyEs6WgifDh1pofbnnD7t6P4kS81sgW1wjaCpCOdhNyG1QSMNFFkQMoAp20X1Wp4n9kUWprUc1NE3PUDLXDdIo%2F0AJH7aDrtrH7uLXcNcrjQOKFmzWKo027rOtWkk54bZ6zfBukO%2Bh5E5wtYvpv8PbiN9N5BTqNtvXMTDTpY%2Fw0vE%2FZZHumbqyz75VpSIZZourWrQqho0drL8TiVQrqQw%2BhABcnSGApDoxi5ew%2B3b93Ad99%2Fi%2BWFOTTrVZw9fVqB2jiG6ymU546LQeDaCPh3QyQ7S9DIXhtobI%2B%2BHpTvONFjr0lJH1BPPesoFV%2FGEoglEEsglkAsgaNJ4K0Dm%2ByelI0D%2B9mem8lkBa62kim5ztKFlOsv6X46NTWJC7MXcHH2olxH0ymCukwwG3zy1EnMHDsuwHnt6lXcvHUDtOjRgplK25pHBt45eeq0QBEVtfWNdbmkzhw%2FoTbo%2BkqFiIEyaL1kVNiLFy8KOJIPgksC3ytXrmjzcK6V9AqUX9cZ7THz%2FI8BighCBeiQEEjOF4qYnp7ByZMntK3K8PCwJEaLaLFYAoMSEXgzAi3D2pMHutqePnsWH3%2F8sfYMJVidmTmmdaEEuPzRujkxcUkW4LHRUWSzbmuSyLpYKZD8Ry1S0TJ1ztSv9vtit8%2FSTKmjjm9Bh2iFJvA0OlYy%2FjeWwJuVQMfzGbnkKX%2BybEWZ6IZgIvkREpHUlz%2F148LLU2iv2ckfx69Wgx4QDXBZNn98g9lNQh1aKe2M7yrXrNvYkE4mtI6b7%2FHm1g4W5xdR5ZpxBgmiI6mC2wiut0VqJXXWMVhEzwiub7Rr%2FqsRxIM3lbI89kKi11jT2Yv2PtqVL2OTWr6EsK0H1rrHLBe5qb6aq8C%2B2MfH2RddURajiyy547lVYxlaH%2BlYkkIjmUI9mUQ6l9dP61op1WQSxYE8Tp8uYXhkBCPDg%2Fj2qxYW5p%2Fh8z%2F%2FGSuLC7hwYRbTMzMKOGfbdpl0zC3Z98aNn26bLqb6AHlWoqMzYbW2M34nCJjtWeuvThuB%2BCKWQCyBWAKxBGIJdEgg0aKG%2F479%2BS4ZeOEG23ARWp9py5ChoSGBp1w%2Br0it3P8yk06j0WDgnLQsnnQ1pRWRQK5WrQkQvlhdQa26h9HRYQwPDSObyypoBD%2FMnPXn1iBcC%2Fr8%2BQJW11ZlgSwPlLG1s61tVmil5LpKWiwZqIgWTbrAcgsSphMYEmBSSeCPdAm62A%2B65Uo540bfkTwGEOIaTbrksizz2A6DCdHdlkGE6CaszeUBrK6uYmGBe4KahZT1qWAMjQwLeNKKSrdjBhhiVFv2h8f5%2BXnt8UmAPjY2hkIhH4De6OPjlRQqQsZnUvxbupW0B85UMyrw9VYT9aatI2Vbd%2B%2FcwZPHj3H27DmcO3MOA6UBU%2BTojaY1o9EW4%2FNYAj%2BPBPjcRgfLn1sVP0p7UT67SSegFS3IKNsMfKalAi2k0izVQKtZA93w%2BZdIcLFiGo0WI6Y2VV5gM9HA9uoC7v74F9y7%2FjUmisB0oYXmyhMUahsoNKvItupIct0mvSIcUCQYk6upk63ny46eOR79ebQ3Bu4M3vma0fzOc4LNSDkBWQcSnZUwhLPWoqLpRmGkX8IhC6PRJ0WSIpx2c23KaKKJeiKBejqLTaRRKwyjfGIWQ6ffR27yHFrFCdTTZVSTedRbKX1vatUdzD95jB%2B%2B%2Bwb3791RwKFjM8cEOE%2BfPoOh4RFFtNUEo5949N10ni%2BcNKB8FczNfU98kX6O%2FN5Ex%2Bt%2B6sRlYgnEEoglEEsglsBBEngrLZsHdaYznR9NRlnlR5dWRQbaGR4ZRj6XQy6fE1BkHa%2F40HZBECa1hjPSCduCg5FcB4cqGBgcUFh8AlMCKRa0OW4VVrCdbCKJ8YlxVIaGNNvPmehCqSjWSIe8sBaPtGIyai3%2F%2FNGDS6aRf%2F%2BjWxQVGfJqaVQKmwKWXL%2FJSLkEx6xPWgSzXPMoNY0WQ20UnhagpIWTwYsoE%2BlYDNufTqse%2BWIb7DtBMWkScJK%2BbfKdk1WTvJAPMhVR39QXU9PcaSDf8Lr9zBRJ0qBMCeAJuuu1mtzH2A%2F9ddM12wnFV7EE3qgEOp%2Fzzus32vgRib8Ub3yXOZkDektwvKGnQUNrvDnOmTOxsw5yzEimkEQSzUYN62svcO%2FmDVz79gdsrSxg4vxxpAtZ7CRzaCSqaBBUcqRocQKP6x7p7WEjBWk3HUoLXnOeaKsZG2G9vdD3y6aqLNJrmOdzuwnL5UXRoIoxneMYB3M6AXtqhkt5HfAkEmZVDEuF%2Beyf8KvaSKCZgMBmLZHDbiuFVqaEVGkYyeIgkM6jlUjJ3Zhs0GicTKeQSxcxMz2JXPoTHJuewO1bNxWcjdthray8wOzsRUxMTiGXK2jMTqbc94B8twB654DzAY5X0uY4fRTweJSy3SQdp8USiCUQSyCWQCyBqATeSbAZArLwI0vQwuirtLg1GxbsQopV0txS%2FQeZ%2BIkWSvtaOwVFCgjdVNNIJmh59ACLR5ahkqZ%2FpaARpBHw2fon0yQEECV5U10ICvnHcn5djfHApjlHbn%2FMYyRZA4AhP4bzbC9RAkTyZoGQ6AJnW5RIaeDm5A5AkiLT8vmcALdaoMLnZ8idJZXA1mgYHfIoWlQ4HQuSEwk4wGnc2r8q4hSuaHrnuVfkJBsC6wSQSWcUcTefNesseWcbLCNReze7UBSdZOPrWAJvTAJ87PjcvrOPX7A%2FMYOJ2c9GLBtraNlstpIa2%2BT9UW9gY30Nd27dwjdffoWNlUVcOXcOJ8%2BeRm5vFXv5soKq1dwab3OVJdi0t59Q0oyN1gpvnGyNTsAGSC0iLJOCH8dENx4F9yIk0eP%2B7y%2FEFNFwg1tAz91r2U%2FdeKZDBwmOz1wiqSGd8tN4mxbAriKJ3VYWe8kcMoUhpAZGkMyV0UpmoVBDbrLOViOYlbVULKJ4%2FBjGRoYwVCnj2tVruH%2F%2FoWIG7O5Vcf78Hqa4J2elglTKJgy59IB%2F2XRG4z3HS04U8shJQnOPjfash4jirFgCsQRiCcQSiCXwGiXwToJND14oJwNJhh3TqZTN0nM7NLlBETwpio00SH6QqUcoIh%2FdVyOAyekhqicroxQUV5cKk7CQ1BLdHoI1ulGxfZ0rCixdYpnN8sxrB5YsKzc1d4Pter8bqu%2BX75sHrr4tteBAoLYokTXVNCcqIGw4nUmjWec5Z9X1j%2Bubue36tgl2A3okoQ44bcvpLpamYoG8SdPzZznt%2F5oYnEXB0aVc%2BUewzm1bZDmRJde58FHz9CJvJxdfxRL42STwTqnskc7w1Rb4c%2BNTs1nXRA%2FHSI1VskeG7zUjR9Pa%2FBhHIQAAIABJREFUdvvmTfzlqz9jfXUZH1y6hI8%2FuYLp4SL2lp%2Bgvr2OKhqobTWBehPNJPfpTCClbVDce%2B2Ap3dhdTDS8eJuq6ycZMem9whWI6yrUGd01u4PRGctGxetrOW50S1S3dL5r%2FFoUgoLGDcMikSzYiKZQSuZkSW31kpiL5FDojiE%2FNAU0gOjQKaEZiKLViIta7GsvCQm4JlAKpNGMp1EPpvRpGC5VMbY6ATu3ruvgHLPny%2FiwuwsLl%2B5Im8d7f8pTxvPua19998F%2B%2BaE3MZnsQRiCcQSiCUQS%2BDnlMA7CTYNzNmHl4BHrrEtWunM9dWC6pjSxK1AOCXNo4EbWi5texADpKZo6KbI1coBLilm4ebdzDdlhDoDaVNBM8sqzxVsgwCUbWkKnPyFtNlWJzgzMGr0DlIYOoGeLIEdT5CnSxVJ5w4I0rJrCo50SsdbQ7Wp1KlPviyZCf68UhMkdJx4SXQkH3LplSO6KXNiQOtgZfE0BZPVo1wcQi7OjiUQS%2BAoEqCXgxvXaNXk2MJJI%2F7o7VFvNXTOpQGctFpeXsFPP93AD99%2Fhxdr67h06TI%2B%2B8MnmJkaQbq5g0RrHK36LtYbe9it76HRrCPdbCGNOvjhof9GkjR1zrWcBtfIMif6BCfJD8cef3Qg048DHqBGu6m86BCl6u3jbbQ8B5WwuFHmv0ENNyfmOJK7rYWLIhUGQOIwatZDJLndC4FmEtVmAtVEBo1MEYXhKVQmjiM3MIJEtoRWKotEwqTA%2Fvv2jXfK3lyNC%2Fk8jh8%2FjsrQCIaGR%2FH91WtYXFxSZHWOhucvnMfY6Ji%2BbVpvm6zLy4X3jsss%2BMcxnxOe%2FjvQ1vf4IpZALIFYArEEYgm8YQm8o2Czu9Tsgxt2WfPTBDOMwsjoipxxZ%2Fz%2BRBIpua%2B25B5lChi1HdYwJclaMItmZ2v%2Bo%2B6PzKcS4SMJMp3KgP%2F5%2Brz2f1bGrtpwni%2Fgjr4N1uW5ud1Se3FAt6M8GTF1Kswg0Nb%2Bm87tytx6Qx5J19ohfyGPIQU783R78dtZJ3rt%2BeexXquLT87ae7osy9aj19H68XksgVgCrygBBzg5CUV3ULm7uu0w5HmQbKFeq2J%2BYRE%2F%2FnRT%2BwTv7u3hw48%2Bxse%2FuYKxqVEk8wm0ai2kBoaQb1Sxt7WOanUbNTTQ3AXoXNFI1JHmGkOtJqe1k0DT3Gv5fnOyi2CTQLfZ4mpR73jrJ54U59ZZGjvGhM4himAxOmhEBpGwaLRA%2BzhjnBB4u9IJA8ZstRmkEcyl0UykUGsC1WYLVaTQyOWRHRxDeeIYBkankSkOAekCkMwiQWDKLWS0jQz39SR9WiW5bynXj1ICCQUEGqxkcO698yiUynjy5CkWFpfw6NFj7O7uCYwy6B1jETDAGyfq%2BK3jnweZ3SYhX%2FFJiavHEoglEEsglkAsgb4kECKvvoq%2FLYUIjozX6EeWgIyusvwjuNSaSukPLG%2BBezgb7C2SBJ00%2FmndkICmV3ScHFxdXgmQ%2BWSnNHD2nzPeoHLC%2FxxPPHpcqXo%2BwysaAbgzgizbCUTbaYiDtjJsrF19Mh5ZkkpN0q1LJV2BTWdt9cqJ60pwaG9fHe6gbyg2bLMdiLOfPf8is%2B%2BMkLuxtq4ASoxEq75QCCRBWVjzPcnFmbEE3oQE9Mq%2FMxMevjf2ThHeNBgV2rn409MjwQBB3F%2FTjXGMnD3%2FfBE%2F3biJe%2FcfaP377OwFfPDh%2B5g%2BNolcLolmoq4xlLFq0o0q8qMTqNZ3BcxqDBS0Z4BTbrp0zSWwlHWwhQT3A5Z8HcRrEWaSP4NedjR%2B7f76IEFhXzrv%2B76R0A1FrGFDikuIjGj8BuhPQJXnIQeyaiZ4bQQICbl3ZpORy5sJ7DZbqNFFNl9GfmgcxemTGJw4hvTAsKyaSOUAutomUi7oEgmJipqkx0miRS8cG%2Bz4DWE08nJlECcyWRSKAygNDGJh4bn2ROb%2BylOTU5iensLgYFmB6biGnwHgDhrP1VD8TyyBWAKxBGIJxBL4GSTwToJND2z8kXIk8LM1gbaO0lQJp9Z4XaND4AKaTAtmxq08gZewkwNQdu1m4QXaDBxaG2bBFBl5NRkIYx3yRKXAtjXxANTcWD0rUZDnzz1A9e0a8LTWDCy3u03RBS4oS1feRgP1RiMMHOSQLxWTEIw7l1vHSCjL9nTPp47UjeRqbLxIgTJBtRXrdUGZvFhdxfzcHCbGJ5DPcVsai9grpVFKaS8KcV4sgTcrgQOGizfb6GumbmOJf081xAlOCXC2mkhrGQCDAVmEa07M7e7sYm7uOW7cuo2HDx%2FJJnn6zClcunwJM8dmkMszkJgLruawUrJYRm54AgWCVkVnBeqbSTT3ttCs7dmEX7OBtCb73KSa2KKU6dXAmTkeuXadlkSTviYAHQTU5KDGsLA%2FUXEpNaAZ3r0giYXDQg6BKkEZDY73zgJrE5EGNFmC%2FNQZtZyBk5JpMCBQLZ0EcgPq98DkSZSmTiE7PIlkbhBI5WXVhCY9ORFpzfFfckbK8uWQ94tNDHKrGH5w0ukMCqUkRljWbXH1bO4ZVpaX8eTJE%2Bzt7mjv6EqlgkKhoPGd3xc%2Fdvt7buTMW8V%2FF6Lyis9jCcQSiCUQSyCWwOuUwDsJNikg%2F4HlOUEULZkEmwowIXRmYuSp6S%2BhEmL1HQ19malW%2BPlxzribQhWoB9IF%2BPHmLL0pKVQG6AKm2Wk1QqouT23ax96Ao7k8MZ%2B8%2BrWLxofnq91SKH4C3m3%2FSeJcUyhcn9QxRns0GuLJcaGIu66jxoMBVG8J9oqJqUIEmJ5HVjroz%2Fp3UG6vdFO0oIi66%2BvrWFpcQqlQRGOEURad7APFrBelOC%2BWwJuTgH8b31wLb4ZyOC6094CjGd9a%2FuS4ySFLCIg5BDscUxLY263i2bM5XL%2F%2BIx4%2BfiLgc%2BbMacxevGhAs5AXFRsn6BrqxpzcADKVFoocgxmoLJ3BXj6P%2BsYLNOheu7stkEWwmWjVNXCRI3OcJWJ1aw0ZAdfiz6JB11q2JuujpZrUDht%2F2vveJum2LA7oXir%2BnBDQ0jgUksdGK4kG9xxlZFlGhU3ndJ5MF5Atj6I0fhylyVPIjUwjURwG0iUgmePGV%2Fq5GUsbYjnKefbpleKibvOe8H8FaqP3RyulCObcR5njdoZBhLI5LC0u4vnzeewKcE4pcBDHckVFd0s2SIjfQH5fWJf5PB70bLTJJ76IJRBLIJZALIFYAi8pgXcWbEblwQ%2BqhX43qxyvqQtRieKf6UVt2kZQnWWlY0TKmULly5MWtQQDj8kUga0BVQO5pkE43StCN1xP4xNZxngNgV3IK%2FM8LQ9UfU07%2BrWWVifkzwIV2mw4U5nvFQ7WNIumKXU8559XQIzyq%2F3L9g77Y8%2FYJtdq7u7uSmmqVd1m8hJoADkPIxXnxxKIJRCRAN8rm8CySaPgddTSANt6hO%2Bf1m0rWBrXr8v7X0Nfvd7A8%2BcLuH7tR9y4eRO5fB7vXbqES5cvY2p6SnvjamQKCBPMcByx6NEcl3KpFFKZDHKFIvbWKthdXcTOyhLqG6to7G1hr7WHerOGFmpocSmDxlNO3pl101xtGeHbrJsh2GRHucbRxsZIt49wGh2fNBI5AOjOJQV3nmxpL1JaO7nGv0l32HQeiWwRKQJrWnJLQyhUxpEfnkJmaBKJgREgy%2BUABJoZBzatX%2B7jI8AttGlrNsyqywBzigZOmMtJSKDeaCqiOicOGbV7cmISA8USSsUCnj17hpWVFY2dHEOnp6cDUGnA0sZYPg%2F8cVxm0Dx%2FzbG%2Fn7H6CIKNi8YSiCUQSyCWQCwBBQX8VYjBg6iwswY4w%2BvuZ%2F6jzNzwQxxVTpQTVKaSFehcbXWCIjqJlglzjKewnbBNlicv%2FAvz2%2FnoTlM19vEUtWDul020jZC7N33G%2FnHNGLdUkNsz%2B6v%2Fab2IzZpvWv4x%2FXdVAgY2%2BX5xLklWMnZV4wn9NPhL6N2r1WsGTFtpoc3a7h6ez83hhx%2Bu4uatm%2BBk2uzFWbz%2F%2FhVMz8wgk8vaGk%2B9n26iSo6gLqAPQU0ygWQuhWwqg3S2iHxpCKXyOHYHV7C3uoz65iqaOxto1PfQatTAqKo2fyfIqUXzPPOWTVpNbWWnB4Ovet84jvLXSc9fm3VTNmAylkygTk8Zhi3K5JDKlZAtDiI%2FMIRCeUhgM1OsIFUYBPKDApotrtME98SkVdNPJrr%2BaRjnQOfHODnS2phNFhK8Ny3UanX9uJ8yJw9kucxlwIi1uWxGrrNzc8%2B0jvP%2B%2FfvY2trSxN3U1JS%2BGblczk0shsHfSIePgU1G7J8AfVXJxvVjCcQSiCUQSyCWwK%2FCshm9zVHw2E96COyipd%2Fcea%2F2euW9LEdvgubL8kLQSwWKgS0KxSJyDHCR8rPtQttyz2uH2C%2FbWlwvlsCvQwJujiqYpLJrRuG2LTaIcbj2kGOj%2F4%2BTPdVaDXNPn%2BL69z%2Fg3t27yOZysmZ%2B8OGHmJqeRiabdQL0AX54GQJEgjdaIOkSyzWKCa4fLOSRyQwiUxhFbnAK9ZFN1LfWUNveQKO2i1azriUPwn2ibkCQVA0QumMws0Y09ip%2FfjTxR9LyNEOwSZdduzIJaWU9A8hlckjni8jkS8iVBpHNl5DMFoC0W5uZzqNF19lEWkDTYplbW8F9YZO%2BeXnF%2BDEPYHB0guxqo4pataq19lxzzz%2B%2FDzHPS6UBzMykUSoVBTrn5%2BextLSEarUqwDkzM4Ph4WEUiwVkMhY4iPebfwqWF1i%2FY8ApocT%2FxBKIJRBLIJbAa5PArw5sHgSuDkp%2FbZKOCfWUgHStRAKcfR8dGVXARwa6YFAM%2FlExogUmFSiZPcnFmbEEYgm494bvjneRNIBBKxqtnYw8K3SDFoNxu%2BUGRFXVvSqePX2K77%2F5Bg%2FvP8BAsYjLly7h8pUrmJyi62xO5QW93EoD0tY4KkMgLZH8vNiGJgmeJzJIJptApoFEuoFkto5sqYZsbQ9NZ9VstRpuFWn09hnUFCJr0ftD5llDaB6xRYsf%2BZyjj0d70cpm0fQWT0Ez31dXLMFAP6kMkvyls0ikMuBem2DAI%2F24vQkDLVHABiLdaoigIcFYubb6JFsmwSu1qdtlwFAAM0P3YhpYTS4M3pTNZLTtCcfPUqkkYEm3WkaqffDgATY3N%2BVWSysnx1Vv5aRF02IZeOBpLrZsO%2F4m%2BvsRH2MJxBKIJRBL4FUk8KsDm68irLjum5OAqTrQHnGcgeeecYV8QUqyFGQqsvI0o2rWnwv0m%2BM2phxL4JcvAb433mrVDjYNzHAdO51dm7RsOgsXLZrcemhhfh5%2F%2Bfpr3L55E%2BMjo3j%2Fgw9w8eJFjI2PIZ3JGO5zlku%2BuwJMFIn2yyRwc1uaCMbRbZRB1TJopfgS0wmWaKmBVrph4NPts8mXXPNJDvvZuOCBoLOa0lJKwKmCfuR4lftB%2Br5Bd9TBeubB5oEtiBe3RlW8sbK%2FNnBsG7gw8E%2FYVEDPdTi69j%2Fgh4USQEZRZc39ltT1Yz0FvTOQz0veh0plECMjwwKVBJq0cj58%2BBCrq6vY3t7GqVOnMDo6Kg8SuuTyOfHPR8BTfBJLIJZALIFYArEEXpMEYrD5mgQZk3lFCTA4ULMhvY6z7nSllQYs%2FdWv0HJmBSmCr9heXD2WwDssAU3QuP55C5XWQbu1flxHmXJ7CxP4ae1es4m93V08ffwYf%2F6P%2F8Ctmzdx8thx%2FPa3v8XshQsolwdkaeN7muarSNdbB3CsKfoeEBBy%2F0j%2Buf0iVcutR1Qd7u1L8Mn1iw00wIjTTa2FJIDUPpPuVfdg0zAaHXK5xZSL9C2Qy2aslOvuEQ%2BuIYNvDsZ5EqTrfgTBTI42pQT2iyfW43Ddpbv2bsU6umKehi%2Fim%2FM0guuAqm2RZVtEG6e%2BrqfFOp6FVgu5XFZeIdz6JJ%2FPaauax48f4%2Fnz5wKdly9fFuBkvgUP8gQjjcensQRiCcQSiCUQS%2BA1SCAGm69BiDGJV5cAZ%2BQVpKIF7TvKrRAada5NCmwmoU4X60WvLvCYwjstAQ8wzXXTEIncZputIAIpA%2FEIPSUTWr%2B5s72Nhw8e4Ksvv8LNGzcxNTmJv%2F3bv8XF2VkMlgdlJa27PXtZM%2FpuehTGV9OH8vE4zaMg28aD7zOtm6zP0ilZVrWNCUFb0rmQunecEI%2BAVqW1HYi1YLCTJKJoy8od%2BV8zCYZorY0AXWmZ4MYhYst9TToGWUyn%2FjosKEuu74inz2xf1Kd1OQZF3ElwHbTXXon3npFraa2kyyzBJNd0cu%2FN%2B%2Ffv4YsvvgCB52effYYLFy4E26O0U4mvYgnEEoglEEsglsDrkUAMNl%2BPHGMqR5VAqIeppuwh3PeN2lcL2Ktxe%2FSE3GqpC8qBTlvWtKlaR201Lt9FAn3qvF1qxkm%2FXAnYXTXQ6fZSdFs%2BkWdaPgX%2BADRqdaytr%2BPOvbv49rtv8eD%2BA5w9cxb%2F%2BT%2F%2FLc6dPYtisSjrXTKZRoZusP4vOHVWP2e8VHhTur2zHP9xIIvbk1ibVlHvOutobyYeDWxqVknrEe1dN%2BupgTxugaI%2ByZrYF1bz3PY%2BHjisdMnYlxQIYn8byiJQZW9dOR4cjW5LTsOJgpDcviaZ1aVZB4ldRXOv5f1jgCDuzcnzq1ev4tatW3KX3tjYwNmzZzEyMqJ1nCZWI2zWcSfvkJX4LJZALIFYArEEYgkcSQKJVtTf6khV%2F5qF%2FVc28tX2X%2B%2B%2FJlv72vZ8MqOrurCvxtudwP5G%2B7y%2FNyrhDRvaM4%2Fus9w7zmwlrLGxuYm11VWUBwZkUclmsoH0GBSDOiml%2BcuQaD9c9JaJSakfOvvl%2Baop3Tnrlvrq%2FIUUutHv7ElYujMnvu4lgWiAF5YzOWoPzQbX55nFy97ThLYYWl5Z0bYmV69ew8LigtwrP%2F3kE1y6dEnvoMN1Anm8c6RIQBTcRf8%2B8uiQIa1%2FApPuX4Igljfc6Wq6%2FR757vMzRNCptYN%2Bv0fXsOo5VEa6UTda9iPgo5dYDs3r9bxZC71KHEo%2BWoDkvFCj6S9z7jsfYY6y5K9arQpQcl0mf3t7e1hfX8fCwgIePXqkdZzcZ%2FPChVnd62PHjslVmkHZDPCKUZ13A8Avw25c501KwD8Mb7KNg2hHHsCDihya%2Fib4fx18Hcp4XCCWQCyBQyTw9lg2o%2BMQxw8pH0ykVsPACTx%2FuYHF423%2FQY02dYj8gmyx5LhgormSBdmvxF%2BUyi%2F3%2FHCpSQkKZBS6x%2Fk%2BUf5Uirgx%2BZMnjzEzcwzFYgnZLJUns8awTEvWDV%2Frr3n0d73Xc%2BflwqM%2Fj%2FLMuv3QidZ5PefduCHlMJ1nvm%2FR84Pb96W7ldhPIWwpLN%2BLQlgqPmuXgL1bfhaHciUIo1XKhkqukSTgVDm9S0CjXsfq2hpu37qNq1ev48WLVcxMH8Oly5dw9uw5uV6mUtyyg%2FZIu3u6O36Zo2PBA0vm2d0z9GnjqrmharhmcgCySNGsn2m68XpoqjKOsAOYvBIt97gkEpyYsmA57Oebf2K6Paft8t9%2F1cmVp2Gy2V%2F%2BJVM6m3FkKC%2BLNNvUhAKTuQ7etj8pyr22XC7jzp3buHHjhqLVMnItgweNjY3J5TYcl1j7gIZeku24Wi8J2PfOl7BX5jD5%2B%2BeLR3%2FuKbzs8bA2PV2WY5v9lvf1okfP8%2Bvin7y8Dr6iPMbnsQRiCbysBN4esBn0kJpS04FNn%2BgGqrbFNH6w8WW6H035svDvPiKf0lg8UIy61fUDq1N2uE6GH3inIMn6FtSPDqTdaFmap%2BiP3Up6SqGy1a3U0dJMkQwpH1Tb8%2BWP3ct1pyOwGKngXePcqjF9qqgc1Rp1bG1vY2FpCeXBCuq0xjhlk%2FsC6gOS4BYC4SfV8%2BOPkWZe4vQoVMgZy3fvszVuSjXLdC%2FlaZCStX0UDl6ig6rCVo2fzmkRz2fIFwvaldXo1WYIJrqXCnsYob%2Bv6FEk4Hnyx33ElEDZ9kPV3y27r91r%2BFR%2F7NZilJvoebeyno4%2FdivTLU0AjM9Vi0FJaR1kqUhrDrgxvSGgydwEWvUmagSaL1Zx9%2B49XP%2FxOlbXNnDs%2BElcvHQRp0%2BfRmVwEIlkGg2%2BqHzfSLmDweCSTbqLSOvB%2BKk0lx%2Bxh4bAMxmswBSd7neKBNqodxPJK6S9Sdpk603z3951jo9JytVZi%2Fms8N3k%2Bk0LGpTH0NAQCDhv3rwBbpOytbWlrVJmZ2fBLVLy%2BbzW95IyJxxIL7jR7c3FV69FAnwGPdAMn0ebXA2vD27K6h%2Bc%2F6Zz%2BuGxFw%2Bvk3%2FS8s%2Frq%2FLVi%2Bc472gS4D3hnz%2B6y%2FjwzkvgLQObDmhqKt0NIEItoQtm5zz3YcovP8LcZ4xAR9gwkUSTK4s0Ie%2FD13c%2BBx0virvkiiTSMSDlg937uq9vwNMwKmDdwYdv6ghHKdfSUl8ffwc1T26jrfBcvwTkRlur1bBX3dPG5VSGq%2FUaao2Gudi6EP8KWpniB%2FnV%2B96Nz2B%2BoI3TbiV9WrRHPi08UrQG31r7lPVIKRt61aeoOh6WeN1nnuvg6DatZztBWvST4ABnLz5C2R1Qqo1GH%2FdPRTw3B9B03HI9YM%2B%2FyERUt5Z9bbtfPSm5zG5U2usZTQ%2Fe2%2FNezxXfA5so83slGlg23rgfJZ0%2BOMY1Gk2L8ooE9mp7WF5exu3bd%2FDTjRtyrTxx4gQ%2B%2BPBDnDp5Uq6UNvHmueQ2I6Ye%2BGeZOexfVApehu2JHEgdP6rjR2hX0xOIPDzWBjN8Jk%2BZatchGI3ke1Z%2FcUfy6CXz8%2FBr37wkMlx%2BkEjKW2R3d1cWTt5X%2FhFwcj9O%2FgYHB%2FHTTz9hbm4O165dw9raKs6fvyArJwGpj1ar5ylyn35xon6rGeIzwvfZju1d8QC0PbXzyp6ubvXbS%2FqnsT2188o%2Fq%2F7YmR%2B97o9itEb3c8%2F766Dn%2Be6Xli%2FfnTNL7ZdWLxq%2F1jy%2F9psy7EfWv1Y5vbv9fkvAprliyaIppTHy0vN63%2FNrD%2FPh30W3pxvVGE%2BXVlO%2BDhGrgH0EoiqDzRL7lyb8QBBQkBmvkrkXLMLuQY%2BSf%2F388aBy4k2Z1k6vcv3ksT3jtndpz5c%2F9i7dPbdNDLow%2BZvIqBDXFayEbXCT8lQiiVajiWajoeFJ1ikfJMgx4sj0PXwdNvngOT8Mu1i513MPjJa5PIZPmefEH63DbLGpTvv0Vz3y3XLPa9DpEPCyKbas9%2BGQdgUCAhq9%2BeK2GYf%2FsUH%2FO7i0np%2BDsy0nMkwc1I3DWwpIhc%2FbQcQks%2F1vVrS4lwDT%2FHnvbngOjQpFLVfJyJjFscj21uTaRr5fzirZbGj45PYny0tLuHnrFm7dvo2tzS2cPHEc77%2F%2FPk6fOonBclnggnLnu0K%2BQp59f1zAIfLd4377elHbeZRi0Ged%2BNJs0CHbSMv2GLgyKu85i9TrLby%2FUu5B%2FPl0LwV%2FfD1s8t4RJHpLJsdW%2B04ZfT03zaYsm%2B%2B9957cZu%2Fduwfuy0lr99raOhg86Ny5c1rDy%2B2ojObr4S%2BmQgn4Z8AfbZzt%2FkqFZXrLrt9yvan8%2FLnk2%2F%2BisunGSb%2FvSr%2By6Ieep%2BWP3fiK07pLoB%2F5dq8Zp747EnhLwCbHIWqLphiH4ncvfpdnOQQVLNOlgBvoqfNyslfrmWg200Q8lZ2Um5CPzDZKYfX0zJWT%2B8OZcqfIFVLwzJWW23bYxmjWejcewp7w7PASVt70dK%2F4tdN4mSuDFoe3fniJo7WulbZyAWxpO4FMMoVWOoNCLoeRoWGUSyVk0inl8X5acKAuXDCp729Ar4JdaB%2FapcMbtxJuQ%2FcD6EkJV%2FMH8WfP3UG5B5A9PNm1qUNQmjakMIUTMbwKU4KCHSdH4K5fy7SfBOpoKbjk%2Bt3govvJYfndax2cavSsr71od5WGc%2F9mPeaze71otHPBGv7HMxt7OC5qvONY5oZIDZfct7bZMndKNLG9s4OlpSVZNO8%2FeIBmvY6zp0%2Fi%2FIULOHXyGAZLRWRSeivFlOerferBceA70M5gx5V%2Fbjwly7ax2aTTnuOqd0208irB075mGDrY%2BZVe0pqZzeb0%2BeSaeP5x0oHgk2CUEWrpOk0LJ9d0EnQyiNCTJ08xMTGhtF%2Bp6N5gt%2F3z7I9hU%2BH7YXkGPveXC2u8C2f%2BpWc%2Ff6l9%2FaXy9S7c%2F7gP77oE3h6w2abu9nrpfZ4%2FchDjuR%2FMeEt9ngOSxJbaw80AHEtKwXLrnFhclh0XbEOUAmWHtFpoUbGjii6PM0tj1ESjxX87eej%2BaNmHpntemGr8h0pgmPPyZ4fz1x9v3TmIzqoTHniIwNAjlA6BZJpbn2SB4coQUm6PuFwmozy2bbJsv5NqzcTRveGOVPtwdyQGl05p553sy%2FIWVOx5ojkSlWAPuv%2BFOTzr1iFXIpoVVupO9Eip7Luv4HmwxnhFC1aQ7Yu99NHoR7tyIKmeN4zPBPnqzZlyw84d2BTL2aTTgUWClnq36OqzgwcUZFbUSf%2BAYgcyYhZMJ0FW1thk5lvvKtlo1tFs1oFWEvVaFS%2BWl3Djx%2Bu4c%2FcuGPjn9MmTOPvee5iensZgeQDZTDqcYDuYdePJ3zwF7PIX7ex23hfrYzhqhWfReq4z0SS9ESxt7dit9BLr3nZH9V%2F1JccyBgfin8ZRTtwlkwKcBJ90qeUenHwOuB%2Fn4GAFd%2B%2FexcjIMCYnJ%2BVq611pf9WCfO2d73x2%2FTWP%2Fucb5bV%2F5n1a%2B7F3id512yn9ta6i7z570%2Bvvr9EftnkYX714%2FjXmRe8p%2B%2F%2FXuG%2B%2FRrn%2F8vr8loBNocGOB%2FWwlz6a7wcJr964PIJJf098EfdBpsXS1kHxA51UuH0WtfL%2BhWnq1aGRhlBTO2nzQ%2B5ospSVPFwh9mz0fyQnAff9V%2BssGVhWfJ86C9j10VrqTouppCMl1CupNAgjgUyKm7snBDKHKxVtuUDAmUqkzKJNNroAhu4tde9DP6lU4vsHmmGPetN2979vIR7cK5%2FTN6mejHkq5M%2Bfs0L03J5htuvb7kmyr8x2%2Bn1VOaCQAZrX935x0sPwbR%2B9ZTcOsNCqh87WLnrmAAAgAElEQVQiTNZ90YN6flB6tNsheOO4ZRNlkRFMRXWtAGpsky7oTVRru1hZWcbdO7dw5%2FYt1Oo1nDl%2FAbOz5zE9PWMRn9NpbSnEWuSlvfe8ClPb89z7zBI9JwY8Bavt%2B%2BuPYT89dX90OZGAYNZiR35I4C08e%2FN9MetmVpZMutASZHJrFN4zxRlocR1nFkNDw8hksxgbH0chnxfgzGQyb6FM3waWed%2F9GxA98txfu5cxuOz9rATF9nXf1%2FPHfQVeOuHgNjtJHtY2KR1WhjRZpp9yne2%2FyjXb65e%2FV2nnXasbvVf%2BC%2FZz37t3TaZvZ3%2FeErBJ4RrgPESf6bgL4TBIddQP4LbmLcwjbanbBBoKw0%2FFye%2F9aACIpb2C5xVzfqipnBo4SeijnUratV6rSBOR0w4eOy776iCp%2BTiuHfWPdOlfen%2FsXfkwZZJyDPFgd5qBQdhbNNWk1ePseYuux2lbi8agFts7e5IvZ%2BYz2QwSSd6FdtrtV7370E%2Fu4f3sh0qkjHe%2F7vEQSG4HAJeAkusoyfQqehR5qK%2B6KZ1SDVo98ol%2FhMNnYT%2BJo%2FC4v3ZnCt9ISqUHVc9UZ9W2a1%2FfH9sy2y%2Fk1a8RoT297cro%2BPulYweXTOvnj5SCsrr5jkf1i2Oj3j4bpRoNi4rNwEC1KhYXFrS9xfXr1wUyLl%2B%2BjMtXLmNqahq5fAHJFOu6SM%2BBndi36NrpJVtftEtHAp6j%2FAfnnnZnRaa359n9DcuFdNvLhSXCs8NLhGX7PQvb31%2FjTbS3v5WjpxBweqs3ASR%2FfP%2Fr9YbbHsW%2BbKWBAUWq5bet3z8%2FZvY%2FUdcv5d7let2H3jXD3P57GdZ59XbZKqmERz3jPilsys6OcC86q6qNrgz30%2FOuFduaOLxEtHg%2FbXqZHESZ%2Bf3Qibb7Os6P3qavcVBPXgdXbwcNasQ2vniZvB18x1y%2BLgm8RWDzZbpsjzU%2FhOHLzjT%2FY6rlMLop1a0UB3VuY9IEao0mkilbd0k3WUZL5Yc5m04jzbVNrEprHNcVMphNiy5rftN049eU%2BaO%2FXlbD%2Fo1yT6oHUQv76GRFRVTup04Zd9ftknTUVHkfhfainVf7PoDUwD133Wn5XJOdEaQlmBMA3NSd%2BXStrTeaWFtdx%2BLioizME5MTGBkdRSJlZTwrosd%2FzIPQJ%2F%2BijkGfg5OXYK9L3W4SdqKwZ6RbAd%2B0c7s0BScwbx%2F4bPlq%2FR2tYXvcjHHPSrQb0fP%2B6HaWCqlqsqgzO3J9eFu%2BhD9GKnc77aeYs8bxlSCnnlseWd0fu5HvTLO6XPfrqfDTzWizISOKPNtMoimLagv1Wl1rNK9d%2FQHffPOtGv3ss8%2Fw0UcfYXR0TJM3WvfZaMmrwGiRnqfpj77NkKtoipurCGCqL8Uy0XJ27kYzWpB9wX1H324kI%2FJ%2BayIvwmWk1L5TUmI7XSjuK9tvwsF890vhr1%2FOWzr1bWztYa9aQwsNfcu8y6z6KbmHPRaYdM%2BgB5YerHJrFLpnR59J39Nu8mfbnoYv1%2B%2BRHAWvgn%2BS9n2P%2BqV2%2BPMRtmUPUygR1wYTop1UgfZSQZEon5EikdNuxCIN2WkbT6wRbd93XcuDwhexWxm120HM7ks7R57k0Y%2BeMX88iEJnfuf1QfUOT2dPotR8nw97%2Fnw5tnBY2e5c%2BHEuKsuQE4q92z3pTuuw1Ggb3cqG7XbLfXNp1q5%2F38nlX4uTN9fHmPJhEnirwGbHeNjzkVVZ90Tz4TYVhwm88o6uGkG0R11DG5fb7As3LeH2J9xjjgpdvQXs7VUVnW9vdxdlrmsZGEAqmRIworJFsGmvEI9Gn21SmWOTpiB5pb77qxZN1bBhBovIRzVyOztGKPWsU0AOaHIhKS219hdthef%2B2h8jbfRx6hU%2FX7RT6Y9SNUU5khLIhcF%2FTJtsNGlRtvWv9UYD8wuLWFlZwdbODjK5HCpDFSRTnoak5JtuO3by1Zb5M16IU7fe9LU167t%2FAMGDsyPy4imfocgzE8kNKEdpdcv3Ba1ctLT%2FiLanqVlf6ZWPpB399SAoNtp5Oah0RCTqRLda7IfJo3ePegFNtU%2FiRih4Ew%2Fii%2Bl8v1hFKoy8Kmysseii3rUWmhibn5vDD99%2FD1o0OZHz6aef4ve%2F%2Bx2Gh0e4SNpFsm3Z%2B%2BQmH%2FhMHN3G7ToQ9MAkxkkjy7FrjYc65btuk3q9%2Bmq1rER%2F0Yv3U%2Bt9d%2FaX7yeFfPke91P%2Bl1yGCrTGbE3I0rOHge%2B8guw479JZJvkvHs85VrfqLdDjlmtAbU%2FOsOeehL%2Bnbe8Y5alvaFj%2BsDOW9zR9WU%2FbX%2Fd79HQOqu959eU66fp8MhQOqXwX%2FRhoNVTOfdOZYtt3kWq0ZTczFfTOEzmo9Qg3wURvJE0NOfokHW0qyGMU%2Fc4MZjKN7fN%2FPhP7%2B6RS%2FbDm7jHL9%2F6LCIgcdOXL2PKjC%2BkF5dzkSHDtGtOkijvX8%2B0MEJq67taGvy0q5%2BSwT3j7e7Kv3aBIN%2FkGmUc%2BCZ45V9N2U3B8dlALy3Jyx74XHUWCS%2F%2BMBgkvdWLC6%2Byxf0w601%2BqibjSWyeBtwhs%2BkfVy9g%2Fsj7drqOp9uLY4MV0lhTm0sw%2FU6w0P7ZafZmgVc0%2BtE1%2BSlNptFJpuRht7uxiYXkFmxubmBhtolAoIZVJodVsmlWOH%2BgE3UATtjWFSLNtAj0N02LcVEXPs%2B%2BLHVm367hnbAaFO2vbh6DzQ%2BL61rIN01uygvh2AlJOBu0DfDS317lvt7OM5Oyl65nlzeBPCnJ7h9RnN5ATFNOqmUqnMVAeRHmwgsXlZTx7%2FhwDlQrS2WywDyDbJSX%2BNIT6tnif2aVuwuxk9ue4jvD1qs31Q4plZG06rDH3wTVVwgr3Q%2F9gsvZ0U%2Bykw%2BeZ%2F3ua4su9h3oCfMbBBA%2FJsbvPdrorS53V1WpnYtu13lUNHGGyanWpKvbDf9oqWNdMu%2BO5XYfHsHB4ptfDXXZ%2FdI1KQNvLluvu%2BGs0pPTv7uzg%2BfM5XLt6Fbdu3kI2l8fHv%2FkYH3%2F0MUZGRmW9UjRSjoNcYy5rFH1pOclmHWUbQb9N3wwZjZxRXvpjYZ3zXlg%2FmRPQ4bnnV7S7oIUI3ZBoNLHLTYhm%2F4zn%2FXDiJPNKXPXTzis1oMq21zQnRpP05kk2NZGqZ1ADaycXdr27u4cnT59oIrZSqSjIEN%2FFZIrTteYRFOXNvoORL6A%2BCSYlPftaghKtEXlxwsfLcRwt1%2F7d9I9ktMSRzzu67O%2Bljv6iC1HfdnQf6M532Zex6taQ0W3vR%2FAWSTgdDPEd6kxy39BOtny56PsXtC0anYRcy45RC57INJbjTevQF3jZSybUjYLXfX9bnfzaYBkpFzn1Zb28%2FLWOHF%2FEMyuYHqeqGncig496YUQPYpvpjOzthexE0dbcQRdRdn09fw866xyU3lkueh3K0qfyzkRb9ek2JEdBOWV7kF4U0vVS8UdHzzN7SKf8N8HrZAe1F3IZn%2F0aJPAWgc3o7fAvln8Z%2FHX7jCxzW03nqqOByKJNBi8mq4mEKat62RxJgk2OqQ0kUW3WsbVXxYu1DW14XSiWUGs2keULLjBpilmCaw4TCQULImm9ZNzawxrRAOg5jfYmPPcjsn10PHu%2Bl2E5oxIOrD4nSj08p4sq%2B8Z%2Be5q%2Bhh3ZQli%2BPa%2FXVfd6nl9SFFUFoeD6Vl4L9hofvqBugxsSpaikJcdsPo9jJ0%2FIxW9xaRHLL16gXKkgk88hn88FjDmjaEcP2j8uQeGf%2BcRLtdfH%2BKgsUWwR0bVVZzrbtPsdZtl3IjqryZL%2B%2BiBqkXZ8R0KS7WeOhP8OeYo8Rs89GX9sJ%2FJyV2rDNxKQ6Ezgs9%2BZFhQOTkQruDJBSnYdilzw3fX9s3mUoGbYEs%2FaW%2FZ5fH8ph2A8crWZpvvXRUi%2BbtBQ5KTRbGFjYxNPnz7BTz%2F%2BiPv376FQLOKjDz%2FC%2Bx%2B8j5HRMVmuWI6gMpE0l0das8gJ27SV4NYK%2BygWfGcjbVGU9sbyXzeuuHKeR%2B9LERWdP7cyvmSUcG%2FFlSW9vDprdxGXCPtyB%2BW3t%2F56rnybr0qNdN4835wgbaFZq%2Bt7xueB3zXFH2AHIp3hqX6tFtY2NvDFl1%2Fh2bM5nD9%2FHufOncXk5JTWgpJE51%2BzYbXpwstnX9Z4twULlfpUKqkARl7BV333SeR33CuxFAifVXvyyOr%2Fz957NUl2JPl%2BnqqyVFfrBtDAYIDZHWBnxeXsXsFrpN1PwBd%2BQX4KvtBsaUbeh%2FvAu0vjzo7CYHYkVOuu7pKpab%2B%2Fu5%2BMzMos0QolTgLV55w4ER4e7h4uQh2nkDu1r0YtSs2XTPnPNoMP9%2FM%2FcAEFnWQdGbiAD2QAbsIgL7%2FsUvms5GJQx98nVlGorJiBwiwcANUvEjBpyqMblVT2bNRMa33GcnHrWAFR1B9Eoq6qquBREkfp1UuH6npFaJzpH1GA6qNeb0hgWqZ5c32gH8sGP%2BT7YeVc%2F2Yr0l%2BAPqlLFiGVumoE4Qr%2FaVHeMi3rIc1pPrW0M%2FkiI6QqWVnm4b4gpV5RbD4%2F9HW6Fx2PPgbi2RDKBSnnYQJY%2Bjp5Gdq9wkVL3oPusfzdYZRM4KsME8O%2BMNMqG0PfaEla5qxgBbm%2BuSIUuEDBJsqt7MZwSKpIrPLON%2BvU0bPGkxyrD2cqFHrZRVwRMqofXVH7N9nB4h13OGlYfzS2w%2BHQDgcj3Q%2FY0zlGqYW60vfs%2FERV75LuSKLwWBoqw8O3O4Ut%2F3pdZacnhdkJtMb04KGUxEK5M3uqEwUZhSa9aI3w4TkUrKZy3TAtggl0jNZRw5X1JqbT59k797KzRcmhREksC%2FhwAopCZ%2BWvNCa4usGTA6uAfWKNdtOu37ypYNPaTZ2eeDjo22A4sk5WFFIAD%2BVzZHoFexbbd%2F1UcEaETLokHqC5KI338%2BlZRqJTPbjhKfMKZkiY4Oi%2BMKsKIrKv6Fs9blqW0CxJmnI2IyuBhyQuvpnq7zNScfkhG3CSHnktmnHsbYVD5MpnoE7v%2FSXP8zjS2sT%2F2IoWlgXb2VqSmqS6Mwb82E9cZU1n5iiOwmGO3kmTqvgMot5H5GUkOlnAGoZDtLu%2Fb19987X9%2FF9%2Fbr%2F%2F3e%2F03cSf%2FvTv7Sd%2F%2FdceaLZaWqIurGK5JFVovzScYa962VLpSu%2BrWVXSkBbhXGd66hvgla1VW7Kd8vKidVmQx7z3wt5qOT0lfE8GR4pksYAWL8%2FP5dzgFYhIJ0DnabcUsegn7NHkADb2bQ6wP4OhBvsYcE3WTPWLp3Ca7UGvp49UP3z8yJ6%2F2LYXL19K1j754Q999QmfsiJ76IXRcCR4Tb6nPB7rVGT2FWPLmA3VoUVtgke3u4mzO7BjObIgjf1gZp7tFsAnSM3Dj4DNfQag3kiXC9cJ08AKWeY%2FyZICQ3yEsIXINrY1KUBFBe0oA37gThlej0buQah%2B6e%2BGjTmUScGEw626ggjjePFvysvUxQmvPxgALjqwKZ41OBABeMKUfc8DCrWB2wNggNMnobnqkaGkuyfMot1q17Rv0zZ4nfSFCJRjIEJ9kZVdHHARDQA9zrBgi1G2i1ca4BK%2B0MvfiP6c9B%2F4qEDUX%2FEh6Jh1co3iuqpN8Ax9xCBaTC60263qPgc%2B5Ish3%2BQGCAc8tkJegq7CTBUoVJKOQ9aojOXhnJBfZPUBhpABx8sNug47BL7476vdUlZoG78SV5KUrllgH4ihbfyS98mDKm%2Fyasw3c8fiB2KlT%2B4FnhVOoefHyquslY8JXPiaebW6bJJ8TVzH0hP0L%2BgGj5vsByagjbzcq18ORwb9tfebLw0AP4hW0k6Nq%2F%2B5MhS4QMGmut1SxtDJxhrBiU7j6lWzN1pip4ku9iYECHUSd7RGdDNOocXZIgOwGg0bSkFzbdqk2bFJa4UjFGwwblh%2F3LCuNYzwkRqlOKRcsL9hpDSyxExnQ8t3mw0POunMqXDUIemMaBDqJS%2FGS318VBkzFII6eOwNJR%2B4DAlyQ0EpqEXZt3zPDDTR0l4ZUPagupLJunmP8nZF40oF6oCfWiCauuJDgWHUyx9w5HAGUTWyK6d%2BakAE3auQQZYjinLG8FR5w7nQDlcfjQMbsLBW09a3rtkHzY%2Bs1%2BvZ2tqqWbtl4pmMho%2BmcbATOMqQhMFxY%2Bb0JB0e0TYUppqtxoCct12GLBwIXnl5Z414oiXAPJPfg3%2FdVoEMsOZ%2FQVeMSRgPV%2B5eq%2BCK2l6O3KRlfeUAgUMPfGVx3Jkgb8UfXldZnHdqh8AHXDKEA5R7tJAdOQ1Vu9wgU1bwCnowQ4GBoR0VrgwkIPcyQBgXxxYbKGpVpzx70KfR5nDSsgJg8VOdQYes2x0aD%2BjIAx%2F9HX02jHLwJ4248nnt0Se9%2FaokAevB643qhTowyCL6K89UjvQicKcM9YsHaBs5Ti4b9GHeiSVJj%2BBbOsOU41W23XHzf%2BXDqW1OS3eu%2FUAy73ciluTq5e6%2B%2Fdvv%2F2C%2F%2BPkv7M9%2F%2FpNdu37T%2FuHf%2FwedOnvjxg1rdtpSMeg4yVjoGeoVf2CzzjzzZbBgMKW5u9zwO0Sr0kt6oyCSElIolewGg6r%2BBQJe2ywfpWvCI2SwLR1up4nLC7CgE3I%2BCVlyrjutEi%2BnVPbo6Tvu1E5P0r%2FO9dk8xWunk%2FiTUKctmskXejXTSrjcl%2FXmfeJbliFtPj2fufJL2Pm8NC2cV%2BQYPnKIDw5gp%2BOfuCnLKzgYt23c71t%2FMIhVOxMdggfN6Y%2FwXvyPggMCvXbLPvmLH9l%2Br6dZ9F99%2BYVt7760F7sv7bMff2Y3bt6Qw4nIE7AMOIRIy2y8X2gp94R6cOLNRv2BHfYHstnS1ayCiWBEeioc9OF4ZKPhsAo2M1ghD%2B3rdFYUGChYlG309lOG%2Fgg9kK1Ou1N9f5R6ZPMZTO73dLiW%2BkYEJCsrnrfT8QFjmkFwzhkOtI28g8FQ9a%2BvrytwFt0mftCg6Nof2Gg09JN%2FGw3rrnSt213RlhH0DL8Bn6SBB5FXONhEdo9voboNRhc1rN8fyibq4ELNEI%2FV7tXumnVXu6K9gOrMiZ6x7JnPHqFHkKOVTkdLn1e6K%2BIteaENdpY%2F2QSC%2BtHIVldXbW1tPeQAhdW08XBkBwf71jvsKY9sa6Npm9euGTSgTdSDrgLXg8ND6w%2F6QVtw7dj62pqtrdMuD07he6936LgO%2BgrgoSMDEevra8JD%2FJ4QwI5tf3%2FfDg8OPciJsx663a5tbm7IzruNMskL%2BQ4ODmwoHrBUvCk8na4tDXJA736%2Fr3ZBV%2BjBHzK6ubkpfOWz4RuNxoK3t7dnvX4fJS5yM3BzbWtLbSJAbTRa1hsMbG931%2Fb294ULOcFtbXXNrl27Zm194xgfxsT7lzs7ahs4AJc2cUr0xvqGrXQ7laI47PXs5c5L4YscQivaA65cVX98U3d%2F70DnjlBGbWq39NmrzY0N666uih4g0OsNbHdvV1vGyAu9adr161v6Bi99jGFAtjsdHO4b7YeuktnxSO1iWf3WtS0dpglRoKu0V8i5CFX%2Fc6UocMGCzZI3KOepyXQnZmqMZdMwuGRBMY1GUgiHh4feKYYokYkO%2F0H1Tpo%2Bs0mfwGhNGk3rD0ZaEouypPM%2Fe7lnL3b3be35S1tbf2ybO2v6EPr66qobjRjFbIwn1u%2F1bGd3x6iP0SSUwOrqipQbRkadL5bcHu7tSQm4MfTRMJaJotxRFvwIowa9kRT27u6eDYe4Wu4EoFRQWmlcGb8cSmHuSRGghKABCnvz2qYUjJwHgmtmbA8PlG%2BKa1PLVDc2NqTcwR36AgfljnJBIaOwpDDX1tSulZVujAaPrdcfSbmSfzQY6hTN7sqKrW9sGPTC0EjvTFBYPdtFucoQ%2BGcbmu2WbWxeM5Ystzsd27pxQ%2FVjBNnDORj2pbShzVp3VbM4wMUQCNfBQApwf%2F9AzgP8T0WMIsR48gxhgLmzs6P8%2FT4GBsesI4OF0sZ4iAZjaHVoL1%2B%2BDL6608J7FOv6xrp14Bd8HY1EK%2FIOoJWcAZPTcOP6DVtdA1cCAE4N7Svv7u6u6MoIOaitr2%2FYzZs3bLW7qpF%2FeNg%2FPLQdjMv%2Bvg6BobwM4bVrdvPGDZ0wipFPQ%2FzyxQu1i2d%2ByADGjT%2F2xSJX8Gf7xUt7vr1twyHtdwcfGeQD7%2FAsDexg0LcXL15oFoOZCmQABwg63di6LjmkXTg0MoQvXspwDbW3eaz6t7a27PrWdfUdOqjTak8wMVo4pMgVBnbr%2Bpa%2BuapIiBmNwUjwXmy%2FkNwq6Go2bHVtzW7cuC48dAjCxJ2mly93bG9vV7LjBtadBnBABqiHdOqlXSxDhQboAQY2yHdtc1PGGPrRB8gLX5Ft9S0zwbp546Zd27omJ46gG77vvHwp2cYhy%2F6CI3br1k1bX1uXgccM46zsqP4dySMDE9CRPkiwCK4KqhsNO9jr2bPnzyrHBZl89OiR%2Ff73v7cnT57a1tYN%2B%2Ft%2F%2BPf2V3%2F9Nzq9%2BetvH6jPZh%2Bgfpwhlti6M9RUO3AwXuy8kI6Bf8jbpnC9VTkuCCZOG7Ta3d2RvEIr4Fy7tqXvNCI3cp4nEzvYP7AX29viAY4uq1MIBuSMbOFkdZQXPYT8P3%2F2TLLNMz94QPuRL%2FokG6mGg4H6K%2FJK3%2BWHfEKr7Ns6RTwcx%2BQBjhv9pewDK92ueABvvG%2B7vMjJwyHvdtVXUg%2B0sQ3jie3t7dvOS%2BcVZdG9OO%2FIIbxCD4ADrUBO0C%2FSmRPfD4kuRG%2Fj6BPsoV9o1%2F7envQggQsMAFfy4ZSDi3SLAre%2B8JUDH7p4pbNi6Jbs27QVONT9%2FPkz8fjO7Vt29%2FZt6674Z0%2FQgAoKJhPr0bd3dm3%2F8FD9l04Abhtra6IrQQT4kH44GNg2OrvXs62b1%2B36i1v2pz%2F9yX7x61%2FZ0%2B1te7r93D7%2F%2FHMtq0WOtp9v2%2Fb2C9le%2BhyBHnSCZxsbKxrpINBCX2NrORuBQ4farZaCl1s3b8rG0Few7f3hyPYO9kRbBYejgfrL1rVrCnKvbQauNpF9ef78ufosPHCd2bIb16%2Fb7du3Xb83PQB%2BubtrT58%2BlSySl7bSX27cvCn9utnygA91iq54%2BPCh7e%2FtV0EstL97955tbVG%2Fz%2BjAg2fPnhs4yCkfDNRfkOvbt27JJkNXeHHY69vTJ09t%2B4XLNrhiC%2B7cuW13794VzdIn2D84NLaXSA7xMyYEpWt2584du3XrloIz6bfJ2F7u7Opkd%2Fo49MLHQbfeuX270i%2F0I3QE7X%2Fy9IlhCwkgkU32et%2B9gw%2FDp5LcJwEOp8U%2Ff%2FbcsAuia7utb%2FcSoPC9VoJ4dD%2F1PnnyxG1nr6e8BE737t1VoEX%2FxZ8ZjQbSLegx9AG6mHfIHu1HJxL4gxN99Am4Pn7suEZ%2Fga%2FILfpVJh792uvbw0ePdNggeGPj0FN37ty1O62m6EY%2FwPbv7%2B%2FZdw8eSG%2FLvjQatrG%2BLr%2BCAZvVJra7aYPBWD7egwcP1cdSvyMD9H2CuIl0gPsY4Apt0TP88BvgE%2Fxcb059PewmhyLybWR8PfQ%2BsJCrxt2GtTvXZLfoC%2FsH%2B%2Fbo8SPbDtlCD6ED3nvvnvKwYqDdbImv%2BKPfPXwgeUG2s%2F579%2B7ZDWZ4u2wMa2iwg76KTcHX0EBPo2EfDD%2BQfuMTdOgmpgWQZ%2Fj67Plz2QVwxV%2BBP%2Fik7g%2F5djYfSZsbmRMl6n%2BuAgUuYLCJSuaX13h0SdaDxlBi1g1HiG7RHwzVcenEKGc6G0s7mO1jdhDTrrX5jKTi1DSacRw81rilTv3s6TM5A61mR59GWV3p2Ob6mr13947dvXPbWqxNZ4R0jEO8b99%2B9yCM%2FEAjnjhC7927Zyu3u9YkKIklKtsvXtg333yjjouyx%2FBgBN9%2F7z3bun69cohRUiisB989soPDvmiAwkQJv3cP54VO7s7z3v6hPXz4yB49fOgOWaOh4OnD%2Bx%2Fq23oEGnJwhn3DIcdoYgxR4Cg%2FTn394IMPdLgIThS4HhweSKk8ePBAyhVcUVgYrPfff1%2FOEMrNR3379vjJE9VPYISDhtNOm6DBNQxRs6mRXILX7x48dAOHQ9gwOaEf%2FeBj1Y9Dqh8BXBx%2B8uLFtpQio5O3b94S93FMuk0%2FTZF2oNgfPX5cGYKkKzjLEJJXhqgnQ4TSxDHEaOKI37t7V0aDchgPBgMYmfz2u%2B9se3tbAwpYM4zL%2FQ%2FuGwEy%2BTBaOE4sK%2Fv6668VcOBIYjRv3rypPO2VjpxnyWZ%2FILo%2BxGjt7hhBHMYSpwGHjPZ3oOsYB2vfHj16LAWPoke6yfPee%2B8pINpst7S0jdFbjDW4IvOMloMXo6Mf3r8vo4EMwquDwdCebr%2Bwr776WkEJRhNccYY%2BbLSs3V21btPlFbl78vSZffPNdxqBJi%2F0vHf3nnXaXWt3Voy9y8QKe3sH9uDRI9EWA0rAy4jz%2Ffv3bWWFQI8lTBg3gt0d7f0iiGKEFKeCkdSPPvrIut0166z4GgIGGZ4%2FB9evtH8aGWRU%2BNZt6NpUu9ptn4XEEcdpQl6RMXDFGYNW8Am6tiMwh684GOSFrvQN%2BusH77%2Bve9pEv8ABxhmmvyLf6BHoev3GDXxqW4kZBSSLQIiA6Ltvv5UzQFCP3OE4apYJPaOlWS3lBd6Db7%2BNvjUWX3EEoC%2BBN4MKHry8sG%2B%2B%2Fc4ePXooGQdngj%2Fo%2Bf5772sp448%2F%2B9zWNzfsyeMn9sc%2FfyV5AR%2FacPfOHfvg%2Fod2p9Wx9TYDKU3rD8f2bPuF%2FfnrP1eDDjhU8LVNQLayQkQnPUAw8ujJY%2BkMBonkuK2tqQ9wGBHOCH2bfkTff%2FDgOzml6A%2FklcDtww8%2FFC02WIXBd3VHYzmiLAN%2B8Xy7CkroL41my0feQ16R5afPntnv%2F%2FhH29ndDSewbXfv3bMfNBt2vdEQzehbe4cH9u3jR8bJvPRtZAAnFH31QbNh13CK2x3x9QX95QF0faS80IWgAT3IYOQmstJu22Q4tpcvdu2771wPomuQF4KSm7duSW7EL80AmD19tl3JIH0AB0yDMzdv2LXNDfEWJxH64DjTXxmcAH%2Fk9fr1G3bz1k2VkUYrpHQAACAASURBVM5klmRvT3wikPdBj7FmPX7w0cianRVbXcUWuR7a2duzR0%2BeVHoQuUanYxtRgNAeuWaQiz7D3nh0B32NfAyMMDPeXV%2BTjoOvBKYvd3fsxcsXmrXZuLZp79%2F%2FQHXsHx7YL3%2F9a%2B3p%2FMu%2F%2BEsNLO3s7NnTJ080q0VQrADOGuIr9KOt%2FBjkwMEl2GCwBj3EbBh2TjNgBOZN2tVX0ERQhs4kjwZxG2ZrBLAA04zMxA77Pdt%2B%2BVK0lQxOTDQHNoMuBPFa1cSsHoM%2Bu7vGIB32FhriF2AP0DXyJ1itkQPKERgTlPHDBhHMjIYMPHbUKmQOWPgd8IpBF2wKdCAoZqXIpOVOODaGPO6j9Az7wpLVXm9TtplyWsoJXsOh9Q56kgUOBSMvuoh0ggbu%2BUPHo1PRawy89fo9%2BSMMfg9HHlDSL%2FnBB8f1ZTWQo2BofV0B5WqX9Vy%2BQoSBNmYhmd0kKATEsN22ATPDw6F0HFthyM%2BMrmYsDw7ssOfBVqfVisFNXwaavhO8ZAA84dJm6h2PWGvmA7FUBl0HvZ7RdnQCvFJdzDRrgN%2FbBNMmk5H1eg4TeXNeNQWTew9KffAYO0sb0O3IOjZqNFoRTF%2BdlFsLnA7UBf%2FHY%2BplAJ9BWLZDOVxfqTERH315qetG4DrFkR1wZZUWKpalvj7zykz6eMz%2B6Vi1NfEBXm%2Bpli%2B47xOrFqABcMEbOOCrlSAOWJ%2F2A4fJuKWVC8gHuGcb8HslN1rW3hbdoY%2BCbjAEHsvFtYoI2XS7iJ5AjxBsIi%2FAEN1jFQGP8tgz%2BhcH6n%2BuEgUuWLA5H2AuZpU62rT7ykBQUvLPkiLt90A5RBdXx0xz5x3Y3%2FhSB0Z2MCJ0eEbqXKl55wEunTvfqx6W1zJ6yyicRixRNN6JUah0RPKjLDFePJOPgITyCcud8Wl9qCPqR%2FmOWMo4Bm7LWg3fd4DxlBJiNBQ4zbZ1Y5QJSmHcwIM8%2FMePtlAOh5aghXsccfIykwB8LTFiMbAMX9PzdruiI3hrdiL2PpAXg5BtBNdxzOTiZKl%2B4eC8QxHTzqr%2BXE7SalezhDIZ8oyc1hhx2sWVAENLkSLIk5KLmQ7qZgZhuLqmylj%2BwTM44Czwn0b%2BWi1bY%2BkNM3jaa%2BIB3FrOUATvKEd7GbljpBNYSIHuuyvit%2BSD%2BptNW11xmHzyBQcAR1EzFNBVS35dhkgnL8G4DNtwJB5sxMy2YOKLWEOKnNkTZqhx6pF1cMJhoi3kEr3gVbstZ45RYYJP6mG2nCVWyDQGxDsHo9BdW9%2FYVKAIAAINZjThrTtYPsINfVimdX1ry4ajddVPEITziOxA15yVSieFQGydJUkx8r6%2Bul61H8ao%2FaurckppK7gia8DEgQQfDDg0Vd6YyaY%2BrDOnQkMP5ABkMYjkgy449cwewKMcHOEeWVQPiJkDyjIrgpPEKD11Uj9%2FwJKRBS4rFLo%2BMweO5AcO%2BZAhuQQ4pegMggpmBm%2FetJV2RzLAIAKz4PQt2sQgV6PtfRAYBFfMHuAAkIeZH34KaGLvC%2FggR1yfPn2mIJ3%2B88knH9lf%2FdVP7LPPPlOAgCwQ3DJoAC44cdCXGUjNUPDppth3zmwFcgWvWp22dBP1MlNLP4Ig8A8edLortrnltAJn9BD1I2e0D72GDKBp4AGyAl9wMpFX9AzOO%2FgTfDXGvseOdHClX7vDbGo%2FsGkLcJFb9AW4MiuwuuEyCC8YSGEAhc9YsdRServTUfrN27e1UgJnCHjr5EUHM%2BCHHqbPrnSUfmM01JWgRnxlSV4s3WfVCjoLGLQLHY9TChz6IOngAv5TfKMvEahqjyT9siu6gqM0UehsVocQAG1s%2BN59%2BEZe8MOhpl%2BKD8ywrK3aeLylPk4fXVtdV6DFt4ilA6AaszbI4O3bum5ubYkuvEeWuRL8MIvFT6sJmJ3vYmNG1mUlBLPgoUNJoxB9nhkU7ukvow%2Fu60pAQ6DKwCwHBzGrykDc1rVYVoe9aLkeRr8QcMg5Z6nkSts21lbt9s0bttJuyb5ASwLu1W5Hg7l833rSnNi425G%2BhHYbG%2Bsa3EO%2FMzjryzJzn5gvwUS3oiugIX0ZuhIgI9vU4eaFFRKr6jsEt%2FCVH%2FWjX8RbyaFv3SAAusPM5PqG85CBDHSG7EZLugB9AM7YlvGd29bveb%2BBj%2FQXBoix9%2BgQ4cUgGzP%2BLV9tAG78GHhbZYAWXOm0jaZ0I6tZ6GP9vgem2Cz0CzPXntcDovW1VWNWe319VQEmupNlqeCu2ScFOhMFI9Q%2FHt2TP4K84jihG912uufgctzU7DDfHVefD4dqUyt8fNAVCQMPdONtZqfXVqXLsBPM6jPYggxIb098Ty8z6Xfu3LKtzQ3pB9nSmN1nZQF8BC2C8K2tTddN6Iaw%2B7JxQStJuFb%2FtOwmhwvSB8P2c89gErRK%2BpMf%2Fc4A%2Bta1Tek26A%2Bv3W44X2k%2Fthr9zuAhcKAB6egx2gmuxJPAhEbwkFlZAn%2F0ELqYvOIVfRUd0DTrdlaEK7xkTzMwkVdkCzwUo%2FomIz1DV%2BiIzqE%2FY8u03JZBcsmV6234zaQIK4Dox%2Bhf%2BjVwCUAVFMdg2HWW9jZdBqmfZfgMFIOHgtMJ2t31BTIIXthCdBPp9LcOA9%2FIlWysD35JmOt%2FriQFGhMk4UL9QBdxnv6yCT4%2BxEiej3qREwWAssQoMWLHDMABa%2FzlYDDCZDac%2BH5GRmvIy0g6XYalOloy0mjIgDI6zvICZgbuv%2F%2B%2Bra92bX0FZ2pTnZ3OSd0AZRbh5U4sYcR5Zqnf6qpmwTCOcnQYUR4OtHSIkWocShxtDAHKghkzjD8%2FlBNKimUTrL0fDBjhciWEQ42ByeUNjFBTP8tBMP60FZxQFOTd3Lwm5QJc6mcUkRlDDBazapBXBpZ1%2Fyyb0SwFuDKzt6dlQ%2BAqhRkKC6eY9mUQgwOjpbGxR0EOGo7fxoYML4YbzQh%2FcHRoPyPi0A%2FawNPV9XXjRFp3CnG2%2BhrtZtRxNPalwRgyjCBGU4Y7DiYAV0aIfdSfUxZ9lBd64jjg8PBDybLMCQeJEV%2BUMMYIHuC0MAsiZ1vWaKKRb18a60vyYDdtkVOqPTW%2B94QRepwVZnYYRMChok3k3dwgUGRm10cgccw1mtvrSQYUrDVckUMvOTnhdACLpWbwl9FiYMpora2Kt5qxRsWzhLDXF10HMUILX%2BVkrK3LWZej2%2FDgAP7vMvunAxQwDL40EppCX%2BqA1sgS8sL%2BH%2F%2B5%2BiAwwuBgwKmDVHhAgMFsQfZJ0bW7KlnB4coggrzIH7xwY4YxbylfLptCDgFM25mhoAz9CisJXOTPeeWDPeJBz%2FehQSsMN%2FkJYHEmwZkfDh15gQvP5IyEMwE8%2Bg3wkUN%2B9BFo6rLie3rADdnC8eNeuOLI9weaAVe7QhcBTzSNgR%2FhzHLuw0MtRaJdGgiJVQr0Nei5sbmhgIF8zIJ%2B8Zsv7Oc%2F%2F4Vmdj755FP7yU9%2BYj%2F84Sd2%2B%2FYt0QL9wIwyjgI0Bd%2FUGQQ1zB4jAz5IwVJe6LovHUT9yCH8xEmh%2FflHv0e2oJVgatk3s4nsQetKrnHJkBdgaJYA3Rb77HyAyGdAoT0yC2xoir5S%2B7XXMB0i8roMgi88ZJsCs3DMOoEPcgkd6Ss4p7QNmAgMS%2BjIn84g5QloyZ%2B8Ig2%2BYiPoi8gAuMEr9Cr6gv7KIFFL%2B9WGNugNFKjBYw2QADdWQaQMAReaE%2FzSJ4EpmQOWaOqyIv4gV9ry4PIMbvBd74SPD8ykbKHnRSsNArREIw2QaSWKBFt6n8FV9Dx9G33HtoOuDnGRK65lpnzHGHunvDjzUdxl1fcWUq%2FsGw2IVTnoAWZxEifwgYcsLfzii19rRhda37v3nv34L3%2BsGWWcaehJ%2F0d%2BKEPfwsmHfrQ3ZR64kAxaaVBTttllE1zhfeoW9JtkgEHV6KvQmzqQVWgLX9IBpq%2B6vBLsuB6ARurbY59Bkn5lZn1lpZIt6WcdhoLO8n191I38gC8w6TfIKqud4BPLYxUMhG8CCZEr4CL%2F0BM5AVf1qQhcnNQ%2BQMIKDvK5HPnsGH0b%2BlEGusEv%2BgCwaTuBqeRvNFT70XPkQwo1GKn6sQHA9QFFYEID%2Bgu0JZ2l79m3xBBmK4fD6KsOD7zAxQddCHYJ%2BF2GNcDPtgvNokUbGBCMvkU7xcei%2Fd52%2BMXiMt9vnHzN%2FoWfAd3V1qANPAAH0tTbpIdGGmigTeglcOU%2FbIDLHE%2BqseKBTD56qFj6roGB6MPeXt%2Fj6%2F3FZ%2FPAFRnnx2APcNBPOQDlNHUfFRpBA%2BXFxjKYEhMiwrHit%2BsL%2BEsZ%2Bhy%2BB%2B3BtvFTi8IfIB8Df0oP3iKH5Pe8KhCD7a4rKe88d33KfVIFvjLQnHtL4QP0JQ%2FygvwJbhwSpH6o1XM%2BMCUzLR%2FM6SG%2BqET9z1WhwAUMNmdZ40pDtkIvUHtlJ1WgFVP%2BdAyMGCPfGm%2BKJSbq%2FJRGV%2FCPnE9GfFnOyFLDiT1%2Ftm1%2F%2FvOftcTpgw%2FeN07c22QfTathKxhCDkdBCaEBNPqJ4SYgCiUupy5O6Iq86sw4InFoQHZerlIWYTBDC6pdGAuUhvDHAdGsa1v5cWy8vlBCWtahKTEZEzlLzISy3BOFFYclpKES%2BjHqR%2F38oa4zH3jIWERArYtNHSNmbaGg0xPDyUifTx%2BjXFDUGALN2MoQ%2BggxpIdPGCRoD34yTjHrwGg0S%2FcwgBph3Fjz0UhHwGdb4gQ88KVOr9uNGvKQP5wtFKVw1N7ACPgKJYwzAQ8YKefqzQ1TBE7ia7CaEdaASdv4ueH2vTYy4OG4w2%2FqznwppzKJklE3uO4QBF1jJt3FUgLqBgEzgDHAeeLgFPiKvJAFuQAR4e6zTNQFjcWH2E%2FGe4rTMuEi4%2BJGCCNDXsHV%2BVU5409%2B3qkG4SIex%2F7hNOTAhnb8ZMRidpJ6wBNZyPZzJa94lwYPXLUkaBq4eZPcQXa6UkfIpFqRdU6d%2BixD2wkKQNuDkTDEMDdwdRyCFoWRVyOCRtzTd6gXs%2BnOnOOa5ckjLaD%2BEH1SiWm6geGBu2RCvPPZ9nTgwJPgmOXtf%2FzjH7V0l%2BWcH3%2FyQxn2P%2F7hD%2FaLX%2F5SM5v3739gf%2FN3f2effPJDDTqhs5Ax8KF5eY9cUh9cQW%2B4rnD5Ud%2FluHrNGtBvkGOcOHf0hfnE6at2xumYwHT94ftseeeFvb9Aa%2BjFT7orHBilRd6Ep0yik%2BsDr9%2BXaglpBykeel4%2FzEh6NAO5qB6Y0BidNz0VzmVFNEj5FEyXAe8DtNQrEl6ZTxrX987Dd8l%2FyAiyKByqBngfBB54Q1vpZsm4y4ZoHzC9yeGAB2%2BgG%2BXAhQBIjmIEA962mLkD1Tg4ib5KPfAX%2FUYzIDEZRGoSoFPMCkEffuhabJ3rbbILoLcSPleyFDonZkXBL%2BWl1GnIA4Nsf%2F7zV%2FbLX%2F1Ke4kJ9j799FP7%2FLPPtdTbV3FwLoIPSjIohW5nZpu977QCmOhgaKvBTdEmaC80GRh2%2FSA8pDNikIP2M6tW4a6m6h%2F4AkzaDy3V7pi1F0VSHxXvEg4AWEYYZJUOc33gA1ZJc5cg7%2BfcyxmPvpiYwKvkgdiFPKVuDd5IzwWetJx2Ig%2FQHn7nT62VDYs2FwOZVR7JIjRzveBsdn1a9WEFiNGJNCfn%2FgsyNMU1W%2BcySx%2FLd8DJfiP5FxeglssashV3ni9wkR4Vzxxb8hC0BRmkUnijPurEymYFnLS9PrsIDll%2F4gafSWeQg3cccJN5BCxxCzzwFeCn9IVsofd8D%2FScBpTHtiAf2LREmDoJwvip7wfuPPMuZYLyyE%2FqOtqcP8mc6Oft9rLuY0Fn8BJf4jRmaCY5SPmNOtMPc5lBbpwDycXkCPDke0S%2FiWlZoaO6KBCi4TCyRlf58ArSkZf3DMxptlZ0dblTX5lKQza1vl4BClywZbQnc0QCrx7hEp1GQgoQpchsCpniTw5YdM7sfFzZz8khPOxVoWMfdtu22mlat920tZWObazyt2IdltDSyViWQL3ApZNjKJu%2B1y8NhikYcQWdypv19K2G793CeKB8HDVXngoopELCQcRJ12FkrkxRIKnMVHHUzz5TvmgpXFCIMepK%2B1P5omxZRydjAa5pXAmKIiCl%2FIgTRsnLct%2BYMUBdokyhFTSuFCgjwiyhY2N6zBzQJo2qayYlnAVwin0EpLCJXaOGjOaH86SAczzWQUPsPYQPzCjfuLZpq4wc4rjiJGBAWErsLqD24fJBZhyRNDo5ok09ojOKtRHBGrO%2BMt7u3LGYhzZpSS24x8wJjYVW3ZgRU1A5ngbRSWvVFTNjwEC3D9lrEctgEyfoJKcwlhpRJ78hGpuZRQ4QcqDay5HeowI1RpYxUo1Q7BG8CUAYGXjCzHyrFc6VAg3SfFTS87rUI0c6ElI%2BaqSFk%2BoWNwyZMHInHr7pcC3OZI7AEJhumCKAlGHl1OaJjWVU2YtCAOEOj2hIV626jstHOnDqt96l3GGLepK3YNUYp%2FPkBg3iIRf8vPy0T0KTdPIklzh4GG2lIxsZzDpSWZ68OBWCC6k0c8fOGrHK%2BxQwwsmRgedtpCUcp%2FkUr1H2V%2FCVzPjyW2SdJYi%2F%2FNUv7b%2F%2B3%2F9VM0Q%2F%2Fuwz%2B0%2F%2F%2BX%2FUINBvfvMb7Sv74cc%2FtL%2F9d39nH3%2F8sZa8asCBpodjSXscJ1FFGoFnZDJxdU%2FOA2YORqONIp%2BYoiaoZ9FWZBbwPmiSfVmUjiXoNGM6I0KtDflg0N2X1gGfuvnpdFzoOvS0xFe4KXiKwQZwavjgFDIjPqbjQ2MVdICPB1rRhXhQPaoNXtC3JdceBAtmLMtLfLzT8eTwCM7AB5RVb%2FBcRAYaDXybv8IBPW016MSjP%2B9kvCnfok8kN%2FAjCs1flQzMOVxyO0BVF4N0bAtgX%2BiPOlo%2BeX1z03772y%2Ftyy9%2Bbc%2BfPNEMPPJKYMmJpg8ffGu%2F%2F8MfjFnZzz%2F%2FTLPzLGdFjrT3TjaGk66nOiXlR%2B1ArzHTQz9G8aO7QQg55xq6IHEkoEP%2FJAzX%2BgygIeEu78hhCFMEgNWeG1Epy0ISDr3iD5hQUDoiKsN2OMzAvVm%2Bn3LC4UQh1eg6Gz2gIKbCjjzAwr5x65zkWbOIGpDwNsBMtUNgaTXpnl9tU58Sdgp4FOjSBs%2BoUuTGj9A71RHv4UUMWCnZWz7tI5kt6AkxJVMVLxxyPqKTfTEx7HJdqOWyKamRUXWJztxNf%2FlZvLJ56RepTPT9qv0K%2BpJ8IQvQFCShKe0TePeiUt94jfDQNT%2Fw5LfILrkdSqzAxdsCEVx38C7TuVJeA3KSR55d%2F4rq2UTxQwSOeh0e7ZM%2Bkz6PzNBJbXU2%2BiPt88Dd9Wtg6AwJzpHmehVcRUcRzlXoVI6q1k37VeSHJHA5%2B5bTLG0xg1yuQ7NZCam%2BXg0KXPxg03vuDLeqjlI5Cd4b2G%2BjUUzNCEYaSsfVYKq1eHJt1JBSGVuHUxSb7IOcGB%2FeaLK0AgODspF%2BcsdEjrbrAikYjJ6rLaZgXEG5tvFOTMfTZms5LbnPREUdD5YuKdDDcHgwwgsUTWnUZgjAg5rn2gKcyE%2FxVAQqCwzN0nhwRTHyEiijdGVvpcgIaD2gUPAURkaZop7EDYcAg48hKh0YBcVBF9kK1CR7tnJWYMTJh23RU996k6PBbFRfh6s8%2FO6B9kwwg8weD%2B24c2vrCjtpjsMe9EGR8ze1Hwy7uWOAMWmGYuYimgqG46WyvMDo0CTe0VaIFHIlu9yMdwLCuzDNGBeUd%2BTVp1kY%2FRTOAiHckm6Azby%2BjNuNHIFrZXwl2OTkR9sYxY42ClV3xskP%2FpXRiODZJTQMCY5GjKIrqxpGGepDtpBVt3K6F8wYlU264CBoKawTXyBEJ59xcnRD%2BmWMfSDBpZJ0iONtEa4aB%2FKZrKlsO3Oo0uVxegU%2BgYdkLtoi%2F0t5AxtHwkdZq6DHKQEG0JAa9MuR4phRchpPZciXhDlfvA0%2BejsJvGeMvIJOp6Bg04DARfUFjzDI%2FGiv2hz9iWVLHBTz2y9%2Fa%2F%2F8z%2F%2BkWaI%2F%2FOmP9s233%2BhAMJaV%2FujTT%2B2nP%2F0fNGPEvjz6k7fG%2BQZo9TWJAsE%2BzAlHVW0P8oMA6UqDKy470gXaW%2BQ48h55lXzFckQ5FKGXQjtJnyVfwSEgqjK%2BzUa4Cs8EC52jPqpa3YGBNk4U0x7JkBPqV8scHQ8upL%2BdfoQWomcyNK4uv5A%2F%2BA4rqF%2By7lVGdcGwrIDUab8nNf%2BUHv9EbuVd9s9p8iwr%2By7SE7%2B8zpHwzChQnj2GHAjH8tibN67bL3%2F5Sx2W9Yuf%2F8x2Xjy3Dz%2F6SLbtX%2F7lX%2Byf%2FumftJzx5YttLdv%2BwQ9%2BoAFKDiLKVT4aEJOUBjoupmKKOJtBgnQXnco7gHRh0QJ1udCXYjj5VYa%2B7gOUnod09qjSGmpA%2FpIyVXe2RsMDSqrI99Ax70nPvsgV%2BZdNli1IijuCjmsEOxHEegnPJyxod%2FTtsg7N7irY1LB3JayijcB7%2F9HsaNXHaK%2FrBHV7VTNto7c8gj%2FZ03gnHHzgTrSLZe%2BszGho%2BSRwnWpyPGIQzm2LB2vYNnSAglYnmKiWt9KJDCI4aRSUVXkjrboU%2FJS%2BoW4Z6GmXdjtBCYcIfmDogVTW6mQTXTWLjAzwzW8%2FD8P1p%2BtB6ZMIMgVVYMPHQy%2FFgGrFo6SHqnKaul9GgpCZNkew3GaIazyHvsoBDOCn%2FVBLvEEzCk26OmjhNQiQqpM0Zz0B3%2BEJUceJVRAVVrM3Mb9fYa5xD8FDPr2%2FgJLsGtBC%2F85CqZ%2BuCgUufrC5hFMItpSVDAV9y7uaXz2AUN8MPZoKKDs977AF6Wgzg7nOhnYOK%2BB0UI3EEUz47AUjvMzeeUDpHYvZGTlg4bx6v%2FZAgKC3GsmLjpiKg3yM0qYKoi1obl0diJSMVtQXey2qXh80YSQJBUU84CPQQPSACwWqzfaRlGSUggaQkAinj70NuVQjiMaF%2FSj6KWbAgHgw0mVvifKFoomlsRgXFL5KSY9GwKnZUw5a4R15XMH3%2Bz17%2BvixPXn4SIHbrRs3bGtj07qMxIskjqerNZrmDrvTPOilfD4DOB5h6UcxcKkGii4EC8gK5dxARSBPg6JtHiw6H9QObuV4e9nKkEWwCRz%2BE9wJo58xYokzIArg7Irx%2FhykhGzMCsvR13Lp4Bd0wakPA4ZsIl8u4yzjiz0TjrDaIXkRI%2BESJs%2BNvI2gTSy3VbBahQnOTmbxYj8oAwYydoLjNFVZ%2BCgnJWhV1ANuGiEO4whQynid5Idm7qDJ4MlxcpzIA3kIIhVIio6en4ESd04cBm0iv%2FpBjOhPYKbqc2fHu7%2BYWC2fkgyqPzkPJe6BE%2FDgyzjqFSxBzDY49xxNh%2BuvkV0a6SXoGzhWaZCd%2Ft6v4a2WwEGkCLooJf7EslROjfzq66%2B0hJaTOdknjOP95Mlj%2B%2BSTT%2By%2F%2FJf%2FYj%2F60af2wf0PtFeZ0XHnr%2FNYuNCNcOb0BtSkPBzFvK%2FkLvpL8Ep0i5klTU1GUMceJOGqwDydVJeB7AOiDfmoLvju9DJjfp9VICkQpNO3vC95%2F5WA5MCXKDhdei75iH6lZXEiNysvfFkZpwZHk4Sn7IDyUCXwITRccd3sM5veh6V%2Fy8JVOaiZvE0WK0V1nPTPPMiT8l%2BG97QZHcgyWA5GWV%2F7S7t394795osv9E3O7779xp4%2Fe6rPh%2FzsZz8z%2FtQDJiMdZHPj%2Bpb29hNqwHPJSNh0nG3niAc70nMx4IHM8ZwDJRhx14OzVM2%2B4kIa%2FULOsN%2Bjn9QGYeVlwYN6KSsdV73zMo4%2F%2BE5lI3lPmbIvaBZUL7PsFD%2Fl1SwTnSMGUFzwhS51e%2BDhOtR1nOtI8Aai60G3X9khUv6VR34LfYDcNMx1kd8HLrRDg5JKrVrr7YTOrPTgHf8Ax5dhKvZuuGuJvhbSaqb%2BCTjcJ028X2LLHKD3NeHLSb3SkdO0KaWmd6KZykdzXE0JL%2BdBLned6jnqL%2FmjJgRI57%2BMpBovOxvaPO2esyTbBCRZogpmvnf%2BBC9iPkGyVFU4Hazw6hNm0D3kRHA0KOi8zhUVwjXkIy7iKrC8npRHp3kO2jiiLm2ihWw6dTqtvfbEJSk1pTmwKQ086ONyEHxCw%2BrWrY764FEQU2D13aWnwOULNrNvqKO5dNN56BgEXJrNgq28Uv%2F3zlZ2R73WjJ7rvvGkoQDzFifd6dTKLT3LAMoJixEmOcOMA7lCy46ubhiKkE7nSwTdYEmBBM7Cln9yNssRqWaPKAu2ZOcOfcoBGbrHMFBh%2FAQy65Qj6o7utOEo%2BnS4ZnS8oGOsIZAuWjbnzjsKVdEaTjk5FOA5zlRNWu4lEQwMReA1DuVKEAxqYMvMWLPFHlVNDwl7jQgSbMTeH5xDls9%2B%2FNGH1el1fLJCvyCgaJP3CqBSYQpJ1QWd3FFxSwReGH2RCXwoMjdIodFDWlXSN41EBGxyequyYBW8EC8pCo94CGcaBygNncqRJ2alClnAEUZmJzLqVUY3aTw6AcQDYLthd%2BeKdkSNap%2BEXQIfhI%2B36hsikTsOgISnyTuWebtcudOXDkvWLRSiXbyrfp6heuRGdJb0huGNt8oa%2BHq%2BoJMGHZxSGnzRsuhotwIHr48c4OxClUFstCzyJT20skFykvR0nvsg%2BDRQSfHKdqaDJqjgWtFFsUvFgyRxCNO0TwZpuFR0qJZ4OjzKsmyOgYPnz7fty998aV9%2B%2BWX1SaKxcTjTvpa48309DmKhj7DPRoMkQWRwhl70N1GvoK14tIA3wYq4OLKpa0iEtdCY2UDVlc59EEoyEw46%2BdXn5Vg5nbNKIDPDCl4%2Bm%2BQBP%2F2soh1vpdcYdPE2uBCHI6%2B86FFfGiZ24mSHDLi8qsuKDWXfFZ7RG9XfGcuRw%2BQzEVl2lh4QIFvgb2afjuS%2B8gnQGRng8BNOpZysremESk7N5FRU5Pp3v%2Fud%2Fe73v7cvf%2FMbe%2FL4kXTzF7%2F%2BlX10%2F7798Icf209%2B8lc62VXypjE3ltUGn5HpWL6svi397bNUPCNPkp0TwWbEcAAAIABJREFUGOUzmSkrLndu%2B1wvCJbklfq8D%2BjzG2kTENqiT7uud%2Far6qxf2TyvREnAVNIzx7%2FQLdWT7BP5BMPLkk1qVkFgBileiewmSxUFK%2Bike09h8CvtgMACSK9cf6r%2FqD2u8zO3dL4eHLfM5%2FBk7jywEE%2BCRugCNTS1SLSrsHveL0GQtjkOXLXckj4OaA3qJy%2BUtOSfqEfqxssmXAq4amBQ1gcsBZs6xdPM6ZMQvIOWQNHKnWABfAcONgTCaTl%2B4OkK0vWetztlBf3lNFLbdO%2F%2BIhAEKXwOMqrWqC%2FvvThQfJBFA86a48h2umySjx%2F180YSowkB3elddRe2mpzKK1Cugz1NhHSAVSF%2F5F%2FNY6gOzy06Vq8dpv8LPuk7Jr5VxsU3C%2BqrMp4SRJW%2Fvjk3FLjwwab3ERfrlNGpPPpyPnXhTJQCdB2r%2FKEQkyMJA0XoOgUYDWttrGuvJvu2OGmOk9kwBoDFRdV%2F2pwUCiMBqvNjICKYyGd9k9OVYJFVt1IWuTwxFF%2Fm4R1KPpoxE4imkiOvDIITR8qHdjHLwU8wgh6qC6Ub6VU9OYMhIqB8vaxTznMxwloZnCxYwgmnMPFC6URJpy15i70avMP%2FJlzHjLJ8ipN%2F%2BUgzp%2B0y2s2R%2BMzIamQY3BKvNGzBwKxT9eEgT1zBQ5dpW7xdbjwDM%2Bir2HJKK96U8CoZgWrFDK%2FzJAXN4RGs0disQ%2FQOvkh4PFtwAAPh0IFV7VuU7LiCp4xLXRRE%2FhSQhiMeMjl9C%2B4uZwqsFei6Ncsl1EG6SqZUQ5xkJxkHX4461zUkIO7TgKpJZaVxrzLci1RpeJfljiBUjmrOyjkgXz4VtMx6wleCn%2BAJglPI6dxE3XodjgZyo4yeW0VnSh5dOgTf8vAGSnl9BW4aFXZjXcKOHBUTwNWNb2LqfBO8pgebnJb97bff2m9%2F%2B9vq%2B7tygIdIx9geP3pk%2F%2Fqv%2F2of%2F%2BAHxmFlOlCFtsdfyqdkjhUSNDCcItKqppMxGOTymQ4isFgR4XssXQ6jJUnjKJesAA49RnUpUcArnDKfZsqjbOad4p2YOxzfw%2B4lwU9s02Cd8zphOu653z1145Qe5Mu61P6s31%2FM6NAQjARdX1%2BDAtBc%2B86bHviwFBF9TsDId4oJOB8%2FemiPH%2FNd0z1pPr5J%2B7Of%2FYv96C9%2BZO%2B%2F%2F54%2BmwIKOrgkAs1qACXlXTbKg1vns8uAVhcswZ8%2BwGAxP12iO3JRX4xyKTfSLOGgT98X8ipA1T9RenqJqiReAhP1TSEszjtNjTvaTEdT99I%2FeuGaz3XJkTJVgtemoLTSd55W4UfeaKfImvZI6W6fgmoONdrBG%2BByCimwqgCjej%2BFS9XT5Kmedhymb6jAcSW%2Fp3tf96rn%2F8025NWJFGiiAuUrUF8G6bzTUGUMbiVdIxicAlLt%2BDpQiwE3LznVK3oGxbkyWtAsOVUR1eftx8%2FwNqWMZXq2NUvoqqwavRMtVJY0TFn0g5Kqjo%2FDn9IsVgQUOAZZK%2Fp6Q6f01vRBtHcGHx8uVHbAgbPCfSdNkMHrj2ZmVbNg5p%2Bi%2FHxy%2FXzxKXDhg01Y4CLtzCjv%2FUV0uDlekTrtczOllFMynxkwmnyHUt97mwUkOCRFp599G0%2BVbzRbj9exoER03nxzpP%2BFT0sDKkUVejLLeOO8vmxLmTeb5vnTQatKV3BnMZ6%2BX1auzIGTWjInlWi2h6sbtKlZ0DtGFSf%2BDSp9okEfDuY7p24EUF6OV0VYJeBGz7YrsfH0RW1J2mTOfC5pxTulR6byvmzfTHoCpNJ4QVtRyOhuwS%2BQrcpmWlyVnmkBqmyHw8nKjl6T5lV7ZgpP81fvSdKsdQ4MOGZuZiss53rdTGeaAj1yVzHuyBslCHwEQ3O8nMEvhCab4jTIpwAdsHjijf4UYxYyk1iUzapaNgtvpv7ZV4Wx98Jum2MJbQEbGBpwKfgJCqy2yCSCSvZq%2FuY3XyjY5J79mzSAWU%2Fkh09%2BfPXVV%2FZvv%2Fud%2FcPjx%2FbRRx%2Fp22oZyHqzpk5cNnPhNTtgvPRgjAefHYr1C1NnZCrOs%2BDmdBHlRSYGb8qcRdBeJnsed1i8dudT0oVZUE10q9AsD6GrAoBsi1dc6TCKVDgknpoZin7omE7zlIjN3c%2Bxfu5t%2FXiEAtBb5xHAAQ7zGusTO9svtjVjz6fI%2BOwSck%2Ff2NndNQ6%2F%2Bsd%2F%2FEf76MOP9O1dPiUCi5Bv5J9f9vl0pGf6Z8HJpfyqBAtomravUJ%2BFVUmysqU%2BVeZKqLzozLsK2txNlonrsWUy7xwIlakaxk3%2BZUYvON%2BOfCu%2FoXqY3hzNfxSB2bq9bKLC1Q8zmsJMbU7KsW1Nnk6LVnfTckfxqTIdKX80rwJXraryQU3JEnogGyAhQ%2BNptDno6tRVPWG%2BquwkzlSTjlliFX6HCsyUcnCFDB6lfcKYXss81X0FtrqZFoi7Kq%2BGA4%2B8nkkoUZ3SfTlsCldv1den4KbNq3JMXy67O0PWZSDq9PNJgUsRbCZpkdOZvp8vokMse1dk0%2B1p82U55T9FJzkr3IR%2Fka6nIENFY%2BiRY4zc4yuyzJXj8Pk%2BIDObnbZ%2FX493%2FGlUt5xACuKo%2FDsiVGlAp5p2QeXBcCl7cMawZYPRxFNtXMnt1PAdhRfgjr542yly4jE9p%2BXu20boFeBDvILerwBhWgRZPI4UepdCOptRNMykiqG%2Bx4xgkkDy2%2B%2B%2BtV%2F96tf2pz%2F9UTM%2B8oFC8K%2FfuK4DgT77%2FHP76U9%2Fardu39ZBXMDFGffRe5c1EJYzTj1qvzvpU3n0JiU62UD1s5nEXCGSOU53jSpPlzlQTJJA35Jd6nOxDTS3Dsh9jUziR1lA8BLaAhSifRm8LMhRJZUD%2B2dtUwXkndzMMO31a3xNcK7vQuFJh4z1fdxvvv7Gvvj1F1pG%2B%2BTJE33fFmTJzzdkHz16ZD%2F7l5%2FZ%2F%2FPf%2F7vdv3%2FfOCyI7w03WA1U6aDpIIY70yB7DL9fnxqFF5EDcW8E6BmBJFNOuh4D9o0IcUlrD96KsGNauToyj4nv%2FP0067u4q7YRgL5WSwTuiV7odpezTHwTmL1JWK%2BKz%2BlxOCkn7%2FkrpUBlioLF7akRLuEtK%2FQqcJfBqtPfHQUuQLA5L34LRK3IsuDtlJpzL%2BcelQ9Qi9KnQI7enSZ%2FCbdA9yiwC5ySdMjroqYkHZidlBsSyh1fhL1T%2FeHQnm%2F7qPf1ret28%2BZNa%2FGpEQrmzFQFOKF5AvW%2Bbdo6%2FKKW4rZCq7gBp3SGtH0iHGZFztn2wBvHVz5ZUX7R7XH0XZT%2FddJUl%2Bg%2BE2K%2FDsjvp%2BzcqOtrI3EC33kt3i%2BqaK6s5vPGE%2Bv3Du3Rg%2B%2Fsy19%2FYb%2F%2F3e9s5%2BVL67Q7dnNzw27dvmW3b9%2B2Tz79xP7hH%2F7e%2Fvpv%2FlZO%2BM2bN%2FRheGb2NGOesOVDzfEs32mGCfymrjvIZlBFzJaufBY5jVwebSoUSAhH3x5NIW%2Fk12VaNmWegIQBKV8K5wE2%2Fcv72FGIbzIlcRBM9Yk3Cf18wXLK%2B8xMxZMzosjeY81YVm7pxA4PDm04GNjaKt%2FUdP3eO%2BzZzs5LGwyHvlfcTJ%2F9%2BX%2F%2F%2BZ%2Ftw%2Fv3bXV11fd%2BNlYqDCS7WpKeXJnKSpXprdxQX%2F69lQrOADTwqJqetDgGhPq24qxjMp32VSUlpSY5Uhi9kjmddkeyvMOEUufJ4sZ3VtF%2FgShkzMnNV%2FAHq8YEO4oaq1fn%2BcbRroTqWFRPIXFTCh4HsqLVsdXVLy8wBc55sJnSmdekdCHivKo8oSI9s6bzImeqhLMo79tThWVt5X2F5qW8KentDZy2ne9q%2BQwR7JOi5zSiYd%2F2X76wR998ba3xyG5urps%2Brhx7Y%2FUZtXRexHeHmHDzOk9OYbLs5XzmY57lkFfydkzGeKUqE8%2Bon0vOOMkQxySYnyOYhnkWdqLOlTK6zmZ5u0%2B51%2B%2Ft1vL2oNP%2Fk4ivWQuydDKslP1TVCraTmx4sG9f%2F%2BEP9sUvf26728%2Fsgzt3bGNzwz788EP7%2FPPP7cc%2F%2FrE%2BF8EJtHdu3zY%2Bd8IeKfZB6lgy5IyTXmXeqTdxmG2wZDhcgCl2s%2FkzPVPzeRbS%2FNPi%2BuZzLXt2vBJG5aFW2b3P%2BCnFfH%2BRXqClwwQdWlt%2FOiwrgKe8WQg10TwljLefLTn1ZmryNvPvq8FVefZeA0EPPiDQbbfsow8%2BsP%2F8H%2F%2Bj3b550z79%2BGMdEsQeZb4re3h4aL1%2BX4MHLCX%2Fb%2F%2Ftlt27d9c2NtY18Aif%2FWAWDvtTyLlUzk9PCZh5GoYmPYB8mvynx%2BDVc54Rj8h%2BxlLHoDc3oLUk57S%2B6d2SrO80mXDT56kdrxxk00GSYeclvlVPOAP%2BccjQ2%2FMqS1IllmXasvsztGEZiDOln6K%2BY5cKZWXRxrM0NYvW1%2B%2BdAuc82IQ%2BKahckbJ8DolDIbA2Mb775uvbimFnKQxFM4uJ7euvFr%2BrU1%2BBAkn75NNiEOmsa9QvnJIm3%2BgaHNrq%2FkuzJw%2Btu7lm6%2F3b1llpie3NccMa43IfaFFHAlxcnSTH%2F1mS4bTJqjLqTdkp0BCYVIaSTVIy%2F%2FQ%2Bs4BTSnXOzizSuxkgAIH85bPqfBf%2FzLfzXdT5puqoCP76ACtQ1c1rwqTLjCfWOtg3e%2FLIOi%2B37Sd3b9sHf%2Fe3dv%2FDD%2B3jj39gH3%2F6I7v30Ue2sbVlnZWOf0hcjjfO3tgaw1H1mSbtC82DsxagVqGtPhNP08QjvlH5agG4SMrgcF5IqtLLi1ZvEkaVMHMjR5AzwXL5m%2FoBSySiE52gA2aAXbqHs9D5NI3P0ZklcJckl5CbDHygA%2BFL2On1VtM%2BvHfb7myu24%2Fu3ranf%2FEje%2FjwoT169NCePntmLKt9wPPjR%2Fbk6VN78rsv7atf%2FKv9zUf3rbW6Ys0VDqDx5eL%2B7WeFs1MdWyJw6vt5mT2u4Ckaflzxc%2FLuXbfiXdd3KjLPs12%2BIiVDn8jSlpDQtfOFivfzjdSHjeM9fUDv5zMV5V%2F7Nkatl8FR1cfgv6zcu0gXWiBY0qfANW0V20mwbVda178Lhrz5Oi5AsEmjU%2Bi4FgKJcmCEe9A32983Gw4qo%2BYyi%2FNCmQyAFhBQoEsBX5CnTjoDBYJXp4mGIHtmt4m1hiNr9Q7t1rMH9oOn39l711Zt9caGWW%2FT668UTqBzVradNf9xra7kBgW%2FCHA0rDJg4Ujn85yy5NGT0ijNVR7gqtT55%2BpFfXPxKOCysbHz3D5vjqx1%2F661fvC%2BffDJp3bj%2Fn27dueOrW1tWatjZv09s3448AhMs%2BUqkQNWWBnAwJsO5ipkck7Wss9NDXYpc%2BU96raAs5SwKYx5XZrxlC%2BODzoBchqsTllZnW2eAhXPkYUM5k5JdBiDGKRt5p5ZZ74ZPOhbxyY6zX3DzG5tbdgPVlrWv3vTDnuf2sHLl7ZD0Pntt8aptA8ePrDhaGyf9fbs5tMH1l3vmK1wWJCOADdr4b7E4ONrid4x%2FkHSpoJfS16S5OpdJdjLm31ENEpdGvdV34o%2Bshza2d9IRo8gMYVzGp8sc5d4ZtrbvM7gnm2oOp33eWzd6obZ2rrJGL5rHN9m%2B68A7MZEa5POa0uzc%2BcVIYw%2FkrTscmCH335j3%2F1f%2F6eNnz62teFAyy996ie%2Fm1QIbTQ1xfm8tvxi45X8mm3FDBdmBuEYL2TgYGw2Glp%2Fe9sOnzy1jevXrX3zljU5jbD8iXln5OBMfSWwV7undl9A5HvlFkHxPMcblSM0KRQoMaxaGZmqFp%2FCN1qET512vikw6fVs8Oyp9bZfWLvTse7WNbP1DWsg%2F5zEqdOlXCj4FIxmwvMTTTj38UF39%2FZdWvRvIVMVBXLQI8I27XvUyxQ6DzQpv3AspQLkN%2B7HLO73c1lPfJS4V%2FidmL3O8KYp4EJT2dpccTFfzTK5SP7xiRN%2BlJ%2BMxjYZDPQpC2u39TkxyVbkQQwng6GN9%2Fesv7Nj%2B3t7OqV2OBra5uY1u37vnnWubcbgCoMsyKkW1FYDlvP4nf75FAo1dHA9zHF6qp7nnBLxBQhW6RW%2FMxMyciQxXy68VrkR1TkdrHfS2QuLfr%2BJ1fLf10ejosFSUEnxcNDyUfnTfzcbNJu23%2B7a%2B%2F%2FhP9nG3%2F9Hs62bMRC2FHD94pxR4ILMbC6hGrOao771H39nj%2F%2BP%2F90mv%2F83u9M%2FsNXxUAUIYZDdGfkNUMcuh1hSXZ18WgqgYo6qmfmUdFaUO17Cl9ZkYut8zB0FjaMyp6gdi0VcPQa%2FIticx%2BOYUktfsfxXeBdHI5S2COx4r%2BtxjnOFlzv5iVtJmxIuCJ2x5UvbUL84RxSQMLnsr0VQKRnQ4Tf%2ByYeUjZxtzOe8SuJ4kIAslxKXSdo%2BLVnCLEtKg5YJJ5Ase8UJ2Y5%2FrYnNArfjc9dv3xYF9D1nODorABVniuRMyysojUPvMTfKmDZ%2F%2Bl6unpFTAGiYsWoBeZrjka1jA0Lv69Jo2qjVtAnbZfRpJh%2FkK%2BurgNQ3NQWOoYCkbsH4gkvjbEFJZyVk3BTfMnWTPVtg0dPM55981YZAVnAXFTprGsCKDrm0%2BMn56G8zqEU%2FXAryhBfAmoFX5PfDkwJvdMRM3ukKl4NWyx6urNnNdss2PvuJ2bUbp2tuUVd9%2B%2F1S4AIFm9mRuPIXYjkeWXt4aFt7L6yz88TeO9yzleqQDCdulixJ7U5RmVLfv1kKHFUvR1IKxuS7TJq%2Fvgncso43A2uBpYkKEndEtLo%2FplIVI%2BMplXoF80026Bj86lfviALFoIRYm%2FKklYzO9YrlkSGfK5kAVT3MpMw0gDdePEvn6%2BpNJkxlMnGjiER%2FEXyHt%2BjNFODJd4txO7lcneMNU4DRjgXMrKTmuHegkhmLfD7Dwwt3MxPjzKpi4XTmbFAuvuK5nC0lbwE6QdXXmgKnpsD8QO60IJIVp8NLXEsJDbV4wgnnsyUCcurRaUVv5C7BnuRCJE5n6jcnAT2uBU7G6eqYRKAqM9UDhJpqR%2BSZFMy51mrbYHXDOge7Wv1WFa9vLgwFLkCwuaRbIJWaARhZczy0tXHPuqOebYx61hiGtC4pemG4c5UQLXlV3kODIwrqFQkzD%2FcVwcwUS5iJY17LTGVa5i%2Ff5%2F1x7zJPfb28FCjlpGylH7xapszeZ7ll8kM6f5kvS5%2F0nOXIz4pI8meZZXUl7Ne4zoDO%2Bl4DXl30NSgww4xj4CzKB%2B9Izz%2BKL%2BMn6fPvEmam85z3x6BSv6op8EoUmJet%2BecSaMpmmTZ3f4osXuK4euZgHnnMSk4DI%2FMmkGVl5vNl%2FrNeSzh5v6jOMi3vuWYZMyNQ2Rjh63MuQWY6K0J1%2Fu%2BTAuc82CykrRQ%2BBZoEm%2FFnY2tORtaajGa%2FlQRl%2Ba5hQ%2Bc1VtI7u3Dn%2ByT%2FZa77FRSCtuI09BkDLZdK8pxyhjCzL7sKo0KkluU7KT1blksMj%2Bi%2BMiFHBaNQLo%2FNOvJ1PtfXmgJOgcWzSryTKKWMpQDl8yLyzcm8HlOIy%2FyL0kCD5Y8UqoQ3MkbdCd6vi4CUlZzuvoJS3ZyuXJ3rHVIglgcm%2F2HVjG0lgZfISXxXeYadWRCUvfAR5F3uiuQsM11hV7ysb2sKnI4CKUZlbqUVAlrm4V6fZ6MAulYJRY4l5Ur4s%2FfRU4pys%2B%2Ff0lOB8rKBG1frZcbXw6UyG8eBCTrwaTvXBenfuw5hklN26DgY9btzTYFzHmwm7ULw5VAhjTzHnySZ%2FRv%2BNzVaDe3x2O%2B27YAp%2BEbbxupF9QLapOrbuab2zOvZahFX5Zs4z%2Fm3WkZ1NlBHcpcYlfdHMp6QgMgRaAKDgQxdQ0fKqRr7h%2BdxsvIgl5k8Cd%2BbKElWEvo10jLLzPV1kJ4BVD%2BcewoskYOUo1fBXyAXDNyQ7tXFMqYAzupdjmBp8bmRKk%2B8lLM%2FFchc6bsE7TOhWwUsU%2FBnKl9nflMUaCydRHCzO8tt9DT7NKWv9Srex9dphhxKm3oSFMvi8Lp8flNNqOHUFFhAAYnanC5cJH6kSQ9OTGdJcJ4EBj%2BXeJegs3xey3fz91Jtxw0Qzhd4l88nLA8%2BCyqpwvN6tGyefsEnrcai8cpoYt3xyLqDYcxkxkFjKgyk%2FDsKrU45vxS4IMFmGCJZuFLQ6NahDtz6ZUa%2F3r5njf%2F5f7L2e%2B%2BbNTs2qY5xP406OL9MO9%2BYpVrJ63JslSNZwYNOo%2BVTNgNr8M3NTsess2KTFp%2BsPz%2B%2FDAj94KIYvCAAxXiMhjY%2BOLD%2B%2Fr4d9HtafahDMZrMrruarFqSbS%2FSj6Ma2YsiFZj65mpQANk4Tj5OokLKjq6Fo1XJFQdCc6LteGytVtvWu11bWV2z1krXms2W77LzYe%2FAwx0v1auBlZMwOMP78%2BqInaEJFz9rnhSyaJY9JRH9hxxMJDfaU8nBfYc9Gx0eWL8%2FsNF4ZONmw4atpg1ZabSEMOjV%2BXfzzxRNOZ6%2FXwK2Tq4psJACuSVwkTxp4GQ0tlazad1Ox1ZWutZBD%2BKL8J1H9GHowgr4ImGtXs7feJ%2BZTz0XzzEp805wCWOEFmHmksPBmoOhNf7l%2F7PBb39jnf09a8ahYO8En7qSt0aBixNsQgIJ5rxFYmQk%2Fis6O8ZtfOeubf4v%2F6vZ3%2Fy7%2BC4PQUupWpKuRcFMyuui7Pmuvh5PgXmyJi3nHUnSSRsMFWgOXu5Y79kzW93asvatW2arq1HPIqfneBRe%2BW2FawEh8SQpFXJecdKHA%2BtxZP%2BLbRttb9vkYM%2BDzbYbqLEx8u8OVc7eZOCateTS3HxWVfFA9Wkgy%2FQyb31%2FeSmQ3WleZk7bYol0BJkpSxLp1IqMlYxG%2BsRKs90xW1uzlc1rtnFty9ZW163F4A%2FfNkTmK2TiRp%2BiCExU0WmxWpBvXj8syFInvQsKJCPjmo9ULbYH7%2BEX39EcDW3Y71uvd2gHL1%2FYwcsdG%2FUObTgaaVXRuI2TPgVC6ZTl%2BfuqCm6mRSq5IymTS534LqhS13GxKZByk60IKa5sK%2BKMfR6PRn56crdrrbUNW9%2FctI31DWuvrloD%2FahvHAe0BELH0H2VkNXMXk%2BTZ7bEu3uST%2FMGq5sn%2BCLQEJ2OPBqaSWf8b7b7zVdmh%2FvWZRC0MbFRA66cQNdFsOu0c0GBixVsimQecHBSlctwCF8pg7Fsp7%2ByYp0bd83ufmjW9m%2FVTU0UwCiUf0v4cZqOsqTo1UxOghUOaRKCV%2FOOZD4zMo5T0u%2Fbs%2FED%2B%2FrBU3uvs273bt6zlc3N2PcD7xN%2BAn1LV%2BE6D9uFTKOe1nAHqtGw0Xhi%2FX7fDg72bXvUtKeHI3u52bD%2BxpYZI6Gdtpys0WRiozEhp8%2BCzo%2FkC%2Foc2UAjW6x7R2EmbR7L%2BvlyUkBy8waapiWvZdAJzHhGtqmn2WhYp9my9ZWu3Vq9Zreubdnm%2BqatdLtKny6tTT1cAKlwDGGtns9y8w4Hls6C1pXJm1qHBsd9qXvlkU8MbTacTKw%2FGNjh4aHt7O%2FZ9qRpO%2BtmB%2B014zuZo8lYg24MAGs1SOg4yfOC%2ByRxSk8GpMIkEqULwSzkNsvU15oCx1EgpTqvmTcHLJSe8aI2yzSs3WzaaqttN1bX7c7mlm1d27LV7qp1Wh3rtFraauDlJNHh46T0Zg3z11q%2FiSLp%2F2F1uB%2F1zQ737HBjU9vfOs2JrXAmUGOigDNV0Tw16%2BfzT4ELE2zSdecVxJS8hecUieQfsdyBEaj2qll7xUeieA8g6QL%2B0c0UVN4tqGxJzixRX2coAAGPElFLTat80%2F098l1aIxtYy56MzL58sWvDW0PbaLSt1VrxvY%2Fws3R4Kjinv0mjsqhE6dTwXtgH0z0w9D1J7DsaTMyGjYYNJhPbHw5spze05%2Fs9297v24vhxA5Ytt3qKtCctNzJYj%2BT%2FiR1LrMpUzPXkmyFaIuimTHwK7MualOddrkoULD%2FlRuWcqTrnJwnUN5xWMPKpGkv%2BiPb7g3t1srErq%2B0bL3ZsdVmUycEEnS25JR5f3F5DCz9IUGe%2Ffqaff3sFdYlFlGgGk4oB8LwC21i%2FfHEDkcjezke2rP%2ByJ4e9G37YGC9ScOGna6NOiuu8xjEkMDFYHFY3vExwSa4SJJKOSr14aK9xIsaUKddSQos05UpTnkVcZaoLPKgBzvWsO3hxF70hnZ7dWxbbbNr7bZttDq20mi6DqxkM2vO6wLyXxHdNkPjBWTQUq9kgALPhlmrb4Nmy4YMTuW7uU8lLQJVp51vClyIYDO7LNejwjsVx8wHyT04oABLGP1vTLASP%2B%2FrZYl8M3stc5T3s7nqp6MUWMypMqDTLEo6MBq5atqw3bBDa9jeaGy9RtMGzbYUT7PZNP5eNdgUNhiDo2hVqIu%2Fgc98fpyiHMUn0Bw0Jjawhu0Ph7a9f2jPd%2FZse2%2Ff9voDO2w0rd%2FuaJ8SsjdmFpRagB3wWRZSylN5XyEUZfICTuVIvp5nMtcPl5kCKSN5fZW2pvinHOXzPCzeoy2HyO5wZKODno1aBzZusYe6Y5Nmw1YaZm3%2BrCGHjE0KxSrJeZBnf16G3Nkh1SVekQLIWv4lCJ7Rh%2Bi%2FXmOiQPNpb2CP9w%2Ft2UHP9oZjDfSOW01jNQd6c0ZmQwcmHMEv0rKehdeQCS4EAVz1V1RQ2piEUbzOpPp6ySlwHM9TbmZIEPJUpqWcDekHLOc87Nuota8DJyetFU1mjJsejKL7dJjQAi%2B1hMk9cK%2FC78R2hkueezatwTaNlq%2BAKOgkeyVFcRWodjnbeCGCzZL0yBuCV1qvGaUyo0XyIZbvFIAEh9GSmcKeYZGx4s2JHaeAX9%2FOUqAic9wo6OIk1%2BqFn0rGY6ezYlvXb9ja%2BoY124ioVJEvaqnyz8I%2F6YliFf8WwYiXic9M%2FhA3BY36jM7ERsxsMqvZ69nzlzv62x%2F0bYDTxNJZ2iaYOTrXsEaDgLkhB6yhb8SGGGelJzTiCNpHEk4AUL%2B%2B0BSA3ct002kblnKd12XlGJRRnolZb8inpXrWarSs0%2BzYSrtjnWbTWq2GnCsCD0QdMeav6mfLgJ8mHZggUP%2FeOQVKGSt5mezgyuAZOpCBt4N%2B317s7dnLg307HA4VaI79DLz2AAAgAElEQVRaPsA2Qo6yYNESkpTMPxKe4uUJt2Sv8FoAG8Blsu6rAicAr19fCgrA82P5XuipSjSqm5CvyEN%2FYGCDWXzr9RkKt3azbd32inU7K7bCQHiU5ULfOFF3FXVdCoIf04jjmjrtp%2Fh%2F059OYZn4ICaMxB7xvswzzV3fXQQKXLhg8ziiTgX3aC46%2F5FZrSUFKkURAn4UWp1yVgpA6vyjrBzTuOo5ElHq1zY27dOPf2h3bt2ylTbzJq7sNZL9GtpGMrAM8cJBSWcr88vYpBERzhMbDoe23%2B%2Fbzu6u7e7tWo%2BTZzkkCKvD%2F013xGkz53hWahI5ZISUGSPV6RVnncvQy%2FTEqXrOm%2Fp6NSiwRGe9SuMFall%2FQixZ%2Bhgn1A6Q98MDOVar7batNlvW6batzVKnwCmlfBnIM%2BEIzDcC6Ey11pkXOMqwIfUTjjSTEQo2x2M7OOzZy91d7dXs9fvuaFcriHwBbp7amexMEeYKXF25h%2FrxvIwRghFBAPfphJb5E16mCW7AzrT6evkoUPH5NE0LYUyZzCL5jJ1N%2FUOaZGo8tvF4Ysj53sG%2BrXU6ttZu21pz3VqtprUSZiGfCXfRNeta9O4ypZ3UzopveRM%2BEnqGsiofNL1MdLlqbbk0wWbK6UIG5su8Lsy0IJH8J%2FWUBcXqpKMUgIwl%2BUuyOpl9%2FyZLZa9z%2BuVK11ZXu9ZptRWcpVNRljtay%2BulVLBLRAEZgSiOkZbSjkd20Du07d1de7Gza4f9vg3HY52WpkOAmInFaQrHSR8jzsAyKuGCMmWBmdofdc5XXbaowq9IPC5%2Fka2%2BvSwUWCQEr9i2Y2VHsuuzUwQWw8nYesOh7RzsW6fZtpVW21rNDWty%2BBVqkq024BZ95RVRqoppYPANtrUCXN%2BcngKFgCQrgsUaKOsPh%2FaSA4H2dm2%2F37P%2BZGwjaxizmdNtAl6yHCRLGHmlmqxKAxdexPHMFwXW%2BTqvxSvdLkyPxAXg5ovXzxeUArB4hr8n8Fz5iwJZXtcoO80z0UAy2dmrfNDr2c7unnVbbWPwrdHtaoCZ%2FPJVTtCDgntB6XxatIOE7t%2BcVKjgw0lZ6%2FcXkwKXJtiE%2FPPyirP%2Fpn7zsN8U3KsIZxEt3cloaF9md3XVut0Va7LsVJo7l6Ie5fFZ6HcWcUB2cJDAFWdbI%2FlyuifWG43kXO3s7dnuwb4NJiM5WOzr4A9jxKmLkr9orC8EnltSFgglXhVdMmGucdX76mYuQ%2F14uSlwwqzPWRt%2Fkhghv6XsDyZjOxgMFGDo23PtlrWa69UJo%2B0WS8Vff3wO8Qe3Jd3grM2s878qBZIRlA9h0SAAOm48lg7cPTywXT51wmdPGq7%2FWFbNIWozPCxhHYNPmU2zS8fkPU5%2Bj7ybQeYYoPWrC02BUn5oSCkH5X2Vj5vQNRKRRUFioQfHnD5vLKkd2W7vwFb22ra6smKtVssabPnhe8MBL0B7BVf435PokPQ6iUQl%2F07KW78%2FfxS4PMFmSmxej6P1SdIfZUvhLu%2BPA12%2FW04BaIgDW9ESxc4zh0ikZ9FoKMjkBArYpLzBLxzfU7JuMRJR90kwEj%2Fq4x7nyYNI9ihN7HA4sN3DQ3eyhgO942PlQ05obJqN2NdJXeF4s%2Fy3%2FOndXNt4T7a5rGWx6f0bcOinwOq7i0KBU8vHGRu0rD9kfdnvGEQZMKs%2F6Nnu%2Fp6traxYd6VjrXbb2trL7EvHz1j9THZwod5lOM1krh%2B%2BNwoMRiPbOzjQTPfBoK9ZzQEy0ERf%2Box46jIth2MZ3JzeSvmasQlFi1J%2FFkmzt0uW1mW9ZWbJ06IXZab6%2FnJQIJUH%2FC79jQWty6zlq0VpLqs%2Ba8%2B%2BgcF4bIeDvuR%2Frdv1gLPRUNDJ4vF5WS%2Fh5%2F2ievLdZbhm%2B%2FK61LlZ0I8pk39JiwpOJtTXC0WByxNszpN9mZI5pcSWdinv8zpfVf18Ogq4wp4GVB5ohkEoiMu%2BiOFgYC0OIdHme%2FdSyC8NVOQ9Xc2zuZYVrz7LwuhkjGZqzxoj%2BRFwerDJfs2eDsMY8J05ZjQZzWfUM5wtn930pbJZO%2BhTt4LYJfK5DLeEwTXhlGn1fU2BV6HASeoQeaTfsceY2Xl99oe9ev2e7R0e2Mbaqq3qQKxmDBy5fL4KLpShvpNwelXYdbnTUeA0PBiNR7bHgNvhoT59wm7NkTUlJ9LrwUvVmIFm4VRKl0ceydgC1I7Tc5KRUwpKjmNSxSmLLMCmTrrIFFgk0ykLp5MPH0DRzL6WYU2syWd%2Fhn3bO9y3jd6qddttHQ5IXSf9qDv%2FTsp7Kd4vIUpJ%2B%2Fl2Vu%2BSeUtgzJern88nBS5vsPkG6Y1SSHl%2Fg2CvHCjoSKA1%2F1PaZKKlWQR8%2FV7fdnZe6sPJm%2Btr1myueIA1cZdXJ5UB7A38ZDdi3yT7Mfk56Dz4ZMp58BwMR7Z%2FeKhTaJnh7GsJbVMzmdqrpM%2BcxDfl5J4za1t4XhFkLtObb6hZb4AyNYjzSIF3KR%2BSUQLNiXqc5LhJP2V2fzCw3f192%2Biu2MZKx6zT8gOvAsFXxTPL5fU88uAy45R6qdJ6c4wgnb%2FheKIl1ZzA3RuzhBY9F5lRqty6cnWtGoDjkq9Eykybp%2Buy9DIfeeZQLF8fC%2F9IxjrhclCgWAp7kgxJdopMxa1oITGu%2FJappKERsfeD0cR2D3u2tr9v691VW1vp%2BKAze9irwZVASGPmPnAOpCm0y0H2pa2YJ2qZMYlQ5QnKVM%2FTzJl1mlLfXSQKXKFg82yiOp97%2FvkiMfk84Jq6ww%2FFcYdFaeje0MWT8cRGo6Ht7u7Yt99%2Bazdv3LDuyj1bWelopjFiwViigro%2F%2By%2FxyCtAuNespobSHGoZhPp7AuWJ9QcD29s%2FsL2DQ%2BsNBvrUiXWamvHhdFlmNPmBXY7wA1EB59nRrUvUFPjeKYBEI7%2BNiS8PVz8Y%2Bem0O3sdu7GxYePVbh51JXyR%2BVfpn997Y68wAq65XB9KjRUMlA4Mp5uVHCwj5MAo9q8PLQLNYu2gVKkAxom0sWUC8mY9r0PqEkZ5%2Fzow67KXjwLpWxSifKZGTmUrZjY5nVv7MicaXOPgNA4Lerm3b9c3N204WZUvwGeB6A46QV9ApiczvyouZ0K8zlxT4JxR4AoFm%2BeM8lcMHRQsOjcV7fw9b%2FgG5WTctL29ffv2m2%2BV987tW8bR%2BQotKw8moZydiCUeaUh0zRdymT2QJQDlHTOa2oc0nhgnMGJcegM%2FgXbSJnwu9qKWo6rjsXAv23p2jOsSNQW%2BPwpk32DwhX6AA8WgypgVCMOhHfZ7NhgRbvDf9CCv7w%2FjuuZXoYD4XASCyU9gSQcG%2F1lGvT8Y2PbBvjGryXOj2bIm39VsND2QjBlNSqJWpbYDqaznVXCsy9QUeBUKvLq3cLQ2DSCHjUcfssqDw4I4nZ7B59F4EvuWZwdV%2FIBA9yuOQq1Tagpcfgq4p3z521m38BxTQA4Jo4ByWlrW6x3a8%2B3ndnh4qBlHBZvaR9m0RqPpHu8bak%2Fp%2FHCPn4SjxeyN%2Fji8KP6Go6G%2BsTUYDpSmfUeBj%2BCoIaDHdGlAzusbwrcGU1Pg%2B6CA%2BkbuM%2BbK%2FuTJ2Dgohm9wcjppSPz3gV5d5xukQLV3PQJNHGr2qvcmY9sfDu3J7o49ePZUB6RNOIG43dIp4qBAWb43jDRIZt4gXjWomgLfFwVSlmeucRAg%2FYNAs89hgeOR%2BwaZMRCee%2Fy%2BmlHXW1Pge6NAHWx%2Bb6SvK4YCGnUkwJtMfKkss4hMnfAdyibBpQdu04Dz7Y4O%2Boh%2Bjub7%2FjTNbI7HWkJ7cHgoB1uzPODHbCyfOQnHjEYI5yLgfJMjq7XU1BR41xSoZDsq1nwVct%2F0gJNZfmY5Pbx419jV9b0NCmhVR7GyQycRTya2P%2Bzb9t6evdjf18nEk6YfDCUdWQzMMUDnWnx2hudt4FrDrCnwLiiQ22K4sq2AP9n%2BSg8ONPDGYIv3H5f97AfgWN6%2FC5zrOmoKnBcK1MHmeeHEFcMjA7CcSaT5rogntrratTt37tjm5qYCztFobJx%2BOEkl%2FhZpBQ7CKZwlNzAEnWMtGSTY1CwOhqYKNKcj%2BVWgGQuGs51vEeUadE2Bt08B5D36qPqEviPbsCGHBfX7WlZOgFH%2FLgcFpnrQ%2BZ4rPTgYik%2FfDDh9Vp84iZUfGmqIAJOBNhRfITOa967F43IIxxVuhYLM0INaRss9gaeZVj31%2Bn0trc1gNEmVujOf62tNgatGgXrP5lXj%2BLlsbzgnBHjjiV3bvGaffvKJ3bx509rttpZlNcbsDWKmMzS9bl6%2FMQluHlIaB64yKiwlG42sNxwo8Mz3ONiczMhkLEanGU3B0ZoGnvPQ6%2BeaAheDAsh5%2FiTzsWeTma6GvjfHdzf7mvX32Sxy1UMsSbOLcGUWhp%2F4yzUH9bQHc7pqg4AR%2FScdqH3svndXjvUk9utK%2F0n5xXaHieBdBDrUONYUWEYB7yH%2BNoPLhuw%2B220i2ORk5thiU8GJAZdy33L1rr6pKXCFKFAHm1eI2eetqXJJCdBiCJy9D%2Fw2Njetu9q11W7X2nzDr3JfKRGOjFLfzD%2FLAk6gVw4YhwGMx8X%2BNEbxp46Yj%2BmHw5X46mCjN4NjDaWmwPdFgXS0NKOpg2J8eTn9ZsippJzKPOSM0vp3ESnAoJiW%2FSnQTG5LO1fNkY6cmA0GA81kw3ecbMmE9OT0c08UIv8shEUJFfj6pqbAuaVA%2BgCJYD5P%2BNyPDkuLg4KGw1hGO11CnmXqa02Bq06BOti86hLwPbY%2FnREcFn5MVjZbLes2G1pK22o2zSZjX9f6hmYy55urqmNWcv5d%2BYyBGeowFE6cY4w%2FR%2B8D8TgxN9tUlq3vawpcVApk6AH%2BlZOlIINPAfjycg7Mom%2FULtZF5fIU7ww8pW61VDoYH1k4JI3PP7GtYdxEBqYDbISX8%2Fqvek5BqhKmddZ3NQUuAgXwU%2FJTKo4vsu%2FLyBmsQQfSP%2Ba3E9QifxG4W%2BP4tilQB5tvm8I1%2FIUUQAGn%2F6EM8YCToxNnqw8ik5Cj5JGJy1sKPmeQLWYm3aiMZVDYv8l%2BTeEghAO%2Fd4HTDIL1Q02B16fAMmdI3WwOPGnVbNZkoqP%2BGXzxQzHmMtePF4ICuYw2dbL0L250secyNK8ObxuL37G3PfU46jAyAUd%2F6HCd7n0hyPA9IZlU%2F56qr6s9EwXKgFPirj7iAafrQWlIwcw79YUYjD5TZXXmmgKXiAJ1sHmJmHnhmhLOifDWfs2x9mzi%2FPT7fet02rbSaVuz4Xs1K6foNYO6ReYdp4g%2FPsKcTpaMBMhRH%2BlynHz%2BxvPkXA4n0F446tcI1xTwmajohwtFOAKOJJXkPvbn%2Bey%2BF6ZvZm%2FIvPX14lFgKgPMUs7OVKa6zut866ZliUAzF1JSjRbODjDOA7hyz1AsqZb0ej0iAG0RpDIta3y9mi5XaeiT3ChptaiV1XsROwedtah8Ie0dRk31RbSs064OBerTaK8Or89vSxXF%2BeFAjJofHBzY06dPbeflSxsOBjp0h2hOB%2B68oVakYSnBZRoHnyj4jDqXmQmMjvtUcrvdWEXQWsKt72sKnEcKSK5jBUHKOFeMQnWN9%2BBfOVk8ZIG48b7AYTAzuc5js2ucllAAls7%2FZdbkqvgrHkdK3mcGClT31Y2DqWQmoV7la1I6afD6xFkGIbmQ16yxvjoF5umSnFlGz6SbyinWzBL5xrsA7%2FVXACpup5nru5oCV4AC9czmFWDyhWhio2FNHaVvtruzY998%2FZXdvn3b1uKgoOnoeIwkvoFGHaf403xwTed7WX4C0%2Fp3NgqUJFtG17NALOHNl3sT8OdhXvZnZB6actVnbxcRkbTjCH%2FZiXRJ2pf7NE%2FbnJzBLkUCMdBzMTiR8GoxSUqU1%2FmOk9ScTy%2FLHH%2B%2FqGSm5XUK4WjK9F3eJU75fDmv2UquR2x5vqTpQbJM0nUu7TgKZbnj8tTvagpcVgrUweZl5ewFaxeKWJ82GY9tf3%2FfHjx4aCsrKzYajYqW%2BOzmm1baFbzC%2FgqfdKCKa4FMNQtQps3fFyDnX9XPQQFoVPHgCFWWv6ms%2F5EyswnHw5%2FNWz8FBQgaYgltyYEZZ6yYFS3z1DS8PBQ4jq%2BLdFvm56q%2FyMT9ovyXh1Kv0pLUTEm1V4GxvExJ79kayjfLy1%2BVN0mb1G35rPYnixYRo9B%2FvJ7O%2Bi%2FKHGlJ%2BplKjslfv6opcEkoUAebl4SRl6EZzGwyys5nFAg4h%2B%2Fgcwro%2FLQnsgP5sICgx9mHI%2B9ij2c67AvAXemkI%2FRaSA1ynZTTrfdJuRaCrxOPp0ARcGakUHHEyT5TvubBDDku1MOi2U3xc8ahDqYXvC9uq%2FYeJyNVpvomKLCIgm%2BGOMv74%2FI3b6bmiwUFDiRFymuVHjfJKfLk33xLWVU%2Bv5NAe59z23ICmS9YP9cUuOQUYJVU%2FaspcE4oEAdSTCbWarWs3W7rZFrfBxZael6TvwHMfS9ozJq%2BiVPjAlUZrnDW3gCalw5EGvbjGgbvfcR4Ua5lJv80kBfBq9OOo0BSu7xm%2FpriSYmLe3U9WODP3vXCEceLdl0cs5TB9JP851o2CprO3Vb6TaM5iyi5mHrJB8BNYZTAp%2FaMVAU85ev6fikFkuJc8w%2F2ZLroySjybIIGypVcpgeM2tFeSu76xRWhQN0HrgijL0Yz3ZlZ6Xbt7r17trl5Tfs4WUo7Gvlpb2%2BrHThalaGYMxavUmeC0HXOUL0KvItdJqkxbcUyumTgP83pjlL5PHsPpHn4i5y22VL109koUFKY5WZJ9bwu9ZXPVk2d%2BzxRoBg049C0DGqyd6GRx%2BVpxfki2pAyM5d8nlr4veKSASN2Z%2FY3DRQX6cPZvLNPOWDgMI8APqIpZ0vXT1CglNfUb4spOU2NYfKFn2SrcpWAa1LXFLhiFKiX0V4xhp%2Fn5sqZMbMbN27YX%2FzFj2zr2jVrdzpycviOX2OMLm%2F6gT1HLfT5aVoDx6wwWqVDdn6wfIeYuJUtjW55nx4QuXziemqVKzaXATsfm1eWhJvQ%2FDlLZyoNzbR32OgLUxW0KWk1jzjv5ulHmv7mX8wXrp8vFgXocMXqkXJgoRQC2J5%2F2cBKJpCNWi6SLEeu0Em%2FUG7Vc6Zzrejns8tHemhVyAdJA6BYp4BT5Z1DzsMKoEAl1LLKo%2FdFmaMvL1WKWgpNCzsjGQ46c4nXl6rddWNqCrwrCtTB5ruidF3PqSjQbDbt2rVrtrGxYe1Wy5rMvcdeTgfAWYjVOOKpYL6LTFOzzF1hoUq%2F4V0gcs7q0Oi9luM1%2FAAoZ6dTJb5bOnWssPVp7WOm2Rr6kDzJTlmnrfw07Y%2BJpX7huE2lYyolyRveTWcTGl4X1Sl49Vw5M3DOyPhW0BE9Q1R1n4SCO5H%2BViqugZ5rCiAGhShUuKZI5HeIyzy8q%2F7KF1F6QVIF9yrdiIYQo%2BEnPaepmKFBziIrW%2BpNBthidlk6tFmYGV%2BgxoAseabfpR5XlnIyYR4aWMEldKeQmal5wcPV4Nx8KyFNSR%2Fez%2BdZQKw6qaZATYElFKiDzSWEqZPfLgVSeZdXgkqCTRx%2B%2FaHgZSQn07SGv59iB4RTWc0ochaTsQguafnnIKcQExdPmaZPsb1qd1AqZyFxieQIiae%2B4oh30AnDzic2xmHS4T8HRmVZcjUmOYrvgw2iL4GsHDfnVZV%2FYtZsedp4PLFJYyL4eh8zzbpXsDnlCs7aVQs4q9aLWfnktOOplOPkFbQr03NA6CrRLil1Wa4%2BGJN81bBP1TSkYSoRkadI9JlM76NVobgpnfb5d1fhOemW%2ByYJCuk86K185%2F3HO5v4oKEwL6G1PNJZDRtr4C4G0iAs%2FyuANJuMPBhFb6I4J%2BOJNXnXaBi7UFpN9GfTRuhD9CP6FQZkX66QiUQxh8SZnn7pWDbTumjuTNpCCkC0aa6qtxRpSShy8afx0GmRfF1fawpcCQrUweaVYPP5bGTlhGTAMfZQA4d1NB7LGMrcZnAgh0dqOxqUmrtMO66tZf7ZfHKeFxgKdwcSPpZo%2BkcqZl9Q58p6CfJerZ9oEU12SnmAqEBz0rBmOEtNY2DB6TM2%2Fsv9Xw0fUY7ZxgmfvpEsNK3VEhS5YZBb8MNhEyQcKHiCPKmMW%2FjxeCRD32o2FexOmgS17py5G5ADGCX2V4NvR1ocTi2Bff7kSMW6SFJFX58Xno7%2BixleorhNEPX1nFMAHqN9%2Fb9ksncu%2BpQP72QjSg77G7Sg3xUSFXo7S5Hj6vygQ9Jm%2Fkof8oATeqAGGWT9%2F9l78y85jutM9Mut9qresJAgwc0itUuW5GOPvI3Hf%2FK8X3zOvB%2F8jj1n%2FLxosUVKIiVuAAEQBHqtvTIr53zfjcjKalQ3GkA30EsmUJ2ZkbHeiLhxt7jBH1OpD7Qm2hvmWQHdKLDesDno%2BB2HDDlF5dGdQrtsjjydI4%2FIZEayKlH%2BzDfLVLMoipUvGVhe7mZd9ERXWRz7eLn%2BlpuqVpYD1B%2FW3jIEvIUMvzBc%2FeEiLMFR39ijtl4pJ8VzC9flAmXVmgoCR0KgYjaPBE314Swh4PCyFSFBbC4G0yPx0WiEJI5Rr9cR05bWxSGTEBF1S0zI5B6N%2B%2FvTar1Ucikyw4%2FLgxU4tAoVjCcXEzJJPg%2FuWTIzTSMzSsVcwUeSRySSIi648znobCSOyBiaaRiZSWkUCRuCmFpOMptzEmQ5wpzpc6VnH2VazZ0GUt6DmYTmYwHiMFK6NEuBdI4gijReCuFFFGJO6i4ncW2XaRhMaODH31XqJj%2FqeffX8lBnp9jYtnFuWmgx9sUXn7K6XzQIqGfJhHCv%2BYLd9FORqjMJcdiu8vzQWHBz2DBjaQRxirmxYfA4jDsvGpSepb4GB6EyJxSTgpEQoad1We4QT2XaIiBmEzR5NXacGknC2d4y5JqMNIGNQIEZc8%2FyuXOa55alwGITB%2FJnF3FmAKVgPfIcaZYhT1OEUYw4CA0HOquPpRY6BGBr2tKXS%2F%2ByPG5P1lw%2Fbw4zmkxNUHpm1PfMyXKtYlUQuDwQqJjNy9OXF74lRPLz%2BRyD4QAPHz5Et9PF1sYGolaztICuaiZTniUad5TTqqIVxrJZh8XFRbqsHVp8udxP5V7gs2cCadEaknkUs0nCKhTxw3eQMZTGc8HPe3qJhBlNb6kRRZrKFFb5hgHCKFoIHZgvCWURUySoZgijsCCoRMBlKajlzESsmSmZ9gWL8TRy4WzH0fnt%2B5POIMbTSLfONSLq%2FDarqtlTILCMtZ4SmZ8LJtJYo3L6Yu4XcZaxYvH9BMVc7ChexOihQ0bQ9gkQPxFv1eLIGMacWkYK4ahxZKu5bhhac%2ByjQGHms3w0KEqLqdgsw9IoNRnYLMec5QCIGV3MK3FvABA%2FZilShy8pSKBgj%2Ba1vm9VoPvDcpYFT%2BWv1TMhoF6%2BOoO76vQKAs8FgYrZfC6wVYnOAgKUyHI97B%2F0cffuXdy8zuNPOmiiWRTnl%2FEioHo4txAQo0kzMZrozWaYjCfIpjNpNxlGYohLNU3KzITPm9LaAq59m5TmS8tJ07AceRggrtWQNBpufy9pqRzzeYrpdIrpaITZZKL9Se1OB2EcWTkBME1nGE0m%2BmU5UK%2FVJchAkogYzE3FeW7hWVWsgsB5gwAJ7YLOdlo8Y38cEc4ZTotBUeTnrfZnV58yXCQEm%2BfIJhNMR2PMwgCzMMJsOkE2S7U9gMY71GbKpFX7xsn88UfrD%2B7VNGsCesyLkgRJvSFP7dqvSbxFHJqlmI7HGI2HmKcpGrU64k4HMc1lmQGZynmGdDIWDiSDWas3UGs0EdVqK%2FeqX7FuO7sBUeVcQeCKQ6BiNq%2F4ADgXzXcrmpiLIMRkOsH29rY0m6bxKsiZc1HdqhJPh4DXe8jUMssw6h9g7%2FE2Rv0%2BkGYiekggSXMpGzMTNFCaTx2jJPlBgCiMFYd7kOjYIq7X0dvYQEImMqYpGglZ7k%2BaYTwYYPfxI%2FT399BqNhEHOepRiCiOQEQ3nU0x2tvFzt6%2BzMfW1tbR4DfuaYpocOb2cj69eVWMCgIVBEoQOApDV1ox008SPw37B9jf3sZ8OkUwz5FOJ9Iyck9lFJkzNFr2EP%2BR0aRglalls0E%2FBtyHGYRodbvYunYdtbU1cN8lOXmmSynQGw6wv7ON0XCIJgVy8%2BtY6%2FQQEb%2FlkEBuuLeHnb09meWuCZfGCOMYQcC9DSzTBHi2LFfsZmmYV48VBCoIPCcEKmbzOQFXJTsdCGgvgxmiyKseTU%2FJWFBLRUkvGVBKb71ZpYt6OoVXuZwtBOSwh14RM0wGfWx%2F8zX2t3e0Z4j7brl%2Fk%2FtxvcdEaRbJeILbLc2BRhREMqGep5kYxHq7jXqSIFxfQ0hpvrwuZmZiO5tgeLCPnW8eYtJsoBlHaMQhms2WGMnZcID%2Bzjb2d3YQRgm6JMayucx7yWzKaRBpq6dZTZ8t1KrcKwhcSAgcxXBeyMa8QKUdClEOhAn3StKslYzgzjffSPCmLQU0ddVRJVYY96iLtaMm2DkCooBNhrZhpP2WxFHd9XV0mg30um1EeShGk6axeTbTloTpcIg9Ct3CEHE%2BRzOOJXyjV%2B7pcICD7W3sPH6MWqOBTquFgA6D5pnwLPEi98QX%2F9SpFcP5AsOhSlpBoIIATforKFQQeLUQMGcIWmUdtUKveY16AwmZCkpaPdP5aitalf6MEBChxTQkXrIUs%2FEIs%2FEQSRCiXqtJ40jNJ6XyWZZKsJDEde1pStMUmTSg5iRoPplhNs%2FkWTGjIEJeajNk3IPJvZxZCu4LpTYzm07Qn4ywk0Ro1iJEdKYxn6O%2Fu4OD7ccY7ffR6nQQ8WgAagtmGcJCu%2BlIxYrhfMberqJfaQhU%2FEjR%2FW4ZKwyM%2Ba4tAxlNWEeYjQaoRxEaSU17N4kfp5MJZsJhgda9KE4k9JpMZ5gSN8q3UIZ0lmI6GCCbjIF0pm0F3IdO%2FBfOM9S4zSDIkY5HGE4nel9rt8R0zmYp9rcfS7s67veR8BxrmoZwL%2Ft0BtRgGk7fEmlxY0AAACAASURBVDWk6lgPjupeQaCCwPNDoGI2nx92VcrTggAXUhkMUYMZoNVu4bXXX0Ov19O%2BPDIj2qtJLedplVnlc2YQYB%2Fpp72Uc3O1Twk%2BciRxiPVOBze2ttCs1SXxHw0HGI%2FH2oPUW1tHvdHAdDbDcDDAZDRBOplhFIwwnExFtFFTyh%2BJNBJfo9EAYkDTGZIoRCOJMZY52Q6atQT5bKr8trd3MNzbNeYya2E%2BmWK4f4CoMUMr6CFsRNKgV%2BTVmQ2NKuMKAlcCAlypqNEkk2i%2FXEwdNYhJGIAM4LXNTXRabe037x8cYDgcygM7HeM1W015qt076IM%2Fms%2FO0hT7g6GYSu6B54972Clsm5KJnU5kmotsJu%2Fd%2BWyGAbcNfPMQ%2BXSC8XgK4sDR4ECaTFqXcP%2Fm4GAfSWOGBjogk5tzA2l1VRCoIFBB4BQhUDGbpwjMKqsXgECJ4VzrreG9995Du9VCktTMcQL35jn37txbUjGdLwDrM0tKAouMpu1TsmLMSyzpF0rg03QmgQL7ttfpIJ1OkZEZnEyQJDG6nbacQtGRD50Jjft0djErvNjKs%2BKc%2BfOczkh5HuztYW9nG%2FPZRPuh5tlM%2BzipSX388GsM9vekPR0Ox0gnU3ks4bedR49wcNBHe31DDocajUahjTgzEFUZVxCoIHDJIeDFbSZ0405whtBKh2wcTWfjKES72cRar4PZbIrJaKTdmfRSy7Bur4fpNMVwNDIGklrIIERs56QobujWQ%2BLH%2Fv4%2BdrYfyVR3Mh6DjGZCnDubYOfRQ1CTya0pB4MhppOZ9mtORkM8%2Bvohkv0D9DY3hQNNSuhdrF7ybqqaV0GggsBLg0DFbL40UFcFPQ0C1GpStdRsNlGr1%2BTUwNwkuJTc4Fls3vS5VWynh8SrvltPrOgPZ5JKk1c6fzo42Mf29iOZu3KfEt%2F39%2FYQ9omOcszSLUn1Fb6%2Fp%2BNLIp6PSdNZ%2FsjMyl2%2FHYvCfZvTyViEFk3JqN2sNRt23uZ0it3hUIRaktTRbjQwl9eSQJ4bsznQ6KRUkupaUftXDdaq%2FAoCFQQuDASIQZ60weeyRWaRd24RGAwG2N5%2BbOavATAYHGB%2Fdw%2BT2gg8jinLMu1Hp3XHYNA3j7FJIpwWxbE82PLMTZ1BzT3u05mcr01GAwnmZKYbN8Q70qR2dzhQvbgHvtXgVgU6FgoxpUfcAGjNZsYQ0%2FstmyCEWNl4XJhhV1W0gsA5h0DFbJ7zDroy1ROfaWa0yO3ML%2B7d1NKtPZuEhH1fzRCsDr0y8DtXDRW1YjXiI8X5utOFf65zVO%2Ffv4%2F9xi7qtQTj0QjD0VDax1k6xVhazhr6gwOMJ2Ns0rQ2qeNgMBARFMlTo9FD9MZIszOkU0ybDe3PTIIcUTbHbDoFzdN29%2Fa0P3RrcwONehNzhODRJ3M6H0oaaHZ70qqqwtUwOlcjqapMBYHLAAE53KHX7DzXPvN%2Bv4%2FZdIzhsI9GvY7BQR%2BTyVgWHty%2Fzu9JrYbhcCTBW1I3BjHHGAHXRSd05T2JE7RaTayvrSFvN%2BxM4izX8U88vPPx40fY3x%2Bi1W6DHrhrjTaCMEEWhkiJmuMYPCaKTKx5wy3h78sA%2FKoNFQQqCLxyCFTM5ivvgqoCggCJf5pHBuYwiJJdnrvpPZVq%2BXPe%2BnRumxJVnMF5HT3sGRJCIU2eKUUngcQz4uJY2skRnQVNxtqjxLiU5iOJ5SiIEn9K3unQgna51HLXkrqaGkYh4jiWloBaUablMSe1cAt5t4OE%2B0J5huc801EoNDE72N9Hq9HA9a0tdHtryjudB%2BCx5xnr12jo7Doj4JhjJdE%2Fr%2BOqqlcFgYsGAWIUu%2ByJeIZbCiaTCfbmmbzGptNUzs94pNNsOsPu7q4cpU1mqQR0tVodkBMzO3uTKlI6PSNzyO0Ha70eGjHVplPzcAvoyCiayvb3drVPtNNqggK3dnsNQVwzZjMIMQ8DRDU7t5jrbp6H2gsq5OqrXt0rCFQQqCDwAhComM0XAF6V9PQgQPJeHkZpEpSm6A%2F6aNRqkthyMfW7XxYL9%2BmVXeV0VhDgsSd22DgZuFoSo1GvoZUk8sY4ODiQGRfPgOt2Ouh0ukjnGfb2DzCiFhOQAw3tpZxDZtVkSmk%2Bxj2budNe8mB0CiZiei%2FOZsWeKMWjx1kSXpE5lxIDHEV2TieJqjnE1M5GI0QcZTXzAsmD1A8TW8aMGqzM7LZiSs9q5FT5VhC46BDwaxXvxBfasxmG0m7KH0EYSuA2GU%2FkTGituw76KyATun9woLMyp%2BkcSbMF4kAee1JY%2Bzhh3pyetmlyO5%2BLWaWWkt63dX5xnmPmDEuSOEYtjiXU45aEQL9IezdT%2Bi5iHuMJkpadOUxm1rBbheMu%2Bjis6l9B4DxAoGI2z0MvVHUQBMRw5jn6gwHu3buHXreLG%2BE1xHFHe12oGSNTUSb6K9CdYwjQ6ZOYzcw5%2BMm1x6jTaWOj28VuFGFvZ0eaxHq9gfWNdWk%2FuZfoMQ8%2Fz%2BaokTGl19p0btpPd1QK92%2Bm4wx7u7sYDg6AbIogm2E%2BGSHGHI0owozeZodDUXp0mvGI5mSDIXimZh5E0mzO8hBZGCNqN9G7dg2tZM3cG9HTUYnbtHPvTFtrR%2FFQA3%2BOYV9VrYJABYFXAgFzkmbYwzOcQhbcDkLrjijC2tqazsrs7x%2BgTwdms1R4jqawZBzJ6VHDGYdAs9FAs1HHNE2FkYhTeTFvaUf3dtE%2F2Md8Ooa2EBCD0QooS7UvfTqbitEdj0fYfvwYB%2F0hENUwJx6MYkzJlOYBaq02tm6%2Bhmat5ly8VQjulQygqtAKApcQAhWzeQk79SI2iQsnGUkea02nCGQ289dew%2BbGuomFHZMpl%2FIXsYFXtM7SJHJ%2FEc%2FSpLv%2BNJUGkQRU2m7LqcWMLvx1bmYuoorHARzsH2CSTTDlOXPTKWpRTUIGOhmi5pu%2FCU3QeDTA7rbOr0NKb7RjmdE24kiebpmeaebTKXZ2dhDWhmI05zRDkxltjDyuoTVfQ5N7nngmqNsPtegyIxm9kIN3xquuCgIVBCoIlCFQMJcMlGfuxVeiDDKiZDZrtRo63a40mvSMPZ6l2mNOKw1uG6AFCK045tSIBoHwHZlPbR2Qcx9bK8fEa%2FRE%2B%2FiRjniqR0Hp7MypjkOhYM48gWcYT1LESQOIEmTMn9rVPEAWhGjOUnQ3NlFfiQMX7aieKghUEKgg8KwQqJjNZ4VYFf%2FMIEAiPsgDk9bu7mJzfcPK0gpuxL39NZPIM6vIUzNmhZbIiqemuJIRCi00vTPmjqGci%2BAi88kfiScyocPBEDzChPHIkJLKytJMpmT7%2B3toNXge3VznzXkijiZlJNziOEGUZ4jo6z%2BJEM5T2mKDTCwZVWklwxxTnsMZJ4gbNfPGCJ6rGSNIakjqDKMhrbN50wEu5vV2dd%2Bx%2FyuGczVsqtAKAhUEVkGAGCOf58JlPB%2BTjCAFV7TiGPYH2N3ZRqvVlqOgeZoJV04nU%2B3hTJWOZxXTkyydrfFQFchSo9ZoaAtAjdxsSqFeIDyaZXOkFPJlGYIwA8IYcQJtOaBzNWo3uSkhCyMdM8Y98bwqzLaq96qwCgIVBJ4XAhWz%2BbyQq9KdHgTIlGiBsyWOjg8yOQtaNpnVQu3OcZRd7enV4NlzYmWe0IA9ezaXKYVA4hpkPWkv2v0jZz50GGSM52Q0FnGl%2FZY8NY4Hlu%2Fti0FMHYFERpQEFrWcs3GKdJaCBBL3PtHREE1lu70ukiREjAw10knpFLPhAIP9XYx15EmAKIl1UDnrxHTtbhf1VkcaTYSivBDV66iTYKPDDG8Hd6hzzHzWCxnKLTwUsXqtIFBBoIJAwbT5%2FY8MyLU%2FkucKHxwAw4MD%2BD3nWToTDuQeTlpkkAGNkxqmsxn2dnYxF24KJBTjScO0AoqTGL21NTlJi4O5BG3peIzpaIghgNl4LMaTWweI2%2BIw0v7P9toaklYbQa2GDAFmXFdrhgMpxCN2qzBcNYQrCFQQOC0IVMzmaUGyyuc5IUCGko7haWJk5on0NtrrddFo1GU6SS%2B1YWjmRK9Moeh5jKICRcBztvtyJvNntBl0SBKZFTQ72EygA2kb93b3cHBwIM0knWWQEOLeor29fXlfJKNJU1uanlE7mU5SzLIMcbMpJxmUwCeNOtbDdcw7LcRBLoYzHQ%2FRD3IM%2BwfygFtrNNFoNZWWpmrUnidJDZ1eD%2FV2FxFNyuIY2g1FR1TyC6RzeEod5MmuhfnsZTOjfebRXFGjpfFRPVYQMAhoHfPAEPIzpo2YkN%2Fk0GeeYTgaYTIcYjaZoBZFMqnlVgIK1Pr9gTzN0mKj3eniYDjC%2FngE%2Bt6O6%2FTKbXkRlzWaTR2RQs0lmU0K28b9PvrzDCMK9gKYN296n6XAj5rMMAL3yPd4DEq7LSZ2SgEvwxtN2vmaFUnFbvqePPb%2BzLjz2Nyu6Ec3V6z17og7AdatxRrLFaQv8uiomM2L3HuXoO7CIcahwFhOgMzHG7fewNr6upgROUygsQ89ii6t5mcJABa06iLCq5DeKshYmNuY5PY0Clo6zNzMs6ixloMKZyq7ubmBjfUN9f3u7h5oMptlOZqtNnq9HmgGNtjv69ByZOYYgxxokPMcuVBn1OVJpP1K0%2FFEhNre3gH2%2BkPtRaIjjs1rWxiOxvjm8WNMeKD6cIS4NUZUb6HWCBHVEsTcF0VzMrrG4KA8JNlfZi6PGhtHQ%2BU8f%2FGj2d%2BtrofbuHgvxys%2Fn%2Bc2VnWrIPCyIOCWM7FqftbIlF9eX2lCC4zHEx0BFSFAq9fBxtq6NJncV86jmsicdtptbGxtIWqMMNvZxoh7Nmk66%2Fa3h0GIWpTIFJamsjnPGp7OhOsO%2BgMcDIc6T3i9t461bg%2Bj8QQMH4xGCPb3ETeaCGs1hLU6kiRBEiXyYps5%2FEo06Ov%2FsmB3EcvxOLCC1Qv2ngck7%2FqZsMSTW1qWfZwXLKpK%2FvIhcKmYzcM7%2BQ6PyxWnGTzF0cdq9OHoaGlYfJdp3wUlh8U%2BNf9lcTeClcSsP5TZzpRcxDhc48WX8pMnhsthF%2B2ZLX0CuuRTgkBMRlJLpNmiFqq46N3UOS84GaSKlCd88Ln6mvHuw5iFf%2BadP6nrFsHlUnwW5bBL%2F2yNNuh4WT5BFUiiHoTm8IJnx3HDUbvZRHdjC2tbW%2BrX6Rzo8xiA%2BRzdtXVsbl2TWrSe1NHf72MejARrOfzJUuRz7neaS%2FM56h9gf2cbO9uP0N%2Ffl2las9PD%2Bo2buP7aTRFa0zzAwWCg3zib42AwQm9jA53eGhJqUeMYOfdtau%2Bm9bVnMm3OXd5OLY3oVTNzMd455vNA%2B7xKxoEa2WXo8NkgeOkHfdXACgJPQsB2CyjczwsxinPzYk1cyFlUo5XF2ibWrm1JqzmcpRhOeWAJ0Oj05LAnbk2R0hP7wT7Gkyn8Xk7mYHvbU0wmY4wGfQwP9tDf28PB3j6m0xSddgfXbr6Orc0teXmff%2F0NdvcPsL27C%2BLA7miEdm8NzXYHcSPQ8Sc875hHo0ioVzGcT%2FbtkSEUl7O3XY%2BTVmEfHUaEkrAfmcnV%2FuAEvVcbCJez9ZeG2fTE0lI3%2BUmuu5E%2F9ncplntZfDFNmjGOPqZnMI2pXGg%2FSIRaGM%2B7mts5WMWEoTlAkUPB2IahQ0ZESy5ju5v5AJ8tXZF46d2%2BL775Ei7anS0QJNwDYRnFEVpRC41mo9jfx1iCxxk22TMTvj8MlscVuPimJ%2Fe6lH4xpC5a15xSfcmOUAQUIowS5GEsky0642nUG%2Bh0OmjR%2B2HP3P03xhPUByOtzZ31TTQ7XdCJRn0yw2SaIqT0vphvmc7oHIyG0gTwCJSD%2FT0MhwNpCNqdHrZu3MDGjRto0lysQ%2B%2B1QPh4G7skxg762O8PsXdwgN76mgiu1loPtXbHhEiL7i3mqI0RgoYfF3P4lID1SrLxzdRdwp5VLfP9yCou2s00%2FmeVt3hXfti%2Fkp6sCj1PEPCzRFrOomJc30Mdf1JvtGSVwfMzO5ubqHfXEKYzNMZjNCW0DtHa3EDMLQZ5jqTZRG02wyyb62xMnbeZB3IktN8%2FwN7eHvoHe5iMhphOxqJFGp0uNq9dw8aN12SmGzVbmCFEGsZiOIkHh%2BMJWv0hWt0emt0uGu02Gl3iQHr%2FLs%2F2ohHVw1EQ8MJwf18Qf4sUq8IWX6%2F4k19NtBo5WLhnwk2%2BPVYw71ccahel%2BZeG2VwFcA1TP24d4uRrmRhaMIvcF2iRjWHwDJ8EfJJY0Yscvxl%2FaIczs1yGyVNmPkeem7mg1WdR0iJPq4FnXn16e%2Ff5GzPLvYwk54T0HSH4pJhsVcsvWhgdx4TI5ZjFpLWmpba2s%2F38LrblGM3xi7fakwjH5cT%2Bs3Fi95OkOS6%2Fy%2FnN9Jpu%2FFOjSScU2RzzIEKj28PW1hbaYjY3EFKwkAOtLMN6nktr1l3fEFE2oDnYaIxJmskkTAeT1xIEIb0Wj%2FH48WM8fPhQToTo3p%2FHBrR7PWxubmLz5k20ul0gSRAlNfS2riGPErn9z3d30O8Psb%2B7h9F4hM5ohOthKNOyIJY8eomp5PwlrpA5nOY8%2B%2B1y9L1Gs1PSEw8J36wYliY4OPRhBQhWBB1KVL1WELi8ECjGv9Nu8l1hxB8ht4PEqLVaWN%2FYRLPdQrO3hrDVQpLPhQPntZocobW7HaRBhL3RGH06%2FUkz5GEkT7LczznPc4xGIzx%2B9BgPH32D8WiAKOSe9BjttXVsrK%2FjOoVtFOaFIZJWhPXrEeZxDajVsLe7j8l0itHODvb6A3SGQ2zdvImk1UToEcHl7abTa5mYIKMTjTgsRsDplXGVchJf6ewUy%2BQW6S4uTtV1ISFwqZnNco%2F46c87h6u%2F%2BzieYRRjI6aTTKNj%2FhjJS6tEdJoZrDGQNv55BANz9toPT5xa%2FpYPMzHmloiJmlP31VfOVcbnsWBqfDyLaOkuz6RTf%2FAPz7KWJ1pzlBDRCUxMhwaEN5lNv2o7QJ3J7fDIOJNCLnWmCwgGtLjUXJvxKBP2Yb0u4mftxg0xm0mzAZ55yX%2FNjQ0E9QY48xq1Gsb9AfaGIzza20U2pSfaCE0yqN0uknpD3maH4xH6wyHo4IKa0o2tTUnxu70eWr0uffxjmpvFQa3ZQi8IEcYJeFRA3TkpmvLwczohylKrrHpneX7ZnFyEcQ6WBUaXpUPZQk9nHkJLRzZxAZUjo1QfKghcEQiUZw2f7V1n90qgGophjOoNtDY2hAPjppnwE0DSZnY6iKNQjnwGtMAYj7A%2FGpnXWh711GhIeIaQArwMo%2BkUPG%2BTXmVb7Ta4T319fV2%2FbqcjAmWapsJ7zV4NW7U6okYDxIdkOLm1YDybIZ5Nha9Fo7w85wiXZFwsY8EFDVceD5ekqS%2BrGY6Jf1nFVeWcLQSuDLP5NDCSOeRB8byTyeGP3E2BKqhdc0woEQlNZmczOyOL3lO5wV4MJ5lSV5hHOLwrPxfOcqgJZTofx9eP7z7MM6P8ZoQtc%2BZvGbH5tBft7luhVs1zzNy5Y4TP%2FsE%2B6rUaut02ooge%2BAgDg6ytgz71RWv11agvtWA6A47dFIQ6WqSzsYFauyUiqyHX%2B00dSUIvierbJEbUboFim5xu%2FpMpIpqPdToIuMez1ZZGtLO2LscWMfccrW8ijxMdB8AjAEhoxUkiIM%2BjENz9JI3c3BwK0RytF9fQaLbQ6fZkRtsfDkzbUG%2FY3lJNPBtrzMjPST8vr0YPnryVHlKaxydPVsWsIHBJIbCYEX5O0AssmcRmtyctI037hQPbLSAKMeWhmVTcNLmFxDyv62zM2Uz4r8WM5nbGJgVpSauBuFFHCzk202t6Z%2FputyufBy16qSUepAXIdGZWIRTaxrG8367FEeipm%2Bazrf0DjCZTee1uttt2VJTzeHtJO%2BjlNMtL7V5OaVUpFQTONQQqZtN1D7VnJEtJ9BZEpWNuih70jKA2YiyYQqYh81g4%2FhHDaQuOaG2tIpZLwTCVOcmiAP%2Fg62AMlU%2Fjv16Wu1%2BSBXcHe5oGHfQPcPfOHWxsbKBeT8R0mtqTKSpTivPc%2F0WfSvNnDGfIsy3X13EzDDGZTFBvNqThpNML0lgyWnUMHj0OU%2BXPfOJOB1tvvIHOxqacBtXiRGfEhfU6UoQ6BoV7Mjv02EgiqlEHzcvoQIhn01FbynM5WUKWZqA3W%2BrHGbfe6SBptbSfczydgB4YqS2lAIj14Zwr2iKAcy4SP3joFw8%2B4Ard2XbDbOYe2oRhDOX8lZCBZ5oqTq59tgSOYbPjwUS4F%2Fj3%2BKjV1woC5xICfpybIaA5iaFDIO6JvHn7tvaad7pd7cfM4ljzJeOxJbyIBzkHAAnQuIf8%2BptvYGM61VSjB246FeK%2B9zwh49jGZhyhk24ofr1el9Cb82hC792ZVk4J02aBaUJpPURz3HqXOLCD9sYWJsSXUSBHQWRIVZuysP1cQvocVsrRiBoDJRqPjzYezmGdqypVEHgJEKiYTZKQJWaR2kvD9zwyWR%2BXusETm2ba6ZcVejHPQMc%2FYUBidUGI2pNscAti1WtKLPtFXCOyzDW6kFPBVy3iXDZhGVum1uUmzc3DANynd%2B%2FeffAsxRvXtixCCXEvdUj1cu4g4Efr3FZc7VPi%2BZidKEIynYooQlJHFgApzclD7tk1ykbMpmNaoihBq1aXo6A5z8gkAUarAh26Gsr8lvMwdpOCDGiaZTpPjiZl3B%2FFg9B5zQMyQXmhNY3CCFESoF5rIJ63df4dD3OluVt2CKJ%2BXvq5T3zB66oyRdZ6MoU2eflu5tK5mPbMz2XiL0W2jaB8XGDMQ0BmHoKrMfRHwZZxjvr2ZI5VSAWBVw0BbiWgwAVy8rPZagnXcC4Qj3HIk7EjntJU8eshLTGCAGGSoMF95xkxGh1lR4gYN58jJaXBOZbE2m7CvaCIeGZwLssrnk8t3BolwpsM5zmfok8CKlSJA2M063Uk87nqESWJ6sH8y3TMq4biRSnf8Jsj3MjUs%2BJClAzznXtRWlPVs4LA6UGgYjYdkUPNpGcgSdB4wofYokwgFQjYSbAYj2m9ZpNELVcQIRmuJDS9dauI5emJKuvEJwknw0g%2Brv%2Fu35klf5eG9%2BJi6xwvsa38N51Opd2cTqYFsna8CAJplU9vAlQ5nQ0EPOHE%2FZh8Zr%2FmUYywRqvaCAEdXIicSaXd9NowMny85tlcpl8krIIw17EkkgyHJN4CMZpMTyKNWklNUg4SlkftKA8mZz7KjfOQZvHUtAYyY%2BNYM62qad7yIBJzquHliYQSQ%2Bnnn4eWn5f%2B%2FSrf2b%2FLP%2BtxD5MyjbX8xcdY3I%2FDbb4PeK%2Fgv4BZ9XQ%2BIcCxzsv0lAHCODLLiSAArSlSHrhJfKXtOYYniceUTlsLKKwxh2nEY8KMXCPJpNK%2FgWMHs4C4jqX4rQsh5hG0RcHjSj9nAofneNhnlhMHsg7cR2rMrhe0ybrD1d5aUf09DgJG8ZUpxeNiV98qCFw9CFTMputzEi%2FeGy0ZR5qaSMt5aEwUhBOpIncpvqioQFoVmcGQ8PUaGy4fjoEl0veIn3dey4ST7R01TWmIOI4KD5i%2BvGX2dxF6EZ%2B0YBbMvcGC0lhKcLWn1TEfR7dNgD%2F6c%2FXlpUPAzwzdyRh4DkJzIhKzmMrcMgfvoq4ohXfMoeQ1PLg8B2Lud%2FZzJOQZmKZ91DwiscU8HdGlkUDijUEMd4IgFc9z6hTXGFWld0IiDyAjtxzR5wNX3Jfn64oIVzTI9zubX34ug4NdU10VBK4MBAwNCR%2BRYUznFJDlmOW5LCjM7Z0J0JbmTBiJBqFEjDhOTOM8l9du0Q8mXRMpEEROmMeyHDMqKw2W4QRnZCopqJXjIeFBIlsrscDPMF8UhiarmXriMVrQcUxRwe3EcKsiXikIVMxmqbvJNNI5DfeVzbMUNedoxEchkenwipNW2hcidCIZenybzVK5Hq%2FTY5zb%2ByXSyzFUzH%2FG8wK5RyxJxFDZflHLK00zOzOrfyBvdHR4Qi%2BbPg4XAr9W%2BHpdljuXPsKYZzDyEGq2O6ZpkNPmimFXYz1C98uzUl4WMFz4drB3ip7huHf9qoEr7WKOPEtN8%2Bj2J3GN5n4%2FCnkooec4INtHxlEy%2B8iYSM405icCjDFookYiSfOLjoZsDIWRaSpVF69BkDdIk%2BbLTIxS%2FRJ5oDo73lfhRnWVWnPhu%2BYMGuDnooOk%2BovPfgRYkeVYx1XiOEb%2BuG%2FH5Vl9Oz0IyLqA88IvhKeX9aXMSbNAa7aJsmZZKiaTuI4aSjKFwmmMWAKr8J%2BsOgLtQ6dVCLWR0oRSiCb4m4Zf2krSJsKLNvOY3t5N22lGuDYtY8OwyqsoB6wH8bJUppeWxjjTQbYSya0MPNNqVJlXEDiPEKiYTdcr1CQOh0M8fvQI9x%2FcR39%2FD9xsz4uMIS8yfHym2afthzDTPH4No9iZ0%2BZ48%2FabeOedt%2BWB08xr7UgPmofu7Ozg7t27ODg4wK1bt%2FAGHaB0OsqXeZPR%2Feyzz%2FDpp39EktTw%2Fe9%2FH%2B%2B%2B%2B64R38JbZmaoCl3gP1oIWf%2BSmbKIyQDypvf222%2FLQRBhwIU1NL5gxSLInAgYf3%2F5QCm0s6pDqfwruM4Yi1iS7zrmg73DS3uIaO7lCCb2uRek8Bxbkkh0gsFzVXnWG73QUvJemFrzQE7X2wvGUz3gBEC258%2FmXVk4ZKk0b5UDKUAeqSNWViH2Z2F5wFaIaHOCIo1VZ%2FLm45YSXtlHCQdEwL4YCDT%2FHb71ONeHvVjOVerThIDQmub1QjLDWen7TLP%2FCuK%2Bo2DscZ9oB9ISxG%2FUXBYO0ogY3VnTZPkYR4mIf%2BgZn3sxIzGbBCsF4RSWmQmHlUp8KoGbvOaTRvDMJp9z2yfPfCXso0mu802heMzVamnWH0e1pAo%2FGQT8NiyB2yWxdUnCmpNlUsWqIHCpIFAxm8LzgRjF7e1t%2FNd%2F%2Fhf%2B679%2BrcPi23RL7hZREsQ62oSH0894dIkhbiJvLQhJgvF4rPh%2F9dd%2FhVuvv4Z6vSYkzu%2BMl2Updnd38eGHq6ujzwAAIABJREFUH%2BIPf%2FgDPvjgA%2Fz85z%2FHe%2B%2B9J4Kbh9L3%2Bwf45JNP8Ktf%2FUoH07%2F11luqm406b%2Bp78VfyYnmT2U%2BAkDtS1KwA7U4bcRKjXqN3URuiXIBF5xsgDv3lQvmKYOIpCdaoXIWigYeqeqlfA9tTW4aDA0pBiIrBI7HDxXcuplJenElEifFjP9MJhmdbSXiZxlKgc%2FAug52A179yuYxQCDJIGbNuC%2BBr0Sdh5jvN5%2Bu0nYuYpadS%2FpVyp6BPSwA6nUfP4DM3jpuK4TwduJ5FLpo2Yo4Wk2vxdBYlXsw8C4Ekt5MTeTimT61xY9zYQmMSF62koM22FIhplPWrpTes5%2BehY3CILomnhKv4h8I6w5Asc3EtnjnHfJ8VoT6fRYLq6QgIeNj5z5wOhy%2Fx%2BQwvAHw4RvVeQeByQ6BiNjn%2FHRKmZvPLL7%2FAH%2F%2F4RzF4zWbDtCyUQNLElh7ieNgyCeEoEoIm%2FuCPjCa1lo8fP8K7772LyXSCTm7mr8QvROckqmk6S8b10aNHGAwG0t5dv34da2s9TCZTfPXVPXz66acg43vz5k0d9eAJLttTatqWyzAshXe5bhIDlzgBMpjyukcJsLDzQnMlyevSonkZIHE52sD%2BVJ%2BuWFTVx5wH%2FMYr517MUHdprcn46ZvsaUUwaUgogUnhlTfLOJS%2FEVMu3xU3X7b%2F5OtZJtYYZnXTgPRRNXP54nGEfTApdSnSlXtkF5RJ1MMwXgKI73PfgUsfV78sw3t1nCq0gsBFgYAXtmlcu%2BWO08EzmNJF2qQqL4Vq3pzHNolbYUI%2F0xaTiU8MtfOJHSITMnP75Q8ByeIv%2BJ7S0vsEL%2BSn7qEsqtcSBBYwOrx2lCJVjxUErjgEKmZTuNmkglmaimkks0Pz1h%2F%2F%2BEe2bzPPpZEcDkfodDtot7sIwwRZPteByTwXsj8YoN1u4%2BGjb9Dv9zGdzsSEErFzH%2BZoOBRzyT2ba%2BtrqDfqYiq5J%2FO1116TdpNaz9%2F85jcKZ7xWqyXJPsNpakvml2all4kQ08LHBVT7Ya0fuHAuEDhnKGNZCL%2FxrbrOLwTUW64D1b9F74lWMqbOODv1pRxUlOPzG98p8S%2BFW4td%2FzPcDQvKHoxoexIm5bFSPJfy9GH%2BrhwKYcaCqbxMc%2B5JKD1HCLvI9RNhU8HnOWB4EZNwbvDn5tBFbMKrqLPmh0MymjecM3mgrQKsj9Y1j%2FZKFVQSOfJxGkoxmx5bLfCjHU9s%2BzOZnHvfiR%2FdroNSjoY2mcNh3KpcHV6tuncJZCd6EUzZk5weJW3xiRJXkSoIXHIIVMwmzVLmcznt4Rl91D6ur6%2Fjg%2Fffx09%2F8hPUkxoGwwE%2B%2FvhjzLNHeP211%2FHOO%2B8hqTUwnkzwzaNH%2BPTzzzCZTnH7rdv43ce%2Fd2f9mTSSSGc0GuHe%2Ffu4e%2BcOdna28fjxNibjibSbv%2FzlL9FqNfHgwX3s7e3jX%2F7l%2F%2BCzzz5Ft9vDw4cP8dvffqRnajlv376Na9euFXvcLtPY5GJrjpaIqOcYjcZIYprS1hDx7NPi38tutVt9X3axF7A8W2xXV1yEDD85gkpW6IrKPZO82MN2WT6e8jKy5zAzo7iua0hQ8dFiukxKt3K%2BpWA9WlmW1uLx70Jndzh%2B9e4hYNCWxQaDPJCXH33k6n6JIGCMU6nDL1HbzqopHn%2BJCaEQzeE7j3OM8TMs5pnARV0MwZkIdi4axSM8puePch%2B%2FzcTJ8QoLkDJu9PFZhpVtdz27MKV3H4%2FCqYu6VU8mPfVwWEDMw9d%2Fqe4VBK4yBCpm0%2FU%2BFwGe7SeyM4fOehyPxmg2GmIWv%2FziSzn2oZfZN998C612LAaT5q7URlKz%2BdM%2F%2BxlqtRrCiI5HqGsxRnb%2FYB8f%2F%2F73%2BJd%2F%2BRc5%2F6GjoL29PZXx1Vdf4X%2F%2Bz%2F8H%2F%2Bt%2F%2Fb9ySETGlOa8NKn993%2F%2FN%2B3tpMb0O9%2F5Dv7%2B7%2F8eW1tbYsZ8%2Fhd18JYXQC6cdM1OJ03sh9lsikePvkG71cb62hoi7X01FkDOgiTdPauWO7ZWFjG2XFSsx7PD%2BsiF1hE0nvg6Kmem16%2FQMj4ZU2VwILnC3O3JiIsohTRfkUoJ%2BFiQCaxjpbxZCcdVgZofBfAIO09Kr4pdhV14CEijbZOE88b621rlp1RpOFz45p5GA7iueUTlcZ9g55GX4xA9%2FJbLXJhn6ruOMVmGt4U7C48S7vLF%2Bnw9k%2BnfmQufPYPrw6v%2BW%2B6Bo96sX%2BlF3Y608VND8f3aJWAu%2Bv%2BovKrwCgKXGQIVs%2Bm8zFKLxv2Ys%2BkMf%2Fz0U3z8ycdi9P7%2Bf%2FwPjEZD3P3qrvZy7h8c4N69%2B3jn3T9Bb30DX927h%2Fv376PVbgttc0%2BmORLiK71h5kjiBNeuX5dDIDKOZDZpqsu4NJH9xS9%2BgS%2B%2B%2BAI%2F%2FelP9aNjIjogosaVefH9rbfelimtLVR%2BSbgcQ5PEqiFpM6PlXtY7X97BjevX0W420SCzabYppnNiZI%2FIzwIEBK9fG3inYFmr9lkUdjXy1Ih1jKbW3pM02%2FfDMXGLfPVwTER%2BcuX7WOrSMmHmP5TCfFB1L0FA88HNCT8%2FNIetZz0xveDeS2mrxwsPgeX5u5ikNgUXjNGFb%2BipN2ABOcJqFeO3qshFqmXG8HDcAgUyQQmH%2BR5aVZ6vB%2FMq0h%2FOuHpfhoDrkAVNYGP%2BKPgx3kJgXc2PZWBWb1cFAhWz6ZjNWI576PQnR5rOcLC%2Fj48%2B%2BhCj4UBMHzWYYkZnM%2Fz2t7%2FD%2FQcPce3GTTkFiuME73%2FwgYjZLJvTeaajs8x%2Bv9fr4bvf%2BQ7eun1bWkvuxyRBRkby66%2B%2FBh3%2FkPn8u7%2F7O%2Fzwhz%2BUF1o6EWI8MpyNRkPHgXS7XZMinyWj9YpGPpvkmXQzO74nTe8td7aYb%2FLC2PLVVFQLdnn1fzXVOJelrgLL4QVYcVzgqvi%2BYYxSjuvDn7gfl8kTkf28dB8cQeaz8OX59xXJqyBBgBByUGJHOU1mwWRWULpcEKCQxglqDs%2FnRUNLX%2Bj52b1WMroFhFY9laC26vOTYS%2BAnOSldlV68j9uK8KTBVYhqyBQMJriHTne7Tgb0nJ%2B7K9KV4VVELiqEKiYTZJN%2Fhw9eowNQ9y8cRPf%2F973xFxyDyW1j9evXcOPfvQjvPfun%2BDhN4%2Fw5d2v8OWduzKlfeP2m3j%2FW%2B9jd3cP6SyzMzjtJCtJC6nB5I8Of3j8idda0myU52q2Wm10Om15n6WzoM3NTTGfZDRZNzKeNM8lQ3pZLxKqcRxJw0nN76A%2FkDktA2SU5wSC9vyqWc5FL3iyWwt5STbMxfukFwmOZ4h%2B0mxfejzBokQ9eRgU7St9e1p7%2FXd%2FX9UYZVfKc1WcpbAVcVVnwn%2FFt6W0V%2FhldR8YUUVv0dpT7TaMLYPRpST1tfzhCkPzYjV9uduEfd3K5ttxeHQ43JwH5lFa0Q7H8Wmv7p0QIWxPAhkfR31BAVnJQsN%2FW4LkcqctfTqO4TxcmZV5L%2BV2uV7KYDuu7fzmKRCm4V5aesnX%2BdChHXPHnrX8yrleLnidWWsIYP2cgz4BvAg8s2KrjM8WApeXeyngxkF63MUBTQYxlVaTdFGn18F3vvddMZh%2F%2FOMfdOZmUktApvL7P%2FwBbj56jO3dXfz%2B9x9jmqZ4%2FzvfxhtvvAlqNamdEyLiIcvzDPM0xd7eLgb9vkx0PQNJrSWZzbt37%2BLevXt49OgxuH%2BT2ktqUcmcksk0bUEOak%2F5jYwoPdNexott1WHVCMC9sTQ%2FJvOvS0ynLdAvhr6PSi2MdiRYWbegkFo6JOhiGxr0y8%2Fy%2FheW5tGkz7xcAz2TeCiZPfl4F%2FO%2BmG8FA7cIeuYmFXmsSMlsPUO74vOJgpj%2FcvWW306UySWOtICGf7I7x60xmiGiMLLjoAo4lOIWg714KGJVD68OAuyh43qE3%2FS9FJH9TaJaR3%2B5ffM%2Bj1y42%2BdJXEhPqybEsdHgx8Tptvlscj3dOq7OjXv8TraeFW30Dx7opYz9J39n5%2Flnf%2FfRifN8FvrmI7hAvpZ%2FPt1Z332dTlKOrzLjPku6o%2FJWHqVMD6%2FHi0%2BMyTcHRPehYDZ5jrTONrU4jO3rJ7j7l6MqcuXDCTczOzbQOgAruMR8Xnk4XTwAXDJm0wbqohvcQC3Q7uKLPS3imwYxQL1eK8xWP%2Fjgffy3n%2F839AcHaDSbaDabuHZ9Cxubm%2FjDHz%2FFL3%2F9a8zGMx1Hwm%2F1egNxlEj0mKUZ0ukM%2B%2Ft7%2BNd%2F%2Ff%2Fx0W8%2BlFMgaih50VSUzCa1pr%2F73e9kTvsP%2F%2FAP%2BNWvfqUjVDyjSSaHz2Qyv%2F3tb%2BNnP%2FvZJWU2DS2zR%2Bid9403bumIGEoL2Tc8HmOOHBEdL3EleK7rJOnMnkjMJUkmt6awD6hZ5i%2BkaS8RoqT3Pk%2FbleHfeLdn%2FrVxyL%2F%2BzX8vmCX%2F8Yh2WQ5HfDw3wU%2FWUiG%2B0eV6Muyoy2dTIpiOjOoJJ5%2FmqIirwk%2BQ%2F6pklyWs3AXlZ2vfIsTvNypCnGaFczOOOCcizUuOZR1jsxJA7KAih5UxqsCXAwE%2FVfz9cKnspfKP3z2DKaI6ChEjBDedZAFHR3kiGaNZ9LZ7MD3PUSUersHJ3n1u%2Fn6yVOcjFuHr59WJ6%2B%2FAbGmfbIfPx9%2BfjLEIWYrDfMvaUleOj%2BPvi9Sn%2F8Q2nfTy9eHdw%2BK49Md982UW67APcJnztijPxjbk%2FNEfRWN1MMGb4UETj3PE%2Bxr6TC2vk9RnkeIKPHkAs6lPtbsvR74CsLlETbxkzGapZzSjOTD94OT9%2BGlOe%2FuIhFMciYDiWZiNZkMarcePv8Gnn%2F4R3%2Fve93Dz5mtihMhg7vcH2ofJ40x4tqbfs0lmhddsOsV0MpFTIJrMztIZwiDUUSvUePJIlU8%2F%2FVTM569%2F%2FWvd33rrrYKhJENKbSnT8tlrRn3%2BpRZf8EeTWhFqvW4P7777rrzRci8t%2B5BeaEnI5iHj5U7je5pNZsk2VvxIoWWgjuggQxOYqQwJ6yDjolPmee1d6d2ire9Sy5k5WTlvLkb2fbn%2BzIVtW3UdlrSuinNewwRPNnjpWt1ORXFz55gYT%2BTkkiyFP%2B3lpPk%2FLZ%2BL%2BF3d4QCgsbjUCMnmFVLAiNTYofhMRxPahAwntZtOm6X8RL2plFLOzOBwWOlz9XjmEPD96e%2Fl3igIbgkNHI5y%2FcV4xIcUupHhFNNJnJgHyFytjaG0HPm36G3hQW%2Bq7ks%2Bvqkni1UMyeMzO4dfPWw8w3nSKnq4luOXYVV%2BLsex50XflL%2BpLiV5Ad99Pv5ejn8enn29ePcwsdYt105hPvLyp%2BKtnG7xvMyB%2B3KYiHF8PMd%2BSpNPwRv9eijMJfBxF%2FGLYqsHQqDcN0fQPhWgLgcELi%2BzudQ%2FHNHlUb30sXghIzefZxJcUXhFZvDzzz9DOpvp7MwvvvwCv%2FzlL%2FCt97%2BNvf19pBnP50xx9%2B5X%2BI%2F%2F%2BA80Gy0dWcIMwpCIJ0ar3cL7H7yvI0t4tiZNa6X1TFOZzT58%2BI1MZnVkShjqHE06CXrnnXfkIIfmtrzoxZZnba6trZWX8aLul%2BPB%2BogOka5fv4E4ItMfy604wPPFvBrrbFurhcENF1s4TIoZRyFqSYxoFiKk%2B3m3gpTjr6yZs1sySefKGOJcWZZdK8Yqg0oEwRG5nNvgFS06pq6uscfEOPzp2fI%2FnPpyvvvRtKp1BWNxiHgq4joTSOYx9%2BPSMZw0baeJpJjLIEAtTjQvJNF35u7Kp1yIBVxi3FVA7sI%2BlPEYn%2F2Pgj5exE9JFOkXZjMzYXffcjiLEydsO2oGn2SeMo7iqUIrwHmSTFYkO29BYjSPauOhyrqpdyjUXj04HE%2B%2FMo4Cj%2Bkbnwfj%2BWd%2FPzrD8%2FGF9VwFRo3fZ2iEz0NrPs3CEehINp85%2B4vDXfk6bT9xHgUuxIUUunHrD5UJqy6f%2F6pvVVgJAgRy8fMD0pQMxeAsRa8eLwYErgizeXxnkImhVjPNMmkcOdDpkfbO3Tv46t5XuH7jOt5utaR1%2BuSPf8Tj7V08erSjDeHXrm1Js%2FlP%2F%2FRPuHXrTezv7ckBkNe%2BkUl86%2FZbeP3m69JKUjs5Ho%2FlxZYmtPV6HW%2B%2B%2BSZef%2F11mdnSidDaWg%2FvvPO2GC7WjXmRGSUTRm3qatR6fBsvzFcSsWEouEiCTlzjEU%2F0ctC1lWJLmBYTJ9VP4giNWg3BcGBOAajJETG%2BArqlRW5lrUvfldqKM4Za35Yj6LOLw9vy1xXln%2FuglVA597V%2BlRV8Fogp7hGDpJwPn%2F2vGFQugnhFJ9%2Bh4TgvDUHiS7IedF5GZjOJUUsSaf%2BNGluITVwyV4pSL4Kqp3MDAXb5kb2joxs4TnLhvwb7ejJCnqUmJAtCOQPScFtWCClTDSdXwFMZIg%2BRYwRrEvKpMB%2F5ot6PaeShJvm%2BOarZCj%2FqYymvp%2BXjo54gKx%2F1XN453LysS%2BPvmFr6tnrYECF6yzHl4SLoO5lNftfd8Jy3A6Fg3JhNsatLJT6tDkuRr%2FQLoWxMPck%2BIRA%2BEOiuH640eC5w4ytms9R5c8dsjscjPPj6gUxayRj%2B8Ic%2FkKZxZ3cXH%2F%2F%2BE3z0299iPg9Az7HXbtzAYDDChx%2F%2BDgcHA%2FT7A0llzBwyAM1AO90O5tlcP5rD0tvqo0eP8Ic%2FfILJZIzvfve7%2BLM%2F%2BzN8%2BeWXcg5EbSfNcre2rmF9fV3aPToMoglnGEaqsWdmS9W%2FMI9H4Qy2if%2B8qTBokhLS4ZK7jkrov5%2FW3ZXjiWnWgHtFa3GMOvuB5mRzM%2BUls7mqWkWdPTG%2FsEJULcvfy9VWuHO2Uc6Z4bZTdBG6qtxyXqf1fFRdXyz%2Fk%2BT6slr4Yi15WakJjZNATXGcBP7EdSuBmoSUU8YfOba59lOiHweR5gU1XpwLT2rvfY1PWvsT17iKeJoQEAHN3rOB4HuNRRhJTXwHUOBWT2KQcCAOpGkttzZwYDIlf8RTGgtuDDIv0oveIc5x1bbSFzjuuLiX41sZ0se3yMPm%2BFhP%2F%2Br7%2BOkxL34MQvc4CJdh6p%2FL8cV0ug8F8%2BrGNce4hn7OY9tC6Kz2wqnjxYdd1YIKAqcJgYrZdNA0KQp0NMnjx48xmY61B5Nmqx98%2B9vaq0kG8fGjHXz22R10Oj1893vf0293dx%2BTSYo7d%2B6CDGvo7PaJ1CUFCwItwGRcjcn8A%2F71X%2F8Vv%2Fvd79Ht9vDnf%2F7n%2BKu%2F%2Bit89tln%2BOd%2F%2Fmd5qCWSY%2Fz3338f169fd2dQxk7iRuxXRomnOSReTV5iNMlszqlVTjEaj1BLamg16HSJDLb3BkunPWfYdoJWlBFXFDK7pr1JwgCNOEGzVkM9ijHiXlouMjK38cu3aaHLtTv8XF7Q%2FPNKiJN4K0VQtUrCvdKnlcnPIrDclhfLnzmdNLdX0dIXa91lSG1shxtwTrxf9Jj2T3O%2FJhmPxAQw3O%2FOPXw8BkBMR4ljdX1dpL8MALpkbWDf%2BJlWENV%2Bjkq7HYBCt5hWJ1EsXDimAJWHSgOwzR5PAqXc53yWIOPJaEWIR%2B3yZFuELj%2BU8%2FR1Xo5xUd4EkVdU2YsNuZMCrTxWjksjaDh0R0eE%2FEerDbNdMrNOaTC1fcCEKSZQyUHqpB7H0vrTlFZllrSjx5VbfasgcFUgUDGbpZ7WsSVhiN29PXzzzTfaP%2FmTn%2F5EDN%2BtW7cKk9d79x7g2vWbOnfze9%2F%2FgfZpkvn8x3%2F8%2F%2FDxx5%2FY8SdhIMaJa%2FFsNsP%2B7r6OOKHn2X%2F7t3%2FD73%2F%2FezkB%2BvnPf46%2F%2FMu%2FxNtvv633nZ0d0FHQRx99hAcPHshL7Q9%2B8AOZ2tIjLT21ktkyzSlR5BkzXyX4nNYjkbGQO%2Fk5h5SJ1mlizHaNxxM8uP9A%2B1OpMaHUUGdYaS%2FESZePF6gtuTxJL21BpvQ%2BDgLU4widRhPtRlPM5izLtLBwUTKto7nIOFwyCSy1WUSbfbWeWxB4ilBmJp1qyZY9i2e1eQY%2B7XBFnue9KPR5Eh%2Bd5iTZmkaFeZwk9tFlXdUvx0HtiVlUCrAxpxFroKO5rEzJqcmkRosS%2FRz1MEK7XkerVkfCfZza3clB7kctk%2FteFKlmhNhV7ZBz2G6OkVJPq4ZCPfS07YQG2rPLfkeofWnNeh3tWh1jelxPZ8hIgNNbuMbQYiAxH6JSjgATXhgAFjFWAMQN2sN1KmKWEh83vov45%2FaBDSk15tzW84pUrLz2ssk5Wc7QvN%2Fr3dMEtledO3oCeg%2BczyV0a9YbaPK4tiTWns0wIC1Q9e8VGT1VM08AgYrZdECSl70wFKNIbeO1a9fwp3%2F6Y%2Fzohz%2FEG2%2B8gVazhUl7gjdv38Z0mmJr6zreun1bDGIYDHHj%2BnW8%2Fvpr%2BPzzL3RWJBlCMlLD4RAP7t%2BX19mPPvxITCbP1aTG9G%2F%2B5m%2Fwt3%2F7t3jvvfeEpG7cuI6%2F%2BIu%2FkDOgX%2FziF%2Fjkk09w586X%2BMMf%2FoAf%2F%2FjH%2BP73vy%2BmlGmN2bQy%2BHym2r4TDKQXiWLSbvM4y3M2D%2FoH%2BPzzz3H7zTfR63bRqNe4kVNr88tA34IlqWu3WIjQBhnOEK16HWvtDvrTKYbpSItSQIdQ9Fx7BFtUkBWOOjrKRNGIO4NkHhqh5sOM%2F7UMuF%2FupV0syjPLp1ho7tUnx%2BWp5lqbj4t2Vb6dtNcJMa8hOgo2BVSNhtKI8vnzG9lFP%2BFINGn%2FtDMfp3OsGBGa3CLQaKBBAssxo5w7cijjcBK1YUZ2edLLl3JUzarwlw0B62nzmn1YXOatK9h7HFM0o6W1SbvZRH8yxWiWSrND0lz%2F2b3FNgCaY3sq3vrdWNjjW3jcCPH1IQ7lVYzj47M8h18vbs3PITBfqEocS8Xa7YYraSoe7WOqeFsA6deDWweI04yZ9HvWE7RbLVAIQ82%2F4kkr6qQtL1S7KnEFgcsBgYrZ5IJFqWxOT7RzbVaiBvEnP%2FkJ%2Fvqv%2F1pMZ61GD2MBur01fPDBB3jttVto1FtYW19H%2F%2BAAv%2FnNh%2Fjf%2F%2Fv%2F4Ms7dzAeDR2hl2M2m%2BKLL77Av%2F%2F7v%2BHXv%2Fo1vn7wtZz80GyW2kr%2BeMwJnQKxDtyPSY%2BzdAbEvZr8Ucv54YcfStNKTed%2F%2F%2B%2F%2FHT%2F96U8cs%2BmJSme%2B%2BTQK8xyNWdEKDhdn87mOjFH180AM%2BvbONrY2N41xd2dtznUOibneXxAki6dTaZ4WmwVh7HMnbyRzmShGr9XG7mCA%2FdEIwXwuh0aS6ntKyFWEaX16BvFZhB3psvKHEtHE7%2Fzm72yyPdtDkcepNPZkmaiurMRpXdJ8nSAz39gTRL3sUTwoeOfvqMt3k78fFc%2BHs299fuU0NpRNiMX9ymI2yUDOM%2B3Vq0WBTMopfKk50zGl92PXmZuR2QiKwe5L8qVX95cNAfYA%2B8mYvhX94fAf61V8dXiNWJFH3FCL0%2BGxX4MRBpMp0pwWKXYEioh2l5Dl8F2C1yKPk7X4OFkUh5PwYmnsrsq1PJ5XfX%2F1Yee%2Fhi8TRjYun7%2FEcnr%2F%2FDQI87v%2FccB7ptNQltGFHM7Ef0kQ2tYZt1eTWwZocUWnge1GQ9sJzAKrNHdcc7zA7flbV6WsIHCxIVAxm0Q22is4lzOf6zduyFT19pu3tVey3mgUWoJmq41bb9Rx8yb3quTI0jn6%2FUfY3dnBo0ffaIP49773XfzJe%2B%2BhxfM5AR1zQmy2vraOjfUNORryGsput6tjTziEaMLLi4wmtapkQMls0gkRz%2BEcDAZyLETnRbyMr6TXLpM4K%2FAC%2FfEInhoUOQSaz8EjFWijl2Wp9r4yDjXO0jTSrEVMGv9Q0liQQq7Vh99fBBiOFJN00lYjam7EbIYhOrUE3VqC3TDEOE1BZlkL1cp6Lerha8h2%2BWd%2BtQXOQrnILWBTYjxdItMCW57Mo5zPoqTz%2F3Se6018oDF3jsDI7ucYFNz4csTFaVH%2BXH5encRi8K9ELEwvuYZjNOkcS8RVjpCClXmOGoBmnMiUspV4E1qfjxuV2stMLSfrXZmUrYb9qwldaBet11kL671FfURsF4E0F%2BR4CGUu3Ypr6NSaaNdq6EeR1kFmwJ4nLvM%2FJhc%2B03yy7yeZ96sYzaV0Dv2Xw3xVfRjf%2BezDFy17gSe3HhA%2FVNfpQuBF%2B2tVejmkcuNyqbZukDCN%2F3Gw%2BGcbs%2B78WJrJEv%2FRf4N2CFDgxvNlc0R5jkZEeqCGdr2mbQUkqPlNAhaPr1m48KHVwo%2FRpTpVLxUELjkEKmZTeCAQs7e5sSGzWe6xfP3W66jV60IaHpEFPMA8SRCSISJzhAyddhsffPA%2B2u2ONJObmxt4663bWOt1ZU5x%2B%2FZt2fL%2F5E9%2ForRkMGkGyyNRyGDa2Z5cnk0CzKNQuJixHDKeN27cwM9%2B9jPwmBTGv337zSKuyEMugE8wXhdv1LINlB7OKT2kA4pmC%2FV6TQieprUy0%2FOMZ9Hes0Hb7G8WXOg3nVaTjDEnTDOK0KnVtciQ2RyR2aSJDQktz3CK6j%2FaYZCPprJK3VUseI5QsxXQzvn00djqouWlxfRwXj7%2BubtfgIqeN4az6O9y33tiusQcl8eVB7Pu5Qz8B5cXxzU%2Fi8HwZrCOQRSDy%2FFNfJdliPMAzbiGbrOpH01o6SSLnpuVBweb8jchEfPWF4aV63DuBuVVqZDvfN8h5bt9Ey8l%2FMd3Om2j1Y%2Bpqul9uB6GaCc1dOtNDOtjM7nW%2FvXcOQoyk1z2N3vf7kaEnwjKZY2lVUlDqjx8%2BCzBmw%2F0A98VwOByy05U7lMiqUxxHPTHYGv2UhLhfFfhpQ%2Fn9OWo%2Bh4VfsbNeFHI%2BfR%2BSLC6wmmlevs4%2BuZRlUvAb2I0OWDpc0MCbtuvTgGNhDScC3IOmMuig3RAr9UULVALIAaUW2qENzX0feZ8KdesVKnqsYLAFYBAxWy6Tk6SGq5dvy5GUMxerSam5%2FAY4Deex0lGhMxQ7doWer0e3n%2F%2FAzM1iyLQ7JbHlBC32J5DY1r90SXU1tHpjRgsYiZHhdFBDr95ZpPnNnU6HZ3BSQaYF5lRXpQyXwYmk21Xm4XfSbRCjPhrN2%2Bq7WzjnKZ7IT3xLtrMheHMUHd5fSCw3TrBvZIxctTCCL1mExvtLsYUVgcwAAAgAElEQVRZhnQyFvHBvRrsdFuwjNAiDaQFriSut3cXrr7kH%2Bp%2F7OKdY0AxWLb74EeKv6teDg6MwnAX1eVU3Z4XAppbr4joOlxnNxwtuDQWinhiDKzvD48BRT%2Bk7RTN4%2FLhWPXji%2FkV8QunQECQzRGkqST69TgRk7nWbst0LI7c5mKNPyuIQ5eCIy%2BsKepZPZwTCLjOV28vjxh%2BEYMoK5IFjpUwQcjMed%2BMIhHZk3SG2TzHLBtpK4qNn1yuovx4YhhLoaaJXmaPvFxVfHy%2BeiSvT8ekXbUWuuxODS8KJ5dxgp93wtUE3DEVPLLRr%2FAD61tuj6%2FKRWuHr%2FcR93KvHH4uM6PFN1vG3d5zs7gSPqO3x3nKIwvkFKhVq2Gt3RItUKcjQ7oUkkzGMF8xfp2lCKtX4cQjOqkKvvQQqJhNwwDCuTwnqV6ry5zTJLK2XPE4Di40QkaBaUHJINkBvnYnfuYRHYpDKT9FW6CGMpZGkosh03iSkIwJ85RzmTCUJ1ZqORnPxy0voEzLd2NiF0zXRR%2BhXOuoMQ7pEYfQmc9B7e%2B3vvUttFoNHX9CGJFi8EQQO0uI%2FGU23q3LLDcOA3QbTWytzTHJMkxo9jufGekWUN9tTlK0ZrPeHBT8uUrbAkc5qY0pfaYUVVwA2%2BYSsEy3QFlShi8zBy5LxfNF%2BPvLBM9lKquYd%2BeI6LJxsAzlcpjvc97LPz%2Fmyil9XI0dvpQuhnFU8k7ZCU3IPKMhjZYcZLXQa7fRrNfEVBoRzkwstakT3IRZVYFSedXjq4aAHw02bqjBzFz%2Fs2bEyrZuWT2Fm4JQnrm7dJqXZhhOJxjPJkhnTGn5yHRaWWuUKZw5HBpuC5zowcD1wD0rrsOBCvIffD6ld5%2Fc7v7DQtvuQ5bjPceb02gqP%2BIH4ezlUp8j11eXZAnHsVVP9NCrq9sLlLyqv33L%2FL0YaGq1rbvqUpVrnmY53jUHGMa%2Bz8yslhYdvXYL670uOq0Gkii0c2cd3lxV%2Fgs0p0paQeDCQ6BiNh0xLwaGjjDk9ZSIx8RbYgcorpLZLBkj723M4jIetZTC2STOjHsqkDad%2FviLnxhPxBkXdKep88ylZyj57n%2BWlujRNJ5MLw2az%2FQS3AVtj52DQE6U6EaccKV3N10GuKXF%2FSybToiLjtCDlcQqenfnXFzIcG50phhOx5hPSCRlSNXJZk5rY8KoJ89YipTSGOEyZqY6tufT9XmpUdQ4qUyWqxXS2NDyIlmKruBSdY%2BKVk5y5s9BaBr%2BeelMPhZKSfF5vAx%2BizNdSXvpLEF15vmrsYRgTmilPc8abiYc4wDQsBGOK9W9NK586KI3zNsiw7k4cF9SkM%2BlzecevfV2G2utNlr1GqjVNJMxmsB7JYnlJHBxP7n7dy4Go29sdV8JAY4ljnX1HTvUXyEtToiH%2FWjiGashGolpuYeTFkaTCdI0c3GYD5C58cdUNq88UrU10ERtbryUivN4T8UfpQ11OJQYUfWWoJZCWOZtQlvPtjqs6VtzCndW1mrvzWm1p48w81qsc4ovCBPSFlqPKEAX7rBZqn7S3lzO5VKHnALEXnUWfuT6O%2BuzsOjwtB6hIwJNHykwkTUTFQzSWs6F5xq0OGs2JXDrtpqaBxRA%2B73tnp4hBAVF94fh1VVB4KpCoGI2Xc%2BL%2BI1JPC3MGf1iJRxBpkeMni2cTGZIJUBIUzIuP26BMTy9GrEscLghfVe8kDv3aZYvWzgthIwXr8u2CLBNfgFg2wh%2FnXcqp0n%2BkA8SL7ZvUUStgeQM%2Fhpj6HrWCAcf5CrKXmVPUKjQTGKst9qgKdn8IEc%2BGWk%2Fh%2BKI6HCLeqmmfpHXDk8KFSi84OIvBmDBHXiCi3IO5sefh5OnY7y5bin74tGnKQJe0QMhUMwTMdcL5wmsEtu0IHheUSWfKNbV2UGdsFQP2IPFVmf4Hnkig7MJKI0FT7hwzhBPCH%2BFdt4rKX3CVLXzgquSkIsflM7VUs2yjqBLM4WSyYxprUFz2pz7lGOsN1vY6LTRbTZQ07maGuQq2%2FDSQpPETFiH8ypUOJsOupi5qut91d04ybPMVNvsZ%2BtmH0PnR%2FOFx9e3kgRrzTYmkwmyNAVS2%2B5ROAmaz5FSI6RBSgsVQ6g2fstbDogL3Pgp4VziQTl64QwsTbcFfjMcyzFNISzH4RxkCiyGzQJxoEX9X%2FyhVJECL%2Ft99cJ2slLx6MLoguU0L16Hk%2Beg%2Fi3RJlZDsVXgkTWCFP8IZzC2xy4nL%2BO8xSxDe%2FHMdjm8KEbbam24q7zGUlJCc%2FEAcRSAVJmco2Vz7VfuNBtY67TRabXMAy2ZUToM0rg1fGyjrwwVGw32txxePVcQuBoQqJhNola3MBm68X%2F9AHDowd8Ud4G%2BfCx%2F94jLv5%2F0znTltLZA2dpseSx%2FP2m%2BFyOeI46LI2gydwxNhCAyzRjb4ZaJM2tSMQ48ccU%2B988slYuJzKiNQSTx063XkXa6SOcZ0nmK2Wgm4ooabdadizkZZY4YfxdjGVL6Tkl8BNv2Rkcci3HFopk%2FCT0TM1izGaNgMvmy4E8VwQ1TERAq9MygdbKM88wITbMYiIyg0UJfaqseXWNOlu3ZxtI4zBDwYG4ycup4IQrVn4WzRz3Tf7aVWeSuvi00EQYvL6xgLI41YzJLsHXjiJW19Bwytjfajys%2F1tQqJ9ShlD6iY675HHE6R7tOwUpLwhXuVYqJr8RMsmQ6TGGZJXi5cgm%2Fw7ht0aLq6VVDwHrNasF%2B0vaOLJcDvLk00%2BpVGzvqaXazWfpQMFgLQvTqdWSdLubcTjDoI5vNpA3nlg8bG26LgAYgR59nOgvSv3DGopHLseXL4oMfzhxL7tmvj6y58CS3YnjBCkIJgGlNwXHp8Xo5zWnAneUJFwse3KfqBGn0ySA6gZUzZ0JyHOfbcRqFP1Mebu4zjXDvwrmRNLLKy%2BgLX%2B0C5s9UzvmJzHZ4cGvYqWrF4Fl8dOOMuKy4hCtzMZo8Wzui99n5HEkYoFNvYL3dkXUHzxkmHiQe9eNVBgEapFYB1cNnXQC3KKl6qCBwZSBQMZtFV69i5gxLeGTFhcWe%2BddJBIv0J3%2Bwxe%2F4%2BD6OLZCr6nZ8%2Bgv11UnTvaklnSEdHBzIi2%2B71UQtSYxgLUies2udeta6V4Us%2BtwRPTLrMk0kJw8dA%2FQaDcyyNqbpFLM0RT6dIqWGPAyR5jlmPMPVebbjiArJQNuqpMXfCBF%2BcUQWHx2TKXLNhmFRH9E2NhBt0SwtrIzET54oOztInSxnT%2BCpTt7TqVvYFcbaahEuNfJkWZ9JLNaJM1vmcYFzDuEtF6Qx5HcN2JcwGo9oohNeiOgnY%2ByIGC%2FY0B7okIZfVk%2BZFbpxQcbZCEzXBqctNYLJ9kYjz3R%2BLE3D5qMpRsMh1sIIdE3GfZuxtgtQu%2B%2FwoQhYqyvht8h%2FEXZES6rgVwgBP%2BPYZ%2F6SYEVbF2wmeIp9Ka4TSBRjJk6Q1RsYxjVsT6cY7e9hynMJOx3U6FEckfaBUh5hbI4xZSaCs%2FnE%2FMtl%2BGfVy1WFz%2BW62hyV6ETrA3FNEebWFIb5tbSc1rf3Re%2BhDvZhS2h%2BLJMBMb0Srvl5auKdUgtftNRnTO8sGQg9jxOYA%2BGirTtOECqBlExsWdWlHnjGAl99dNcVxZhijTQWJOogPSUIuIo6xtDhS37i2I4yIKKwLc8lVGnX69jodLHZ66HDczXjSDhQ%2B5OFV8vrLuG3GHF8Wry9evhUNagg8LIhUDGbDuJ%2BQTqqA4wNsK%2BGNMohLvwMJFdPq9dR9b1o4VwIPEM2Go5w584dXNvaRBLfkOMlLYqyoX15KNsvF%2F5OmIq0YRUYSFNDBGjECdZaLczmJsGPRkMM0xRTLu70XqxFjEflkBCPbIF3XoczMqLU%2FjmzYSvBFiaa8YigKzWZxUqCXq6Ue%2FZB54XR9GOQ9SIc9COMHAHo9ywznn1fSNx92pd7N80Oy%2FQnG2gfpKvfYu8mO8QPgpdXQw0Dh2PYxyJxnVMx1VnEbS7PzdS6GHHvhGIUXjgzdWmAxGTaN2%2Bqre80pKUyOsu1F6k%2F2cfdzz7H4OuHSNIUCbWZ6%2BvaV01hCgUlBg3ntMwNQpsnZlp4Bmjx5QH9Epf0xAh2TIkxnF5LvgyAbJ7JtELH3Qg%2F5ZjOUkz6A%2Bw%2B%2FAb3vvgCD3Z30d7awGaraXt%2B5TQNSLWr3c31YoL5qcSB8wxXWWDFdYGWj%2FNMeITCjjy085vFQBmqfobMTxZV494xbPM5vaab%2BS7nES9WUTjDrRueuT5Z7qcdy%2B1Dd4I04lvDYY7Jd%2Fh5mUk%2B7Tq8wvzYXpMFmAa8xPpxvKvHhMuc1Yc6L5X1Bp08cm%2BmZzR57BOFzFz7zREWBRps2yEm1oaBE5S%2FwrZXRVcQOAcQuJjMJiexm8gLGJ50sbJ4TyRfZLT0VI5XfrZIT4YsJT7jl5O2%2BIyr8UzZs87letsa4EPMYc5gMMC9r74Sk3lta8sk0ysoVp%2FqJBVY6qknEi4CjHS2HBnK31JaW1IUKOmnc6TSSGrY6HQQJTGSWh3bgz72xyNpOnlcinnUpVqUZsHOW624ATJYTvouBkBLlkw3Wa7%2FlWv4ZI2WIbCIuxz%2BKt6kwSUhyD1gupxmTd6YydQZgWhClcOQfrk11hCTCR8JMyubRBk9dFJjIibZmeuRcMyp9j7j63AJGg8yFzSOmHCTyTYJehLwdM9PwlHPfvyYIx%2Bl5RijeawbaxRokHHljzS7iKc5wCNOrvXWUJvM8OV0hq%2B%2B%2BRKT%2FX08%2FvoB3rj1Bm6%2BdhNr6%2BtoNZomDJLOyplHFgPQW2QcbsUZA63K%2FhgILPfF8tsiGcPVjUajF8Q0GSqOMZr%2Fz2YT9Pf7uHvvK3xx9y7ufn0fD3d3kCUR1t64pT2%2B03wOnkWsDDSpFvs0Od80fum9O7DtBosa2JPGZgkPMtTXzTNMYo4D7g%2Fm%2BKOwxSZvRKaTGYiZ4Iw9qrWHSz35u9qgM5btCCCuZ5qHhN%2Fc2uT3kqrmxdw4eRkvGpN1FO6iWbRwR6h9rQyTmTELUL1sH%2BeiisvwWoS%2FaI2OSl8qYbnooxKcKFxZSdBmVhdKVAjJ6Anf9mdSS62tEzk9zgZSwydhhLVGC1vddayv9XTsUy0KbY8m82CHc7tFMbZWV5wt4xffwtWxTtScKlIFgQsJgYvJbArUnLZ%2B6prMULSfsL%2BF%2B6%2BLnvFSeH7x032FDeIiwQmefD4niHqKUZ5s2ylm%2FgJZlSHLbIiL%2FcVHT5%2F7YPYcF%2BfMaffIlA3HI%2Bzt72M8Htth4jL%2FIeGwWAxPCnUfr6iXKuFr5O8%2Blg0LRtEWtNLQYAwOreWLATamkiBEu15DFMeIoxhJFCHhUTX5EBPu5wSQknAjAeLGHhd7kkUyO3QOqPyQtmqSCFssUr7qhCnD%2Bc6LMPXPCniinhbvZf4VIahKGYzEmJGZIRCdRizTkTFuTpIIcsf7GOP5bLU9aZOX4FQqQkSY3kkMMzfTShOwTKMw4Rb%2FvZT4DB9Fy5TzZ19ry5xpgVVvndtL8igH0gxplmpO8dtCi2mmYRpvlMh7AkvjyzTo3H%2FEPUpJgweVt3Cjt45rtSbiH03w4Ms72H78DT7%2B3e%2Fx1d2v8PqtW3j9jVu4fuMG1ntr6DTolbEGEmfliWLjd3Gk0xLFVW5X9fwSIbB6tmim8nQHzksOeodXNAYdY0hcPR6NMOgPsP14Gw%2Fu3ceXX3yJnZ0dhEmMN65dw%2FU3buG1t99G0mlhfzTC%2FnAohnOS55gKt3Kk2o%2F7QjlGOJqJF7WSO0GIB4ivrWale2GdinppUHGsO4dUFObxzGoxnzaPXXN8ls99N0qDoHFzi2UTp9PbttsfShwv4ImxMwQuHKJ66suR5fu2HhnhWT8oQ4c0CFdfJzL4hLoPo%2FDP5U24Hq7liqBnrckJ43sInzD6MdGsPb5VjLhos7SZ8jIb6MgSEsLyj0CnaAhQC2M0GnV0Gw0db7LW7aJVr8srt3noNqsNbiWggM5qbTAkyFmqv5er6PvXfy9%2Fq54rCFxmCFxgZpPdwinrkYm%2FH%2B4ui%2BMneQmlGjpQMv%2B1hCUOZ1O9PxUCAiX%2FOHBqzT2cSpEWcfiZjAmJGB3pIocKlgmJBREMPsPcpOLM3mdzOPvyezmenk0IWY6yWBV8aKn%2BImhcWxTMZ5epRTNTMxLwcphCeSg9GjcaSHg0QJygU2%2BiPx5jOJtiNJ1hmmVIpRlggbZg%2BeaxUbbQW2XKjLlvrxFp%2Fs1V%2BgjizDfpZd8FG8ek%2BQZ5Ikd8nJOos60y3XSaiHLbFU9jg7U3aLuuWG6OAhdy5eWPR735yrnvjqFnLqoDTVOpraAW2pUuLYDfd0uikkPBfzyqmFMMV3ks048RNwRopjebzjCPcx0VxCMp8jySZpNppPVRfekt0RyXaB8w910S%2Frl5VuYxJhyv7XpD0vtuq4VuvYFaq4NrP2hi%2B7XXcPfOHdy5%2ByW2d3fx%2BRdf4KsH97G2sYE3Xn8d79y6jRtbW2I6a3Es51iCkhOoSMPt4eWHL9%2Br6%2FxAQFIrt7HSJqfqRm0m96Lzx%2F27Dx48wBdffIH79%2B5heDCQgOH65gau37yJ1998E9dvvY7mWg9pGGBtPMZuvY%2B94RB94sB5hikFImTQpM0MMHdelOXganlpKFAjK1IeLrmOKTNBG8cwL91oiUAcm2bSuNOzOZvCb2X8Yime9a8fuMRbnDvGjdN8V8yt9yzOuhKnSThF6w1nFbFIvtQWXwspYf3LadyJ11SmM6F1jKaEUIQJTX%2BlnTMmlJWi0Ncpg1UDX2XB3r%2BcRt2OyINFEGynUdQyrcc8c%2BSZ4W5aGBE3GoNJzaYxmVzHG1EiPwxrjaa2x3RaTZ0pzK37FNIpX7fm8tlWH2M4tYa4tp1GG44A04UJ1rjhnxMDw0UsT%2FYL09qqosdB4AIzm%2BXR65%2F93TV5acA6JFGGhlafpUj2ldmsCC4nfabnQ9V6prSrIp9m3Vbl%2F5xhrFa5qYeruQRWLnYuQqGBcUCv12pY6%2FXQbrWKY1B8XlwIPSPyrNX0eRTpfGVLFWOcpy76xSJu2iK2WouWws2MK67VUY9idOtNHIxH2B8NcTAcYTCZYELijUwCmWxZQxoHIc2tryTrxIXNvftg02c5JvUQvIt2nYMHgdZTdyRyWCdH9ZFx0%2BIuJtNMuxhme1Fdp7hbkc4xhIeb5hf6w%2BFPe2d5%2FmIeBt9c5r78VqvXNfZIKHpikUkySlDcPkmO25dxsRT%2F4wSTSS8ZSTGWQJrOpM0MkhriJJF2PaKjKnmLNZNgElbeZJbCETKedABEoQjHabNWE6PJMzR5WDnPUNTRJwA6awl6rab2UN9%2B603cvf8VPr9zB%2Fcffo3Hn%2B3gmwdfY%2Fvrb%2FDeW2%2FjjZuvYWNtHc1mw%2FYmS1tKXcGTg1Vh%2BvMyoHjOylgMv3NVMeFijiuZgM4lBBxPptjZ3cGDr7%2FG1w8e4Ouvv8bjx9tIZ1Nptd9%2F5z28ffs2NjbW0er2UO%2B0gCRGFgaoJTX96vUGmtMJBvyNxhhNppiRSZOmk3PfvHUTB5Sv1XPMmCciR5rnZ%2FOZ5iqPICOzNJ%2BlCDJ6kzbtI%2FNjruU5Xy7jpM%2Fl9Jz6YWjCxoCMbQDUoliLU8otAxSeRvS%2BDWOsS3uri7lcKnjV%2FCh9fr5HB0oyRLS44UWmmNgklpO6EKyrmdwbgiXceBncWavcWXoo%2BKX8UV%2B5kpZHw8mLX6AVy8HebT0lLuR52TwXm%2F0T5QFoGsutA624Jm3mZruNXrMJet7m%2FkzJDrR%2BWe18%2Fj5fwtS%2B8K%2F%2Furq%2B%2FuvTY65Of5FCizb6Rh%2BuPNezIyDm6cNi8RBhxtjVdREhcIGZTQ%2FuowYfw5d%2FfDtqzPvcirvP9sQJipRn%2F%2FACDNdZVs7DlyDzz748%2F%2B7BynDiDmq2pI2JuHAzNEe328FbIl42kMSJZfYsfecLdffn6cIiTYkpVp2tiqor41DCbcPMGECZ00j6CURRLLObehyjVaNJTguD8QT9yRjj2VTmtXQqRCdBGRkZx3DZmuYg5QHn2qJvKtAFuOIXb%2BfoqejsRVtIsFEbxz6nufF0NsN0MlHv1mo0Q6YmwlYgM02y9midKTpl0UaGPyvPx9osEY7MgxwYLzJpAGp8zjLMRmNMJmNpKlg%2FHvWg1rg%2BtkRn99c3mXe%2F1k4mU4zHI9TrdTSaTURhJKI7zueoExgSelgbY8JZXhP93kwTjDCcDCVNw9qNpjSSJKz4a8SRufRnG%2BdmJkbT2nqjhu5aB9duXsOb77yFe%2Ffv4%2FMvvsTdL77Ef%2F7nr3H%2Fzh188N63NHe3NjfRbrfRbLXQpMbHHWHk2yOILb2cHQzPZc5su5sWL1Q%2F5nEUHA%2Fn7%2BMdk8ZNPQlYRpMxuH9%2Be3cHX965g48%2B%2Bgh37t5Bo97Au%2B%2B%2Biz957z1pta%2Bvb6LTbIHnRAc87iSOkGlSBiLUg2YTCcfWbIbBZIx%2BbYTBaIQxvXbnc%2F1mWSrP3TKlZSX8xWdfbxem6s9zpHTCNhpiOp2i0%2B2i3myB7KuOHaF2nf98XsqylK%2FP%2F4R3nw2juymmLRA0naXH8ThOQDw%2FmU4xGQ6FXyiwYrtpQUD8zg5nU8rN0fOTTTxhrY6I5gj48lc69ppOZ5iMhmIkm80mao2G5jm3d6huYoyphTXNrMerwpWnpG0s1%2BmoZ1bH95S%2FHxX3qHAPY39njqI1SG9QK07mkEeaACZo4%2FrcbGn7QI%2F4sF5DM4okFPVOgBa1slw9fHyPGru5KPGoulXhCwiIoTymk5c%2F%2BTd%2FX%2BRTPZ1%2FCFwCZvPZgMxhWqADPryMcVsU%2BGx1vWixy%2BAsP7Mdh98JdzITXACo0ZOWhtL0eY5Op4v3v%2FUtUMPpjz05k35a0S%2BFNK0M%2FBXxGKSfJxSkvTOTGmmRKHXn%2Fg9qj6JY%2B9m4D45mtAMSJDRJm070G47HGE2nzryMZ4yaSY6qsDRgTTn4cgZtGQDP%2B%2BwAJ0%2BHxvzoGA4xOjxII8dov4%2Bdx4%2FEMG1tbaHZ68p0mmbVZQKPnJaYrRVVWSz6Kz6uCNKUX8p8gRN4phqpyXo6x2g8wmB7B3v7exJ6sH7tbsdpPJ0TnhX5n3qQxphpXwnRg909fPHZZ9Ievv322%2Bj2ekAUI8gDmEbTDiGXZkcS%2FLkOH2%2BQOSUzSW1THCtMzGWSoMY9xiHPTSQxRrNwIOBmOs%2BEs1FBgCb3LdXr6K31cPPGTbzz9jv4%2Bv59fPnp5%2Fjskz%2FgH%2F%2FxHyVIeO%2Fd9%2FCzn%2F0MH3z7A3muLWDihkTxfpUfCIsXWX9WpfX44tA3MRBPgTWTkLGgtnAyneDB%2Ffv4zYcf6nfvwX102h384Ps%2FwAfvf4Bbt14Hnbe1yLDwXEsxKAGCyI584lgRFstzjSuapBOXU4Pea7bMg%2B10inE6w3hCbecQ4%2BkEM2kqzWnYquqqjgEwnY5wsLOLh48eYTad4vZbb2GtVpd%2FrDmZCZ5xnGWYp7Z308BxCCirClgZ5i0fDOn7Pfa8z0NqLkPt88unM4y3d7DzeFsCtbW1NTQ3N2VtIH2hmaVYCSX8c1ZTgvOfPzJVwSzDqN9H%2F%2F%2By915Nlh1Jnp9fmVrrqiwNDXRP90zPDGkraPNAGt92H%2FjC%2FZ5DszUOjcOmDXdHdU830BBVhdIytc68mvb7e%2Fi5596UVUA3qoC6QNZRER6uwsM95OamdK48NWmj2Iy0U7AoZBqtViDSsZWWFCQFfV3OncjO016mgDbKimvXYTst48nvY6yRhgQes6a3IrtXtaGBQcMeVssV2UNGNYf4wz6qk9iXGWh9ZlTSPELq0%2BtKzu%2F4N6crJ6P1032b8a%2FLgtPa9EjR5XC8OQFIfHp3faM58JYHmycoXv5V%2Fv6Edl2KfFybewTWB6Ln2ys%2FfK%2FAXrn0P1mGjMzTeJsCTRDK0vKAAS8WbAAHhs1iEsZylOKhP885VJGNMnRNMHKglFvtfl9Dpw%2Bn9OZGcBOjampeIuikLDao0AYSvrEMPkYFWIWStTo%2BmkSPfr3VtjrOFsFnoyFHq8m0TRDqYUwvkUFP79s36yk%2FKgkt4IzTw390MDAKwgZQey9Xrb65rYZ%2F7spVW168pLW7BNx%2Fyp%2FL1KflUS6dH4eHhzbcNtt%2B9sxWtrZsZnDILl%2B5asPDw3LKhWFyGrUmkYx5tPsdklCcVyQMfZXOeoE2Wija6oOH9vCbO9ba2bNf%2FvkvbWFxSTxlKqGPIqKV7vCTF0d%2FsIpzxeZVaQMrHT6PY%2Bm7MRJo6gxNptnmcUx4u0w9GC0UyzY%2BMmIjQ0O2ODNrN5av2o0rV%2B3O17ftyZMntrK6av%2Fn%2F%2FV39vkXn9tHH31kN2%2FetPn5eRsYHNCoGeAZ3eYnfU88pyg21NVVOtOdWIneULf0g7dx72%2Fezn%2BlI316cxFK8nqWS89r6hm%2F4E%2FMFJB9ZZMUbcjWMnSFNY2aeordabW1MdujR4%2Fszt07On6KjdrQp08%2F%2FsRu3bplH3%2FysS0uLnonYHKskWJmrZnqkabNhw6hh8iOEcdypWpDlYq1Bzqyd4xoshb0qDZq9SYbWzEt1tc4greknZRB4i4UhOPdF9%2Fa4zt3NfJ69eo1u7V4yWZnZ0U31EM7HVuC4RmlU4FbjmU9t%2BJc6hyjMqfqnaVxlUvTc4WXz9SgvMOjI1tjs6Snz4xAc3H5il2eXzRmRPBLmisbmAH8Y9wkewt62CXZ3XbHnnU6tvNixQ4ODqw4NGxzI2OaReS21nXG8fQw7ST6%2FxjoCmZiDljEX%2F79q5cbUOikTCPKdKIVSx5wVul4G9B9ucB5mWk9uzraWHLAqKdPu80sadKjwMV1Abnm%2F4uvx6%2BQGDqgr%2BjZ8WQ%2FqjeiV%2FXkR0XWO2JegwNvebDZrb2qyFFz4xoMyQUSfDpW6SNd37UfTN%2FnV3rsb7ReKfNblrjHoOZwh5%2F6S7sP8oCjQjCm9YqkZcpdrIWRw%2BDrYmTS3Y%2FpNdg5%2BCfdhrxDlmH3Asc8TuSP5%2Fx9wIh34Cw46SxD1ydvOCI%2F7zRVJzMbfBQAACAASURBVOFMHr7hi%2BF0taykKWbtStnag4NyuJnOFJtknERLvAvc4xrv36Sr4mUITj85vPEg%2FhVsfW3NyvWGVesNmxwbs8vT03ZjYcGdwlzaP8UtvARdHG9wxznGCZ6oVOU8bj17YbXNbRvqmC1NTNoAh9Wjx8mx9%2FWTJzmnBEiuL5SBW%2FI6P%2BVKTvB0ddA6%2Bwfi3cb6uj3%2B6raNFEq2vLxsUxNTGvFkgxK3Oa6XBHb6S%2FYP%2BqSTOPYcXF4sGI0BAYL0O2SXcGc3YX%2Fl%2F4IP%2Bs3u0WXWNc3M2OTYuN24fsOeP3tu9%2B%2Fft7t379qjJ09sY3vLvr1%2FX%2FhduXLF5ubmNMW2xI4b8COxpKhNwvy8TnD3HT498gTfTqpEBEvwlCnXOPmvx9HXkcIfMc9FicjJxeXrOEV2PqcQTR%2BodwQbfkZsWrKgAD%2Fxt2Pq9FlfX7fnjFA%2FemxPnjy29Y11rfO7fOWKvXfrlt24ecOmpqY0dZt1weiXb%2BDm4lP5FJ4Q4eKdcS4fn4rIZ%2FQIWaJvPs22U6lae2go63QQDVor7esLqVv8GHFdXV21l%2Fcf2OPbd6yxs2vL8wv2y48%2Btg%2BuX7fhoWEPsHM4kC%2FQinqYISmo%2Ff94pEYefuJfus9fvAj%2Fl7SNRsMePHhgh%2BubVm227PLUlL23dNnm5%2BatWi2r7lF%2B%2FDL48eL7vOb6KilSZXXMBjod23r%2Bwh6trVvn4MCmh4ZsYcYD9OjwcTuR6nog%2BX3idg4sZhZR7HcvOmqBtE2lwgtZnJhKywh4soPohH9LaeI5VFp2JifAHgzdhkWJ55CoKtLfHp6X523%2BLq7lWZcnJjpG8u%2Fe3f8oOfCWBpsXMEeZtYq0OF3%2B0v917fd%2Fs8SZkCNX9uK1b04r4bUBvvUZM94WkEgy1Orl81EvHHjWybGmj8Yv3MnjUroYK8jXb%2BvysJgtyC%2Fe5a9xn%2F9OcOzuTwIM7sDIGnly8Qfm%2Fl%2F3jeNC%2FgiyI7qKNFzP%2BgUtcT0r7Q%2FxLfDPO8Nd3njgBV4btZodbW7KCVoYn7D50TEbr7hJ%2BiFoA%2B9mpyWnl%2BlWbY6xmZy095eXbev5cztYX1PgeWlqykaHh333ZCQtQtMRC%2Bk%2BHEsFQylgex2aIk9cUZrB8XGrfPihTQ4M2Beff661k3ebDSscHtrArVs2urDgAafWSeI4JsWkh5%2BZsfyjzYNQUbryS%2B50pbhPU5sokL8QZvqmI2By4Qz08euwwQZr1GaqWqc5OTNlV65dtadPn9rDRw%2Ft8dMn9mLlpT188siuXr1qS0tLNjk5aWOjY5pmywgM9Z6OGGIL7gmQkoVQJ0zbz1HRe6b5FTruLAaKP4Suf9cyM7m%2BAqCgF95I9zTzO8lBo3kOzO2mb7yloCnxk69szrO3v2dbW5u2trpmz54909%2F29raVy2W7duOGOgcuXWbEcM4mJsazEbrMmlJkIkA4xX3M8uCZ%2BpAMAfgQdJKWPzrePJ8HoMI68jAdt%2B27KoN7vV639ZUV%2B%2Brz39vXX35lrUbDPrh61T766GO7df2aTbB2mVH93I6wgk%2BnhfTe9Sqh%2BArcPj8pHVRbu0cKgLdXXtrS7Jy9d%2FmyLU5M2Cg2pFi2cplOlC4s0Z2rXt0v399dlCGWmtnS1JQ9HR%2B3R7WaHW5uWaFWs0GZgO6xU85D15zAJId2vPqjXME3%2FqKAoCGeX%2BUK3o67Q41nXdOZowow%2B4B6Hs%2Fs98GP7It3mEQ%2B%2BS7db92787A%2F73sU8PZeI9Tv8qSXlmzZkljR5Qd3WP%2FuvJZuU9QL4d3T28KBtzTYhL2oY1c5%2BxmOcisgUEPnJ3gxNaKbg2rAf7zprQrH3%2FRDf5Xnbon95bwKlLclbS8nT8baAzW5SpIRzgQTT91x6ljt6NDWVldtaHDIxtn4oVqVhDzsvEgJJ5cbOeNKKqQDPiHzuMa3%2FJV78kZ%2Bv5JDIbMCTl%2BDwDt%2BTOEhVaI4OVc8RcAaKYEa93FNQLLyeO4tO1K8mdee2gbiEJaCFkan6ns7tr%2Bxro0YLs1M2%2BzYiFWTY%2FhDUeTOcEfTnoXrQNWuLS3Y2qUl%2B%2Fbet7by9JEtL8zZ5PCQVYcGJY8YFXCc8yOZ3Cdp5gKCV6UN1sUfw0Vs%2BFOZmrCh0k0bq1bsD3%2F4gz15%2BsTufvmF1fZ2rPHee3Z5edlGx0a1cQkOuBpudv9kKjPzVPlpl8WcYFKgHA6AXKxUMBcXYFyTzvMomRasUwJkwYaKQ7YwMG%2FTM1O2sDRvC0sLGjVjF9OXL1%2FY02dPbG5u3q5fv2aXL1%2B26elp1XM2O%2BoUfLMsFcdCwLShFKOccJJpnwSmctxVn%2Fpri3K%2BFf8E518JWReEAigF45Klt2TAaUvGjPz6SDbvVA85icPMavUjOzg8NILK5y%2Be2907dyWbVrNpI6OjduPWdbu0dMkWFhZscnpKo4XlSlmBnNZbayqzlDmhfUILmnD06Yve9joeoUKp8yOl45tbSAhweWrUtOizC%2FZ2dzVa%2FoevvrQ7t29rrfEnH39k73%2FwgV267HqORWWH0VKhrI4TjX6LYmB7W19sozfJACXsv%2BsFzrMr7%2FrL5%2Fbk%2Fl0rNup2dWnBri0u2uQwy0Eov60dT7VxUa7A0Ny45j59p9s8PO7VrhbMxocGbHJk2KqFtjX2d62%2Bv2ft2qHWo2sTsWLZj%2FZgjafkLAsgXHKi%2Bk64nZZZeOY%2B9j%2FnPl34FpxdO50j3Acd%2BpbrFOG5t0zP0y0sUvAmoKQ0euxP3%2F%2FchaQ7tQvnpOnL8nY9Jh4dr%2BqnkIEwaJeYydK2DscisYYYG88Motx9xv5TIL17%2FWZy4K0INvPV%2FKJsJA%2FTsqzdNGtylDSd%2BCyI74MQnlXudSQ5ljaXJosM8u%2ByWhAQuh%2FV4P%2BYbUuQmhzPeOy%2FOrs7OkiZb5qOxe6kabt4BLS%2FtWE79%2B5YdWbGBsuXrVIatUK7aIWOT5sTzDOF01%2Fq6c%2FHJeVpzxOVGrFIlK7%2BLl5GmeHceEl5deum7GLh77pfclDi9s2%2Fgr5IyNGRPTut7XrNKuurNrizaXOzs3Z1ZNAmCVYaR905p39qSjtm7NrIf8Um2%2BJ3rNKq27XhQWtemrfWiyfWXHlhhw%2FuWmF0yIbm51DgbvAmG6MzEZJT25Vrl5ST3nW%2FnnSX5UijRGWOZrG2DQ6WbWJ50RbKBbs9ULJ79%2B7Zy8%2F%2FzWzluY384s9s%2Br33bWB0xArlsjtSBJqtpnWaTfGYNXta05XqIcEnQUqU59fQX8dMjivQ0miV3oaYcQzYmdPMBnS2TdXGqtM2Nzxg789N2%2FrKnEbPmK65vblq99df2IsvhzXK%2BcnHH9uVa9esVE27TwM%2FTZ%2BMo1549gNcMO7sKJkWd57EtLfkXfD61dD1dWjSUdo4BVAOCf4jDgXkeGr8JKuOdWp121ldtUcP7tuDBw9tZWVFuxprOuXlRbtyZdkWL12yyZkZqw6P%2BDRl6Vw6SoTdcFQWF6KoFLwljSG4VNmUrz92PnZdcb1x%2FRBKjlny270XLkw6adWxiJ7u7trWvXt29%2Fef29rTp7Y8MmIfffyR3Xr%2FA5uan7fqUNWKOKfwQWW2tLFVh%2FaEsoM3wjXwvyDXM5sVyB6%2FAqm%2BvWFb33xppfUVe3921j6bn7blsWGrlgnWWmbMOmgVrMhOvUFkmMjjIL%2BXN0I9lRW8qLZatlAyW66W1KFb3Vyz4b1pGxwds2KxIj4q2KfKF0uqYzFz4XtB6gJAhHeku6CYIvnxK9C6ENFPf%2B52ziiPkkRhnibfTjvc%2BO66KhOYgy24aeZILx7d8nmfQclw6U3943mC0sQr6WFQ3kthITo%2BxdC2Watu1m5YudOyUnwDTALVm%2Fvd09vEgbci2EQP0deott6kncZmT0XHUaXVNqsfmh3tmZUGjIN8sx8JAmD28qI3J1ecaGKPQVEPWhpNOPbxR%2Fgi16D2UCc%2BhHy6DiuioPc5HNjq2nMbu%2Fu1TTWv2%2BDEiBUQGzDzcE8TQU%2BBJz2clPG4IhxPdfyNQ%2B97r0akv9yuw96Xutv6kEVoHMelH9qb%2F9xHQ98jci5ubtr084f2ydGOXSpN2bI1rFrbM9MpKMe4dD7JJ%2FL9%2FGznpaATpGIt%2B2Bi2AYmhu3J3bs2%2FE3DBiZHrDyIw13UCKHD6crZdfU16DgToRwj2dSn3bZqqW3DcxM2075u77WO7Pn9%2B7b76K7t7qzbweozG%2FnwQ7OZGTPO2VPnG%2FUsBSjgHnUqOZfZM3iozvUiJIqERsKFSzhO4Rwoi%2FNCgWehbWOjgzZTmbdrU6N2sDRrOw8f2dqjh7a58tw6L5%2FZywd3rby8bAtXrtjQ%2FLwZO%2BxqYxVKTA1A4Cu84HsOf%2BGb%2FdOL9I%2FqydstdWzRvqWRwB4SJaSkewRse7vWXF21dc5GffrU9jY2bPToyKarVZtZWrKZa9dsZGHBhscnbGB4yIrFtlnjwKwRsk3QxfcEF0cy04941x05Iofe5nWFl0ltMnyB0f9DT%2BnsefHSDm9%2FY4f37tvc9ra9xw7IH75vUzev2cj4sBU7dbOjRleHgRPwUvCZPQfu0iElTGlPKD%2FDpx%2FZ7EP35vDQKnfvWOXz39jPGgf24cK0LY9Ubah1YHYAA3FcUttP2fp53Tir5G4B3%2BEuCqB%2B8tfu2LVCw9pDZdvcO7SFZw9sdHrUysUFs9ZAl3cUmdU1HgAUwL4DPq%2Ba9TsXmZdfus%2B%2FOpEmT6Cij5Xf44SeQA15k63S157Cjuv%2BscpwAsi39lWOV8f4mCcqeISOtsxaDbP6kQ01j6zVaqrzV8dvaYZAAhRZ8mDe3b%2FxHHgLgs2kWakO9%2BiZdI83hJ8k6H7FrFc21sz%2B699a%2B%2FPfW6NYNbZEl%2B2XWDyfS6hbG%2BIuB%2BoEIUaq%2FKd4F9f8N2w9DU4Xv96vP6Inkd%2BdfpOnTNTnggL1dgdLcmxrrK1Z6cEDq9350vY%2F%2F42VBocEJpckD%2FbV78MhIWcOn3MB5fNl0gSr18SsJ1swIq7nYvP2Jmi3rbG3Z52HD21%2Bfd1GN15YY%2F252cTEa9EUoyavlfkimTgO4uDQRp4%2BtelnT7VxyuHqUystLEj2OlvwdXXgIuWfmsZ1BTUqHx3Z5Pq62cqqDW5uaMOSjTtfWOnKFatOTmqkwvlEHh%2BRYlaB%2BvjDEe%2BnQfrZo6QnYJIcWWzbqXWJb3wmQG7ZSK1ula0tqyL7nW072D%2FQeasbIyNWXlqysdlZK4%2BOakRWBQo%2FYZ1ih3ygEyglPM9DN5L%2FwNd8Lc%2FfXxgtRhFTAHFWHkaym%2Fv7drixYRsrK3aws2ODnY6Nc77q8LBN7m7Y8NpzK7FBT7lsRxEQnchHXnqgdFaZp39L%2BU9J4G1uooudutfXbevxYytub9t8pWLTU9M2vr9lpTtfW4213Qlcxr8Tcc4VFvY7d%2FUs52XMwdBtt7u7xY7az5%2Fb0J07NlYu20jr0BqP7mrDI%2BpX9osyuy%2Byu56bV0WlJ%2FM5D9ix7W0bf%2FrMijvb1nn0re3e%2FdKqE5Ne17KysQ%2BIOntxDuA393OmGyegeIw6XMgT0r179R04oH05yH%2BaJLwuaf%2F%2BdsvK7aZmuRX%2B8DsbOty3Cp1pybXX8UqngfkOKL7L%2BqfhwBsebCbNUivk9zhHfse%2F3b8eI4Fy0rO5vmrN%2F%2Fq3VhsYskahrGDTc0S%2BMC49ub0NI8mZv948Aal77WZWdfqpBJtyRs4INsPonMFfpvkN1%2BsajamVy9r0oZ%2FbXe6%2B2l3%2FtCChcaqT3Av7eF508XvCLKfjvaW%2B5pNs9BlMPhNscjbOTPOaH1PQwfEGA%2FW6zTSb2pCk%2Frt%2FtlYpN%2FPgFcCfSSWyPTPBxQriSIZSDXwbro%2F3v7EaZ%2FlpvXHXAe%2FV%2FK5T2vv%2BYmW%2BSipK4lzBoUbTKo26b3L05J41vvittTVKATTXVf7VmqwIOtP7V6kLPbhxBmp6cSqr0xRLAlKCpGarZdVmw6ZaLRvXDsAd8bV072trVCpdXUB%2BYq8HmFFOlO%2B2NZ7eviv8Oj5l7wJ0uLBOj%2B8zEB0%2FSqTZtFHsKjv58l%2FanZgR77rWwfouwFm2U276%2BX9KslNeS%2FNO%2BRbaGX5px7SOtFa3QXYpZgfRctmabNyFnRAi3fp13jS7M%2FE%2B8%2BMJ6CbbCh%2B1y2%2B9YQu1mk9dfnDHatpwq3fU%2FVWLOKHU7%2BUVO%2FpWGg0bTzylrsHP%2FrZNhb0pSH8HylW%2FTsgPaXnydP8u2DyBU9%2F9FesvuzW1F150gMqT6rS1ZwO7Jhd3d6xysG9FZm8kuYTn3wvh3dPbwoE3PNiEjWEuGBl088C%2Fx5WXdHzxr1JQGoCVFatom%2FViX6Ou1jqXJyey1zI6UXYOTnZL68QGF1Fm9uFHeXNiw%2FUGUCqHv7%2B3Vk7w%2BXI5Ma%2F08Cy5X5Royj8fh4tCUzoF0N8Bpndtv1KRF0qs4K8PL7Hw%2B%2BDjCRh8Vz4AMgXIAZ2D6ws7vlazQ2MI6nnrxLNI9Brvn7sBacD5%2Fq4eiDmiOaix3ScdbyfI06tC4nsOX0EQ3yAqEZcD238rJ%2BC8ZD0xvxgaTErgEoDYICode9RT1jEa8nDOQyAPKa9%2F%2BXz59%2Fn0r3qfh3mxvK9f8sVzug27GD7ffyp4kp9adwqPZB88qfDN6m8ufXabdgH%2Fvm3nBYgHLaGR4UKmeLi4TC5Q1PeTJI%2FSRdCMNN9P6T8IFJF8Bh1nz177QVD%2BkRaalO8EWXiwGZMSWattxgim1nqnUc1u9QZA%2FP1IWfUjJustCDZRLpS1V1M9oOla0DZnHpIGh0S7GHo21jWVlIwzu074CXQv7CxVF3z26uybU%2BAI%2Fx5v62wwb%2FvX09hwUbr6%2Bf5d4WXlnuDwq6z%2BArMMuZsT8urr94HcRcrPoXLebQYuuzkvxwnfT6P3hKSv%2BirnUHardiovj%2FJFWHtS%2Bvw74XbsxathHNnjytZ4ca5CK7zOHMjAO9LnPvWZsfyX73Cf45284LxTD1gQCaT6i8m9l2Ofvgfuuc%2F9OXueSdefth8GzxkqyR6elCZg9cPrL0B5A0APNscfAlYk5xrv8qnje%2F7dq9yfBPNV8r9O2tNwzr8Hrz8lbvmyRVNf4fnHfNq4j04O6hc%2FJj1k3%2FyV%2F3tC%2Fct%2F%2FmPdBy7A5178TURlkegJhefz8TnPh4AV2c76FmnOuubz58vlPX%2F5lT35tAEz%2Fy5%2FH9%2Ff9Gs%2FznkeBO4nveNbf95I%2F%2B56nAN5Hp7Gt9PeAy3yc83rZMxCT82Z%2FPvjpb9785Zw4A0PNtFQNPA0TfX3jBkeForWKpbtsFixqjVTDs5tTNocCi3B5OBFo5YXGO90XllH042yTwFDeeIh%2B%2Bo3x%2BDhVFHeKen7sp%2F9mGCcBipHVkImB64vU99jLuF3vz3Gg9NAnkDPaawCJn8KVF4zcD%2FGn6RaF5nH1p9Xz%2FzT%2F%2BE0Wi%2Fy%2FnsWykXlkC%2B2n5yzYChfZE7yOZfMVB8isIkGRXx8Dccxk0NOFIFSVuf6iToXyd7qGtkDLs%2F6iw%2BnwDvp87F3x16cAqz%2FdSDT9z7kBViSCHzuIW7JxqZAPEcPMnn5izpGmoDXV0zvY%2BAS1%2FRVZedS8hzvWD9P8tADkvEtcBYuASdlIq1wzZeTAu1IL%2FyhKW2ek3%2FPPQXkywWeyg44qczXvaiMlDlozWAFgdmLk2%2BCvMiv59zLeE9uXud5yH0eh%2FgW7%2FJ5e0pP9Pe8yz304JB7f9ptoJt994I78Ftqpn%2F8K2n5HPLlrTfc%2Fh3c9T0By4akUsZTaUrpL3w5CVAiJE9PHpc87OCxkM3RlE%2BTh5N%2FH%2Fd5FDJ4J%2BAQ6c%2B65mGRLsqO99hevUsf6LDn2BNQh%2F%2BRrr%2BMwCuu%2Fd9VFjBfs50OeHn4ocfx7bxrP%2B6p2cnXFSXpT5cnmvL5ni%2B7n4ckOAbjPOT6YF4geU%2BSPF96Prwi3LPg9MPNP%2Ffzo5%2F%2BnufQrTyA%2Fnsy9POx6wsA4ahctsMyyytYq53S94N59%2FxGc%2BANDzbhXWgu12TAeJ1V%2BqI1ShXbKA9YoTqo0c3Bto9i%2Boo6jKcn9n9dURm%2BP2lqZDbVKK0t4rwvldq3u52vecrJNmsAc%2B%2By20A2rtmHV7tJ2c%2BfjisquqyjFPKqPgc%2FHZjbDQ5Q90ROV0qTpU8FXxhbz59KOD3XRcAmw6at9sFH%2FQAXyXhysf1TfGMax8mpe98eyyvdDH7C4lMa14yPvfC6T0FPXP3LqfC6GU%2B9O1lHkl7kcnmJObw5Xy2%2Bn4F35IvUvZgHgN5r0BPrNPwA9nSyJQDyjVhv1tOfTsFR%2BLwOvNNL6v2SYjLhXChkA53QCE9ObsejXuT53Qv2ok9Rb0mfvz8tP2vewiCEfHW8AdYx2Tb0W2KIgE5n7eVs7WnAU71UDcjxPG5P5oUDky5QqGAEZl1bJTmKRr%2FDzKoeyg5wNm96VqeFb3wkY8cHZZGCeGFCxNeM%2BgahCbouAnTy2rXT6D7tfY6MbpKuTjhfUtnd2pYl5QsbyqmNkm55j4yfq%2BlnIOrsVNGYp8FtEPxRu5XOKAWw6umJeEWxZ368gBIEnLiGZYhnrgXJS3WEI3YoMqEv3ZPexZpSBJzyCrU8fvHBp9FmdkXJ%2FVsvj%2FM49N%2BHXFx38qX0pEz6yfmdBGT8wDnSB0Y9edJDpJGOyxtx3Qy8j%2BUJuHFNCU5NfwxAt%2BAuhvTTgGUvf9AT5OD8oo8G%2FfL6dxLYrh5lVPUk68IKGvl8Fnd6svc9hGwCv5PgOIWJqlz%2BHH45VQpCuyTmOeQWEliqe%2BloHzpIeIZXLnBSoMsJnxz%2FhEB6rfvMNuZQAz4jeK%2FLl7DLvSD1FHADN7eVvTRm2XIsyt5d5CZHHyByj45D8IWnvvWaxzEJSTgy2b8CKo0XjP1SxVaqwzZT7jtV4iL4vkvzRnDgLQg20eak0lnr5Eqo3d7KFRuaW7Cb%2F%2FP%2Fara6ok0nsvN5VA1SVcjXiJ6RrOPWwBU%2BLAKnybatw6Ybh0fWbDasXKlaaWTYLM6Ey5dzolgpPI%2FAiYku%2FDJVwVPTH6%2FQKWlf44Xh9PYn7QCYGtCsBT3VaT616O6H8PW%2BC93NlrX29mx3Y90OD49sbGLCxubmzCrV1%2BRnv%2BMZ6PbJpl9cKAS6J8XQQ2RUoxNNlNvYEzN7A57lyjQse%2BP6EXg4jC68XLKL3mb872bI0O%2B%2BUrFRKkg6ZolWOmTyDUcuX%2BRxmKk755S0uWzWqddt89kzW1tdtenpaZtemLfS0LB1Yqv9fOKL3EfDK5YFVpCVGHAi0RcBfEYa6KzXbX9jwx4%2FemSlUsmuffC%2BVcfGvUKBk0YG0iYh4CD8HKbj1sX1jJJO%2FxQb7ijFCcLuy6m%2BMOHRsf31dXvx8JEdHhza5OSUzV1etkF2AhbOua65dLh7V%2Ff7gGaPOQKzzYjcYaMXSxDhWZAsmXhmvnq5nKPLZhApUdQ3Tati7go%2F10%2FSHW5u2bMHD%2Bzlyxd6v7C4YJcuXbKhiUmzQRyS5BgSGPCHTEp0bDiuHmC7nAQ7lSvU1M5kxL3eDfBUbjpGgnvRl0xGRrefy5ovRIGmNsbw%2Bqc6yA7OBwe2ubpiL1%2Bu2N7eng0PD9nly8s2tbBghcFBt1GAZ5fhojvDMZKYjFe%2BmFe%2FD7mFHCVT562AxfdMUvkiUjvbbOmc16OdHVt9%2FsK2t7dtdHRE53ty9AobFnEuLGe%2Bep2JToA8LL9n4xHVdBegdCdQSw3b8UzH3jjSIXfXVQjIESNE%2FJkzK5t7e3b%2F9m1rNps6G3aUo4VKJQ8%2Bot6ncmQHkLXguf526z%2FtbiAU9cM1VPLK7LGn8aSRLvKdck34C%2BtkW%2F28WqAUzOo123z%2B3NZXVmQDpi9fthI6xA%2Bk6HjKeMAz9ZOy%2B%2BStNetdHaa8DE%2FBkoQc7rF%2FE18oJ2Cn3KrrWfkOiCQ5hglHBVMJbgRYPObfOy2RiNgl7IyX31OMF5WCTXSwY9ZquQbEUUuqy05lZjOVThFkZke9xG7AnDDQJY9r%2Fv2p9yK%2B%2B1U4ix%2Fdd9xlvE%2FoSe%2Fy5%2BGGDYormaQkrt%2B90M55AolM4FFgTkQZSEcUt9uD35jORIL4c0R8zCYydmEOFEs2XBmwkc9%2BYTY8Ktmfg927z28YB96OYFNMwyCx0YUroB8qXTZOEK8uLtvCf%2Frf5AB6g06a4worMK73ue%2BnSETpMEoFs2bTOvv7drC2ajSSQ5NTNrK0YDbkR3L4RHPgOG4nQzzr28k5jr8NmvrQz0BnN8ez6k0yDqd81WtA5IqRseozdKdnz8MHyHn4nA5JXxoNq6%2Bs2ubt27b67JmVlpZs%2FtNPrDQ9487kOdmPfY5WRfTliexP2degR%2FrsGnm5pvvgka59dKvcPt4EiKzolIf8AUOv4j0J%2B%2BBmefM3%2BXLy7yN7HkZf2uBPFJXh0geHR5wqfhyeTj4cmjxo%2F3rs39bOjt37f39td7%2F%2B2n75y1%2FayKefWnl62qxceb0GRCIonDC9MhUtNI8x%2Bxher%2FQCO3R4aPWHD%2Bz5%2F%2F3%2F2MHBvi39T%2F%2BLzXzwvneEwIvk4OGkhYr0OEqvVGBfYulH7p3klHvuv%2BU7sz3Aqd2y1oNHVvvtb%2Bzpoye2Vh2w9gcf2PUPPrSR2RkzjhmK3T6jHPKd94MnKADTnNANRkvDoRF%2BfY5qHl7wKtLxDZ1CbMBJgZfe8Y0dVV%2B%2BtNLnv7edr762zc1N2xgbs92rV2z52jWbv3zZhqem3T7jIAIDOQQdAZsCKAP44J7Jqq9e5HG96D0w4Tkw%2BaXR4yx71BlwUoCS01HqVKQ%2FOrL65pZtvHxpqy9f2Mr4c1ubWDd2R15aumRDn31q4zdvWmF0NAPtukd9zNN1hgxzRXeBnHIXMoorycRPgOQBhd0KowBPi2a1mu29eGEvv%2FnGHozcs3q9ZtevXbOhTz61MY4SIuAZGEjnwiadCVvTgxLy4kXA5zZ3z%2Fv8Y0%2FeEx5ETx5eogUZ5uEeHdnm48d2r%2F1ftYv2jb%2F5Gxu7dat7jq3qDrxOQVnoNjzKwCfEMrgJ1wyHLKGXLb0M3r4iXWSTjhXlTF8mgwAAIABJREFUx2R14WDfXvzLv9q93%2FyrXb12zRb%2F3b%2BzYYLmKLrCFPui23feQRc%2FAq08Y9HTgB%2BBJ2VmtHm2E%2F%2BFJ8Ev%2BBz1kMTilwCl8rhPz1E3wC%2FqjlgavEm8D55zJSs%2F0kX9ivLTp%2BySxCO6Gg1Pjx3RFM6cTQIm%2BPMHvXXOVeUcqsS7ABhlxzPXi%2FCnJ33%2BIe6D3njOXUU7hCSeZQxIacI2R5bgVTxf5Cq6UkdB3B%2FLB47JDoWeqD6TQZnSYFK61ztgAigEkfyNYtlsfNJsZKyb91h57168qRx4i4LNULx0lQGhUhfMhktmg8M5HucVmdfRMHkbLt0PRU%2B56G2McR1K0LNuCtao121ve9te2KBtFNdtcWnRrty4rgOwSUmPn%2FekUbE8t4NNDWy%2B0mRYRtp44dN4%2FKk70sgzEEWRDAI9jpDtBtSLI4UXrV5TB%2BIZVU9TRY76rDYjGaqAFXni2i1UgLOeOC%2FK24IuW5XLcRLAzI6kD05Fyqt3cQ9Ouu9rIJgC1mxZY3bL9iuj9rIyarvDw1aaXLTFK1dtcHgkNUgJ4R6%2Bp3fZJUe4eMiHRL%2FSdIwRgOBp10AnAHlcJQleQGcuwIrGI02%2F7ilazgJZfLTBdcVTBGYd397KXwI%2Bwevy3SUb8pW2RuassIDpuuEkOvJKeoK8gjTg%2BjSr1BMbJObrSQKrUorsxtqxFg0s7TANcd%2FP6UyNkUjq2ObKiv2u%2Blu7NzpjH372F9b45BMrjU9oNCZoE5hArI%2FGjB%2BSAOMQnpD31N9MvJJPH0J5mkgYOxH3l9X%2FHGDiPaU2m2Yzl6y2cWDffPmlDTWK9quxOZu%2FdEkjnYwuZckjf%2B4aOtBLTy4Bt11iuh9Cz7pvJIegPxNXFI7Mkk4yykKdKk1fspn5K7b69Tf27Z27duflln00vWMfL12zuYVLNjQyaqVKBP8JUOAS5cczePCOA7kpXI5X2%2FmDTORsixj%2FfhJXAqaSJYELpttBjci0fXQTvjGFtHrlPVu%2B9bEV%2FuqZ3f7mtn377bf29daeTRdW7Fpp2C5Xxmx2bMamZmZsZGRUgUG71dZB4cVyWcdogC%2BjiG2OWcJOMqoGvtmvayPdJmQfem8Cf6Ge8AdfguJCUbNhyFCGp%2FwkD%2FexfATc8zjJbR350ag37PDw0Lbqq%2FZ096XdfbJqq2ubNjAwYYt%2F%2FoFdu3rVLl%2B5YmML82bj42aVivSAI2X4qTM2jePCL3%2Bm6FAMzFfCFZSUq%2FuPnlNaeO6ksaavbfDRy6Acb7e6%2BswXh0ZZ%2Bb96vWEbq6v25d4ju71Ts%2FbsJbtx47pNffKpOhKbw8NWrFatkI5i0egzNisCigw08KO9ECrZFNFowz2p45F%2Fp%2FfQFbaMJLLLPm2Z725H3FY3Gw0dKVTkmKN2W0H%2F5%2Fef2t2pRbt166YV%2FuJ%2FNFtc8n1NOm3XIY5Ekez9iJluPfZ2JmQQPBMFIRfxOumljgRqW7FY6pGV0%2BYa6RTm7uOFgHqVozzKgpZWsyFb3Tw8srWVbXv8bN2aU4s2P7tsi1evSM7M1KD%2BM6W21WpKX0sVjiDDxnPEErrdkmxLxaJo5tgljqpBzySvHB5xi6123jrPQRG%2Bwh%2F4pZ29xQcJPbHFRyGBW2QXcNK2Ws7f0OtQYxUUdTYJWJdUv8ynwmYzB7AlzHZI%2BXr0RLarYM1a3emEfrVxfsSU122Ag5fvXtUiMDVgJr80ycBNZUJSbU76EIzRo38Psxo6klJKwPEte%2Be10u0v97n6nGkE7IC37vSmqcDgTXkgkPDqAr3AXczauEhe7%2BhUSdhWeJMFm1EUbTGwzoKX5Bl0HmdGAHt3fUM5cNxDfBMRTaOZ0Yj1oFhIvUgpDeZMeitHIjm6sRaJIKvYyTqNAw4VG0fbjQYBaVuNB400FeCoU7S1wr49axdso12wcqliU5UB65SrxrQa3Mpy2aeZqJFRQ%2Bg96XJeqGmpMcFYYnQxAKTlxzsaFNZVZcY0GQetF8BIp0ZIRoL05bJMhRsSd7l1n6osRTouBatUysofZZFaDUayNeRrdXCMCilocIPtTgoGIE33gU95nBNOmYnQOqOuc6AzyEiTAhOeZdAxuDrvjU5Rph%2FhBLaVrlxOTlOzba1CyxqjUzZ49aaNNQuacvXkoGGDDbOZ8qAVk3F1VolisRk6MpwTf3kXjW7cB3%2FgR0vOslkJOdCoJVMsepNzSD7%2BeEfZrHnr0u4ypgyXhjsMYjEbsWiAxZ0vd%2FKynOr5E0z4TwOanGB0L3AVVPiPXCV5bHaaphmKLDl1G3RgImfBlKw8oUoAf8pxTmlKWKPZlCNPPehxRNteP8AFHRUfU4PRrroJoZnt0o5ci1bBebeCzvmjftVrNXuys2%2F39w5tuzpkzak5q42MW2lgOOMrukA5IAZu4nNqWML5cV4VVYbSqpp3dTTySX9FY3J66VDAOeIvJ1%2FO%2FERxMrnk6ir1TejwTm0s145ZtWrF2UVb%2FNkv7cvVDftvt%2B%2FZ0PI1G15ctoHqgPNJFHh%2BOK8pjaLJcZBM03ogSSaVFeWgIehiNML5NXukh7cg1RIMziIsWik5T%2B12S9%2FFvzgPENQLHStND9j82LR1phesOT5tX3z%2Buf3329%2FaupXs54WSXbkyYGMDgwrI0B%2F4LScS2fOMU42TlQIznD%2B0Dr2RDZWeumMaOubODetDfUpambMINdUz%2BOLBA%2FKkPIItbEIZx3fARw68M8SsheNcrFqpOmRL0ws2cOmazXz0qT1%2B%2FFh%2F%2F%2FDVXSt8c8%2BWFhfts08%2FtQ8%2F%2BtAm6dBQ%2FRqwSrlqDdl86kbVl0OgQ8Vi2tHc64nT5bY3aHV9S3VXdsF1S%2B2HfLjkbOfk3SpWJKkWNls21POEbutdwqdWa9rRUd1WV1bsq6%2B%2Ftrt379rOzo6NDA%2Fbwq0PbfnKFbty9aotLMzbyOiYEQQ00Gf41umoYxT9h2%2FISBoivLwtJBh1edKOebsgvqpd8jrHv6rL2Vo12oWQF98Y4HIbHnxx%2FQ2ddFuAzNF5ApajoyN7%2FPSF%2FfrXv7aHDx%2Fa9My0vf%2Fe%2B3btgw9s8soVTQNuJvuXKpw1202VUzL0GlyLajcY1aVOquxkKxqtpnAuacqg1xnqAAlJlyQmeLyHBrW3suNF4%2FxJ6A574nrbMbXupY7oPzg4sLtrm%2FbrP3xtpaFRm%2Fv4MytMz9lBqSr48Kid7CL8U%2FVX4Ok6L9tZ4IxZt7O0NaFPzu%2BuPwA%2FO8XQE%2BhxP4ErvFe%2BdO8fk%2F3lW1iG1B6jZ0imhW0oVbUxWNPKVpxdssrism0UC7LLY%2B2iDQ0P61xe6hjlt6kf%2BAvpvGvhWSTYlKdlnAKAniltKa23DWY70pm%2BuNw8wAN%2F%2FuN%2F6jl2qVjRG%2Bmn5AYO8DHRTh5k2S4l3ykFnoKVyTiCEnIlW53gEGiTv1SqOG9T8Kt1heKb2JTqaNtKhZJ1BgaFf0u2zuVhGuUUVu7HtTpq6zpqC53%2FgTf0qR4mHKh7UOS05wJd%2FI6it6%2FIF9sj%2FPFrlSH5gIIjlqgOoLfYf3SrXKjk2m3VfNcT2Rxv46ImCA%2FpUbSjqc6qVPdRw88QJ%2FGPU9sJbe2C7w3rmpVk6Qrv9Mq%2FSDpJPYRm%2BUH9PovTIkWI2%2FOuef06L%2B27728MB96OYFPscqNzklLqdB4tRKZecgSKX6noqhJUUAxmG0PPV68igE2mTL0tcn4wylGhlaxgtVLR6sWy1Ur%2Bd1QoGX8VbR5ERfdpWh0ClmQQZQkMx8PXclBBVSWBif3AaIKzKrwbUTV%2B1rGmbKS%2F05bvICoavJaxloJG0J1vd9IwBFr3pk5BdyyAjyHGUHYUgbtRAhwHvcthwGlIwSBltKEJA88ghRxKDEbik5wWYHqZ7EqfYmJvuFOQFAGyeCAjTTje1iwZJAFOGhXESCZaKbdgJWt3aGDAw%2BXQLhdseHLW5q92rPXsmTVLFatZ0RqkZ4ZdcoZxsgs0DiAkEXdlHPbaeU3nmjfeLZXlph8dAq%2B2okLns9TOHGYEyjQc9MyRFozljNPhkBoLTb1RA0mnh5%2Ft6s2yWbPT8uAPoapNdL303hECoIK1Oo5bs4FT37GBalW8gufMYIK0aAQIjiiq1UTvoMt1TZSntARX8JIfgQI8KJcKVhGvvDEAbhOe03MNDB3y7dVEsqfsNPIr306OmgeCyM3rVBrFEu1mHXis4MllCZ92jur2dG3Djlpm0wuXrDo6bu1y1eqSg%2BsSvCoWCHaV3dTkJjk5LmU5CqKRRNRsTe1y%2BeXxk3MqpxhY9Kq6RMXEdIuuIfsI%2FICnepqcF9UFVQdHiGcP%2Bc0KA0N26fpNu3z9gf3mt7%2BxOw%2Bf2MKV67YwP2%2FVgQEPlGVrKJ81g3IxrFMsaL9seNpWJ0e4AN5og6rKgeccsyJ7hK3wDg7hmvgMXXSNtdvYi4IVNesPq1c0AjqqPVWiCY%2FSJhfFStnK1QGbXSzbx8WylYdH7JtvvrFv7t231e0d%2B7Of79pnn31m4%2BPjcsIpo5wCF2wjdUR9e03vILJCyet2GxZHhxTluzNFHVXZjKzKbrVNKgv9dDKpk6vkdSmNkHbQz1LRWuii9Jq6npx24LD7OPwYqNjM0mWbmF%2BQLJYeP7YHrOV88dJWtnfs7%2F%2B%2F%2F25%2FuH3Xbt64Ye%2FdvGWXLy1ZtVRW5wo4oF8aOZJNdec2Wpp2hyCEwKCg0WHkhe2gA4CgRqJVkOi4tVvJNraQkAdDdPR0ytSRltWb3va4xSkm%2B%2Bp2uF6v2%2Fb2jj158sTu37unK%2BsZqdOXr920mzdv2JUrV212blYjtaUk2zpIwAfqO%2FwseJDZhmfMGKTMTtvxRleKRWu0CORbVk4VAV2LUV3y4Igm4tSxgOEp5fS%2BrBFggp6i9CocaHCFPzxTrrjQ6djW9q7dvn3b%2Fvmf%2F8mePn1ily4t2aef%2FcxuvXfL5ubmrDo8Yi3NvPbRLfJRE2Tr6NhAr%2BjgU1XA0BG0o%2FPoGp0qUi%2FHW%2FWAyu02jzYVQAo8nfEpX1fvtIYvdZbg5NPRQVLaVHST%2BndYa9iLtXW7%2F%2FiprW7t2KeffmqzS8tW75g1Do%2FUSdmxuhxt6j6BfELBmp22NRghTW29G22OZPNADeEpICl6HWg2vUPAbQ%2BY%2BKh4tVIRPtGuA6%2FOaCUdCFHvOqY2o6JlCV7naYeOakeqX1KXVl2dEuWhERuZmra11TV7urJul64fySbX6nXVDy%2FfO4%2FLlY5VKlXpvnwN2oRWy2oHNdURcCQ9%2FKpUKvpDH0jLr9Fs2WGjLj6oc89MAdrg0JB3htKWoZ%2FtlmhqNJqy7dGG0HlSrQ4ordaSprbuSDCbmlZO%2BQTwdK4PDAyY6gjC77jfd3hUs2bDfbSwR6SrVj1IQ%2BfgdqNRt8OjI%2BmYeKDOm7JVqk4X9hA6hWu9YbVaLem6SNUMhqHBQStXyslx8ra33qgb9bxe8440RkqhaXBg0AYGUgdkG5m2rF6rW6MJvnXVQeoVuA4NDbldVwDZsXq9qf0s4Bf1Bn5Xq1UbHBzUNWwwbbRg1mrCoXZ0JPUcGR210ZERb6%2BSv9JotQTz4OhQaemEhv9jY2NGeuRKZYQ3jVrNaodH4kGj7qPAdLbSdoyMDCstrRFpaWdp6fgv6oZz7N2%2FPwUOvEXB5nnicENBM8WPK4ZDf%2BqJZblIw3b39kwVEzucviuDe6%2FudMoBxfH3Zq%2FRatv2zq5t7e7b9t6BDW1u28jLVRsdGjTGF0cGqzYxNiKnV45JoWBMGdo7OJSRDWcLIzw4NGhDgxgM7%2FlnWtvR4ZEdHB5Yp5kaznbbaCzYAGJggBE8d3QJKjCC%2B4eHhkFwJ5%2BlSUM2Ojoq4x2OKbQe7B9YvYbR9GAB44sBoJe8lNbIYTDZfGf%2F4MBq9VpickGGinRDw4NuXOBXuyWYB%2Fv7ajRw8mkkMWyjI8M2ODDghkSNS9N29%2Fds7%2BBAI1uIBYM5NOjlE0RhtPGZadz29vZtP%2FEL529gcMCGhkesUq1aZWDQpmdmrdXqqId8c2PbDvYPFWTR4A4OVG1sfMyGoUubgLA8pWn0RPOHgYd3BGekIS2NgfhKg11v2M7OrmGAMazQxYgB9PNXHaiq0wB%2F%2FeioZltbW97AaKoco9olGx8bs2GMdqWiBhknGtq3trfF19BHGsLJyUk1HK4Djqvo393TVCf8G5w1GreFhQU1hhh49PWwVrOd3V3RRaNNo8ff0PCQTYxPiCYaBhIfHdZsb3dXPGOKE8xm5BhcJ8bHNHKlYKXdtr39Q%2BEK%2FTgvONQDg4NqYJyvaLrzis1JGG3RtKyEA1MVp6ambHBwwGXQ6djeYc12trdtf3%2FfcKBevnxpv%2F%2F8C9s%2FPLKr129YdWDICFQIhA4ODm17e0tpVX6xaENDgzY6Nm4jwyNWpdeYEa1mS5uj7O7uSm89GChKrhMTE9psRI28oVdN29resp3tHekATjAOE3VgdBR9GXKHpGN2cHhkOzvbbh%2Fq9IAXVPdUX0ZGMt2i3rFGc3tnx%2BvCwYEd1Rt2VGvYt%2Ffu29KlyzY%2BMalgDqcCXoHr0dGRnGFswMjIiBrjoaHhzHFAR9HB3d0d160kq7GxURsfn5DdkCPf6aiebG1uCjZ6Dl04GJMTEzY%2BNi59KZeK1mi2jbrKmkZwQK%2FRFZyWmelp8XVqdtY%2BqlYli3%2F913%2B1uwSc6xv26MlTW1xaUjDAxjs4JCWCjEJJ6%2Bw2Njdsa3NL98gFJw%2F%2Bs%2BkTNGJrCIKQ%2FdraWsLV17%2Bh1%2BgKdDH6rTrbNtve3rW19TXZw0azIbqwbeCK81KpDlCUNRot29zaElxsFkEHH0i7sHjJZucWbHtry548fWJ3bt%2Bxr7%2B5bQ%2FvP7Rvb3%2BrYHN6asoWly7ZwsKi%2BOrtRVs2cH1jQ7KFr8CEltmZGZuYnJCjy3Ex6CBy2ljfcN1uMdLm5YMrugX9JXCtN0XT%2Bvq6nD1GdwhExifGbXpqWjZpY2PDnj59pkCMYPPRo0fS2cnJCXvv1nt2%2FcYtu37zps3OzkpnwWtv%2F8BW19ds7wBbTJ1takR9fn5e%2FKIjjtkj6NU%2BOpj0lVE1bC46MDc3q%2FotO9QpyF5sbm%2Fb5uaG6hYBXaVUVtsCXbRbxXJJtgl9Rq%2B2tralA7QxtAPIlT%2F4RtkrL1%2FaH7780jtjbt%2FWiObwyJiPcmgKooe86CZ0YAeBu7%2B%2FJz4jb%2Fg5OzsjPNBzeH1wWFM6AnJsMgYPG0na6ekp1VfoQjWor1EHsPUwAB1EX9kgCzsTtnh3f9dWV9fEMzoYsaOkhWcvXjy3J8%2Be29z8gt24eUs%2BxuMnz2x%2F%2F0C6Sj3EIV9cWLSJiUnlIz%2F1cJ11txsbCVfvGKQdmJqatMHBIauUmfpitn9wZJtJB5kJAl%2FBbXZuzuZmZ21waECdj812W%2B3A2tq6rthteAV%2FFubmpVua0WSmjo6NzW3VCdraerJFml1UKKnM1bUN8ZS6tbq6busb65If5dMGTwhXdHtE%2BkteRuBfvHxp2KJmCnZo18EVOzA8NKROaPyUnb19e7myInuM7tCW0Q5dvnxZ7WGlXNLAAIEWuFIPjw4Pnf5KRbKnLcTPKVGxzJc3rW1s2vrauvwn%2FKzQwfn5OeGKvaLOYd9fvli1za1N6Rl1nnaNdOjWAKcZ0IHVbKh9YhMu2jg6CWgL0CtmEyCzitazUn7Dtnf3bZ16uOf6ig6SBps5XkVWBFptI3DDZm5uuC3GvgwODtv09IzNzs5ZZaCizhTpK1Oc11Zte5t6sCvdHhkdtpmZGZstztpwmZlAdDI2bf%2FwwFZWSLsj3xBdoR3AVoDHUGlYvK41GqJ9E17hF%2B0fKCiem52xufl5myiW5OfAF3yMtc0NyQD7DQ%2FQ0Xmm7JdK8onwnaiz%2BI7Yd9qCWpIX7dvS0pKC7aGBQce17R0iCjXdRU%2B%2B5rvLT4UDP6Jg0ztLMGLcoc9%2Br7ZFwQa7L2KYdvf2jV5ofgwc4EQTtCgoU%2B8cwV1JwSYBpxuAmm1sbMoRwaAw6jdYLdtQpWTzM1M2QlDGyAK97h0q4aGtrq7KyNZqdTkqVMKZ6Rk5%2FBgFcMRAEjzQKNeOalakcSmWbHRs1Ao2qylfBHQ0RI1aQ8ZqZW3NDmo1lQMcjBBGnnuNjtEQHB7Zxsa6bW9uKfCiIcQQY4QqpYoNpemiNFoYFBoCOaT0DpbdwWjPzKiXEHz4gevuzp6trLyUsaLBwVnEEbS5OTVCNBo4nrVW3bY2tuzF6orVGnUFQQTOszPTGlkYKNOb6CNT9LjhjNHI4bQTENGozS3M28TUlFXLZRscGpYTo4Z4e8cDw3pdjgeOYPTolcpMYUx83dlVQ7C7SwcDcEsy7kpbqagcRotwHnGatrY2JTdvtAbEV9LibCjY0yak9WTct6RT9JzTaKFz7FKsqWnsq0AAt7tnz549t739PY0wAYvGkt5MZAVMZOt83bUXL17Y4f5%2B1is%2FMTGuRl7TWlOvIzoCr3Bc6NXmGwEujdbwEEFZWhdmHQUt0kEaTXhlBTkAeE7owpB6niVaNRoEg97pUJcOTCBXzRglgCyrccGpIHh79uyZeIVD5jo4K5gKNBhNbbelz%2Bvrm2o4wfvho4f2zdffyNGdn18Q3jiONMYE%2BtCE84SThW7gjCwstK1arhh6RQBMIIq%2BQhcNLA4tOjg5NZl0jGmSPsUcXHe3d%2B358%2BdyYnHIFbzMzEhHqTMuV59%2BiA6srq6oMYYrOI4zM7OiHecc%2BQGDwBg7gpOBo0uji1zphGAq561b79nw8IjqHbq3KmdgW%2FJCPsgKWaAH8IvKjX7itKEDOC7YJPRqbnbOqpWqeEb0Ir6qbsMryj%2BSAOWEEaAPDsnhhK%2FQj%2FOO8wy%2BdCzhNBNAA5Nglw6FqXLZrndwdA%2Bt3mzayxcv7L%2F9939UmR9%2F%2FLH99f%2Fw13b50mXxjiCKQBBePX%2Fx3KCPH%2FxB5%2Bn5Zm0i5fB8cHhoa%2Bsbtp5wxca6w1gWj3COkSvvj2ro9ob4eHR0qHqJbVHn09CQVenIKLIGsmm7O15f0Fd3CIsKjIFNsENwhOwmxibsq%2BqgrTx%2Fbk%2BfPLGnjx9L9teuXbPPfvYzu7R8WbqDQ42dpm49xxbXasKLjg5oGxsf10gtziMdSfv7h0qHzuJ00sFB8Aj%2Fh%2Bn40xRJRjSdVy9evJRDTD1ANuDJH%2BVQ71ZWfIdZ6GZkbH5hwQiK0RU6HNBb51VJdYCgYWNz09bWsZlHwmFsdFQdGQRR6Bc6hG3BIXQdWJNOUF8JdifGxrReuqKRChztlu1t79jK85dq59AXRl3m5%2BZsbHjERoaGRRdwGzXsu%2BurRnbU6TdonVZHPED3nj19an%2F4w5d25%2B4d29vZNQLhxcVF0UK9BS8CTDpWaY2pR8CCp9h5yaBYTKO5IzYyPCreoSvkp3OGurW3vy%2BeUJ%2Fn5loGHwojPvUWexGdiUxNxtGmLDoR0SuCCGwwbRZp0QECWIJTnmnjsBGMTFMvsD23bt60a9euq%2F1GD%2BlQxL7Gb3Ji0kaGWRuZRpfTSBEOOZ3djAhS77EnwnXIZzFRt6GL%2Bo8twIegI4XOTtmTKZ%2BOSDm8p43HFqMHdLpgM6FrfHTMWuPw1Tvo8EeoI5S9v7ev0Sh0EPtCEEG53nlHnWPKc031%2BvDgQD4GHb%2FeJo9JRqxcYuqm84u0u5IVeKH%2F4%2BxsLfdKzpXgUz68g1%2BHR4feXhZL6oChfOwFmVxedXWSwQdsSIzoAoMfbS7JCSKpT8hfNpMR9VZLPOAKjzwwdX7BWzoGuCpcLRSkf%2FiC%2BAHApaGmoxefBDtPWyQfoFJVZ7fP5NLUEy3Hos7QsX94WPPRYnVSj6hsaILPrKEBF2BSPoEeMikVK%2BqwpdMWH4RyQIx6hx2go5COEiAQ4FKnkA%2B0YQfFB3SmVlN6eNGulK1eH5K84WusGaPO0OGMz6AOZWYMsHwp8cwXjrnYyEenFG2dy0YjDcrPulT0F5w0ZQa%2FWctQmOXiswiwD7TpvCc%2FdMGH%2BJMQ3%2F3zk%2BPAjyrYRHqqBEmMbIxBpcYyofwcW0IDRo8ZDoMch1yg6Wuf0rquUlnBpk9ppYe6pspGBaLS1mpHZq2SFVpMyfJGgAYLA8DUOBp5jBrOIEaAhgcHj8qnaZ0aZaDCYgQwWI4X09WYAsWIJ9%2BgR3%2BioSPjBP44GD4VlalHmmwo9wLbRvqY5YVBkJOZ1nXBDEy1%2F4kFiWduIGQc2r62SuUnhoIzf3QqAltw0jUMC7wpdDCCnia7igbKZGIUzYSIcWMlFvh7AnVGZMiHQZOhk8vEiIxp9K5eH5FxRR5qHIAtPnXhqt3SZgCswSwKZqvljQmwxaPEJ9JCBuUyIujrmJoabQmDzne1GSkdPcY05ITK4MA9%2BX29kCsfeXCiCZJoLJnmhNEl4FWnBL36MsDAKFqVqT%2BVirV0nA6y8GlG4BR4OAwvD8eTHw6G4%2BNwIy10wU%2B%2BATs2sQIX7xDAHXW6gu84a8iQMoFLYMSok5p29waEM%2FAIWKAFGaHbgwQNAJS%2B%2BYgAcIYZnRwZkY6ipzgwONHLly9pFFRZ0CvS4qiMjlidkWQ5Qz5lCH2hscQZhWfgCUyYhANCvRtm2hJ4S59cBtAVaeELdR7HjRF4TYNMDSJ6DZ%2FAlQBXfOh0FIwxao5snTRfBzlQrWgkv14bVbmMEsMr1tdxpMujRw9tnE4FyhocEEz46LgWbWRoSOVJX6gLrLeBh6QdH9M36CfIYfSVb9Gww2Pkx6gBnRFymtOomoIBgnKQTbqJvMEFpwMnhR%2BzKxghASd0kjTI5MOPPrCBwarW1H179649ffrU7twtG8eKgAsjAMNDOOlFyX%2BK0a60IzfB1gijHuVSqitud9FT%2BOOycoecPHQmwXNkxM%2FprRqjebwnmEJeOMR0vIGj6kuxoFFDevo12nU0KucJXjKaBF%2FQxdCnUUZGx8ft5fPn6nijo%2BzF8xf27bd3ZcPXN9a0BnJmdlY6z6wHBVONppwn8A9dlzOVpquDFyOefMcJhG46J4bHA%2FuHAAAgAElEQVSpF1pfCMm%2BthuZ1moztrtbVQfJ7t6uPXv2VMGEBxRO5%2FUb173DpuzTAJl9QTDiHUk%2Bw4RaCx8GGR1OnWz1BjM3vCMFfZGupg3H0F14Ms2IjDa58ZFV8XVkWO9UFxgVg4aREWO0Y2R4SI4ogSCdTtSZMuvdJC%2BvV8i1LafUp%2Bd73Szb3s6OgrUvv%2FyDPX78RDNPfvmLX9jk1IR4BM8IqEeZiSI77O0cdXRocEB00cFIfUEvCIx5T%2BBAGdg28BobHbFWc1q2gE4vOsQY1Yn6TUpsNHaVek0doi1Gvuiz6qiCPucY%2F2LbCNagFZsPZoyyPn%2F%2BQkEV9e3G9Wu2MDenAA8cGRmlbmHH0VVkgF5jSykLnEeHhzQyiTxx8KlDk8FXdfpRekG8ol4jN4JkdeYxEo6NSR3U1Bfo8lE8H0EFDwQPXeCI%2FqteMeKroHbEWg14NazlFNBGRwJ6i34TsGgkr9mw8bFR67TnRZ%2FsOzwZH7ch7Ca2UOtlfdQffkOfb47DprwVmxgblw1FVyLgQiYz01OG7aSDgf5zAmjNLkm8JjF40ynPqDt4ePtSVtuveg2b1Mw4XfAFKR1NTKi%2BMYWTOowNV1ItHTDZBGwcbTUBGz%2BCaOSBfWXWFr4i6o2uMTqOPSatt0WOq%2ByVppm7zwDvqC%2FoInYA%2FtCBAZ3Qw9Iq8mO%2FsA%2B8o94wMgmuzEgaYNYOukIQV%2BR92SZpB8oEw%2BNyvOAfsmMJDOnktxQLjqtmFLkOwj%2FZ11S3JQBjTWnJOzYY6W42hCv%2BCZ1pWRvjnBWu1Hn4QmCKL4ZcoZV2Dh6gA9hDeEi9hlfYa3xNeExHmgY%2FUFT5PhFsqpB3%2F%2FwEOVDo4MW98T9QzP8Fwm55vKnyFHzhmdSMSioQ1HTNtkY06Tmnx4o0GAGMOek0LUEL6v0ea4hrxnxzpvnRe8Z0BaYjMTq3uDBnQziTjCxOTtjczJQNVNzZpceNXsSNjS2fmtJsyuBjBKYmJtVLTgOANSTQxMgzCtms4zj7vHacAQy5pqLgRDM1l9GP7S1b39zUPYaJ9xgGNlygd54RV5o49fjt7qo3UUFbmo6Dccbo0TDT4LExED2OjK4SGNMQwlUaMneemDbjG3Sw5o%2BetujJlOZ0aLSqasxxokmL40nwvLWzbTtML8HJVZBX0MjH%2BEhyHrVYv6SeTnqpDw6O1HtIoM4IyihOxqhP32N0GWehXqvb0f6BRsJo4GjQMXiMbsIzjC1JMaj0INKLSh45LsWCGjLoQhbQTwDDSA2jkATwNC7wC4cR40qDiIGFz8AFjqZuHbIGxoMPvmNcgUn5njZNDWVUkSmB8r07bsgnJowRJemAemjbdnRwaLt7O1rPEcE7vc5MSaIXXDA7HTkATJ1DVq7bHqgxSoUDT%2BBFWn44ENBVTx0lHlRV5JzBKwUG6GGHkzwObGd3T05TM22swYgucNEFNch0jKj3vyb5ch8BDA4k9GtkMwWr8AdnGn1h2uMXn39h%2F%2FAP%2F6D1Z%2F%2F7f%2FkvmuYDDuhRPXXMNAgyojEvlxWw0Sh7w8X6Nh8FRL%2BRRZTPdxwtrZfSdM%2BCvkXHDOmQNfJh5I2OH4Ia8sEv5M4UdXil8lmXSlpwYCo3U0NVZ1Paw0ONEsA84G2sr9vnX3xhX3%2F1lUbY%2FuN%2F%2FI%2BaIkaDjnMFL8LUggN4gm%2Ber%2FDAg6xYm0jnBB0bPi0VfcUbEq7pzF9kx3vggKPSKjj2dTLqza6j%2F%2FDVp9FSPymbtDgMaAvf4Cf1mxkcBGNffPEHBQ1MH%2Fvggw%2B1xm5hfkGOHHWaOkY%2BeMAVuJqerqCf9aU%2BEkv9y6dlRAlcSQ%2FujoHXWRxsySptboLzxtRn0istAUCa%2Bg6%2Fwrah8uKVZhf4BlfAxT40of%2BoJntAsPnwwQN78uSpZhwgO6abMZK4eIkpuLM2SLCQdBgYOFLoAM4oukJQgQwoH1xDX8X%2FhKe3UN5phC3EZjB6SQDPrABGUOE39XBxccGuXr2qMzOxI9CsjksC6yI6yJ%2FPrgg7oFEdjYj4JjrwBF2TXiedFg7YHeopOhgbdTDtOc2ICP1HCbSuq9EQXtCnoEgdIWXJXPZCXqbvCIqsSMcreEBdh05G5%2Bl4YcSWDoAPP%2FpIukPbI%2FuIw6zOENdv8A5coQu%2B4LiqvlA%2BdUAzUXzKNWmxfeg0o8rO%2F9Rpk9KqHBDTMYkt2WBw9QDQ6wz6L72SvjoK1D%2FaAcrHqUavOUv33373b5LZ1StX7a%2F%2B%2Bq9s%2BfJl8QfdxibRwJEeR5u2VUzxJkvpqP%2FwPzq%2FKQ39p%2FzAFXrRJ%2Bqs9ArDmEbHlLbsSzRU47QOEboiLTh06YJnBIH84DZ%2BBiNo0pPEF2T%2B%2FNlz%2B8d%2F%2FEfJ6v0PPrBf%2FeVfKrj3Opg669N0csFUffU6iD0FVzocZMRdqLIr4ItPxQ9%2FxOXquLpcfTM%2BYNLWq82CXPGgKXwlVxerRqGBKXsJX5PbKj5pkxwfHUUG8N911Tux3D4x2JArXx1cRckAnyn%2Fo9zQf8qBi2oL6BTI6QrfSCscNDrryCLP4JX4otk7%2BKLQ5fUVmPhv2DT5fPBVa0F9RogvUWEdZuqIT3WW8pGr%2BKVZFthh3yTIdcV1ABxcr9zPpO1XxxDrgaVXCMvpUtrMb2CzxKSHacdhklMedgnb7cFmrBNnE8JkA1UGI7R0RFSzDkKvn44X9L77%2FTQ58BYFmwhIZrZPUm5QPcD0ChQpGalkYXo4DvQ80SD67l1UQg82VfnSJjlqzOmpS5sJsXkOazaZKoODwnqWS0uLdu3qFRsdHLQKvcyVig0P%2BsiOtsKRQ9w05sn7LvHuTlGpvdFkRCho8YabBpaIBEOiHi5Gu9L0zTB20E%2FjcqQGznfPxIBhWHFeZRBktNzJy4yrRoa8%2FXNnNO2U4hZPBtOdQW%2Fgo%2BeV3jhw1i81BG5ccVwcVwwt7qKP7vk6JRoFAhZwVc9YGkV0XGkwykZYLqeqzBbrpGUNqjutCk4xxqz7oiEiKE4NABsKMfqrDva0ORA8U6CttK4mOADgGnymYcBoKi0OYdq1E%2BdDjlZaqykjDsGMYMiwurGOxg2WQYcMaIJHIyFHODnuzjBvEKFfWpkW1KMJ3gg4U9wf8Kl5yIAGnLKDvwR67rjQR%2B4wJYM0JTLwleyZ6prqiBxtGkMCfdHOET2p0UiNnJPpvZTQB99DKykTmAQM7uS74%2BY89QaQtHIKU%2B85jbzypLzgEnWOadq%2F%2Fe1v7Hf%2F9jv78MMP7T%2F%2F5%2F%2BkjofAH7rRA65Og%2BOK7COA1ntoCWdDvljXIRMsyhZh%2Fj4aVuUh2FKvrI8qk1D4MuauHZF92lzIz6%2FOB3iQ8UFTypseRKoTpySn9969e%2FZ3f%2Fd36jj69%2F%2FhP9jPPvtMUzqxP%2FA3ysrTl4fpcgpHCoy7P%2BGfHBR0Bv1weJ4GqtHt%2FE9PcsrSyHDoa7IRkTZfEvLFFhE0sObxq6%2B%2Bsgf3HyigZpOaTz75REG0RjhTUAsc1QeNeHSPA3Jee2ChyhcFfk9X9JlfL9U54Mnu0H2HjcLRo%2FOBzjWmPD94%2BEBBEVOyMSizc%2FN25eoVW7p8WVM%2BxycnFLzhDCMnLwt6kgTdC%2BvWr6RHKCiywcFm6cbLlZdZkEkAxpQ%2Fgn2mJl%2B9dtUuLV3SlH1GhtUBkOQYdMU1R5luIV8hRn8CNyEJX5%2BRoiSJH%2F1wgoM%2BDgdDaT98M7MA7Vd%2F77rs9QFYoEtHDdNmv0nH0MDf5eXL9md%2F9md2%2FfoNY82fO6nuZFMvFdCoNoNBlOS8y%2ByPCvCWP90KfYm%2B%2B4%2FenfWPV4OkMCkhMhLysmOpMyjxnnaBNoc177%2F%2F%2FPf2u9%2F9TrL567%2F%2Ba%2Fv000%2FUCRfQqHeh64EcPIJG6gU2jbKkQ0EmmeP%2BLMT7v%2BXyACJwiCvJSaJk6aXwI%2BSUDWJUFHunBl0B9G9%2F%2B1v7%2BuuvtefA3%2FzN32ikHw13fL1AlZXyq4ykY8gtsawf0%2BxZeRNieTyzBOkmR1qXsP5EyfaDfgRpJPGAvz9xvrT8faRLtJ30KZL8YNdAimv8nYRM2NecMpAs2rbUOSZdl8xPgtH7Dj0JG%2BcnO%2FR%2BT%2BCFVl5m3FNvpOvSdx98UduQOkKEx3Fw7978BDjwlkyjzav0SVKJpsodAVKQg4CE6QPeY1Qw7cJYGlHDJqXHadPmQb7zp4wx6xOZy89ceDaVKZUVCDXqRzZATySb3FQrNjY8qGlARdYtas2HPEDt1EpPGeeFsSbL%2B8WS8QevaMxSdZaxTtMQwZtgFaQwL061ewjk47%2BS4PqaKGo7RlbfUu9ZwFdvuHYE7TdCyVlS6%2BvBF4u%2BtUFBeodxEMzohYJJ8rX4h5FDdlkj2PS1VjFFU0lSI8Q0oGIJHlRMu8fJIWWsGCo88KGxEDvUI0xPnMtjsDCgxrDWaipordWP5KAx6jU6NGyTY%2BM2zBo6GJYCDjnaABPTcK45bJkU3hh6qR5wBo%2BIvtgBj2ysnyCrf3POu5F3fWNNBz%2B%2Bl4U0DoQ7sdrxM%2FEOHYp87AhaKaMDQiPJ1Bt9Ri8dno9OA6MMDqJBwzdyDoraDCEDSfeg6GpDHxiDVgrAyJvQcBQIrBjBdk45a8hFIspJiRNlmrol7EVf8EJo%2Bj9kQeZUrGBR2XVVDk3qIfY37sxQNGI43Nux7Y11m5oYs%2BVLi6pHGoNOQZjm0zEikHOUE4OSTBJXJQew9E6AHHaeXNrlgSZJS8F8vqpqO7%2F785XouaX2qRej%2BzXkodqX%2BMJXzSqgMwRdZirz4IAtLc7brRvXbW9nyx49uG%2FzTDsdZCrscAqiU09yCvbgE3VBI6YAFa7c4A72%2FiSXFOQIJ6k2WLn8s9QZDBeRo0yqBDN1BChbyuRZks2Rc1K26WmmpA5qWjPTHW%2FfuW3ffP2VHR0yq%2BDQrly5oql19OCDhaY4JntBB4T4QpnIl3JSuf10ZXi%2Fzk2frpwE29%2B5LlKXmH7LH%2FRNTU3Y%2FPysPXr8xJ4%2Be6qNfFbXVmz64X27evWaXV5etpnZGY18aopwWrdM3QUuAYZGylLHoWTU8mCdGRVbm1uCyxmgbC7DjI2x0TH78P33FLAvLi6pM4Jpg9qETLzHyU%2BUnEMf5ZE0J3LJAuSCF8Izn%2BAMPpPMO3xIhF4CBwhuNzWVW6WF7fJOBvZAYFOjr778SqOAdIR88MH76my5dv2aaKZjkbaKMqS%2FXGWfexHyb06AaPDifSRLbWAufa4%2B5t6eces6LrvniGS40EaFTQYAeznAC9ZpPn74UFNPF5cXbGF%2BTqP3Pp0YWlIblnEcwty%2BFtloEPnQQyq6c6iJOH8Zt7mv5946RJe97gNI%2BsBjsAfbjKmXvdH3jjq0KYTZWTPTk%2FKT1lZe2P7erkyx11dSxFIkByw7KNi0bl6GF51sUR%2Fm5FLOpKcOpS9RehTO8SnoiefcVbTgf%2Fh4gUoIPc0lA7sovfe1nqIAdC3uT0j2g78KjsX1JITCp%2Bh%2BE0myJ9CWZCMb3E1z2p06SM7gXJYvsS24p2saIXV%2FwL9kHXVvNJ8zqt7d%2FJE48JYEm0F9qHU8917ja1RLGi4CA3fpPLDSKKcSeCoaax2zwaia1nh4LyT3JbYkp6O%2BaHKOqxwZoalNONAFKzPqE668ejBbav1xQuTaMaU1OQzUM%2FCLonFq%2B82z8Gcb%2BwgwUvqgyzOzbpJGjNbDp1mpYdCj0%2BT%2FpkASFjH7LjWGfNP3rOKHIeK933c4osGtlaeGSUICXvIqBZ9cwtshibcCamzJL1ecXnKJiSmMrm4K6iPIAKJ6gNnynJE1H6V0bHz32ecrL%2Bzps2c2WB2wa1euaq0L8NXYZQ5RVxfk3iZ8u28TD3qcs6DLyXOWBLehNO67t7zxI2Z8ZBf4XpSndf6kUhOPeQdrSOFs5S6CJRDysAOjHHyXW8TRNYFDghX0yIGIBy%2FaMVE6gmjP658yKBmuep%2BHGSOGGcykCyAuvB2SOg7y%2BbKyI6NSdx9Iy27Om1u2ub5uU1PTdmmRYJPQLvEuV4ZGCBLNXrKDopiT5Zoc4eCtkiPXxFfhKk9LwUGPTLtYChM1ivlC%2Be6M6knpD24vUF829UJuTA8nkFh58cJWX67Ys8dPbHpiUmvGgI0TDnifJsnogiNNfi%2FK8QbWSWwlVXLXU3rHhPSCLHgOy7%2BAftT8LoOcl06asgRvmQ2QpkRhY1gXy%2BgbnUpMJb1z%2B7Y9evBAuw6yw%2BmN6ze0tokpphqtB05sFpFoCDq4uk2MN4Hhq18zCNnNWVJ1nBREgQPOEDa8U9Zo29DIsM0vLtrVlasafXz%2B4oV2bfzqqy91hMrlS5fs1nvv2eLSotbCMT1M9p26igZrDT%2FTyX2KHpursCSCjaI4T5IRfUZUWXfIbprwc2npkk1Nswuq70qOblAXsAMueyfsvGpGql5p9%2FIy2JOH05ui%2BwQclkmwlIMRWU1v1JTB1EGXdFQdI0RQaQkIU%2BQJpj%2F%2F%2FHMF1Ix4v%2Ffhe%2FbxJ5%2F4ZkCD7Ebp5ah%2B6dZtN5vwHfspbWDerdv99dBhRrpjUE594aM2fHbOaXQcXVVHiTcOpGl0WlY%2FPLTnT59qHTY7fV%2B%2FclVrm7WeU9Up2sn%2B4hwvt%2BFu53njJeYlFqOCr05HUJCHJiwSKC55qFirGM0EEelbrGcdHbOhatVe7B%2FY%2Fu6uplsyHRs9V%2BcpbUMIMcGV7VYd73bmZoLuZ0eiHVyP4ZvS9uN7AojslfMVE5%2FaKL6I2KCKF%2F0l5bmRgYqMuWv%2B25twD97Qchr%2BCUfkkyc5Jy9S5HPn70%2BkkA7lHmAnpspS5OFRbMglcvH87veOA29ZsInAzlJcuaOSqqqnOhi76eNOuu%2F%2Bp1cM3ftom0YWCx0rE4Sq54z5GmaDlZJGMxujI%2BoN9KDTg1k5i3KyAORnsnkF0%2BmNwifMoHBIdiHwkY3wztCuRqaPkSazN8mgyMwG0JTLYbuTHYCCD7AtYJ3kyvIu%2BRBZ0Okwchnl7MZbf%2B9l8s7Nk3jbb1zkREX50cAGhn4lt9Yqxjl8THmr17TO6d69%2B1o7xjoZNnDwaahugyk%2F6AqI%2Fc%2FxPq7938Ujfcw1Xv3yiMxRXj%2BN6XtmWJN%2B8Vo4kh6HLYLslD%2BJ02mglzzB8fcnSaq36Yl0OfSiRL0KePG9%2Fzneg6WPeJL9eLmRL67dfH4nPKAvlxcHBYrazaY2DTnY27drV6%2Fa3Aw7IpfVaUK54dAAm5KDtTxncIXWcbyUP5q9fpkpCOu21Sfl7qWjV9d7v3WfwAlYLi2v48idDSwuLS7ZtStXbG1lxV48e2bzs7PaEGJ0hJ00OSvQ8xHAFdPZwIKccHcedMvqvwsNycvB%2BRS457%2BA58m%2FeO95PR1LBwg2EWNMHWWjDc4N5coGRF99%2FZV2Aq4dHWn9%2BnsEYgseiJERhxaYCupC59XD7h0pUe7JWF387avCgaaYsVHSELePrA2UBm2mWtUoLccwsJbywcOHChQ5quD%2B%2FXvadZhNevh%2BZXnZxibYAGVAxwAQxLI2Oqbmsl6RQJMr71jzfev9G5pKytpMppOyMQs2jOALh17qm%2ByC60eXD%2BfRed73LqQL3BFUKHj2NXjSNQXVbhOAQHnoP%2BtQ2TWWQPPLr77SmuWpySl7%2F%2F33NU2eTaWY%2Fh51m1yq20IDZQ9op%2BPl9YzvsgK5K7eByen5j39JRhk6hQLBvafiEijRCcQsmpfPX9jzZ8%2FUWcYmMIsL88aGU6SjnqgOq2O2vyS3aQl0ZhOdiuytl9ef9RWegyunZYmSIp2e0wP2ir8ix4qwCdfoqPSRo6rY5VbTuX0PRV%2FakyukG2iKNLeGwchcuvwtZVN04JL%2Fxn3gGtf%2B7%2Fln2pXedP3P%2BdQ%2Fhvteak%2Bl6ILJlP80QWC7ZZIuBgww%2BZT5%2B1PxfPfhJ8mBtzDYPE9OOcOTNJ9LvhLovs84YkAZgdMMGI0YFqxC4EMjyW6P7P43MW6VUkFTyzRNlKkcaa2UHGtNqemWpsY1X3AO9fxrxyd9zH%2FIpe8hgPf96XJAwDd%2B3buLG%2Fp8noATVy%2FGU%2FSmo%2FHqNz2eSw1bAIjmJuFIDgW5jIRqq%2Fa0wZG29t%2FS0SEcccH5gUuLS9rpjU0Cvs9fnibg9j%2B%2FclmJNoeTy52TS7w9ray8DCNtXJUnNdxxH9%2FOup6Z1hHJnK%2BAcxYekUYOJXzrpy%2BtWcIxxfHGMUeO7Gyo6ZeKv3H8wuk7jqGjdfx9lM01X67D6qY%2FL39%2F%2Bjzck%2B4zWhmhpFWWtnjAAPlMmb169YqmFXJ8ApvBcNwDu%2F4RYPDHL2gOG3GRnuQuVb2Yhd9w2vfe1MefyKd6qGDDZSFY2p7fdzwssfMsO3iOjdkXX3xhDx8%2BsN%2F%2F7nc60uKzzz6z5eVlbSRFAMUZtaITeLkg43Xx68f4deA4Jr6GTqNYCoB9pkaM4rGOEqebzdbYsIdAg8DzwYP7WtuJHFdu3lLQyTEepK3LTm1oh1vOyHz%2B3I8EYmMtzshkfTL6wDm0bLilDWG0VENKID2Q7NXZIG3IyH0dOrPMr3qTgl1G3VstP9pBEVkfHOra0dGRRoG%2F%2BeYb%2B%2FLLL7UPwvXr141jcrhy9Aw81T4EqX4SRHd%2FobHdN8fvUsexbARfydPtiDq9NTsBkoqLMr09D3S4Uhc1hTZ1TjGyy8j9vXvf2trqis7CpKOTjfjQbwJN0rDuw1el5Wnj3svoxySfqv%2Fb6zwHvKAsDyO%2B6R2RNaOZ0Iejk8tAXRjUztaTGmnHZu3t7mgUX0FdWuOe5jQpusTnCf65THpKy6PRc39eqvO%2BB7D%2BdP3Pno63EHry14D1k72ew5ZzPmdsu2i6LMO7m58sB35kwWZX9bt3p8u2N40bUBpT3sfIA7kxWazXJNgcG%2FHzznQ2mdbd0Tvd3TyEhssXRPsZT3lH%2BHRMXuFLL9JnZnyFpGfCyX88GyZfcy1Z1xXPQOS%2F9tzTEGqkh6nLvqMsAQpOy41r17XDJ%2Be9cTwGU%2Fxo%2FByXszHKCv5T3%2FwJ0Prei3hNgGfpODtGxu7FOODsBMy0S%2FLg4PlGNx4w4sCcBesiInzV%2FK%2BaPnBwZ6vLMOo9a%2FL4Xb68bB988IH9y7%2F8i86kZQdUdjxlbZ7THTbC6WUqukZauuCimGPXCyQ5luciL4CLMwp%2Bcqat6Tt1andrP093cmrKz3EcH9dO2Z9%2F8bn9%2Fve%2F13E2bPbCqB9n7LEBGATlN4vAO%2F1j4X4ufeiVli1o3opv2kJwlXaCxGZpsxodgVPRWch0iHC0CQEm5yoSSBJc%2FR9%2F%2B7eaEvvzn%2F3cOKsTG3X79m379t497ZBNkPoXf%2FEXxq6lHGzPGcjsao2es7EYU1WxXL4Dq%2FObYFPrGVmKQVvS9eTPJe37TBDrT5FTbI5GW8YfQRZ%2F0MC5tf%2F0T%2F%2BkqbNMBf75z39uH330kaYJE4ATUMNT71BKG%2BNk0u%2Bx%2BhdE3%2FO8Pls8v6aRqk3q4qA4jLoLjakARqqZCk0nQ612ZMtXPrUrV5YlR2wWPMg6jl4fqQvSfn6y8%2BpV2DhslO7JoEk26ubQ3hJM68ZGsYEVO%2FbPzs5piUyRlexprXuI8LvU5PNwPZ%2FaV0nxpy3tVTB7l%2FYdB35qHPiRBZuvL76YOoB5yv7o%2FcZp0kZDZSsP46z4kRkyYxhsrY3zDUPkYKmX1BszGqbCSetSXh%2FNtz4nfOs29YkcMdN3NmUKU3mwot0a5%2BbmbHxySjvtchZUnDNGo5nrWn3refJjJQA5cTzC2tqa7ezuyPHGocE%2Fi0CzS3vUuu6bN%2F8uKa402ndXxpnD4Sbo4JiL1dUVjXLOzc1r1BPHPUY33Ykn0NTq5h%2B8F55ggmnqDXYRTmfRaSRHwYbTSiBx6dIlnc1GMMXI1p07d0Trv%2F%2F3%2F85%2B9au%2FdBicpZeOTECOwakfRqYEPPDYd9tGL%2BMP%2Bnw3aUyK5rbIQuFQsxM0GyERVN66dUv3BJb379%2B3X%2F%2F61xrhQ5YTExN26dKS1rAyjZRRXoJVlzN1oK7yPfhyDvgOpZTpayHglewatu0H%2BFEnwRcc4Al%2F3DMbAT0lGAdHZP33f%2F%2F3mmY8Oztrv%2FrVr7RDMaOZ6AZ5mMkQARlwGOGMdb1O2nfRhlfNG21xruEJXic%2Bi%2BVphi34chQZSzfYNXhhYdGWLy9Lxhw%2FAy%2F449439npVfH4A4WZFgmviR3bnR7AgP%2F7YUZuAEz0uFsuukxqpdT0lPzJGF9793nHgHQfeceCiHHgXbOIIqUefxtVHJoJ5sWunzCrGVUelJGcgLTuJ0QA3wu7MODx6rcNAB8R319M4AM9wdqLXlN10JycmjS2DPLb0HnKmLqqh%2B2F8stPQf%2Ff%2BBA6E48n6tfW1dY1%2BMNJDvWCkh59XqyTTU2BI3id8exNegX%2B37wMnHbo6hiN%2B48YNOa7Pnj23hYUnGulidBM9x2H13%2Bm0%2F6npg8842zjShIfgiAx5l5cB55Oy0dOHH1YUQEMPAdg%2F%2F%2FO%2FyEH%2F6KOPNcoVI7n5vH9qmigvyocO6OGPH9eQQ7zP%2B9AETwSIfOPqI3am0UxGNH2aqDveBN4EVHGGLzzJl%2BedK6xl7fLSR%2FV9jSz4RB4h9yf%2FxwMReMUfNHMFX86JZaSP4zE4JoNzWAnA%2F%2FzP%2F1wj%2BNAM7sHngJEnAXj%2Be%2FUgpSuTV89Lsf5H%2Bfm65u0KOPHdOxx85PbFixUFm9SDmzdvGR1F2hhKR1xx7qcHnY2Gb6QUdOfpfZPunfdul7p4hTxMek2HCX8cWUPnILod%2Bu56ij54nenCeHV5dPO%2Bu3vHgXcc%2BClx4F2wmaSNIVWjEQZVwWSEPt4fKPOslkvtlqbakkLNWGrUAAecvFPxU1Koi9LqTZ83eOGIFMtFK7QLxkHZnNtW5oB2pmSlKZeFXIDyAw%2BVXJTMn3Q6RkM413Z9fU0OOs4MIz7UjXDynUFvj9NC3Q59DeHyHMEzdGFLmDq5tLSk6ZcPHjxQMMZupASgkR9YsjmMueksvmSDAvAPdAV%2Fgof4Ia%2F4Bc58Jphk5I8gi1ERRtTapd0AACAASURBVL04j3Bzc0tTK6E1plXmYQQsrvAieJB%2F%2F8e6p7zgf9BIIBjv4srUZg5LX13dlAw52sOnGK4rwP7FL36haYfoN%2BvcWMfINNuDgwONbCJ7OhwIxGLEz6fqdul1XLoyd93p6sT3yYOg6yxeI3d%2B8IPgizwHB4eaNkug%2Bfnnv9eoJWszf%2FaznynghD7y5YNpAvNo%2F6K80%2BR%2FMRr%2Ff%2Fbe%2FEmOI7n39Krqqr5P3DcBAjxAELzmkEx6O5I9W5m9X%2FST%2FiD9Q7tr9la2uyaZPZNm9N6McTgAQRA8QJC477sbfdex9vl6eGVWdXWjAQJ9EJlAdWZGRkZ4eERk%2BDfcw%2BPlvg9RZvKIsvlI3pkrNIYpO06PcPCEVpN1udTj6CjOc7w%2FUI5WC1CKB%2BJGB8juTHVr3AUPEFvicPAdd97XWWtOX4UPAE6WPrCGOesjMVbHe34f9RuhxbngQMGBggO9OFCAzfYMt8%2FcMfvpziTc9Cu%2B0Qx3mD6BLLkGZCpMmjcfnPnwxse9F7OLsJUcgF%2FwVXyGf9ay6ZkZmR%2BOT0waXiCZVUbp7GuKWFyWCWwrUyxCNooD1N1qwgbPmB1HaJmdnRMgwYSWNV7b%2FYh%2BHgIsZQ2gECAaIY3y4sH0%2Fv37EtgBnQiwvM9zzp6Wm%2BbFPefNOhBEAb6UA2cxTt9KahC6wzSSMz%2BEU8zwbty4rq1A5ufntF8loIt6Xw1wrNWOVub84iGkz4fbAVGntjYrH%2BEmAAGApN0ySXLt2nWBaABlmEczaYCJP2AbE1k82AJE791zk2nWNFLPmFJT%2F5QfYd7NaF1jTCmi3NF%2B4n41Pr14ybM3vJwxmmXhkaeHeHskf8AU5qTU5cWLP2iyBPrff%2F%2BkzGYBYZSJuKQBSAGgkg%2B%2FACmb1ZShabWDR%2FEY%2BqCbg%2FXlrM3lhwn1gQP75RyI8SfqxNP1yeQIWy2frRDeu947eUMc6pb2jOUJbZ%2B2zMQgdex16jzL8zWr2837Xm0FHhc0FBwoOPB8DhRgs80jPsAJPuZGIjlYlajiM9Cxp157qjTW%2F8iBX%2BdHvJ10cbE2B5ztigPrnz2bkZB3sNky9jcb6O%2FXbDKe9FhbWwxta7PzdT%2FNCxxcI4zkD8JCq4mQjkCO5gvwFVqefPzteZ0vswvY8AEhm7ID1kLzh%2BCGIx22iQCA8HNBnckpF%2BJcoCOdzeFG1GmcoSe2L3HNXyddUecI3JQZ8IGATh2j4WO9KuaWT54%2BtZPvn5RZbQBO3s3n05mygzCeRx7dz1%2F0nrrgR3rxIw3CXKPFGtWGtHYI2ph9o8m8efOG4Qmb8uFlFeDIDyBJ3RIOnazRfPr0qQAn3od5P0ALcTE5pc65zvMgwEq0lyhv8CbKGeFx%2F3POvfjaHQYvMKVkfSraajRdAA%2B2ueFHOZhY4OBdypEHmw7snUrnN9cb27CDZ1E2H9JjfI6z00Uc2gJ1T70%2FeHDf9qf9UMfGxvXNIj3i6Y0Ezih35KMH2%2BRPvixBMmFYY2CpcOfOXbVhvCjjKyH7JmV8S6zIPYuUinPBgYIDBQdWcqAAmyt4wqCYBpXcM4Xy1c2tK%2BQxgljoOZkgDXO43KvF5RocYJBj50FApKxkSy1bXlqWtoB92xDEkMiJJw%2BJcDuz6lsj5eLR6%2BVAZo6o9q91mC7Uky8OQljXFut%2FENJjbRdCWwhur5fGjUndhU7ycjDDFcIr2gJANmAE0zxAJ5q%2F0HQ5D1xLklG6sUJ5lq9fqZ8lE1r1TQnZmaDtsai%2FiM8kXEXgmYkEQBg%2F3mXriLNnztrss1n74AM8eh5SG4Bf8d2EBzih8Xx9faT6vC9OEJDJhN3VeBNCsH%2B787RRJ9SFA8vQ1Dq4oAStVklOrJgUCXNnTCkxi4VOeaNNzoFC09Pfj6bLzSpJF%2BDFM0AYoBLAST3funXT7t69o%2B1QAG6YFcMD0sSknDI7kPf1u6H59PL75GbUgXN77b9r9ynK7P2ONAMoRT0QxoE1AprZ8%2BfPy%2FkTfIBmzGY7zaLhq2s0Y1IiqIP%2FbIPl9UDdrFZv8cbrOzuPffyAHngU5ygzYXyvAJpMErAmE%2B31zp07VLcRL08l%2FAse5sO34nWe%2FmgjTA5QfxwRxp6wTIxcvnxFbYC6D155XW7F0hU0FRwoOLAdOFCAzVRLYQLEuFhulbU5eXcFMmSGyU0803ttIZNBfPMG1qBpe52TgK5xL7Nvatbr2oLB0EikkU77e22q6LK9OPu6qQ1BBDkVT54uyLkAg8DM%2BjUEdyZvELDR5v1SjhBiKQ%2FX%2Fl3wvp%2FX3qLto%2BwIcWi%2Frl69aseOHRPYALTkAepm8iYE0jiHABrnCI%2FyRt07zWzzBJBzc8OjR98S0EaLh%2BMgNLqYKDL5QNnRfvp30vkVW8aQpvNS80tqT4C5COulMfM251T4Pr8ZF90Hk7fHoJ%2F0OHgv2ieAECdOaGPR4tFO0dTidZczwAMTWjSZDjCcTugOEIsZMWCRONQ5EwqYTwNgALH0A7y0ovUkPdLmDEj1d7M9WOk7kS75Ue6gPytdXPUeb7zeKDvPHWQCLoKf8Xbcc6Z%2B4MGFCxek1YQO6uvkyZM6Ow%2FQZPeJHpxhed04Dfm24nUZ%2BfemMWjYuLPzwduMtwvypuy0BTTymEQfeeuIJohGRliP6pMVAS55F74Q7nWzcdT%2F%2FJyiHqJPeD%2FzOfSKJonwvoslCm2X5Q9MPtCv6d8cUcc%2Fn5YihYIDBQfeJA4UYLMtLMaHOAk8Wj2Y1hK2W0SmuSDI3%2FC1mxFldaEgYrwp52ww11V2K50F28n4TpmJ75zQYJpZlfUjQ0PaQoEhTntqItAjwXDPy9o3L%2BrgTeHp1ignbTwTJl1YC8qi%2FYdmE%2BEdIMYaN4RwjhD2PK73qXgv0onzauHxfDPPnbSldpwIimcAELRYgE00RmjQAGB4LwVssB0H%2BMdBTGcaW6dsvSihL4aWiG%2BmfzcBW%2BynioYP0I02G8B1%2B%2FYdm59fkFD%2F9tvH5M02HJBQdtoLvwBstC%2FaSaTLNWAp%2BOoUZdoZ4vnXgIv0ncBaou1UzEEDgI81mQB%2F9j9Fk4XZIGHQg%2FZu3769tndv5uDH6fQvkeeTCd1BTwjh3AOy0e6i1eZHPbP%2Bk%2F0L6Q9o%2B%2BEJGm%2B0hmhEAZ28B%2F8APwAalahU0v6tUb7IP8rvANvLnD6PbQDoPCStzAES7zkvHcRzX68v25MnPhGCBhaeAIDhBVtgxEQR7%2FELGihrlD9odbriL8%2F1JAI29RxtKsoRxNAmsDxgUoC2eOjgIdUZ3yuP67xycJkbyCKBbXPOaHdeOOHUIf1ucHBA3yr6LSbF9BH6Anyg7LTLOKhXr3tVcAQX54IDBQcKDvTkQAE2e7Il%2B5BmostKYFN8ZldhXhL2JIwm0Y%2F9SLVhqV4RfBTYBF46H%2F2qXCoLaO5BAMOTY5%2Bb2KoeZLLMgFkxtJzFsdkcSDWXvHkifKCxQkBjdhyBBY0Bwnqs1wwgQByOvLC62aV51flTRviBsAbgYN0fPEGoRYgDhCLkEc9BlgOaV03H60gPmh3IOeDM6t41PmgHMZ2m7ADOy5d%2FEtj6%2Buuv5ekz1v6FxhAaA2BxTXreRnxig7y4dyHXzWED9EQ8fy8AMO3LaSRdgKyDzCcCvmHWDNCgfYYmE5qZCAAsInSHNpOvf%2BQX%2FAyB27W0QZ%2BXn%2FokDc44XWEdOqAWE1vMqRHkWQ%2FJNXmTL9pQ%2BME73h7ciRTlo7t4%2Ftl3L6PH%2B5LHc0DuwMjBdvCVsOhvAAeu0VyhzYMWgCYaWGigfgCaTBIBPLO8MvArq57sQbBF58inI3BTb5xHkOB8codQ8IEJANolZzS5aJ3Hx32fVOddTIjBT2%2BbqxR7U0u4VubeRzIexHfY3%2FHvNo6QqHvaK7xgYmxhYdHQ8HbG5y3vD1uvntfiQvGs4EDBgc3iQAE21%2BB8DOtxXiNq8WgFB%2FJa4TTIydvSSm7yFMjJwNVXadnoyIhm%2FUdHhq2GwJfWNklAIh%2B36FmRYxGw8RzICxtcIxSzLx8gk%2B0DENYAG7GOL69pyt71FrDx1G9MjgAHNFeATcwoMVUEcO7evUeCnfMhAxQIhhlvNobGl83FNSSAOrSzOEhyZzH0aDQlu3fvksYOIRZAg0bv22%2B%2FVfsAzCDYwxtAHXxiDaGv4XRgRHvBRJsj2heWpT6pEWHkH85%2BHKQGwOTMxAcgCo%2Bx%2FDARdPNua5s4HzwIyNyhdgq4ohx5gLcauAiaXJj3bSTimmeAbX6A79HRMZWXvAG78AItJ4I9Wm%2BAXZjXMjkDT%2Fjlj9Xbhgv%2FDo78DXgEDaQBfzicXjcFZU3e48eP7LvvvtcemvRXgAZbm7zzzjvSylInHOSbAVgHql2kKd5W%2FRPtNOijXcETvlP0R9okkw60SUC%2F7zWbWRxEe%2BB9%2BBC8iPS2x9nbSLRPaPZ27d8eykRbRdsOX2ibmFbTJvzIg9XtUeKCyoIDBQe2BgcKsLk16uENoOL5gMIHPgS0Qdu7Z4%2BETzaQZ1bVB0gXwlcT%2FN4AJm7JIiKkuBDsJrUI92ybwA8BDiEaLRHCHfEQfkPoBVw0GsysuxC3JQv4kkRRRnckUxIfcDiC6STarKtXr9mBAwelRUOgJ26mPVg5IfOSJLy217xsmKZ6nQMQsThgPV8I4q0WALIqDS4ADlCJNpc1gWiSaB8ItWiTpqYm1UbQtOENtVKhnbjW19tWxhOAA2AhD6woKGHentyzLGkjLIfzH8AuQA863n33XYF%2FBGm0WDhHcZAZ4M61PVmdZKwk%2F%2Fzh3yYHcgEOoS0fTh0z6RKaI7bVQHuIIyHoYvIB82o03seOva12Eua19KHoL3HO58814VEnsZYUx03UBeEc0f%2FgEVpezGVZpwjQos8CtHDk9NZbRwSMI6%2FgP%2FcBWrM2203J1rkP%2Fmfjh4NmykE9oe0OrS5t8dSpU2qL7KsZR1ZOB6ek6d%2BvjK8Rdyufow1kNEYjjn7l9%2FQB2iUAnEkZNPD0yVizmb1fXBUcKDhQcGD9HCjA5vp5VcR83RyQEOmz5ghY7Ksp4abl2goEp7zw9LrJKdJfmwMuwDABQDyvIwQ4NCZoaxBUEK4BWNQndecCYAg6CH8xu752Xtv1KTzih5YJrQEaNLRYATDefvttm5gYbxdvu%2FGDcgEyl5eb0mjTDhDGo59y5kDLibko7QHQdebMX8QDgCDC7OnTHwoEAtIAQqThaxi9zYT5IkIv7Y12RtzIizwI44czopmZZxKYAVM4KAJMobH67LPP2luRsJ4S4TpojHqiDBzevrn29uogk2t%2BrsXPAI2DuaCHdwOYkRbxoJvJByZe0HSOj09Ia8T6VtoEe1pCK5pGJmhwzPPee%2B9J2xkmuSIs%2FYm8yQvtL%2BUAoJv5ek%2Fo5Bl0Exd6%2BC0tLUqr%2Bp%2F%2F%2BZ8C%2FqzJ%2FOu%2F%2FmtpM2NbE%2BI5zc4L0vb8SDOu89RsrevgDVRF%2BSPMeeKm%2FlgaYD7MpAO8npycsP7%2BAfGNeFFuADztzXntfXprlXhtaqDbeeFtOe5TsJ5xTdvEAuPMmTOywgiwOTDAVjeU29t%2B%2Fr21cy6eFhwoOFBwwKwAm2u0ghicVosSH%2BzVnhfhL8eB0E5IbdIqWyl5wmO4FM%2BLke7lGPuK3sr6hZtfhTBH8gjbCKozM2g2n0rAR5gFbIYpGporDoBKJuiHQO5C0SsidVOTgU%2Fxo5zwAMAD4MSEkh8aLcwWAaJu9piRzLtb8RvjZfI1b9Dn9epCbAjngLsQzr1caClNZqpo0PDE%2B9VX58WDP%2FzhD5qYYHsNgCjapNAyevlJO4Rk1yhFu4EWwCVaTUArWuNLly5pjei9e%2FcFPkmTCQ%2BAPcAOkIlQHbzlcxJt2NumgwmeO5jm3r89xIOWAGNeNgd0Wc0R19u3Yqd3AqDG%2B5QBTS%2FAkzW90AggR%2BuNCSPa39ibFSDEc8C688ZBfNAd7Yz%2BF30wNL1BCxMCgHvAFfu%2BAnBxXAUAJ300vjEplIF5Jvhc2%2Bv8yEydm03fYzVf7q18DY%2FioM2g1USDh%2Fnwp59%2BKq0mQJN6ibbh7%2Fh7tPN4Rv0TJ%2BJFutvpTLtwABlU4yiopPX17LnJpAQaX86tlmt7YaG%2F59%2FrmNCIFIpzwYGCAwUHenGgAJu9uLLOMAai7TzYrLOYGxLNhSZfV7Rcr9sMJphoAAbZVDrNykKJImqM3BC6ikxW44ADTa8SB1UhfCH04zZ%2FcXFJgjSauzBHQ0gLQR0NiQvzXq1U8y%2BpT1EWABcH5QTgoKHat2%2B%2FTBW%2F%2FfY77WfIOj0HWNV2w3YhdzXeb36499es3kMIpw1Ae%2FygNLSSxOnrqwgwATiHh13L%2Bc0339jnn38usz20eYBC%2BER80iFNrvPALvjDeW5uXiDz%2BnUH74Aod2wyLADB%2BkN4DOhkk3ocoXjaDpgDyJIWAI17nsd3h3vK64dfE9dpiHhOZ7Rhf%2BYvOa94O95JKSlRzwstLk6C0Cy%2B%2B%2B572iIH0ExZAIc4FmLSBg%2BxAGY0cbQnB0A47WG7FKcBsAnt9DPl2jLtJQoQB8DCb0yMMZf86KOPlCZ8oT%2FGETz3PhoA37%2FDKdlU%2Fnhje535PjHRgykxE0CYVXMOoE75fdihzO7oC2cB0SaCt94uM75tBy5QBm%2BfARy9Xikvz%2FgWsb6YfoJDs%2BnpGU1ExDpWfzf4sx1KXNBYcKDgwGZzoACbP7MG%2BPDGAPQzk3qjX4ePzYZc%2Fdn83LzdunnLJifG5SCoVkMId6ApfuOVNicYvdGM29TC54VwF1TQiCDI4uUTYRihhTW49BEENM4IdA7CEHJc0NnUYrzGzGmv%2FnMtCAIbJpLHj5%2BwH3%2F8Sev0ABJot%2BBLpRJC3NblC3UY9UnZOACCrZaDwqjj0GQz%2BUAYgnmlgjmeSTsHaAJkoa378ssv5aQGE2zWf7JuEa2f88S1dQ4QAfB1TWSwHhMzP0whAQ5Xr17RJAeay%2Ffee1%2FmgGgMSQeNHaDBtYuc%2BW4DHrI2TPpxRBk5exH9HZ47CPH2no8f11Hnce%2Fv9K5PeEYegPBSqSoNN1pun5TYJ7DJuk5%2BrKEDMPIDPO%2FYMSWA5N5CY81q53hEP6M%2FAlpZm4lZMf2QtZlo1AG4DuyjnG4ODM0xQZTni4NxLBh8T9F8GbfLNe0RDS%2BWBYApNOq0RdoIvIn6o9yde7d6W3eNsV9vlzKvpJP22LsMtEdfyzwu%2FqBlB4gPD2fiovf7%2BFatTL0IKThQcKDgQJ4D2dcjH1pcFxx4RRzw4SwELVRXTJ92Jc5aTcAmwL3Vstm5Wbt%2B47qEyolx9p%2FzNTS8RXr8upPoSrG4fa0ccA1QAA2yQkDhwHwSAY4zmiQEf4RWhDiEPK5DiHWB3wWWhFleK9UbnTg8QWDtFmDhC2ABARfh%2F4cfLhrOg1gX5QANXqaek%2FhKGhykF3wPnm90ufL5QUP8oCvo5BpawW%2Btltc%2F7%2BVpdm3efgFthNuzZ8%2FKSysmjmhT0H4CzIkXPHSt%2BazWBF%2B9elX8A0gBqtAKnjr1YVtDGCaqtDdM86HJaQ0NuihKYdCe0Rdl4ksT4DIrNxMmWR15fWTxiO%2FlXO0rlQFcB9Nl7YUZ6TNJgzda2gl8wbQ2nLYwMXHu3DmttcRrKFpbzGvDBDbS4AxPMIMEVPEODogA9oArNMh4Co71ifCHAwAOTd1H1Btl83rNtHzdcTfq3vm%2BWm7ef7pHCtoRPEGjyUQF3yfWKI6NZdt7UD4vb6ThefCNcj5Fm4dfq%2BW%2FtcOjPrv5E1TTNvgmsTcs5sYLC%2FPqh%2FAmjrX5H7GKc8GBggMFB4o1m2u2geyDvGa04mEPDrBrZjZUc%2BVAky1OBCxyo7QGrYQ2AJw4CJl59kzgpIVmAdE7acXK23ydTA9WbdMg19jl%2Bwj1SN0xE84ZARjtS2i4EGKj2v09F9pgAOG%2FNOGFMlJ2jgBhwS948%2FHHH0tLdf7813bkyFs2McFaQkw81eLbppvwBY1xCMHcO78C1Gx8E4qy0W1DAA1A5%2FXp4MvBS%2B%2B6pRxoyABUIyPDai%2Fnz5%2BXFu%2BLL75QO4JHgCq0fWjLw6ELpqUIwaz9RHsJeCcewAzgEKay0Ek%2BrDsM3gdw9XsHfvAzK4ebTfI83skL5d6G%2Fb0sre66WAuFOFD1emRCAnDn3msjP6fZ13RSHjSQrK8EJLFtSmhz0VaidYJPH354ynbs2JlMan19JiazrM9EG4oZLkATM2XeYe1n0B9lJ%2F%2B4zrdZ11x7GalngGzQGDRvZCsk77UOHns9dcaiTGiIaT98ozCfhS%2BUmfW6nCkPP88iy8f7HPyh%2Fvy3GWXvLNHPuVu9jTJxw1ZArB%2FG2RvbWRVHwYGCAwUHXpYDhWbzZTlXvLcqBzqBZorG4J%2F%2BKURjOCHSb7lkUGaGv2EN1vWhJUnPSM%2BHRR%2Fge0oRq1JTPHhdHOglaGEGyfYSAAM0LpOTU8lcMRPmXQhcKej0Su910b5x6QboSi04CbJo6w4fPiQA8ec%2F%2F1mOYNAkYMoHCIjDAVzccQ7hNw%2BE8s835pq6Akj6EXXZbXYY4R4LgMAv6jl%2Fj4YNsIhWD5Piiz9ctJ8u%2FyTnLYAs%2BIUmCi0mJpCABkAC77COEeEYTSD880mNzryhIPIFUDhYiToJYJIBrdXaaCpwAhuhKV1ZF5FXFr%2FzytPPgA00B28CAJIGkxWY1wKe3SzdteKAx3AwhYMbzJABovAEjTlp4fEY81v6JFpitvZAi4fZLNreOMjP88q8CMcz55NPljwH38UrW%2BSMuXX0FZ%2FsYMKGtoNTIM60F3jF2evLNfMBtrvr0AFspLmyfW2Rgq9JRneZekWm%2FCx%2FgC%2FUfyyLYGzm%2FfWk0SvdIqzgQMGBN5cD2Yjz5vKgKPkr5EBPoJnNA1spZ0bLcM3QjeBVMgTXppz2V6pVGxwesirrrDBDxMtpMt8h%2Fmqz1q%2BwGEVSq3AA4cN%2FWYQQPhBGYl9DBDtM9vjF8%2ByNN%2BkqhFMvM7xDmGP%2FWIT%2BMI9EAL58%2BYqEPDR9YcoYAn4AJLZgCGF487nYKXBTz0FvN21rtQF4wgHIRktJ3FK5ZGf%2Bckbmn999953AJjwBdBIHkIAWE3NTtMSEZ%2BbZnbk7sMvCumnJ3%2BevszdWvxKtSXsasdaXRmjI%2FK1IJ9LoPvOctevl8qi0vJgIY2IMEAd4ou3kh2kxjoUAmIQD3PE0i0aTyR%2F4FPRFW%2BzMK%2BvfUS88p4riPmgNh02d72%2FknWuXe%2BWYp5fnAGp4wmQFPKIM8IM25J6gfQKCMvILHq3UaJNa1u474%2FaiZPuFxfeJtkN7iaURsQxi%2B5WooLjgQMGBzeZAATY3uwZ%2BQfkDNNdzpK26OqJK3ET7WS7b8Miw7d6zx0ZxEBJbFCAxSuAJhNrxenGzARxwYbO3gMczhBLWQzETjsACmHLHLBtA3JbNwjWA7IPo%2FHNC0QriLAjQhFkj5qOABYAUAB1Bj6NbmEVo3jpgc31MR3CHZmiPMnXywr8bTFDQhojXlxzQhKYcoDk1NSVwAHg6duyYgCYAk19oBnk3AwrPp%2B9F4vZK7ee%2B3ytNeBP8gWXlMnxzHrmms6YyA84B22h16WtM9qDNZF0nJqJ8MHG0xDMAFbR6eyJX11ARFu2JZ%2BEAKD9p4HHI3ycTgrZetG9kmNOYTeZk95Qt02RDL7xBAwxvAOHwjb6Hp2wmfojD%2B5SV3%2BrHWs9Wf2u7PaFNoNlkTSttCWsVgHlYDmy38hT0FhwoOLC5HCjA5uby%2F43IHSPYVtv8LxUZGSH5CpK44LKMsSYTYdu9JI7IdCzMZhEIfKhPL78R3NsahVxLwAzZDJDJ%2Bh4OBBWE3BBkt0YpNoeKEGC7eegAyh2UYBKJaV9sxZAX6tTug8k9AOjmlGr9ubrg74J8ngdxDRAAZNJ27t69qx%2BgAE0KAi7xcFDC%2Bk7aEyALk1L452dMTd0EP9LsBAzPAxDrL8tGx8yqPQNV0ED5KDtAG4BNfwNQBthG2wsv4C3aPHhG%2F3SvosNtU%2B3on8TlF23V%2BecAjDSJ5z8cD4XHVujYaI6szC%2BAcZTBjWBoE1lczPpZq0n7omyYGwPSHYSzXrOucNpU8CB7%2B826inZAG2KCB1Ps%2FDp82oG3jzeLL0VpCw4UHHh5DhRg8%2BV5V7z5ijkQKzP7a%2F1ydMF2AO5gBZVmyiwk11ecd5Hci3EAgYQjL3RgQssMOIJtCLUR78VS%2F%2BXFDgHWBbngG9JwRdpM1h1iLhrr7hD00G7m%2BRtOWrYyd%2FL0Bp0hvLpnWt8CBwDDD5DJWky0TZQdxzeAIkASWhW250ALRbsCkOMU6MKFCwJGrD8kTqUyoKyireV5HTR009V9H%2FFe5JxPI3%2F9Imn0ikta%2FEKo55NH2TLNm79FHAA5IOrHH38UkKLNwDNMbAHv8AuABY8x1caRkm%2BbsqPtwTZoz87Z%2Bmrqgbw58xxQH%2FF60b45Yc6bqH%2BnAeDs5r%2Fc06YoP%2FwAQKHVpI%2B5c6bMgsDLmEOpm1OgTcs1z0MmfeEV3yUmwtBw5p%2FnwfymEVxkXHCg4MC24EABNrdFNb0hRDLGy5S2ZFWtT2IdJ8KpA5tKqWxlOcx4Q%2Fix5YoZ2g8XzhBAfZ2ca5UQbgENgE2EXbQtb%2FKBYOZbJTgXXDjLmyLiZbYhoRezUIAWwjBbVADW0bqEeShCMOAj%2BsJ24WuAyqAXnhCGpikc%2Fly5clnr6B49eqwy4%2FSHtYi0IYAm68bYTgee4H0VYMW7TG7g%2BCbM%2B3xGKmalPEfycr6v3M4jaNpq5wxkutlraBIDCDHpsLycmYXiHIgtdOiLeKXFERBeoBcWFqWRAsTHWk4AO%2Fzy3147ePCQADvvkq%2FXDzx0c%2BRod96WvT3Dz6Bls3kHAOfn9Rzen31CI2jGFBvADR%2BWltxxGZYz9C8O4uUP7infm3s4eIc%2FmBlz0P8A7GiAaSsceQ%2FPCij%2BFBwoOFBwYBUOFGBzFcYUwZvAgeSEAuFqub6sdVtlbXZe0tYnK0xxN4HEIkvngLv%2FOiWYnQAAIABJREFUx3slArHvoYlAwppNBFk0ToBNwNKberjAGh5bEdARbDFBhCOxPq4lxy8AKQTg8JaJ5gVHQb7mNYRfNEvbi5sOTBwQMDmBdoRJCYA1AOjKlSsC2ABKnCUBNOEDQBMz7DBr5Dm8IAzNJu99%2FufPbW7eBWD2BWQNbICgUsnbpsnx2DZjWttiwMEdQIqDsjHZwD6kAHMmJdg%2FE40dDoNYy8q%2Bm5iIsjcxoGlyckIgnT6JOS1aUNoY%2FL94cVhgPbZCob%2FC4wCdAboyngYwY%2BJjc02TvW95P4JOn9Txvga%2FAEXBM0xAL1%2F%2ByWZmpsUL2hdazZjIIV58p7x%2Fbm7ZRPgm%2FvF6x2FXVQ7L0HAC2Pm%2Bcw4T%2F6wONpHYIuuCAwUHtgUHCrC5LarpDSCS2em0bghh6vGTJzY0OGijIyNWYVP2NAPNQLjtJO5fTPWF0O7gJwROJgcAEQgjAApmxDHnY03Zmy6Q5MuPEOzN17WbAM7YPgQQBdACBPDDWVCsK8OcnCNAR2i%2BtkOzorxobxcXF%2BzJk6cqF2vA0DRhQouQjwkxZUe7G%2BvoooxxJh4aFdoWvEIABmyd%2F%2Bq8PXzwUEALs1oAk4P6zBQ0XwfbgWdBb7SV2KuVfoY2F8BI2QHd8JF2cvr0aYF1JnngE%2B2K%2Fjk4OGQ1LUvYIf5ieUDbunXrpt2%2F%2F0BglbSY3KAeMLEdHx8TcA%2FQCc%2F47nLPz4%2F4FmweR51PnXQAxukn%2FKAVM2NANlpNJiOOHj0ms%2FXQzgX1eZ47eI0JnojxZpy97F5W2hCTPEyE3bh5wx4%2FfiQnS97H4LtrQIN3bwaHilIWHCg48DIcKMDmy3CteOc1cEBwUukCXBAOpiYnrdpXtdpwn1XY%2BBzpK5lNbTcNz2tg2KYkiWBBNagiRIGb%2BgE00VgBMAEDmNIWQohXkQtwTTlWIcR5KCa2tUhoCwBaCP2sT6T9I%2FhjRlqrjSghXzeXgSjS3eo8xlwWQATAcZBzSyawtA%2FKB8BkCwrKCZCEDxyUlQPAEGXs768JnBIHUMV6snPnvrSLFy8qTcz80I6SFh5GEZYBFRlAUpLb4k8AHoilHNxTPtoFJrMARPoc5saffPKJyj06OqLy%2BrvezuiPaKhYjhAgHXD65MkJu3btqn3zzbeqH9KinqiTgwcP2L59%2B8Vj6ilocS21L20IDeDm89bXkYKBvZ0AgDJgjLk1wPrZs1lZXBw54h5ombyIdgWPeSfu39SxBR74wdktVmg%2FfJeYAHv48JEsV%2FCYzRGAXp7%2B0pvFqeBAwYGCA704UIDNXlwpwjaFAwx2DGC4qEeoajYaApyt4eG2ILAphBWZdnAgNEcBOAEGmOYh2KFxcoCUF1I7tQ8dif3Cb2jTCOahbQmBttnE4UqmKQIcYdoH8GJdHSamgDPA58iIt380W857FwojrY1gYQii%2BTxXC6OsaC3RwgFgvvnmG%2Fv66691jbnnBx98YO%2B%2B%2B640JmhJAEnVqrcX0ifdAANo9TTHJEGYNXkVac0BnGjPAZxnz57Vlh98N%2FBae%2BLEOwonjoMhrwP4zUH6%2BXIE%2F3qVJ579nHOk251G0NBND%2Ff0qXiPM7ykXaDNZB9NePzRRx9pfSZggH5HerQPykxbIQ7XsbaO50NDgwL18J333nnnXZkkh2kyW6dgwow5LuthAaaAVNonJsleFw2Z87oJ%2FeaZnMIXfpQr2ktMUjDJwDO0mrdv31GZMSWemtphAwODqop4nxuuOTydbIJDgW%2FgH%2FiBRQJ8pD3AF77xTEqgLaZvEYf2xq84Cg4UHCg4sBYHCrC5FneKZxvIAZ%2BhbrV8Xdf83JzyZpBDwmm0Gsb%2BnGXNSG8gWUVWq3IA%2BSyABdo4hH0EE7ROCCM841AdrprKL%2FuBC2Ju0hieL50nriFCUHahrSSBGADAmjLW4bH9x82bN2xsbNRGRtw81DUOvcFSL06GEN3rWT4MOnodvM%2BPuuQMwKAcXAcgon75EQdBlHagNZWffy6tI%2BnSJn77299KA4c2jnu0JoChyDvMsgE1Eca7kEZ%2BHMSJMF%2Bn%2BK7MPgGdOMr5%2Fe9%2Fbw8ePJS2D6DOe4uLbq6L4BzFbLUykBR1EJMnr1JTQ%2F7whDP5c0RZsnw7NbjwFV7G89nZZ3bhwjf2xz%2F%2BURomNEuffvqpffjhhwLVDijDvNX5FdpQ55XzzHmXAVL6KKBzampSkxq0OUycccL0L%2F%2FyL3qGw6Hf%2FOY3MrGF%2FnqdsrgW0bs3gDbfdjK%2BRjkzvnaWPficr2sxaB1%2FsrTFUU3ccAXfWK%2FJc%2FhIO2TNJhrvMLOONudt2k3bIyxrg%2Bsg4hccBR7CHyZ0%2BKbDH%2FjImnzaMwd9%2FmXq7hfMtqJoBQcKDqzCgQJsrsKYIniDOZDfhDt5n4UCBBs36nEBpxjcNrheVmQX2gQAlAt0mErGrDcCHVoWB5g%2B870iiTcqwIX7tdotz0J4xpQUHj58%2BECaTTyv7t69x4aH0VxlgAIW8s5a6XaymXrzPtQZ7neRfwAD1r45mHTQAzDoBjUI5gAO4tEG8KSL1o2tEgDKaDcBz%2BFdFq0toBCQA92engOVhCUV3l1OKMyXM08rgBWTT%2FbgxOQTLSo8I2%2BcmWCmS3vk8PI4YKZ9dmr%2FqIP4xjhPXtVfaEd4J3%2Fy5UfZEeb58Zwy8XMA5NdhgoxW%2BPz589Jusq6S9Zlsb4LH2fwERp5eQHWeZ72fkZ8JUBw8OCiHVABZwAX1iOkkmk60g2gF0XYC2si3r6%2BmJKG5Xg8HRgTlgafnGgCfu6yevT1GXQZP%2FI21%2F%2Fo72ft%2BH1uzlATqqX%2FaAuAZzWw4LaO9xOH8CSDuVgar8SzeeVPO0dfp46zbpA8BNjHl5ucOljonhd4U3hTlLDhQcODFOVCAzRfnWfHG6%2BCA1mK64MXgFmu4NNOMRgMTMdaRtKHn6yCiSHO9HEDAQzBGiEaTxYw3B0IIwh1ObQANvYDDevN4k%2BIFP9EeIRhjCsoaqTt37sqkFk0gWqjXeUADJr9eb66hSsppbYUBOGu1sjql%2FsNUlvV%2FN2%2FeEuDE1G5goF%2BmsgAUAAzCKiCT8gXIDME%2BAIgDlZVgZbUy8z60kiaeezErpf0Bdh89emhffPFnrX8Nc1AHuQ7CyBNTZgegOGDKNM2r5fey4ZgCN5u%2BPZDz2IE8eXNAP2WJZ4QBNNHKATQBfjwL82NAO30s49vLUuZeZUm7XG6298fl%2BwuoZcIAsAbYjD1OAfJojNFO7927x%2Fr7ffsQpx86HChndev3PKHes3CfLCFvjpgI4DnxOHgW8RWQ%2B8NrPI9fPIr4fI%2FQdD958lh8o0%2BhpcvTwDsRv9BoBgedJ%2BGUyr8HJU1AMKEI0ORMf2NypzgKDhQcKDiwHg4UYHM9XCribAAHXOgolcs2OjZq%2Bw8ckBakVsXRjLw%2F%2BPYnTcSZknUpeTaAviKLECThhDsIcRPBEEIAFAj7CKsOKtYPHAruhpDnaxJZK4eADOBg%2FSaOWwCbCMchIL8OnkX6nAMIoJli%2FRaAoFTyMw5XYgsTgAiABPM6JokAIwBMyoBQSntAc%2BXaNgccXoYsj5cpC9%2BFSsXbGBph2hw%2F8kMjx7pvtgYB%2FALUME8eHh5qT4B4%2Bfx9wAv0OXhxwP0yNPV%2Bx%2Bss6g2QzkFewefQaMJj6IWnmLNSBkAS25MA3NE6Ur54r3d%2BLxbqdMHLiiYEYv0wdYlmGg%2B2%2FG7eumk%2FXf5JGk%2FqG8BJPRMPGtEaRhkBb0weBD%2BjrDx3TWe0Y%2F%2Fu8xweAAa5Xt%2FRCTYj7XAwB1gGDO%2Fff0Drg5kACSAbdHq9k1%2FxrcrzPPhDU6VdUM%2F37t1tg036esTJv1dcFxwoOFBwoBcHCrDZiytF2MZzIAnRzGkza79%2F334JVVVmTzEJ05x5kFUIB8GJjT67HBj8b8lUEfNJNJwAC8AmM94OLjrNPjea1u2UH4IbPAvQwXpEQBtrYeEvgjNgCaCRF9xfbRmjXn3tW5aPAyO0bfPzcwKZaDFZ48c2HIQDOACX8UMTCwCkTKFNCuGUc7SjABbx7EXK4%2BCVtLydkQ%2F7SgJ60GLSDtlfEeCJcAyd8JStPaJ9YgpO3ln%2BGQ9ehJb1xHVg45MKkR%2Fld60eTpWWpTVCm4h2FodbtANMgQGbAL8wQY6yryff9cSBHnjChFKj4fyEf3yLyZeJhf0H9tv1a9fl6AkwjPMnwC%2BaVsAIdc6EE%2FVOel7HXt5OMBeAE8oclJZKoRH1iSznz4sBQHiJ%2BTe0ooHlmwTfaJOUwx0lBT15rrxYPvk3f2nXWb3RD%2FygP1HPrBtnkoF2iYl6TA5EvOJccKDgQMGB1ThQgM3VOFOEbzgHZChbYjPpmoRXhB%2BZ82AuBeCMjcR9anzD6SsydCERIRJLN2a9MatifSECM0IpwjH15oL16xPcf5l1kQl4COzwEyEPTReeaVn7CFgKUNApwPfmiAvtCPCuuesdy8EkdUiaof1BmOQXptKs4WPLDUAmTmtIE%2FAL2GCdKdpXnBnh7TO0XLwPDdnPaQEY8PNwD1uNttXCyT8ONO0c7KXIhAf5w0PAD%2BANDTGmlbRXPOHSTsk7ypp9Uhz8RLqv4uz58C3rTC14Cx8AwwD3Cxe%2B1nYk3FPfJ0%2BeTAB5vA00SYV3XvXhdYHm2esG3sBDAC4ekWmPRw4ftmvXrkvbDr1MgtAuAJq0A8xvAXe0C4Ar4C%2F4zNkP0g%2Btp5fD83bee7SIu3opPV3WDWfentFqAoiocywB3nnnhLSabJvjde35RqpBU5wj%2FE08w4Pok%2FDU25h7hmatNfykHwE24TNxov%2B8ifwqylxwoODA%2BjlQgM3186qIuUEcYACr1qpap8kcO3IVA1slrflpyywbRE%2BRjWsDQhDJ8wNt0cOHj6WVQeBEyAwBhHor6irPrbWuEcAdRMBnACXaQgR4tJsI9WhrEOQxWcSOvBfcWE1ED0GyFwXkByjgB2hzIbKkCQS0RAjvsU8mAIP4CJ%2FQFqaUsSYTE0zXIDkIIG4cXOeF%2Blgnl48TcXudI6U4Eyd7t2TNBDjJA5AUGi34yNpHynHmzBkJyrH1SoDiAO68m6exFx0vGuaaS9%2F7Mc8DrnmGlgjAhkMb9tAE3LPOFG%2BzTC7AW6fJ28iL5v8i8XuV3XlcEujctWu3jY76Fj2Y1mLijZYT%2BgEhtA8mHeA9EyUAFNoEJs%2Bkk5Xfr2lr5BnhfDu0bGIdRKsdCJ9SZ2WrN5bt3v379sMPlzSxAFA%2FcOCg%2BIcDqeJYPweojwCTrL%2BnP6Edxkyd9sqkDW2X%2B%2BIoOFBwoODA8zhQfCmex6Hi%2BYZxAOGBQa6evFsiCFZxKJLW%2FvSUrjeMuiKjTBB14bBRb9rc7LzNPnsm502jI2PSaiHYlbq2ryi4tx4OuAAegjegknWb9%2B7fE9jEUcyxY0ft0KHD1p9MFbtTpQ%2BtBji7nzARoLyoPb3kABNPntPTT%2BV9EoCGJhNTXrRtAAg0bgEmAJ1MMARgII9Il7Q54hzXxPX4ChHIVsQ1%2FnhKWQR9K%2BQurGXNlI%2BDlATISiWr9ddsqor325rValX77rshrYHEcQzACMDp6ziHlXCsM8xyeRVXnaAqnyLCPHxGU8hEAhMKaGUxmwVsAtoQ8OFVo8FWFExCuIMleEz4qz6i7UW63EMnwIL8mASBJtomIB7TeeiknQA%2BAZ2Y19IuDh8%2B1F4vGdpm0gi6sY4olXwbncgPbaj%2FvGzd9BCP93EU19LkiEJk9bK8XLerV6%2FZpZ9%2BtLHxcTt67JiNT0xYH2tJyay7EWWZFlddHIDvznuvIzBl1DvfASbAmGhE610cBQcKDhQceB4HCrD5PA4VzzeGA8kbLfIAg9j9Bw80uE2MjVl%2FzvGEBIZXL2NtQBkpWRKg1pHbVi5iABPq6fGTJ9pCAmFyaHjIqn1VAU1HHO0i9yix%2BxXu8WDNoN586R26ZkJb8GFoNjONQp%2FMUvft3SdTQAT5819fsPHJSdtRC7PAXEGeAz5WyNr0OXONIIL6%2FNysTc%2FM2KOHD%2B3qtata74gjoKHBQdu5a6cABOAMcDE6NmYD%2Ff1tc1n6ZUeNJrN3F%2FADzDpQCLAR2tQ2cErVuILOBD%2BipDyHbv4DOBpJO1auMC0VibSszFrOikkTd%2FToMU2EAJIwBcb5TpjVoj2k%2FQJK%2B%2Fpe9TrjANYO2tzEvGkLC75VDOtJf%2Fjhok1Pzwi4vfvuO3bkyFviNdokASuBafcci%2BYvPIUGH4MvnedeXOyM0X0HuHBEhgba64o4gHDyDO2ka7TckRVgA2DJ5MPdu3cENgGdbJPBBAVaTzTgTJAATHHQxDvwAfrjW%2BJ5xz259qI%2F389pt2kiAwdWyw27%2F%2FChXbl2zWizH3%2FysR05etSGWKsp%2B2XS7pVmNxfe7PtoU1438FsNgcZgI6OjAvHUK%2BPz7NycvgOaLcp%2Fe2hH%2Bft1sDRfs%2BuI3iPKq6zbn09NDwKLoIIDbzQHCrD5Rlf%2FVip8GixaLZufm7ObN25KOBns7%2B8Amz7jmhdKtlIZVqMlBkLE8Wwgi1De0nUao4nBfRYzl27%2BpVzwhl5KKDWbm521h%2Ffvy5Rqz%2B7dNjQ4lLaoaVlJi2xTGVYUJmDJ2oXJPw1erEhKXFoZuqH8eAWZwdIQ9kPQ475W65fzFbRd165ftwsXLsgrKUK0wEiuleR5BOfz8h4cUt%2FJtSvMTjHZxCyOdaGABLyfAmoRKJeW3PEPprJoM3fu3NkGC2gKZZpYRssUibrGu0kImQMmcvQRzUGiU0orIC5xAuI1UyGiLP5OJ4NVlqh31nGzXLOUttaIvpReocyVcslGxkbtUK2qCRHMUuHjjevXrdlo6Htz%2BMgRaW0Bo3i4DaG7M%2BeVd6TfKy7hcbhpKEsBMJut2%2Fy8m82iqUajiUkiDnZOn%2F7Qjh17O5l9di7wBJwB%2BtxEHe5k6Uc%2B2TmexTl7Elc58iKoM02yKHndADRD6wv9XjY39eZZX7Vi%2FQM1m5qakKYY0Hn58hVpxNFy4q36xo3r0nJGO2INaLUKuA8HUk5GtFnOTmNo2KJFxNnrHMDJljzTz2bspytX7N6DBzaxY0pazakdO6wiE14SW%2BObmuPAL%2FKSZpBj27rKKP8IZflKkGm9tWx0fMwmd0zZg4cP7OGjRzY7P9e2KqCylEWqQF9DnXq%2FvgNr5%2FoyJGYpRjuPc%2Fbkxa8oxc%2Bj5sXzLN4oOPDL50ABNn%2F5dbw9ShjmVa2WPZudszt372g2fc%2FuXUmuStJHSCPbolQuKAWpPhT6QAYWy4bGJLAjeLeS4J2Eg54yQvZiJP2zzr0E5rywLGFaYzDlYU0fBLTs2bNpe3D%2FntWqfdJsjAy5OWKz0dTWNCGgdhCncgMzehXC0yW%2BX5Gpc6DzKkIjpohrx%2B3Ib5Nv8nxci5SIh%2FYIvsFzBHvABeaKOF45%2F%2FXXdv3Gdfvp8mWbmJyUthEQIkFP%2FcK51Mg5ZYk84SfmptQNB0BzYWHenj59onV2gAJMIfnNzc7Zjp077JNPP5HjH8DZ4KA7iml3P0wZS4BFTy%2FyobrIS7UW1dJ%2B6BXLcw4Uj%2BW0v6XCUtvgmd73aCvu9C7rMxFwyyVfNxbfj5xg62s4nZekB5Cs7d9vQ0PDWkv49fnzMl2dfjots9r33n8%2FefwdaK879XoBUDocDmBJeDwDFPE8exbOVVLeckRU0fYx7EuKJ180q4BN6pctTdiaBY0xJsmsgyMt9gGlr3l78PQjj2BNtJu4z74qweXsSVyp73U%2FThUmJ2ziPhFSGXmm5w4wlY7CPBH2QGbygbWZg0ODNj4xLs%2B1TF5cuXxFznrQ4GKOffu2e1XGPJw2Njoy2tZ0OijPA%2F0gEjoS9al9eatj3XLTFpcW7cGjR%2FbDjz%2Fa%2FOKCnfrglB04dMgqfX0%2BwZI0miqCksklFkzZjmcVI8qySgH0OOuUvb%2B7ne%2FyCu3M22BTy1qIMTI6YhOTE%2FIO92T6iT2bnbXlRt360r6ofF%2FK2qbMfSzwjtKhj7c%2FHJ15xR11o3wjoOf4EA%2Bzmuxs76vxIh%2BfjFaLR%2FqJCr3S9V5kX5wLDhQceGEOFGDzhVlWvPD6OOCakeXlJVtcWJSgINOtJBxjJLfdDsGqNLj5EIfGx4Wn9n1AL7y8IsCDRNM285zzpW4LCynOz%2BOH04EckBdaIRdBl3GXtU4uJ7jg2cLzY8uF6ZmZac1yj42O28T4uEwqMWtslppWkjDumhjMG1ccaBo6CiZOpcGe67QuK5UeeZHoCC8SaDr4kgSEFZlsl4DUEgIw0d61Tg6RuiW%2BolU8deqUPX76xL759huBezyqlvsBJZl2jZRY8wyf8MzaweLEjka9LkHxzp1bdunSDwI%2Bt27dtuGRYTt%2B%2FLi2iziwf78sCwBogB9vx17vgALCABkevpLP5Ks25UVLERTajsxWjNBJOyMdr2F%2FIelJUlxvLBGDeC7UurlnCLLtrJLDGd07ITK3VXsu4eimJvA%2BOTFhX5790r766itNbmFW%2B9mvftUB%2BqgHDjA9pKbb1F%2B8T%2FCcLVTgC2WOyRgcJfnhJrQATbyknj17VmdMdz%2F77DN5nMXEFC%2FcYa4qvijdxKOUUnbK12yEUmLnJCFtfsTjOLf5HQFwNEsPwMk3QPWXBXsM7Z%2Fp70X6ejfVJcBjuOKgczI5kXr%2F5Em7fu2atMlf%2FOUL%2B%2FOf%2F2xHj75lH5w6ZW8fe1vtDC095e%2BTJjJSTvmImESr2pxPzjHntVyvy5zz7r17duvObWlLj759zNBqap2ptazMMoxc%2BbydZWXnirIGzzufbN071XSeN71Ipf5yddgrSj4sa0HetvnWNxrLag%2F9tZqNjoxYta9iT5%2FO2vTTJ7Y4P2elATwPY9LetBYe5OkHfL8wb8fsm0mlBEjzefXid7tM%2BYgrrqGSQkU7iQmvuOeFfKEjfi40H7U7%2FQ5z63w63RGL%2B4IDBQfWy4ECbK6XU0W818sBCTfuCZOBX%2BuvQmjUjGmanX29VLzi1BnR%2FJeNbS4MhjCdhXvWfo%2BGM8CYh8SQx51CHAGuSW%2FHmLlKTB%2FckRSTsKBhOoAedLgmExBJzp5tyeYX5u3eg%2Fs28%2ByZ7dq9x0bGxqzcV7EWERDKEd7QomHemLRCmXCQiPGiZZRxr2r20ipHhCkC0yG%2BwIFUfn%2BSPY942%2B0stiWPnQCcADkAFgQ1nHOg%2FcL759cXvrYrly8bgHByalKCYGi%2FdNNs2nK9IS0mAiJ1h%2FaHftWoN7SO7txX5%2ByHixft2bMZaaI%2BOv2hHT50yI6whcm%2BfVrrhrAOHRUnTuaK8L2a1tvBY6%2BP3tyW1jJXNd7yiesVDwDQpISC0myC6tqf5%2BtdIaktiBwJrwH2spQj9UhBlEmzWBIfaMa1%2Fn4b7B%2Bw8bExaRLZruXcuXMCgaxF%2B%2B1vfyvnQYBBaMUhCnUAGEJABkzCGw7CQ5DGnBOzZPgsgJ7bQxNHQHjEBWhiooxm7%2FTp0wKaTCRkaxgzzR55hUBOmmsfPM%2F4oNg53uffVcyOmR7AFtz2fqV8eSH1sfa7Aqntu%2BxC%2BThA1WuVklWMtaV91g%2BfJyZkosy6Tva9xLMxptr%2F%2Fu%2F%2FYee%2BPGfvv%2F%2B%2BfXDypO3dt6%2FNS6UTWmqdfW0xfEdzTx0AMeYXFqWZP%2F%2FVOVuYn7f3P37X9u7ZY97u8WAOcaswIivBtruK9uD1rL%2BpV3UWJQ%2ByO7ng73TG5k4DsaqePFrNhrhHU4CVQ4MDNjE%2BajPTT%2B3xowf2bGbaKum7xeSTxpw%2BLBYYB5hkhALSpLZ8ksCblU8skyPtDWpEH3n2LElGqZeJN3r9lGJ6Ftek7OVt59PJjCzx9tVzI7RjFhcFBwoOPJ8DBdh8Po%2BKGBvCAR8MmFVHm7Jjakprl%2FqSYOuAJQmXCErbZCzQUKu1T4mJgCkV1Yc9H2ZjKPQ4WfGI4z%2B9osdR8N5bX3RUVUTtCMzdCNBmQ3sTjSuqmyTkBnAUCSkthHWEkGfz8%2FZketrK1YoNjgxZX3%2FVmMIuVYgotCkHHtw57VGWICovBqXShXDLGbmX4BRdJ%2Fbmg%2Fz4o%2FiRTqSbK9%2B2uewEFSFI%2Bjo91woz%2BYIjlnffeUfmiOF4BRCKiavaVNr6o4rHUgRANA0I5%2FW6zTx5IiGfNYLXr9%2FQGk3W2r1z%2FG1pM1kTOrVjygYHBuXFFdah1eiTJhneZpWhekmTD8RzzlOGTobrtiNQFZeL5PeeenqmE%2FUccSN1B0L%2BMlM1fANyAms0izY9EdMEugG1LkGzF2efTP8A3jundthHH32kb82Zs2cFgv70pz8ZWki81U5MsB8ngNK1lG4u271dh9NBvQU4jAkDgCpeZgGzFy9eFEhFe%2Fzee%2B9p25jY7xNqJdwzsdYDIEW60TZyTEyX8SXxmurCkh3R4Wyv54S3q7A9QZR7FZb7xysXyEu5OuJJ1LkqlvL0yZHM8aFhO3jwkHh8%2BafL0u7eu3fXznxxxq5euap1wawPxpwY03EH9%2B70Se0hfXvU2AXkmzY%2FO2t3b92yG9euae%2FUE2%2B%2FbaNDQ9ZYXlJpKiU8Y6f20kn1irt8%2Fa14uMUCBNBy7S3qLnpNkBuTmqqKdv2qBUSUzjNpYpzMd4MJlZZZtVyyRrNhrUbTBvtrtmvHDnv88KHdY7ubx49tcnTMJ11KFX2z64vL6gdh0eITld5f1TaifXTm3O7z3WXIR%2FNyRKmiHHHOx8xfd6bYeZePF9catdvcitDiXHCg4MDLc6Dyz%2F%2F8z%2F%2F88q8XbxYceD4HXBRxQSaggd6KB0lQlCBVKrtWrOzCNfu01dIaJgY%2BXkEWC%2BHr%2BblvZozcsAbhUV7HUh2E6XF67lFdi%2BiCUkJeeu5pSiTwiMHYFWcJlGvEUUo8T7sC4KwFwNlmcgrHHApN5tPpaXs6M22Ly0vajuOb775VGY4eO2oHDx2ygaFBCZpKB6GUtYd9VBbRHD6E0Eg7yEhThHaIP8vWqFHX%2BiUG6nmaNXfB1tPqYOg2uYmyObk%2BmRKAovMZWL4sk9pnz57OiIteAAAgAElEQVRJYEfjiGOmkeERzWDg4RRw01euaP3c8sKi1shduviDXbz4vTSZ165ctWazbkeOHLaPT39oH50%2Bre1Udu6YktdZbTWEMCh70eQEBlPqxE%2BvhxVNzftkuwa7n0ddu5BI8l73rsF3AFOycmp6%2Fjxy7K7IEDRTf%2BruYqmt8BZtjeYs0C1w7KH%2BHfEywmu8o7JVBsAPjfzDhw%2Fs%2Fv17NjPzTBpHNJzhGZbyOxjMvkE0dTedzcIAm9QTZrOff%2F65TEjRgAJg2T8TRzmshQX4iqoE4lR2%2FsBLnfX4uX%2BcDelrkUxNg8srzyTnefQ8p%2FxXfeZEqq9H%2F1PcCM%2BlHdiUyQ%2FMutF2Dg4NydnUnt17ZJa5tLRkjx4%2Bloby%2Fv0H9uTxE1taXBTAZ90l78ZyiqXFJVteWtJaXyZRWGv83bffCPS8984JO3XyAxsb8f5ACTFL1v7MqW2uxsh2M6L9rBZpC4ZHvfesK5WkXbJ2uWglfsQ5XzDCWtas161eX1bfoVrl8Cetk0aD%2FOD%2BA7t146bG5oXZObv602XVX7VSlUM%2F%2BohPEPskCvS1mxWtT0zOOO33La0DzzWflcVKLReKvRxOb74EnS91PulV4s4YojSt0Ya%2BjMbueMV9wYGCA%2BvnQKHZXD%2BvipivmAMhiPgAUPL1gdaS0Lt3z14bGPCtFTQyKVLSHPjI9IqpefXJtXLqA2mD2lm4ENy%2B7b6I8S0YlJ4LqCWTI67XM3CuiJMLkDCeBlO8gCJoZ6mG2VPT5hfn7eatG9oy4smTJxKS2Wftu%2B%2B%2FkzlgP5o1vd%2BUcIKgTTp9lT6ZYDbNTbEQYnz45m8GYCAJEc%2FPwQzigBT03wM16x7PM8GekM53szibfbVewEA8qpszAjIgKF%2F90lSWmtL4v33smAS9Wzdv2aUfLglg1peXtW0JgvXU1KT2p717545dvPiDXb5y2RbmF2x0dMTeOXFc%2Bx9i0jg5OWlDQ4NWrVWT%2BSKoqSFewjfM4jSxkwjxNZoufq1YhbtaBbQLQYR0qKBcZ5Xbrn2erZZWm7L0bgiwOYFQ7ShlRQtTG%2Bd74Q1Pfm8Bn7RRwJ%2FATLNpI8PDMvHEqgJPqfDt%2FPnzAozEZXsUwCF7%2F1JHUa9q6%2B0y%2BlpbTGnRjF65csW%2B%2BOIL%2B%2BmnH23Hjp0ym0WDvHv3boHXML%2Blrj1N6j%2BZHq7zG6cem8qrCSi4uir%2FnP85uJ4qpPPUrp7O4Je6gxSRo%2FkyylnWFjQD%2FQPGvrxTUzvs4KEjdufObXlCxkHVV1%2Bdt%2Bs3bmpd5%2F79B%2BQIizXhfJ%2Fu3L4t0%2B%2Bx0VF9M65fvmx3rl%2B3%2Fbt32ckTJ2xydMRqyUMy6wXFTSYaqP%2BgRdcpIIXFs9QJI7q%2FtAX%2FBl855w%2FVbXuwiVgpRmKD%2BkRHX8o%2F9wkv2iZ9qdFcbn%2Br8Vo9%2FeSJPXn8WF7IL%2F3wg00%2FfqJ4aO9379pj%2F%2FRP%2F2SffPyJ778pkJpaW7BbjSFPsV9Hm9Xqy%2B5CdUX3HuKliGSzKISsDOV5JBvn7J3sijed4u016ZCVoLgqOLA1OVCAza1ZL28GVfHVz40NXOISf2zM92GDEQh0HBr%2BNMu9jdijMuYKmEy6GDBzWLSjQIrNH73bzSSpdfUsn2pHAvFqd6DCIz1%2FGEO2tEuM%2BDxuJ%2Bz3aBmuXb1qf%2Fj97w2vkhzsscl2GXg0DeDC7Hd%2FrV%2FrbQE9VnEABUhJhfFMEdZFhmcUT7M7oiU6JYWk1%2Fykv8T1%2BCuf5aJtq0sHMFEyhD5v94AR%2BgCanEq5orWahw4elGOfP%2F7xf9m333xjDx89VH2gnUNriRnc1StXtIaQNYFH33pL9YRGbffuPTK9LcvkOWkZNNEAuxJX2wppHFb5xAPP1rYqyNdIN%2BvjWdRrLq%2FuqNR9aocOQvMRPJ22PC1NVKTdfi0rRxIdU66uleQbEsC%2BXNbaP3g8ODAgDX3%2FwICNjY3L7BXNJNqzjz%2F%2BWOa2OPIBcKK5yTVNgUXSWFpatEePHtv3338v01kmZQ4cOKh3T5w4IS%2B48iAMhSI7FVRFzMqRL%2FGa1ypYBh%2B8nJ5OlHnN91d5SIqv4ohUOMMf2pDaecms2l%2B2iakpGx4ZsZ27dtneffvtzt274jeebD%2F%2F4gsrl8%2FakcOH7dDhQ1pzy7rXO7du2c6pSa25nZmettmn03bqvffs0P790rShlQOYMpEg8E5lpyblzTvjc54%2Byqt76NzCGs5umqOeWPYQz7wkFLozhJKvvgAjxU%2BTH3gXZuKLA23m1avXtMb2yy%2B%2FtG%2B%2B%2BVbbk9WqNWvWG%2FLm%2FM477%2BobRNuhroFrUdd4rva6D2o5B22u9QyQlwaHfMTOa9WlppVSPycdT7%2F9%2Fep8o51T5Nj1uP0aE8RZ68iuVsQvAgoOFBx4IQ4UYPOF2FVEfl0c0HCR06zFGOnheEA135x7233%2FO4GVhDjhxRgssyHXeZsKKAYg5IsDuUgawjUguvC2%2FhohpbaQ3n4tDa4tnHokgRBZCxNY%2FmEO1TJ79nTarvz4k507c1ZaGwTmoeEhqy8u6tml73%2BQA5tPP%2F1E2s7awICVW3ilJRXXMVEISuclhJo4PC9%2FksWIoieOeOSkVXJgFu9v%2FzNgMq8l6y4f92gbAO5o2Fi%2FOTc%2Fr%2B1QAPwPHz6SqTOaovfefccAoyMjo1r%2FhlOWPXv3GtogeZetVsUwNrn3f1RKxuV83jRDtZsQHNUis7jBeQ9ZGR7P%2FRx1vnY8Yq02ERPUJFHW93NNmfAOKTu9FAnhm20XWtpmhTVoy42GzIxZC64j8dXjmg309WnPS7YgAViyHye%2FP%2FzhDxKk8R574MABORbCA20cTAxQD2xrwvpMwCb1idksjp1Yi8iSAOct6xh9Mg2a5Pk5%2Bl4y%2FYxeEuk%2F75xxNAEOx0vPe20dz7MyriPy6lFEINvlOP5Jt1YuVaxa6rfRatWGRkZsz7599vjJY7t29ZqcYd1%2FcN%2Bu3byhPTSnZ57a9999Z3dv37aRwSGbHB%2BzkaEhTaJgBSNwmYAShLQn0FanSk%2B6Sxj3GU%2Bfk8AGPg7a4hxZw1fsSdT4U6DGmlyAl4c3ueKb23nEt0B9T9Fc84%2BZ86Wfrtj%2F%2BB%2F%2Fbn%2F8X3%2B0i99%2Fb5g7Ly8mj%2FEAWCYXNYFQs0pfxRqtppvFs44%2FgLt2QPE2QM7ZJydocsryo0QnhfFcnSWVI96Ns1LWayvL151axi7e1iFnhL24ExGKc8GBggMvw4ECbL4M14p3Xj0HZDbom7zLDG1%2B3mrVqg3098u8Vmjz1ef62lNkSGcQzw%2FtIcCTOQMug6IPdjE8xln6T70fhAYsIw2AXK%2BD4CzNLEZQkoX4FQDUc%2FJNvDUb3jY9a1m5VbI%2BtEHNprE%2BZ%2BbJU3l7tHrdbjybs0f3H9nDew9suL%2Ff3jtx3Cr79lpNG8E7OMKjrSiVo6QQiGJ450n%2BB01%2BH0JKnjcApJWHUl8ZvM1CmDwAoDggceIjDO0ipUTzw1YdX311zq5cuWw%2F%2FnRJWoX5%2BQUBGJyqoOFgn8F333m3rXUeGBywqtbMVbytJU1mPi9yzPNa94m1IQDyPN%2BWg8Wrhcfz9Z6Vf481zd3vZ4Jq9oSmEW0%2FC3VBOPjIdwSz7pa29MkyUluTKbNvNYNjINZp4oCJNZ3si%2Fndd9%2FJZJktaACPgH6EbNbJPn36VI6biHP58mW9gyMg9tDcv39filtJ2j0HwkFj5B1nb%2F%2Fx9Plnqsj5T1xx0F%2BKrvb8JHrHUF%2FLpdc71qqhWa%2F07x8pKbU22z1GqVK2PvZLrfbJOVW1v2a010NHDmsdINplTDbxYMs%2Bsw%2Fu3ZN5%2FmCt38ZHR2xhccHOnf%2FK%2BqpV7Qu7Z%2B8eTarIo7mcLXm76CxJ%2Fi6jtF0Y%2BkeApHbg5l901jX8hE7OzlQHmNAZ5XOtISF8%2F9V3NQHYrgQvlFjgIwRvxtusRWaCZmm5YU%2Bnn9mde%2Fft7oOHNvts1mOltd04FqvU%2BnzNJcsAyry3bDhowku5NMXkoTGAASpyyHgKbYS2a2NlFI%2Bs8MSJ9hjYfiufgnWMF%2FkoWS7tsopHKY6P2RltftWRQPfD4r7gQMGBNThQgM01mFM82lgOIBDyD40NggWOOXZMTlpf%2F4CFyV%2FnaLSx9L1Mbm4%2B5G966UCJkRIhuaNj%2FI8nBIZ47%2BZJekNgM%2Fdu7nI1oRsQGalG9DYpLgc4sE31EJ4n%2BUgAJCdGRm241m8zjZa1lpdtkXVvlYr191VtfHjY9u%2FdrXOtUpEXUwFpIeuWldACdWTuJqLODIQPFzRyzHGhQQTyxyn1dbBcoy3l4C8J%2B12Uayuead9xdIM8Bxrx1M%2FqD3jdbDasXmerjZZd%2BvGS%2Fff%2F%2B79rvey9u3ft0ePHNj8%2FL5A6MjpqYxPjduDgQTv%2Bzjt27PhxgZxard8BrLQfiU8SwvNtMcu7TWX7gneifnKSaPZKe9IkF9TjMuqonfCKONmTiLsiSqrr9Lz9QnKo1RY%2BO7WjxEYrLO1XR5IpgUCvbU1n1YaH%2B6QZlhZ%2FaEgm5HgBRtPDmsy33npLoIZ1zGxJw9pYtjXBkyprMwGbsT7TzRHdrDDfDrQ2LrTWWBEEOEptpbuddJCudt9mgCqGcvLLh3a%2B8wJ3ouHlUxIt7df920NY%2FoDt8nqd4rXKJeuvVW1yYtKmpko2OTlhE%2BM4aOq3GzeuyznQ4tKSHFhh2jk3N2uL9SVrlFo2t7ggB2ejE%2BM2PDoi79hKW99VMvBZuDz%2FoSUoc3P%2FuOdJN7V5yjfvOqtfwGP6rnaAt2B6jBt%2BJi7fdN3l%2BolKoldUYz7X2PQtZpxXJdu9Z48df%2BeEvj%2F37t%2Bzufk5qy8tOYBlO6SBqg0OD9LJrMEafb7ncjAHdz1P57NPsHZzLzjtRruphBHYHTlqhvaZj9P%2BvnogVjnRE1T2djoeDlVxRPdX%2FK5kPU6klb0T7xbnggMFB57PgQJsPp9HRYwN5ADjBYLczZs3JVhgLjVYG3CzzhBIGAy2yTdfA6yEHTeJ7R7j86yNYTkGSEZSiUhJ4xKKhvWYh3XIHpGJBI24yZ1T%2BrFGENYGezmz%2FnJ4cMimxidsZHBQa35adRdG2M9u%2F9498mx6%2BoNTtmvnlNZNuRzsFaa6ouCRqJcqIyBvzpkipapOcYIiB6WY5TqPEJvEofZ9lujGX3ULsd0U8DzaLRpMGCLzM6gH4KdC%2B7XfoNGsNxo2Ozer36WfLtm58%2BekPQP0LC%2FXrd6oJzBZsmp%2Fv42Oj9vkjh3a%2BxRNJxMCIXZ20NQWwju57XGc12Jvx0u9b9avBaIuya9XnrCk3Uh6Z6TQaA%2FceFq0A623yr%2BesojccBjDVi4cbQvYLu0VcR34%2B3YmaDXZExM%2Boum8dOmSsZ4w1iwzIfbgwQPtXTo3N6f9JDFbRvO5a9dOaTijXiWA58w8oSMPJomXtRGn0%2B%2FzhRL5%2BhPpKp3V%2BJlFf4mrxMCXSLtNMfxWwVILzBOdKEolTe2%2FJa0lWypxjA4P2eChg7a0uCCzWbbRaDbqckRWV99YtuUHdWuWSza5a4e998H7trC8aMvNhtLB35I7XUpNS5NaYnQudyhQzevrE32lXYZgA3HW1T5T0q%2Fx5N%2B9oDoBzl7fd9p3op9y%2BT8Ia5cuURnfHy99o960erOu8rKd1Y5dk%2Fbh6VP28NEDm5l9ZnMLc%2FbwwQNtj8I68sHhIRvHMdlATSa0aKrlY0HoMfMyyxin8Fz%2BUf8ZdV4Xq7IvCtTVLgPMtkvXrquo70iXHLPyk2%2FWLB2COheyOMHpVWkqHhQcKDiwJgcKsLkme4qHG8YBybYMjC1jCwc0BEODg7YsZw9NKzd9znOrDPbP44sAgwTgppsWuRuS3KDWnQLiQwyC%2BUEuhjnXajrMImaSINKpO7W2hJF%2F0Jls7gmJMCA7AMqNw8qFjdGpizE0DIMDGqcRkvsqZRsfH7P333%2FPfvWrz%2BQ9cnRkNG1QnwSgdplSdqKhkxAH2VCQ6MhR5pf5%2BM4nQrzoLhbkhYcVr7%2BmAAeMyGNOH2A9E1p6ZeqAqANMJrNZ0iKcI54Thonm7Nyc3b5zW4AGD6do2jDvBL8vN%2BrWrLswhcYHUPpsdtYajab11Vg%2FhZMU6MvzME%2Bb55kPya7zEwRZ6M%2B%2Fymovn5az0QW%2FtajKv8P3gBYB63i%2FezJHLOVP4q3iK%2FEeOXQBT%2FJhMqBWqwo4Ajgxnf32229UF3fv3pEzM0A%2FBx5r2bPz8OFDNjTE%2FqeDoom6iIO6iHrOh8V1lCPuX%2F7s5Vut1iNdPe%2FBiqy5xMM4x5vPP6tn6jVfp1dR4Trf82rxb1uABVmDqMoceDKBMkRbpm%2FgLTmtb%2BYbh4lmX62q9YpYxDyefmr3Hz206mC%2FDQ0OWX%2F%2FgLZcCa1lb3542cg%2FngdATR8ZfRtFaxqGKEX0%2B84SbcRd1IWPA9z5eMBVPGuXJJUpwSc9jmeJVhWM56lteoJ6CFhH216q9Nn%2BA%2Fvs088%2BtZmZpzY9%2Fdjm5p%2FZ9PSM8karObUTZ09Dmhgm07aWHnDYBoju9RzeOUVOsVMUY8bL8DBaD%2B%2BSX%2F6Ll8bgYI37KBbXVOY2JZ5vJ3c6716GsuKdggMFB8wKsFm0gi3BAT76CHY%2Blrc0Y6rhKAlnaHjk4TQpXLYE0asQwZimH2vwZJLKdhJuBhnjXRssKg0GNH7YHcGBGOAi3AdSxmucQMjdTooiAT0SDXo0sBOh%2B0FEWOVMYko3JZ6isaYKhz%2FDI8PGNieYSiEsDI2O2LG337Zf%2F%2FrX9sGpUzYxOWmVap%2BkfnKOgZxkuE6LixwVpCyIR%2Bm8hH7XSR0R%2BQVf4t7PIR5yt5EHQJC1xVDP3oEIVqxv6gYS3TSF9jjikQ4%2F%2BAmIDAEWkMk%2BjZjJ3rp103744ZLMNGeeTdvJDz6wffv32%2FXr1%2B3a9euGGSeOZtBwsjckmjZAp9JSA1mLO2s966b%2BVd6vzNeBR9Zq4747V4HKFYHejnIyrffB1LK6o8c9VATP870l6od4XFPHbBWDOSzx4fEf%2F%2FgnOQ3as2ePvNWePHmyvX0KcSLddl6qi7hbeSYflS1PiKIREPxyYO1vd0bM7rjK7lbm5CEq%2B2rR8uF5pq6WWK9wpeEJ6VveK4606162dn0nPvFN4LvfajTl8RQPy2HazzPWIOPNdu%2B%2BvXKYVa3V7MqVq4bZ%2BJPpaWmkd%2B3cKeDP3rP0rzBbhhSvY%2Bij77ImGlDi9YvzJ%2F9mxQSSf6F80iLWQUad9CrY6wqLiokz1HOd%2F%2BXzTuVQgaNZpHcjiTbjs%2FfY%2FxWNptaKl5J1y%2FCQHTlyyD759BN5v5Y57dy8PFSzdyrm4wODg%2BojbaCpJAGRaSKT%2B6Tszo%2BBaouJxp%2FP1dx3uIRzQfJuyZsxHQynVD7WRq5xTuVvd8IYD1N4cSo4UHDgpTlQgM2XZl3x4qvkgIZKmRIicJVktoZXuxDY5B1VIOdV5vr60kI0cfHEtSrM1rcF2CS8%2BaBKybnSApc0xxqDX5wTnek9yQYSFCKPrnKEENEWULue97glTafXqemIwrrMoUEbGh2z6sCAO1fp67N9Bw%2Faf%2Fnd39mv%2F%2FqvbOeePVapVduChC7chi0plZK4mZvRbudB5iqbWkE72C%2BCB%2Bksc1yucyqGJEMRuhEH9YhwCsDjKJcRSBFSMwUa4bTddp0nwuK9EHzRigFaMddEEMZkdn5%2BTt5lcTRz8eJFmZQDUg8eOGBvHf0bG58Yt%2BnpaTt37kv7j%2F%2F4vbylPp2ellD%2BbGZGVgE48AjOMeGhSmi3i0TMVjxpMskp56838xzhYnISWHvQLzCvNpYeqrMkQKmJn%2Bwl5ZKATRbqV%2FHd4Q7PsdSjvNku1zUJ8PTptLTOCOUc7EHIVkBMEKABpT45YnLBhe8oEecAO7rM%2FRFVUXKvtqS1zdpXjh%2FpzXyI8yx9VnIpc%2Bk5Z%2BduTXBX9HQbb%2FV%2Bumpoeo2u3ZFCV6b%2BDACXA9JqB5pds8X6os3Pzdni4pK29Gk2mtI279671059eMp%2B%2B1d%2FZW8ff1vP2a%2Fzx58u29Vr17Xe9p0TJ%2BzA%2FgPaJoUtVqgbPBHn65fvXqNRV2OjrtnTFsYrTmJmxPfmFMApxVmVAa%2FrQdQ2516%2FjNt%2BFfETPXolx%2Bs2mT7ZwS0TuwD7Bo7iOFrsZFW2ifEJO%2FH2cXv88JHdvH7Dpp881bKX0eERrbNl%2F1QB%2BlyN6xtIMvrGq2LTOOdJx1%2FPKaMrK0XEWOUsTBixE70i2cdcz9%2BvKUez5JYGmkyAEiYYlHT6K1o1C%2BIZrvKNWIWaIrjgQMGBHhwowGYPphRBG88BPvMM6IBKZkfZG5D1UJiwtWejtee8b8a%2BVb%2F%2FjFMxuLpgopIJHGWe8dz8iZldQTBJkT7PG3%2B7ayAbQl1BSKoe5gNkd%2FwXvlcyFQlZckSbkgUcMTQDNkfHx6w2MGhWqdjO3Xvsk1%2F9yj77za9t%2F6HDVsEL6grnJgiZUSI83frwLtEzCdAuhiYwJL1tvjxcx328iyAo6eKFi%2FiqXqB%2B%2BdFeaZu%2BjQWpI7g0ZMKazyviucCavUucaq0qkA%2FonH42Y%2FcfPDBMZfk9fvRYybCP6YED%2B%2B3osaPadmN4eMgWFhdtz%2B7dhtny6MiIff31BWlB0f7Mz87a4sK8axPCE7CTlydrS12rzzgHo2E7fQksBvkxvSIZWM%2B8L%2FGc5qdviMK9vXj7wwNteqZUqQPvp5hX8vO6oa0ma4RcvrzChABOy7755hv9oPdv%2F%2FZvtZ0JkwMAzTNnzsh50OnTH2ovU9Z4RvvGlDbKKBISPXHNWbTnPmxBo8eBZu8LEcVJ9K9AfB86zt0gL30zSIV40bPyNLyOa%2BgkL%2BpCtRIF6JUZgER9yyeTcDezuLRsT6ZnbHZ2Tk7J2Yd5z57d9ulnn9nvfvd3ApsHDx60peUlu33njt24ft1u375t9%2B7dtzu379jkxITW0OK0ifW3w0ND8lzroMiJ4BqmiD72dqaP1%2BuaYAB8auKzXFYd8ozJg0raRziK4W0o7l73OV%2FTcU2eUbuev7c5f473ctV7G0d5OHH8hxbQP8yVWFkZbU577PZZuVa23Tt32wfvf2D379y3u7fu2KUff7TB%2FkEbGxmz%2Fr5%2BKzHxlptQSLknhuClbOX32%2BPQMKMGOj8Da3Kz%2FXKUP8VuTy65ab7zhuaVWr7GI2dGGomdf2k8jvht2%2FyN6jBrFrZ4WHBge3KgAJvbs95%2BcVQzXiDoIfgxS8o%2BgYBN1tyEUIBzCAZFQNvGDuzrZ7fGIwlTCE3xnrtE8FsXjtlKHrMtPdHg5yNZXjiIt3mPp%2B7ZNqXSHvjamUT03LkdKQtzCTW7T4InARI4mniOdeE7eMy6qNrgoA2OjFhff01rAY%2BdOG7%2F5Xf%2Fmx1%2F713tj2cIYtLkJccSmgmvGus9vcR4QsyyVXlcrklwFHa5oOHRiJH%2FOTuDpiyljb%2BCBqoYk0o0lBy%2BLs9BDM%2B9HjPavN0CKHjHeU08TP9Ya3b58hWZyeIY69Gjx%2FJAy16aR48etaNvvWW7d%2B2yoaFBgVPMB9HQ4IgGDRr7Z06Mj9uX587Z9NMZqy8vGRvb%2B%2Fq2zrrMKNpKV759AxRFixX%2FaAgSGFPDge8tGTumrpW%2BB7QceB5QQdFT40rFVHuLIqf6i9YVwXj9TTml74xTg0bz1q1b9pe%2F%2FEWaZmhj78z3339f3yhMatlXk61oiAPw%2FPjjjwVwqB%2FiM2njbcDrg28a9%2FGDhgijLH44NR6HkM7vXrsrt8EDTlodMHgfLrfLEylyjjIqj46blO0rPFGWKI%2Fo5b7d41dmRFmZ3tIEAPFKpm03Zp7N2fzCklWqNTty5C371a9%2Fbb%2F7u9%2FJhP%2FgoUNaH0tqE2OTdnDfAbt%2F755duXrVrl67qm1pLnz9tczOAZtHDh%2B2w4eP2MTkhLSY9JNwokU%2Fhl7yhxYxK%2B0PSbjYpXpT09R3YGUpNiIkajJqNvKEwnhGmGvxuHKM5fGFpxIYYw2sT%2BJ4e2zWeYelAQ4aeYPvllJutmygOmAH9h6w3%2FzqN3b39l1bXFiykeFRGx8dN2k25YY2LE%2B8VzpVscdmrsEG2T%2FzrHpppwHFlCGjwR8Fb3jOs3TWywBgD3NHYzzrOuL1ruDituBAwYHnc6AAm8%2FnURFjQzjgAzvfc5zQsGUAgngfe3RJ5vQZ7xg%2BNoSkl8zEh6kATtxFSCpDqSVnFyTf3oOSobw9sy49THovCTjBA3luDcLglkbKCOhx5n1Pm4f5a8gKKgPIE4c1LRI0EAxx2ylg1bJqrWRjY4P21tGD9ld%2F%2FZn9%2Bjef2J49OwxLQjQQGuBZY9VccrIkXXr9uW%2FCRF4C1543fxMVkkEyfiGmOO%2Bcfz0Kt2lBDgwcNKL1QshHGI11lxKw22jA4zUbAHlfExZrMtnA%2FsbNm%2Fbd99%2Fb1avX5PAHTeaJ48ftraNHbe%2BePTY6OmJ4fPQ8nCXcDw0NSXDGWRDbntQG%2Bu3C1xesr1qxenPZGo1l1Z8D4q3Wc6Lddtat2qfaqWs%2FBD1QYyZNMiAKCT8Ef5%2FA8A3loze0U4T%2FkqpTM9EDf6o9GEUC3k2bNj8%2Faw8ePJSnTYD8%2BPi4gCR1e%2BPGDfviiy%2Bk0WQLjtOnP5IjIOoJM1qsMCL%2B2bNnBDgxq%2BV36NAhOXMCgN6%2Ff18Ahrg7duwQQKJOwxy7ozGLNjoEFw58HCB4UBuPtovmcbJ%2BXDaVMRcRXrV5Ez0rH9BBwKu8yTKR4nINrIGg32r6N8%2FrE4CCGXPJypU%2B27Nnn318%2BiP7h3%2F43%2B3jTz5pewr2T1zLBvr6rW98yibGxu3QwcP2%2Fvsn7eqVy%2Fb9xe%2Ft%2BrXrdvXKFZ3ff%2F%2BRJgOmpial6dSkQKzdxLlNpU%2FOtfRty7U3zEvp%2B9QbYJTrzTsyvmY0EOacy86pshUpTXAQK40l7IlJu%2FHGwXVMuvSlaYH0fW41NQlGHx0ZGbbjx9%2B2%2F%2Fpf%2F555RmPN5s6dO7RtjbdTAKxTQLq6hjS1x9QvM6I7roibn5jseLiumygLkZ1H7nRKBKTRht67z%2FkAACAASURBVDYGgOZbQn4ez%2BP7dYSsK8siUsGBggNrcqAAm2uyp3i4ERxgcHGhShcS2BGg45CQjZMO1lbgUj0nQEWcLX8OjazmVNHy4eyimRwnIEwzOGez0PlBL8qmwY%2BBUQJOeyiPx6ucxd2UXAKeuZiIERLwkZm8InwK3O0UfahuNKy1PG2DtYadfO%2BwnTr5lv23%2F%2FYPdmDfhPVVFqxVb3q9lPs0OdxXS3mar4NSwm2ASebkyrqpMIl1hw3JWX4SAkKIqzhZOZo3%2B1JAEkGFrRfq7IHpW48EQIc%2BaaNi%2FjxpRAhr1OvaFxNt2IULF%2BxPn38uT7NTO3ba2yeO29Fjx%2BzggYO2Y%2BcOOWSqVqtiH9rKpeVl7TdbqlaspHVnZtXyoO2s7rFPf%2FNr6xvot8mdO%2BzRo4fWKDVsvr5g1VKf1co1gdXN5tta%2BQfIVEOlrSSc5Xou3zpB7Z9n%2FNAMtpusazz5LrSnNpKk2PmpINAfUIcCrK2WLS4t2JWr1%2Bz3f%2FiD6gQw%2BNlnnxoOf1iD%2BW%2F%2F9m%2Fa8oR9NT%2F77DP78MMPDadA1A11iodatjoJEPmXv3xhX331ld29e9f%2B5m%2F%2BRtrps2fP2r%2F%2B678a26N88skn9vd%2F%2F%2Fd24sQJaaYBMAIvajjBJfoI5UwWASGwC3w6YCCmypH6FlYSaNsdnzqf3DeK98d26XOyeGJTZPp6zu2MPfm4ja9EPlPqSxM51K0%2BhyWr9dVsfHTC9u3eZ3t37bG%2F%2B93vVAdTEzus0uozPjMCDFbWWkM0%2F7BuoDZoAzLvHLX9%2Bw9oy5pr16%2Fajz%2F%2BaP%2Ff%2F%2Fv%2F2J69e%2B2j06ftg5MnbWxs3GrVmrwLRz9WPw%2BtNFY1TLrJj4Cvz9bzPPGbdh21yDm4Gtfcw0h6GP8YZxppvPERp9lsaMJFgJM2VK3qe%2B5wEd5ih9OwVrlplaqpjzWbJRsuD9iHn3xgBw7vUz9AU1xvLdpSw82OlbNIS%2F1Z%2FOE603Z3sEykZxOjHc9e6CbSIMH000yL9wn1K2yKtM6eXpPkCtkZxUSvT2AFyZyDyy9EShG54EDBAXGg1GK0LI6CA6%2BAA9GQ4hxJatgDbPHBlmCUhoAUsZmc5%2FCZZzkH60b4EV%2FmVEmz4R4Fy1qbFWlvvbMXCuGx2WKGmPumWcnNZnG6UNam1wDNhpkcU%2BDVlNLHmVKtZ2gLTse5FzfSM0ndriHqFQsJNf8p0DV1UKloLebS4qI9efzY7t67IwEZ0zW21ajitTASVPLNZJKGxqihYqBhyQ6uGeBRh1bSjzkv7jk78OSM%2FrdlfQKf%2Fn4SVNJsdJbm2tyCA20a8y%2F9jGvq1zWaaHR97WYInwIOTTcJR%2FhHeCUM4HL5p8t25uwZu%2FjDD9J8TUxO2f4D%2B%2B3g4cN26PBh27l7tw0ND0uoVftJfUHbPdBeEMb7cGKCp8jMPBNPtI8fP7br16%2FZkyeP7NChg3bs2FHl7evNXjUHfgbzcq%2B64JcL0CVaOuREL588krabceI1TntgRvLeTDp9mCj7NIZamFpaMoekd3krcD7wl7V4jXrD7t27a%2F%2FzP%2F%2Bn%2FZ%2F%2F1%2F9hZ86clSb5o49OCwziiGlpacnee%2B89gU8AJ5pMNGFoJGkD9BV%2BXKPNRBOKOe13330n%2FuPFljW4f%2FrTnzTRwPYo%2F%2FiP%2F2i%2F%2B93vpJkDbEbfQ7AXTxDIKR%2BERtWpf3lervmRXqYdIb6tKmp7HisxjsDgoSJk93H7Ws%2BOBp%2BbBe0cU1bXypYFguD%2Fgwf3td0MfD9y5LAAPozxPtdSf8ETNvf15WVbqi%2FpO0Q6mOU2Wk1bWJxXOpcv%2F2RXr12Rppk9ndmi5tixt%2B3UB6cESpno7KtW5UjI6Wk4qGeSL31H6dNuxZD%2Ftj23eD0iUClRwT0erwgivv9cckuVqu5COg4ofcxJXtBLPpEJyGy26tZoLglwer%2FKr1HGTBsgrWkLnypreT9RG08NSNpz8sm1e67lXElrWStpQtTnhTKKowu6dUfvogXEXfF0lYDevMt047yW8UhtBpCZvhBMT%2FVVqrLmqejrkT3TOBX9sV1LpJXPM592kOjPez3pjBF3xbngwC%2BfA4Vm85dfx1u%2BhAhVfJjdc2NJXh6nZ2asv1azYVypl1nk5tqirVaYzqFHpcgBx7qVDK1XOrdYR7esn4Bla9la9SWz5pI1GkvWqC9Yq4U2METjJGymUSuGOMk7XUPe6nxJL7f5l%2B7bLzjNCC4IDJ42OTlMRiAnBhq5wVbdDk7WrVxpWnn%2BqmIsJkBAJN5FCGP9E2m5IN5IDnQSUNQWBP1W7uu3cqlq5Qqz6DWzUr%2F%2FKv1mFe4BsVUHn03WgzqMyNbaQKMLep1De3DJCxiljXPn0zYT2hfQ3X0EiMyHExYakHDzz9YngEoO9iClXS8uLNrjR4%2Fs%2Bo3rWpeJk5lnc7OGZ8xDh4%2FY8RMn7OhbR6UV6x8asDJbx7CNCuJgyazebMh0rdGsS7NC%2BnPTs9raBC3Z%2FPy8zS8u2OLios0vzNvc%2FJwt15ft8eVn9v3ty8mRiQuQefq5XlnS7hgbd5%2FxGCE2UZfqwttlSQAApzv9bMMzNGKjw%2BM23D8i5yRov3itjjlz060gAJ992pbGtdBeYBq6cKwmg%2FDe%2B9NPV%2BzcV1%2FZ99%2F%2FICdAT574OkuA5oEDBwzg%2Betf%2F0beTTFdjnW6QTPfLUilPQBUcESDeS3xPv%2F8c%2Fv666%2Ft9u1b0nRSFoDnV1%2Bdk4kt6Y2OjgrYaGKNTgRAbjLp5m0J4ZY2piVlTNY1zFhXV2q0bHlpyeafzdmzmWc2OzNrC%2FNzAluNelOTPVqPF2vd45sBo6Ly07q9117T6njR%2B%2BK8MleADJq2MDeHX0xa8S1pNJu2UC7Zt7cfWR%2FAMplUM5kCYBwadXPyoWF3AFTtd9Nb4qHDq%2FWXrbqzZOPDw3b0yCG7efuW6gKnQmg7b964aTt37pL5Ouuk0V6j7aQeqVvVi9ZnYzbPdjid9Pf6dnTGIAkvu39d%2FamPfj14EnVEND2mPUTlrXiYvth8iEm9YU1bsoYtW52xpbWsX72xYEv1eVtanpeTMb4Vdf3gb8OzoQmWAYxp3WpawwoZTGpRF4wLmJsz4cU9YzR1Ql8IZ1jOD6eTv152N1vtBGwZlyhmmo%2FOAqFqZWB6vpJvWUjwyCdl%2BB7zPeivDVh%2Ftd9q%2FGoDVrMBq1b6rVKq%2Bs9qVmpVNSFaasVkpyhLeao0SWrJkcml6hf%2BZ1R0xdCtp9DrSRFWcOCXyYECbP4y63VblkqCRatlc3Pz2u5hfGzc%2BnCMMjigb7gGq9f4ldbQhNSYMF6biXrAXeeDCM6GlhAGGIyXrGRs9r5opdaiWXPeWvUFa%2FJrLFiruWitxqKvb2zg0n%2FB6ktz1mwsWQsNVhqcGdST9O2ajjSeAWUSRTo%2F%2F08S4pMA7%2FGzEuTfJzQEhdj2wYGje2GEpvoiQM%2B3g0A7hGDCQN7UmibXuqH5ARxJftZaRQQ2TEBrVukbsEqlZqUyYLPfrDxo5b5hq9SGrVwbMiOs0m8lS8ATczlpPpP2E42WqiMG9XxZPCwG%2FHgSMfNlzaTuztD8Hbyg7TlP4gnCZiZtUk6fLDEJx7Nz8%2Fbk8SN5w7x186bdvXdP25WwrvL48ePaJ3Nqxw5Ds0k7R0OMPFVvoYdBE162ehIXF%2BrzNj0zbY%2BnH9vM3IzNzE7b0%2BmnxoQM%2B2niYIgf5qAIg85wdxaDPB6mf0E55%2BBJnPPPNuW6XTkJCebFtQTkWMPNem7Wh42OjNnkyJRNDE%2FY5NikTYxO2OjwsA1U%2B62%2FUrX%2Bvqo1ywi%2FJatIDYiQ60CT8iF4Li%2FX5bEUc2a8%2BWL2ihYNcAM4xNvo7t27bNeu3dJmAgwBkfpONTONtviZ%2BhXthB9rzgGqHNeuXbO7d%2B%2FY%2FPyCQAv5XLjwjZzU7Nq1ywDQ9B3qTWyQYO3r6NLchZo%2BmsvGQt3mZ%2Bbt2dMZm3s8Y7NPp23m8VN78uiJzTx9amx5AwAVOKs3fP1dw0EracuaMNHqpwD3IvU1%2F4lKjnOP7Dq%2BT%2F4cQMNBfwMQMRGDF%2BdKtaL5pr5a1QaHBrVueXxq0ianJuU5e2x83MYnJ6x%2FeNDK1YpVmeiqDdkwTrXGRrRvKtui3Ll71y5fvSqwyaQQ2wgxKcRWQwf3HzDqaHB4SHUHJa79S9r3dk%2FqUZY1gmhDGjcETlK95%2BOv6JgRwFu%2BXlTRk4dZpQafpMV0oLncWrDFxpzNLU7b%2FNKsLSzP2uLSnC0uz9rC4pzNL%2FLNWExgc1kgX986fabLMuGW9pNpPT4kAtqY3KLpLasOKD5xqBt%2Bane0N03ARF%2F2glFKtUHOGhR6tAMF%2BTgbJXYWd8eN%2BzhHHhoW%2FEZ%2FfRSg7%2FAPLeZg%2F4AcGQE6BwaGbKDGd2PYBmpDNlgdsf6%2BUesrD1rF2L6oZmVtR894F3nFOVEYhKbg7nEnR0z7kqi8Fim1HxQXBQd%2BoRwowOYvtGK3XbEYXxiAWi3tM4jrega1ibExCWOZWO%2FYS2P0KywkH%2F4w3RW4C1zJAw0maXhIGbeDNWDobTeLlaMcHOQsWKk1b9aYNWvMWGt5xhpLs7a8PO9gs8HZwWapuSztZquxgMoiG6gxlYyCJsADFeJTKnsP2ewFueLg2l9ywVOCUCSMEAGABAQRlvC0rjGdIkymwRXDzLm5LKik5GQQm0ytQlPRbGHW1iftZavMth8IjP1WKg9aqTpsff2j1rc8bKXqkJWrI1bqG7aStJ41NmBxrW8paTxFY5ixeY2oqtIQHg4gBC3SqO517LGizJydp88f%2Bh1oJOE9AYsIQ9BC28h6zDu3btndO3fswf0H2iMQbRzr%2Bvbs22t79%2B0zgObQ8IicYKE1QaOz3Fy2ZYnS%2Fz97b9Ylx3Hke1putQKFwr5yJ0VJbKm1dZ%2Fpe6f7Ye7T3Me5H3ZO98OMuqfVErWT4gISIImFQO1rZlauETnn9ze3iMiqAgWSAEUClUBURPhibm5u4W7mbm5et3E%2Bts7gwNoHHdtt79rK2gO7c%2F%2BOrW%2BtW3%2Foq5kcfzIcDW00Hms%2FJ6sUKLxhtqwVIq3Aimu8uvGXTy09xz2i%2FvZ3xLVDWKWVZPbjoXSy4jTfnLelhTN2bumsnV8%2BbxfPXbCLZ7nO2%2FKpMxIqWQ1rWdOaOL3CdE5N7IpCp9vRXky8%2BHJ8A0drUCwKOw59VlZW7dNPP5PigXlsrFpDH55pN6140UVUJiSIwzxzfX1dR3BsbW2KL8LT6d7ennGG6jvvvJOc1JyzJvVybzRpLzf7UOtWZwsB1zCz3kHP9jZ3bWt90zZXNmzz4Zq1t7a1stnvHli%2FP5BVCA6PNNEzpi9xBVvVBsck4Oqdihwi89Nt%2By9aoXp0ydCWHxNatA1vrdmW1difWpuI31E4Z%2BaYiJi3%2BYVFWzy9aOcvXbRrN67ZuUvnbXF5yRaWFq05P2PWalq9VbeZMzN2emnJzl%2B8aOcvXLBreLHd2NT3y%2Brz6sMVW72xojZC4cQJFxMOfMv0F97m03gnVKcD0xu8F%2FFhilo4TK3kkEp2uF14T99sokbqil1pVR9k0CazbDK0wbhr3eGedfq71u5tW%2Ftgxw76bRuMD2zAyuYYXqHvSEqmqApkHw9QaH3Sy%2Fu6Ar3EONSjxlwqK%2B5SRr0fZuIxoaosxXecQBMoHoyJlQRYdfKIoqjph1SwAuM57tMpUxVUTjWmjpMplOR%2ByxqNprUafHMzNtuat4X5U3Z6YdlOz5%2B1U3PnbKF1xmabp6xVX7BmfU4Kpyus%2BBrAyiaNO0I8lRLPlb61Wv7J8wkFnmcKnCibz3Prf8vqHkMHJoEIezjc0IBexVNKaTXg6z8zRkh5SrKX44HilZQrzcRSDhtKK%2FtQtGJCbpz9INix53IkRdPyrtl43ybDXZsMdywf7tlo0LHxuO9pclY7uVAQRjK3bWhFMzlvoOwYvFIVw8yOYnn%2B8j8XDKbyCUwUhOBCsf6PdOxjQUxHqJAAIkcZThtS1dNZcwh%2BOHAaI%2Bzo%2BAA3KxTJMAfUak3NGPAnk4ZZzoom5tF4m2xZVpu12mjeJqNFG7cWpHg2Zs9Yc%2FaMNVpLVmssatZeRAHJqL5QP4w1mGP%2BKwz1TM15YwKDdo2ZehQyYGEGxmy9%2FwJ4eoUmSUrkzhXKBspdCPkomuzXu%2Fnhh1rRpI1wHnP9xg27fOWy9ufhCAiBmP2u7AvD6yUKEXQbTXIbTsY2GGa23%2B%2FY6taarWys2irX%2BkN7sPbAtve35WnW6%2BZtJf0%2FrZRQF7ElqMe3IhodqhPsVRGKlKSs7t%2FwqVQ0wVj1TMjpLPZxzayvjd3izMXZRVucW7SF2UVbXjxj1y5dsRevv2g3rly388vn7PTcoi3OzFmtNSfCuMDIPrVcZzL%2B6d137L3337e19TUbjgZS9U37Bk0myhx5cuvWLe3XpD9izyC%2F4AeUjpj8Cd5g0oF8f%2FnLX3RnBVXCeVJQ8ETMhAR7Ol9%2B%2BRW7cuWqzc7O26mFBZnKSpilUbOJTUaZjXsDa2%2Fv2trnD231%2FgPbeLhmOxs7tre5bYP9ruXAF1%2BDmVMNM08UGrheq5mpRfkOHs3lKdFTu4HbIT78wrLSjF9qf3ihgaUETuLoa8W%2FE%2B3zH9aHNqodWJf2aPiq2%2FqZB7Z%2B94FduHLRLl6%2FYlduXLWzly9Y6%2FSs2UzN6jMNm5tpWSuZVF6%2BdMV2d%2FfkHZojiHR8yp07WvFmn%2B7Va9fs2vXrWuXGbBcHUTVZW1AJn6hT%2F%2FTIOnnd4RM%2FZofpMN%2B%2FCF8SDi8Rdjyd%2FKv375ZnRh54mZXMzMYTzGVd0dzrbNpWe832upt2MNi1g8Ge9UcdG%2BV9G02wmXDzfPox%2BjC6Po0vMk12ixX2d0Zn4vzuyhr0h5%2FZWlHLfTsB4yLflPeL%2Fk14a6c2hwnTmPbFQ1dw5yOJWKHN8bx0FH6acIG2k5r1x3WrjfkSnNb1etNmu%2FN2euGMnZ47a6dmz9mZhQt2eu6cnZpdtrmZ09aszVp90rS6cZwXZ39jZpvq9kWonsSdUOCEAqLAibJ5wgjfGgoweDJgMSvPXqMYSpKs4daBEfiEsPYyfRDX6K3xwwdGnPnELx7LgYw48qFojlyBxGxWq5MHrmgOti3vb1k23JaymQ9ZORlZA69%2BdczwWMdyZROnQe5EyJ0KuSVdWb6EWpA5NCMc%2BD3O%2FVjSlUWUIBjvi3BXsCNSK5miURrzIQjvkCwzq8tslsyszHiuSK6EIiDOXdiryt5EZBBmiluW5zM2Hu9ZPpzVimZ9uG%2FNUcdm5vrWml22GjTjKBbhV0J1SZ7CAmnigByCiwtmpGNSAd5yXEqlQSnkETjAJIEJUOknWSkpmwTBpyiYmNzhZIajLVAy1lbXtJ%2Fp1Vdesddfe13mlCgqM7OYD7u5JAom55IidA7YM2UTG0xQMru2sbdl99cf2Keff2b3Vu7b5s6GdXsdG2YDG%2BYDrXpCc4Q%2BKToI3S5PieZBBaUJ5A%2FdRa1q3aLah9J986%2FejpXWLRS7YDTqSj%2BBgJ4PoV%2Ffdtq7traJYr4i5Xztxkv24rUX7Nqlq3b1%2FCWZv9bwlszxFtnEet2u3bn7mb3%2F3l%2Fs3r27dtDtiohNeflt2MxMS5NdYeYaJuExyQBdUOjE%2FqlTUL%2BljsL3sZEG50Ccl0ocSmbAYULt4cMVe%2Fedd%2Bzll142FB2O7YC%2FZxp8c5jMjuxgr22bq2t2%2F%2Fan9vntz2zj4ap1dts27o9sMhizSVV7VBGiHRlKDeqhaPpqZhGamKPS9ER9A7%2FA6UuWrI4w0MMjrM%2BQ1DI%2FszH4eJI539A%2BfOMonzvtnu2tb0tBv%2FD5JdtZe9FeeP1lO3%2Fjss2dXbTWqTk5laKbwAT01KnTdur0kl24eFH7bj%2B%2Fd08r33zfnIO7vrGhszqxTMBRFEffoHSyui20Em1dMQucy7vMuFH%2FtQ%2FVVw7hB1bbvH93Za48T7lKKx%2Bj%2FC99B8bEvv44Zl%2FmZKRVy%2B5gz3ZRNHdXbGtvxdr9bRtZzzLrWzZB0WQfJ%2F2od48cexI%2FekWxDpDrsbLp%2FKM6MVmSeJ10k2Zg43jqreFt5MlCHSO%2BAieKiYLTXZhofKvW%2B1Ci4vVx0nhicAcfTTSpobyzAzsmSPlkB6MD67e7tt%2FdtYXmtu3N79rZxYu2vHjBTi%2BctYWZJZttLtpMfUF9iB%2FPg7NCxq4qLtXnAtmThxMKPPcUOFE2n3sW%2BHYQgA67GHDrda0gsD9KP1ai2B%2BXBoYY754E5uVQy3BYCmZ6k6BWHTy0W0bCgoZ5rUTi%2FAdls%2B%2BK5qhrNvIVzXF%2Fw7L%2Btk1GezbJOlbLB9a0LPlZRVgYa4Yep0A1LdtI9fLZZJSH0NZicP4aiuaXotU0UYqsBSUeEU%2FCw22jPJHRpQn3uish0o2smN%2BXM4tJ38aTpuV5y7Ixjk56uvLxwCwbWnM2s3oLIHgiSsJ12ruJQOFyaSiYrkiqTStI%2Bfqmr04GzzGzPxqOhLwrG%2B4d1IUU%2BBLFstwnxcoVZpKhXLKaubGxLsVzZmbW3vje9ySMvsARJufP2yIOS9jrp8UqXxXFrBiFaTgeWX88sqxutnvQtntrn9vHd2%2Fb7fuf2cPNh7bb2bHesG%2BsfaKI5I3McnhFJEjCn8vfrmiKxvpTUdKKJpx6CAU1ZCVyec6pZN%2F4i1bjqpjAPzR3QlR%2BcxBq84mUb5wnNesz%2BrK2O9t2MDiw7b1tW11fsZeuv2Sdl16zV66%2BYOfOnLNmvWV4Vv7o1kf29m%2Ffts%2FufGbdbkemmKfYx7d81paXz%2BhCmeD4k1%2F84hdSPnQWo1ZvYBVXGiCO%2Bq1azVqtpvaBss%2BZ8zU59gRlk2dWyra3t%2BUx2D3cjmS9cevj2%2FanP%2F7Zrl6%2BZrPfb9np%2BUWZeNazie2tbdq9Tz%2BzTz78yO59%2FIntbzJ5NdJqZ21s1mA%2FqvaicYxDIpJaK80%2BQK%2BkbMYnWOlSptp1SqebinlSLwmDKTwfF3aVM9P3LWMJwr0fEN%2BKoT2erhn%2ByIYDaw9GNuz2rb29bxtrG%2FbC91%2Bx62%2B8bOeuXrT5pQXOD7K6PJTiUAil85SdWlzUFg5WndnSwbW6tmp37t61e%2Ffv6%2F3FF1%2BUwsmqp5w8aT%2Bvr%2B6FlQTKL%2FyBQqp5CMaYdB4v82FZNrZR7g52MO1MLJ4IU36Nrtb5X1YlWXVEweQ8XVY0B1nP9rvbtr67YhvbK1rR7I%2F3bVzrWV7rW1Yb2NgGltVGPq6oTwyuONwO9KVO82IMOi5pNGlkP%2FROS6CcOs%2FFbJgnPg5cWdsA%2BITuQsD5RH0%2B34wKY5tKjAV1OekbjYfax4qztXZ71%2FZP7diF5at24cwVqy9gAePHdYH%2FRKvarrCG5c7h2jG2VMNo%2B5PfCQWeRwqcKJvPY6t%2FC%2BscAw2dMftiOANteXnZV4M0c4xwx0COzsm5WE%2BmEmXXL2lWYz0DkQtvlEEKV1FcEGDAZ%2FUR07iR1Ri8JwObTFjN7NpkuGf5YNfy%2Fo6N%2B1syo63nXWvYwDAyZcVNR0nLtHSs%2FVnMUmuND2nER0HdgyaSUvSSQkqknwwRpiWcrwTTqXQoq2%2F%2FmQp09ZIgcnh9UPGzNNWufZZ4AJyMLEeYYtU4H1kt7WXFjK7eyq3WnPgpKQz4ISlL8QQmzME1TSgppBr8SePtjUDKWZnse5QyMzNjzWbJXMgGNAtCI6tRKJkoDQif7LvDkQywUCquX78hD5bXrl2zSzi2Wlz0o2FQTFJttXKP6W4SPn3KIbPNvV27s3LPbt65ZbfufmIPNlesjdk1K98cus6%2FGkKmlo%2BlAMM1VdkFMoiqIivEn67%2FVENUXoJ80SqVqL%2FRoypQ8EcgAQ2i3VQz5D5MXmVWjsDOnr7cuv2RDUd96%2Fba2u%2Fa6ezbeDi0116Y2NKpJRv0%2B%2FbBzQ%2Ft3ffelXOUq1ev2ML8gnF%2F4%2FXX7ZVXXtYkAf3P1atXtTJNn0TfFM5hAifu8JW8xdYaxvwY76yIcp4m%2BX%2Fyk5%2FY7u6uVsDv3Llrd%2B58Zmtr63LmAzveuvmxvXPpqt24eMUuvLhsk97QNlbW7faHH9snNz%2Bylbv3rL25Y3l%2FaCzuS8nEiBhlU1wLk6YLwogJvO21mlNB1kM9IKjMW3Q7laRP6TEQ%2FHLgYxow1erIRIqgSonwKQnqxnfLIvF4NLHhfs%2B2%2B67g73Xatt%2Fp2Mv91%2B3qi9dt8expTRRga8KqN%2FoERxaxR3N2dk7j0JWrV7QH%2B%2F7nn9uDhw%2Ft7t27%2BvYvXbqsPZ03bvjEEhMS7izHy9fKZRq%2F6EPo83R2rpSwNMGaPN0%2B%2BnOlNvQUueX0ATK6Z2KuL7NYHP%2FsdbdtbWfFVrYe2G5ny0bZgU2aI6s1Rzaa9LSqmddGyk%2B%2F4PRM3CBGiHYR5bxx5NVWkV%2BusVJqaluMo65pK4aSjoOqkhNKf73A4yD8tVwomU5zaOBUoF8VpqIvaPL95qPMBv0D9SPjjDHenfZNFsxmGmbyTcUnx8it%2FiedGV1BAXkFWP5jkqEcVwh77KpWYJ48nlDgu0qBE2Xzu9pyzxzePsNID8yxEHhy5BiBudk5P7OLQUBmazFUPZmuWlBCoyi6f4YQYkrVyKUxxF0GJjebrdXwNItTnwPLxx0pmlkfoZBr1yajfatnrmg2aiim5A3FkoHI9w%2F60OumPjEKa4iKcUq4xMyw4%2BaC95Nggq9PT6fUUQlCtE0oFs9FnaCFv7iQhQKP8MzmIYl9cgbEiiIK1kjS8MQa2VhXcza3Bm1Rn8Oey49IKdoPrSv565Um5eVIWEvuPVlp4EL54%2B5nHdZkGomA6IoFHkvd%2FJEjRthnh2dRLhRO0mEei8CJsMlKGCaTmNaxkglcfpTul7eaY5P2OFkuD7O379629z%2B9aZ89uGtrOxvWGXZtzISGn%2FojPN1hR%2BITETQgO5HFsxJigzuILyifWuLQ7a9EH0r9LXiFS7xWTDpZvQkh0x40FrzrZk0OHBrZfn%2FfBut4eR7qmJDxaGwvXL1hrXrLOgcd1EHLqwAAIABJREFUmcr%2B6Ed%2FZ1cuXbHLly5pooDzSVEQ8RAbE1%2F0Q%2FBorFIRHkJk3DOZcZarWCgcTECw4vXqa6%2FpOBIUTo7Z%2BPz%2B57a%2Btm7bWzu2ub5pvU7Xunsdrb7VxrltPFixD%2F74jt364CPbXFmzfrsjk9km%2B%2BOYRsHRiQRcplRcgC7aWcIyzeQNW9AqmC61YDEx8Y23aGD0ZQr23rjMkfpn1YkKl3WFPq44exi9DF%2FfeMw%2BybF1xx3rjYfWHXD0R9%2ByUWY3XnvRFs8tWWOmof2ftC%2F0Yw8j5tSNxpItLMyrPS9fvWrXVlYMD9NYNuAEamtrSxNPOABjool2d2uGlisuqc8Bk9grTodAMTjzckvWRBdHu6yqsHeFyE1nM5vUWNFE0exab7wvs9n1nRVb3X5o2%2B0NG7KVo5lbrTHWSiZKaVYbarKqWKlUCRTmR7p4gVUm4dnfj0FpCr8vfknjViVRtZRKsM%2BXVAOOfY7cJX7HJjsSmGrBTSCqfST8xDtWIyM2xujzwdx4MpzYZD%2FXdgcmJcfLI1tazGxhFvoGLiQnD%2B8%2BOwm06BtKVDweFL4eTUuIJ08nFPiuUOBE2fyutNQzjCddsLptRt%2BJ2dzsrJwwaIa46X5oo%2BN2OeDJdtWCprKFRVI0neA%2BCLmA6zOgrE5yrElfl026Nsn2LR%2FuGoqmrt6u2ahjjbxnzfrIGpjLxuplmqF2RbNUuMrmTSUmASrCpwazNC%2FtcY5zpPtyd2pO%2Frh%2FudyRWvQ7tIqpsEhw7D3wdulYgpdW7xB%2BPA7BbMwsM%2F%2FGmQ37I5kqN7OBzXF2aZ39TktmtXmzCd5qw0sgZoVaP9Zh7uyP9P1SEgHcIUYOhlwczo7i6Uda%2BOq5z2IjXLCSiZLJcRWYQrKi2el07NSpRfve975nb775plbBUE64OHtOSmxFwJT8EcIHRTZYx85tlI1tr7Nvn977zN7%2F%2BD37%2BN4ntrm%2FbQNWcnHSW2MnLxMSLjIH7%2Fs9CUsyo0zCNzWSbEch0a48fxd%2Fgf9R3KmR%2BEWTBE03l9Q5jL6nl36Db5VjZDB5Xt1alZdkjh7p93r24tUX7PqNa%2Fbf%2F%2Ff%2FZi9df8Feffk1u3zxkhQKVp3gBwmW47FWoQQv9n2J%2BG46G30Sdy6U0ZhgAGvywRMgy6TJ6aUzduXKNfvhD96y3kHf9nf3beX%2BA10LM7M2U2vaxoNVu%2FnOX%2By9P%2FxZ%2BzOzwRi9ge3cuuAJOXKJXio%2BowqZStXMn%2BCJ4Igi2aPJWyR5Og9qva8BOhD3PrkqtlPbqCsrWJhwosixQxwlizaqZbn1231bHT3UMTfjkR%2Bl8mLjVVc4OeeWNqY91eZ1WTrUmw1rcu7z6VN28fIle%2B2119QXfPLJbZ3VyWo1yicTTiicTFhgXstERfQH8FWtxt50vl0m0bDU8b6GdlWNonoFhfj240LR9AORxvmB9YY7ttNZt42dh7a%2Bg8n9po3yA6u3zCaNXIpmlg%2BlQKn%2Bh1cqxTvA9jOBvcgqp1Q4SWkLpP5GD4eRqOL6aJSOkDQlDWj6pDVn4WON3C7Vx1Zvct7twPLRno33OeuVI4XYM4%2FVzdgW53KbbXjfi72STwV5v1ztG1KXofGG0b2k6qNxPok5ocCzRoETZfNZa9HvSH3o6KOzd5R9NpGOucGme0yPSJM892lGn25azhSeZCUdC4lALmM4YsXUP0ODfP7J1JVZZZuko02sa5a3LR%2Fv2Hiwqf2ZmNByzEkt61m9hpI50QUMCQ1SHNwkyoWIqIswQCzS2YDVUISfAj%2BoBgwCDlEw8jz%2BnboDaLolHj9%2FmVLolK%2FHPB1Ocbjc3I9RgV54uZVVEiudmm%2B2bDLW%2BYHs38zzkdXr7kGxBdtoPgIaYcNIjYDt5WkVikPhJ5mUCBQ3zGGHw25SBliF5CgVMZvFuaIolCiZKJh4I%2BXq9%2FsSIn%2F84x9L0USwZOWK1Q9f7QowfrZoYUHlwd62NdTMTPs0272O3br3if3u3d%2FZh3c%2Fso39LevnQ5vg4bdetyzxPot1KC5SWjAn5qd6Rrsdpm0q8Jm9pfqybw9eUafRkGKOKD7OK05Xambt4diGG0MbDgeadFhcnLc3%2F%2B5N%2B8mPf2xL86flzXZuZlZw3NTRjL23LjD6HjsUBoqptqmvgNEsvtLJnYtJEtJz0W46vYRF%2BHrN5uZatjh%2FymrLZuPzl2Q6O3rzLR1tMuz07OY779kHf3rPth6u2bDdM%2Fxf4v2S7iMbYVEBoKa1mo3CRFFckPZmBt970wd%2FTDPCoXmsSuTT5iPgP50y%2BOZ9jqq8q1vTsIIagOI50VEyzVrNRv2xbT5Y015tnHTpSJPZOWud4mNj%2Fx6cxDFCNWtwVAreqrUK2ZAXaSaVMJO%2Fdv2a9vXevnXLOK8VD8Qcm4KlA06EsNDRdpCZGZnqBv8Av91pywMyproopZz7GGaeTiXaL2YaXNGc1IYynx3kXdvpbtjq1l3b3Hto%2BwdbNpx0zVq5VvazfKTjTbJaZo0ZLABYmfeJzOlWqLZH0G66mZyuFTb5VjyCN%2FSp4n8UseO%2FgEo6zW%2B77OHgJpZNMhvnE5lgt7CSyId2MN6zSRclc%2BhO%2FWqcLY1hDbKKW9bITJatHEcKdQUT6v81fCuYnTyeUOCZosCJsvlMNee3vzJH%2BuHqWJHGD2aUERjxFNeQhJe8T9K7V9N%2F7eoGNnFPk9ppN4eDx%2FNfCq%2F5Xk32abK6aZyVOdqXkpkN2J%2B5bbVx25qTnjVqQ2uwmimvo1IhJalqHweAKyO4lCMJsiihUUG%2Fa5hill5KqI9VmkGVwvntGbyOCrAlTd3MjZrIyK3SaqTh0u5D3TnPUx5%2BM0yacL2fBD0b2sRGNuJQ92Fuw8L6a2KN5sRqDQR9lL5Z8Qj0kpKOqRqu%2BlFMJrkd9A7s7h2cfDzQPr033njTLly4aLOzM77akOfWbu%2Fb%2B%2B9%2FYL%2F%2F%2Fe9lHofSgOD4gx%2F8QPdLly5VHIJEPVEwfHJkmkmTsoIZpvh6bIPJyPYGbbv14FP7zXtv27uf%2FMV2DnZswJEEjYll8EJe04RLo%2BkmvnwGGeaiOD7RWZrE%2BweDUsQ%2Ff0t8QwbRNvCrkP3Qo%2Bc4FPiteD0O98AWBY89drlNdCwPHjR9xRg6GyvfmGXXaxK2R%2FnQtnob9vH93OYWWrZ05pRdvvG6LXCea84Kci7PkrQ1v1Acoa0rkHWtXKIkxDv3%2BMFj%2FEKZYBULPsC81vFB8XQTWLFmNtFK5szpZctbI9v%2BfNVuv%2F%2BRvfvbP9nG5w8t741sdtLyo4dyVjObUlY4uoc6syre5Lgh4auZB18zmZqESHKvBOrAtLwfpS51iKtM92Sfjpb69eFHO%2Fg0U9mHOmRfNcRb9lBbF7B%2FIM2wP7b2%2Brbdu%2FmJzbVmpdfdeP1lmzmzYPWZplZDdcwH3x5OxMZjmfQDr9Fq2GJrweYX52zpzJJdvHTRvv%2BDH9jqyoompj7%2B%2BGP73e9%2BJ7N69uwyQcU%2BXlY1mYBYXVuzf%2F23%2F9t2d3fkgOpHP%2Fp7s1P%2Bzc%2B2XDEFIVbQaurr8Vc9smHes%2B5o3%2FZ627bRXrW1%2FYe231%2B3sR2YtcZpRZ%2FJNR1Clc4idb50ysOXWsarrGiiZEK7SttEEnqWIO%2FXb6gnDOGvI3Zciqopsdc4qYHagpA%2BgTptzreeJvrqNevlQxsfHMgkuT7D8Tpz1uRIpUlTsgqTGHynvlJMVX2imXt4IqaDYDr18P7NJ0yYE3AnFPjWUeBE2fzWNckzjtCh3p%2FOPoY4F5rNBsOh7ezu2MLcvJ3GyUq9Uaz2sW9TU45PjExRugP01QxJm2lMdk2TVJg94TkWQdYyzGu6lvX3bNzbtXywZ7VR2xpZ15o2tCbCrpwKSO3RKonqmqRRhnYJtGVRiQ6kCiJxd8EoYeerGYr2uJJ6T4wgTwSQU9X%2FenWkTbsCKOkF%2FEWRdHd6SCvMUerdEVS9zjE4de3lxCkTAljGkRejhg17iI0tq83NWsPmzerusVX0qygClMOKFSsJH374ob399m%2Ft5s2P7NTikv2P%2F2Ng%2F9s%2F%2FZMOi0dQ%2FPijm4agyJ5MFA%2Bcxbz00sv2%2BuuvyzyOlUycgNB2Ba9QA7VrqoPeg4yuFEEDqj2asJewbQ%2B3V%2Bzd2%2B%2FZh%2Fc%2FtnbWsXEDzy%2FU2emEUiEhU2eSooz7r9XAqy0J057fREO4RDSTcOipE%2FUDkWfk7rV04TgpnBx3oXr7Rkb2wdHmKOVjVqgkMXK0zMTW99ftTx%2F8SXvBTy8s2bXz12yhNa%2BD2jUdktiy2rbThDtKVcA7P5DS4%2BE3YNBdAVew1Yo1a7D3EqUQYweObtk7sI37K3b35ie29fma5d2RzVhD%2FR6cH5M1goFjKWrL0S8FYhWcEv5FVIFRNeS45xLacbFPJqyC55MBWEIpNKLKKlWycfC9%2Fjh2QXmv22iSWQ0Fvt6y0SCzjfurMsVmpZIVxgvNq34WJ%2BbUGV5fMUnl%2B0obZTXx4%2Fu6nU8mUjjPnztnV65clln9xYuXtLcb09o%2F%2F%2FnPWu3Eey2m95jY%2FumPf7R%2F%2B9d%2FtY2tDZ3rubvbtp%2F85Kcyw63NUgfnXz9Jk%2F4QZ2kDG4w4nmPb1vdWbHt%2F3bqjPRtODixv9NUn8CXwLcBgnJCMtuQ8CKmSopn40FXzUDSDlNU28j4leDpSfJfvUaOyDsH3rnDCRhqXdZYok954KUeJ9wnwAef89szmO4u2sHDG5mZPW3OW%2FmPGsonLKXKUnngP6LGFw8f1aAPoHGWX2Jw8nVDgWaXAibL5rLbsd6xeDNq6aqYjJO7fu29nl5eteeWKNRdP%2Bb46OudSZ3niNXTBIa1OIAyquFD2GBxcbLR8bJhzjvtdGx%2B0LR90rTbsWYPjOSYjXayVuPltqYgof1KCXNH0VROJMdUx%2FtiaxcBUTXhc2LGZ%2F4aBTjcazt3gxx2UAn%2FuEJu9lml%2FIgKTliN1hoEEAJnXIjDh8CLrWjaYsVFtwRr1JavXzshLrQQjFD8uzqFUGXXrdLparfzlL39pv%2FnNb%2Bz%2B%2Fc9t%2BQwOXM5oBZEzENdWV2xzc0N7udhvxWrmK6%2B8IuFwaWlpyulPCGC0Y%2Fwqj%2BKdqB%2FiH0Lr0DgLb2QbO5v2wa0P7eM7t2yv17as4cqw9lWlLavSOVm1kyLlSiz7SgEMR0KlKifwDCYeFiJViVvg%2BKzdg%2F4IdAjZmhDKMD10SmjBkT2yHIOBo6lsYtt7O3bz9kd2%2BewVm28tWOvsjI68kBioFZ6SSqxYRrtSlswpdQ%2Bh0YVTZzm%2BZ%2FI63QkTfpqYQOif6ExM4gPv4cHA1u49sM9u3rLNByuW94Y2k9esVWtIKXUR2BtWnwMqQx27cQxDYy9f4Mu5mmX5Efr83Kv87s%2FauykTY1YUfUVJZ9wmOtLn93tD217dtE8%2B%2BMjOnF22%2BVOLtjRz3moz9Di%2B35O%2BhEkM2lffJPvARWvvw6ExEwxMRKFUYi3xxhtv6FxOvFajdH700Ue2trYqp2K%2F%2BtV%2F2gcffqDjb7rdA%2Bv3hzo255%2F%2B6Z9s5tpVmWayaM12EiY48UA7zgfWGx7YXmfHNrbXbLezrZVOd2qDx9SYdFHl1Owy4U4jFwGMYPE37gWPTfUowTX%2BHcXbs3unnum79akrp1MtWZqk1WUYYJC1bbe7afO7yzbXOmOzzVPWqDiqw4JHSivEEpMA2%2BkoWgdJq%2Bz67BL2pGYnFBAFTpTNE0b4FlEAhdOsd3AgL38IZBfOnTdbdKGNd7%2BeBso%2BIFB%2BMegUCqcrjCHcafBH2RwcWDbomknRHFljkhnrTpwa6WkRRFwo8UEeMymeXGOmLqWi%2BUUjT4xOT6Pe3wTMEn8ctyAAOo2jzgjujMcQHIGOnWooDD4rz1loeOBEncDZkuVDM86Mm%2FRsPGzbqNG2ZhMPjOyn5UgaP9OyVmsYgmW707Fbt27br371K%2Fv1f%2F3aPrx509rtjpy0vPvuO9qLOTM7I1NavJK%2B%2FNJL2mt14fx5Q8nEu6z2TB4iFYJnKCKBfggVvNO%2B%2FFB0MHsc5EPbO2jbnYf37IPbN211c00rnSPOytNROtiFoow7XHjFdW%2FgIHTiLMjNcTVbHuRTKVMlFzycop7JG1wlEoheTgztt8owOUS5qBkrwTKNhW1gLxyO5XVb29ywm598ZOfPXrS52XlbXjwjEzjnxLKfcXM3hy1zbM5jTP3QNFGDx0M5rUm5AUNWVoEwGac03DDrHo6tvbVtd299avc%2B%2FtQOtvetmU2sZXU5BTKUZvVBHPXkvYomxNi2yZkeMEoUO43Mc%2FUGbeOqVtypntRyJjOZvEnqFqp6La%2FZjDW15xtHQaso%2FRdu27mLF2x2ccHmlhas3mq4kqoFZvXWPmnmNvPqyxp%2B3o3JGqFm2v%2B5sLCovoNzdtm%2Fyd5vnAh9%2Btln9pu337b33%2FuLbaxvql8YP3hoefZ7mXHPzs1arf5Tu3z5os3PY0HBBEomk87huG%2Ftgz3b3t%2By3faOdYcdy%2BoDy%2BrEo2hm6jhgCRRPaq5JKTlLglXEhRUSKaUT77nlo6g4tPEf44wmhpLOLi%2FArIZjTdBgCnlg3f6ube2t2mxzyeZnlqxZn7eWxi3GHqd9QPM73Hgcl6ZCT24nFHjGKXCibD7jDfydqR4CI%2F8mE%2B2N6Q8GOlqiwN%2B1wEKAL8Kf0APgY2WzKsF5mK8gyCwWM9rx0CbDnlY08%2BGBVjRd0WR497HbYbhw4hqJr3rImQk4M%2BOpcS4GuaODnlctwp9QRf9mYKIecY96c9dmR78rGE5wsV8rU8qCsplWGgwT5aHVakPLWeEcti1rta3RPGM1w6TJVwA5M69z0LWPP%2FrIWNH89a9%2FY7dv37bdnR15G93b27dPP%2F3UEAx%2F8Yufy9HHiy%2B%2BoDMyzywtFZ5lq8pFySNHCVlVPKtcQFvj%2FHaQ4xl1w27d%2FcwebqxZd9S3UW1sQ5RnFEvNgrv5pZQMKRpJSImVf9HF91E5BYOOVXyOC6vGf%2FefYQnIJZPBWH0iLO3RlZCd9DEcLcFNKJ0obdloYt3BgX2%2BtmKf3PvETp06bTPsk5tlVqvpDofoi0LpLxrWHf%2FEJIJ3Sc7PERZJg2cmaaVUK9UonVrddPPZ%2Fn7bVu7dt4d37krprA3GNoNDoJyzNFP%2FEJ8LC%2FUVYVULLcV7JPrut%2BuXq4HzebX2hzmfr4deWOvAMnbAvJTjRsQ84gn22dXyzHDQtHLnvt29fMkWzyzZpblr1mzN6FOWApLMtdXG8FLwldrVv3javVFvak8exx%2FhjZjjkdivibUExf7pj3%2By1dU1GwyGUmoOJn178OCh%2Febt31iz1bB6fWI%2F%2FzlntF6yeoM1zaE8y3b6bdvaXbftvU07GHZsLGc1UjGlAE%2FkgdspCN9BF7%2BgCpTwn7oZKUS8J%2BpFZEqTUk69Pbsvx3CQSEYHDPf42aa1WqbVbc6A5uzSTlI4F%2BeWbbZ12hblidz3b0Z%2FANE1vay9mt4OdCxF%2FLNL1JOanVBgigInyuYUOU5e%2FhYUUFcvYdoVPt7pjBHs3T18bjneAJ8qcjHgcI%2BLAnlmpRLhL3cnE6OeTYZdXTbqWX3izoBYbPAhPQ0qYCyJNQTFQxUgGvCk0WB0KP7IK4n5xT29fidugTP3eK62aPLiJ0mOcF%2FVcYqiehIW604M%2F6xg9syyWctHbRsN9q3BCufsvFmjZbV6wwaDkd3%2F%2FJ7913%2F9yv79339ptz%2F5xLZ3drQnGJINhgPb29szTGjxGvnjH%2F%2FIcP7TajbleOU4geC4sCC%2FK6JlnRBTmCGXeWct19l%2BKDhc7WHPsrrZMM%2B0H8xXKhNtOE%2BW2vInKSvFIpZLiomGj6JlYPSM3xOpUdJ9zWqiPa%2F1pJBLUMSjL98t%2ByRrdR2lg5clTqbZae%2Fa3Yf37cKFS7Z8esnmW7PWwotPUjS5%2B%2BV0pO2n298tMYLKYt1H5IXl1abEY9I7HNn%2Bzq6tP1ix7fUNG%2FeHUjA5S5OeTs2cPhMptXQ%2FFXQUVvQ38T0FJs%2FTPTGBqHtcz1KaNut7soasT2SyTp%2Br5W7Mlms2GWbW3ty1h3fu24Wrl23p%2FBk7tdD0iS%2BRuKKwoUIEP9AYKJkNtVw6SzMmK%2Fz4GxRPzuXlHF5WHfGITdH0aVg%2BcCzPvbv37D%2FlkGpizVbNZud%2BbqeW5uT4J7ORdfr7ttPest6obZkU0Nyw%2BmDlXBNx2mdY0iD4FwqJX46wRfBN3KsJgq7VsGf5GRqIUj46Scn042mMo8tYNa7Tj0DvseX50AZZ19q9Hdve37Cl0xdttrVoTWulSVFoBbzgGX%2BOsGeZkid1O6HAcRQ4UTaPo8pJ2DdKAXXxDNx08xOTsM%2FKErPCIdzpbLlkNUb6p%2FtD2EdV4OfPOroEjx4cTTHGC%2B2B7iiaTct0REfg73aQvvkuhhqHppom1FMtksLJfsZU4F%2Bp2nGCwV%2FJ8o1FR8t8GRwjD%2FdoYJ59jVgrnEnKjlVh5wUE%2FZFlec8mta5leAUeonAuyoz2oHtgdx%2Bs2q%2F%2B69f2y3%2F%2Ff%2B2jjz%2By9v6%2BFEtWuNj3xr3fH8hkm%2FMzWWmQ85%2BvSK%2FgVbK74il1Uy47huORbe9t28ONVdva37V%2BNkJcdMcj2pyltTjxAKwgBzKiSHCOm9eWqEV4GfJ8PR3mMd5dSZcSMEUM3yeMcI%2BjF7UTyv%2BwZ%2Bs7m%2FZwY8UuoXAuLtl8w4VFvttqe06BK15coShe9RD8PB3Kt42yI%2BvLPLeDTtc2VtdsfXXVuvv7NhmNtKKJIoqiKQdIUiL8u4A71D8ozOta7TD4RIp5iENFP7uv6nELcT5IpPpCtqRhqQ%2F2mQD161plVnTKDznxZDypWdYb2N7Gls44vfziNZs7c8obTd6ufVTwFvEJUW%2Ft9FdjWHIIVqwc%2BlwiiiZOx%2B7du2e7u3sKpA9inyftKsdgtZqOW%2FrjH%2F5gs3OIZmP78U%2FfstPnZ62X7dteZ0uracOsbzmO0%2BhZ8HJNrWo6TdR1GRGASvno409VLgj%2BqVKMsPh5feLt%2Bbl7n%2BrzFm7N5A6afCqLD0zHM%2BOPgWPNJkMbjA%2Bs3du1%2Fe6OLcwu2Ux91iY1jtKq0rNKweCeatjJ8wkFnn0KnCibz34bfydq6AIBCkauPS8cjK2zz2ZmrcmMcfIOh9t%2FncHpi1xPsW4M4Qzi5aDD4D%2FB%2Ffmg606Bsr41JkOdp1ljLyG2bdUpZI5q4ec2b2kAciWqmOGUIkWi4wb4Rw1YDvbb%2BZd6PArv6kBLmsNp07skZxRP3qEXJmso7zyxWohgjYKPsMUsc9%2FyUcey5r7lrSUbDHL79O66%2Fddv%2F2j%2Fz7%2F%2Ff%2Fb%2B%2B3%2Bxne0tG6c9cDOtls7WxESO%2FXoohnv7%2BzoW5YnRFNRTm7Kbqjfs2ermuj1YW7X9XscG2dhGdVbsXdDU4kgqHL4ju5QOf5LoCsUeRdknhvd3ARCK1dTkjFNGJIc3grO0V83f2L%2BLMsHFcSGsCA2yge10dm1lc9Vu7N2wFy5etXx20c2ZA1hBDwUUb%2BXDo8JTCqIrOIF2Nh5be3fXVh88tK31DRsc9LWf0Fexvc8INcqhVMrQtxGlOzdooiqCEs8Vr8%2Fsg1PIpxeiwauVTUQv%2BtekSKQkQVG%2BMZI0E68Mh5ntb%2B%2Fa%2BsNV293aseUrF21mjtVN%2F%2FmXCd39iVDiIj4lO3LL88xXM%2FPcLl%2B%2BrFXOwWhow9HIhsOxjcdYauSW52NbWV21t3%2FzG6s3Mps%2F3bDvzb1snfGO7bW3rD9s2zDj%2BI2R5fQfKJuagGBV1b%2BDw71EidvheOefw%2BmPIP9cBVRpFM9OIfEaxMQCu46qn9lowv7Nfdve27ClhbO2OHvKrDbrHsPFez5pRd6yHZ4rgp5U9oQCosCJsnnCCN8aCiCIoUjOL8zLBTymR%2B4wwQUwd2Gfevun2nXH2WIMNiibnFGAV9SR5eOeZYOOTUZda%2BQDa9rYGpNkZsNRJ4ViGUOLJONDNEaRCqXzUFRRrxAEDsd%2F298fhTf0iCvqEGm5c2n9piK5kR4D2kQrDd4o9G7W3GwgQOY2ygc2GR%2FYeNSxxqhj%2FeHQVlfu2q1bH9j6xorNzc3Y5cvsf8LZR8v357VaNjs7b6eXlu3GjRfshRsv6NzNaLXA8KveES3cZYefidjudaVsbmxvWG84MD8Fz81sfe8XCjXmkzhQ8tUtnCKBj47uSHwRIvOTwvOr1u%2FbkE%2BLVVPm54mfNBnhFIKC8iCrYwnSd60lRrPRODPaZWNny7Z2t%2ByAfdjiQ7jRYX2RiIjC6yvYX4IarK6ibO7t2%2Framu3s7EoJaWSs1Hs%2FB7RUkyOAj2t3d7h1JOkzHBBqld%2BjonQPBX2CgARUJwCVmMhIQB7%2F3jjTmb2b%2Fc6BbW9sSdkc9QfWWmS1igMX0yRHAUPAo%2FgvvMODy8vL2hc%2BMzNja%2Bvrckw2GI7kwGx%2Fb9%2B63Y71%2B13r9buyutja3rKHK5%2FblZeX7SDbtW5%2FT8rNKOvbuDHUpIjXJGrNuALzp340WeU4YlFnODueiQlOhw7AqVqXfGGVnqHIoJ%2FzgngjnffsfJImLtI4lGvKk%2F4dE%2F2x9YZd2%2B9s28GgnfbRcjwaK80%2Bdmnfduqn1Gc9Q5Q7qcoJBR6XAifK5uNS6qmnKwe%2F6aLKjnA6%2FNl8Q4Cbm5m1VqulwY%2BDkn0A9UPstaLxtXrsR9G5pKen8AHZvcpyviOeToc2yQ4sH3etlvesMelb0wbWqA2tZiM5EnCFKeWN5SrVIeCnAT0G9ggu7sRXcTz8HPxQDS8yJ4XuUXHVdI96Ply%2BpwuIUfrxuUl1XArCDl1aUgCKNIOkpKdnASc98MqSQxhCuJaDj8lEij6OMti%2FOcm6ludtq9dP2fxC3S5ePGNvvfWmvVVvWaMJT3HN2Exr1pqtls3MzOnokyuXL%2BuYkwsXzh9fra8QCtaswI7yzHqjoe122raxs637KB%2FbJDkEQmDBdFImwqo%2BdfNzGEP1KE0q02IvNAn55yvg9l3LcpSjUBqZdDiOR3x6QpwjGqVV8cSXBUdFCyyVAAAgAElEQVSxRZjVTXkI3rPNvS3bP2jbaHlsLRy88C%2F1M%2BRxteYoJpHGaUrKQ79KkMxcs4n2Z3b227aztWOddscsyySWyoZCCpML%2FGXtHINDkFONAqdKQYcT%2FtX3gBEJvbwoP0K%2F2fthnLwHATO%2FpCIWKEXtHfND3aBAVVMAI5Ssarha3bJRZt39tu1v7Vh%2Fv2PzeKVt4LU2fIyDy5ejDhOn7AdnawjHKe3s7GhSbDzOjKNPdnd3bL%2B9Z%2F1%2BTwpnPhnameV5W1o6ZeNxX6tnvWHHchsaR51MOPtRlAjFMnWlRc2Sn4FEraAaBKuq6F576uKXeDRxVjVtUKkg%2BGM8iOwp3fH5qykC4PEpiY3UxWq2sjw6fZkjYH%2FRvYTjQ1OUQjglx%2BSwTFHUt2PIXJuMrZb1rDdo6wzUcdazvDmvlc20%2BzrhHfm%2FCIeTuBMKPLsUOFE2vxVtGx1d3AMpOrno7CLs6dyrM%2FTTAtTTKe8wVGopHOQggbUsdwmDviaB3MwaNfbafbkhZLqcoG%2Fcp2P9zYdil2MZsFm1HFltgqkbToH2rZZ1rJZ3rWk9a9T6VreBDn4GUzkjoQ4MMWkPD03oAyV%2FESTTfap4TxEpPUpUSTxACICq0%2FcprIBThXu4joffyRRlBoDj8k%2Fn4%2B1wLoeUZsTBUgk8VbnqwnsMuE4DViUL5bzG0B3OPCiFtImOQS%2BhUhMfEINp2iQf6ziU2mRgtcmB1SZdO7V4yt588wWbXzpt7d7EZufP2PzCGa1ktpoz1mq2jDMr2bPZaDSlgM7OYlI7q7pN1zho82XvKEQT44S8g2Hfdjr7ttvZt%2F6II1t8%2FQyKxLyJ6i7lGU%2BkXnv2bUJtVlV45PKcKKdfvEevWgdviaP4u8DscD22msu%2Fx2%2B6L6hiUMWb54iDVvQViodN%2BNoUGUqaKyIKwjwyQznP5SCI1PGN1pt1w1Pt%2FuDANju7ttnes%2Fawb63mrNNXRIlSoRbPVaycakf%2FVtLF5%2BooWD4cG%2FuJ93b3dMYizqlm6Cc4TzFPx9poLZ%2Fy%2FB%2FwXbGIkkSBI7g4fpHmUXfHzb9RAJdleA6Pj7pW6U48sYd%2FVYocTh9pq%2Fmq6SN%2B%2Bh4p4l7yehGiD6fSzhUAXgO%2BLXiEY5MIiYuEVcsVfXlFvRh1alluo27P2hvb1t3eszMXzlprpikT7KIdUruCT1wVFI480tdwhBKrmktnztjV69fFwxrfcGKVZTbORjKj1dFaEzxUD63W6ls327aDvY71R10b1wZWb6n3M8OHQJULklMb7TMstn9Evbkn7tV45LSjpwEa%2F%2FRFFQQmrefxv8r%2B2H8cjCA63CM5o6C4k%2BDRJZWp4gnsHp2%2B%2FE4j%2FREEFOCxR%2BF4OI2MJOLjFiuU0AvphHajfExpmewcjLs2GO7baIxn9FnLG6iac2bWVLXcKosij9vnfTxuJ6EnFHiWKHCibH5rWvNoh%2Bed7xd3lk8K%2FRAqEeIkyIUU%2FKQK%2BGtwGHDxEkm6Wk17Wdhb1dIB5siKE18NQjj6WiQ5js4lch6bhlnK0T7MkVnet8moY%2FmYlYiu1SehaPZ15qPMbJF40yke1KM2YR9NXYJrWSpAowIqoCxcT5GSe%2BVyabqS9tEwfIgnacAqS5wOLcEFNA%2BJN2ZuUXbKdOVTCVthEuh8UPaZYUIjI%2Ffpi4HaIfA3L%2FfGkkwRrnhytmQJyb09smLI%2FiaSNeoTHRWQ1zI5C8pGbWtOTtnZ5XM2f%2Fply%2BqnrNk6bZPajE0mDZ2l2GSVot5ICkuch6hipIhwtmJg7qFf7S81HOduqrm5s2X73Y5l8HGqkCZXEIZRNpLyBAV1TQmETj150JQAnWiUaHUYV%2BAfDjuuBsKjSBm5PFQopg%2Ft8WEdV8rjh5Ule57AqArB0%2FDXY50E8cybX%2BLbVDdYk1DR2Wo6e1W0xymMmfUzP%2F90r9e23nioCYJwE0RO8lKeC%2BVVbKrPjln5zcV78LPfR8OhddsdmdEOen2b5LmxnxQTb3DCXwztT1leHqX7Fw0GfIsO2bGKN%2FB0KlRxcrzLEM8JHwWd%2FF6m4OlxIE3n8DdhlObDvCQPj%2BcoNe7HwSjxifpNK5qelzinT5l%2BGlqUSSj7c%2Fm%2BRKuEpMeXf31Ch7HPIeItuLOzq9XNiwdXbOb0nGFmy6wGPZLagrSASKiWGE%2Fjwpuy1tLROfWaLSzMa984DoJGGX0XfEBfAFCeR5Zb3%2FqYz%2B5u2nDUs%2F7owLLWwBozTJj4eBllOxJwMzyStn2II7zeJW7Oz%2F7uiqbnJcRbXvgmLhPDxYTJ0WqJDhFcluEh1ffqc6QvCFcGFMRMveShmMT8afLteJiRpdIwEaS7t%2FlUUFFqGRpfvSZj5HvBvVQLZz5C4ZDaCi%2B1tZH20%2FYHbctmT1len7V6zhFcLbMJCifYfl3ZpcTv5OmEAt81Cpwom0%2Bpxb5phe1JlRdK51MiyxeCpYNnuMMt%2FMbWls3PzdnS4imbm5lRR83ArP17nDHylH5AdtGOAmLIweW579ccMeDLhHYgJZOzHs24co1DCLQSFKWkeZiGt0Jjq0oolYEvhKGiXggO5CdNXFFvV%2BqKpHoIWOWdJ8%2FhOJWihNfN4z19mdbfvczIkcqNKL1K4ytlnSlkgm5ejmNBJseDUAnNkEL5AFy5CIR%2Byu4pApLPLguClAeUUZw2GTP%2B9aHVaQs8BDfNFufnbNJYsGzSslGGAskZaC3NVjN5MRqPJOxjsu3ead10sixRyH3lPwhMo%2FHQ9jv7trm1aZ1Om4lyq084gsOVaI7j8D2bFZoFnaeoW9Kn5M8SNeVO%2BRL5yshE3akAvTx%2BTavwCzjiTW%2B5ImwK5zLUn44TIafTPAqjqH3A4R4Cv3MRVKmscPpbYjR3woRlBHwlSwnJiy6wD0dmnW7b9tv7Og6H45YcU4c5jeEXvRUNVyZSEOYZPqEwZo%2Fe3p7t7%2B7aeDj2%2Fgya0W%2Bo3PSMXJ327AqYLD68O1D7xredBO8osIpBScsI9ZDUbAEhshZ3UkeOIjA9EB5w406Unh%2BVqQIv8sf9MHwvGWgOLMqI%2B3T6Mt10eLwBI11FpaNlq%2F1wkSoyWjbOdCzSzva29Q96Np8tyeKA8TF6RWmmgq%2Bvo8h73APHm8jzrJnNch5jw49CGWNCjSbaqFs25vzGzBqNNIFmOA4aWn9woL2Btbr3J9o20MjckVWakvAy4VcsRPwq8IwRLY1BgW1JU57S5WRPypSPXwXpDlXMJy08MGDpHjASpyhsKiKlLtIF4BQOTYtJlUqc0vt3lEBH5KH7EcCVeOKm473UahjP%2Fh0qY%2FhXSPcUm8bnzOoomza2g15H13iRbRIcm6Ieig85lR%2F3CjonjycUeE4ocKJsPkZDf9kuQopfpUuLLvQxinp%2Bk6hvd4cb7U5HLuKXTp2y%2BtVrNrO8bOx5ER0llPlM8dMkVph%2FunqEfdvYsmwgz6c6%2FmQyctPZCc4AXDHUIF73%2FXY%2BEDP4u3CjRSIxEn%2Fimq4BRjnFwCeYR9MBsRAMlF1AEyB%2Fng5x0cLrU%2BFEPYIb8ZHPoTuwSMuoL%2BOyEtlCMSbfcXkiqeM6jbOXpmE4FeE3yokyIz%2FQKSMp7TwmZV6TIiTPODNxYFZvWsNGMnmu52OrsTrQkIwvhyx5XrNmAyUdlL2%2BKHoT7FFTK1VrUmLw1Z5Uv0lu42xs%2Fd6B7e3vSqFBoaBWeFWut3wfMkJmYu6pwpy6JbcEdZyC8ZaySD4rwxAQvZbHklWZytS88hY5Ao1KimPaRsmPlUQr%2BQJUAX26DMAeC%2BJIPg%2Fw3BWeDSUM%2FBNoSp%2FidxQEVpVqeKP1Vq43MMlHwEegH1mvdyAHLcPhQEpfpfiv%2FxhVnkyMlc1Ou629muMhEyM0nB%2BXQTLYEQ7x1c2iSs4eqZVA6DCFo%2BeICKcpEMuU%2FuTIBEqHKxfhtEs8T5WXAkXjw5lTadV8xySZgjsFu0hcQuCJvlMh%2BuM9qj5hVbKsX5F96oFM3otEsN4E87i8ziusOHP2ZbeLeeTQz%2BN0UI6P60MB8rHuUlR17FJdEx7wYp3xot6whiwWUFCYGMnEgxkeq8cDO%2Bh1bTAaeC3wyF2r6QgfH3dAyusBZbRWj5Mx0cYRdl44rq7x7RHnl38dPpGoilZqdgRCWbRSKf5RdEl9bgVc5bEK2dvqaNNOF%2BZ1AkTkJb76i%2Fe4kzSe4%2B65p98chsbrBFs0kaIZK8GOY3gP1h7aycgGw57hYZiJBSaKdBVtU8EtUK4EnTyeUOBZp8CJslm0sJuPoiiyaR9X5HS2M7MzEsdH47ENOYg5zxU205pRT4XQ2B%2F0lZ49GW6i5weI06cAT51ZxTyVAYZw%2F%2FGc673RYC%2BAz4ASq1WPomNygYSBU4J2GrJjthTByYWmvvZ%2FcMA0%2B0NQ0viRjjSel6PDvKyERBEe73%2BLOx08YmSv17ONjQ3Ls8wuXbjoqEgmc8XpaeNWkDyNT3gI5UzHPBtK4cQZEAIBTcBApNVWIYUE45tKi3EtpXAzLhLRsnEVVUsDYbmi4mmqNQUrLwsvd9O%2FEt608O70csHbTUNJGXzp4yD86SIGMD0%2BUUAKhq%2BilnWMVKQEbb8XdVLWCFOSwhSXUJUmQS%2B0IRrdTZTA1ktO30y8IYCjJDCDLJzSt0F6DlMnXY2jZ1h9Hlg2Hlg9j%2FYR4%2Fh%2BPcpFkgfvWs1aLb4NMV0RFhh4qq%2F%2BF7JEfVlBlcA46BnmvtqrOmFFwydQqFvgAXou6KTGqKJAVQrliginFrxWkD1I71HCwRvV6%2BklpVomxcsxLeGVRQKkekWM10xvAhiFRvyj7gmpFB25BOJRWQ6lnU7mfKv6J9DCNuhR5PWS6AO936UPpb9HKCcRff5QCucQxaLg6enSvs5bKsby0dj63QPrdbqGsukTB87f0FrHWEj51EeSikyVS20fdPPIFMeLJmKCK4Kqfq%2BkUn15r8LhOX1aiW%2BnaxvQRK%2BUMcICUJShvq%2BKfgVUlEFQ5IfckTeSpiL0SpziI1GKjNfIM30nUUA5mpI29namD4kCym8Ps9bBoK%2BxiHEV5fN4vjgKexoPf6O%2F0YXTAVpdiqaPxzpj0yZyWsY0A%2FQYY0%2FNtpKciZCuHAex4s4%2B41oLT6dj9YlRR1WhUDKj6mW%2FHjgFRUTRKTq6qhrpdK%2B0i%2FrmMrOiqY%2FoWNDZ2%2BnxKJJKquwZjrGB%2FBQV30YUG7xTTgQ7jEiXIFZuPrEnaMchRR%2BtbrFSdw9IMCIT98pVK3kBk%2BV8ghn02AbDvtF%2FwDukZzsGzOXHdtHW%2Fl5B8OTxhALPDQVOlM3U1MxGMZNIZ7G3t6%2FDlZnRvHad8x4XdQbf5uamDfoDO3vurJ09e9Ya9Yb1%2Bn1bW1217Z1te%2BONN%2Bzs8lnD2YhxCDRu7tn4PxrZQbergQuBB0UQZRbzvcXFRSmEg0FP5qM4jAAPOiv28TDriQLDYfMos3Ozc9Zs4oPdu2Dg0OmTb2tr0%2B7du6%2Fn8%2BfP25Url21x8ZSEKhToUDa5hxIagx5h%2FID1t%2FhpMGPWN5kbUR%2BUcuoKTlI21N8n4eAbQNKHF%2BjsF6a0KDItw9mIhhN2DabVCWY9eXT6VakoBaEYrBLioWDEq9qzLCuEiHKQS0JKclDgo3GZXuqZHES4hKABTrBDWYQfHStysfKHVBMrsAgyroL4wOt1j7%2FOG4U0Ku6MBiANEPkxelO%2BSkjvEc7eT1ciA%2BuQIFWucMPM0dMLKn8EhcO0gYtygBTL%2FD0O6FE6%2BUZACDf0I3lunIxoI8cJ2A28i9bp6nw1C5jAOcrrqUAv9uv%2FBVUmr3JWKIaWYfLLjq8aEz81y%2FnO85g80qPqH1jEpxjUdD4KbTm1iRPR6eZVLpoBkhLE3WEeU2fxYVQ1BHBRSIGOA7njIhioIchFWvJGnLIe%2B8c5ICEUylFUOPLr7m3EY3oVCkU9CGXmoJK3xHAql%2FCQsgCsBIx%2BGcgI%2Bg2ry9kUygWKhRPNvw3w9e%2Fi2Op8qUD4DX4YDQZa7Z5kmZxd0a78gydc2Uj0QTZN3ywV5cvUv2jXRJugT9xBytWMhDuVjooTCfjEXKKU%2BgEnpN4T3GrlgszVsOrz4fjoAqZwOpwolUNwNR246h0cU131%2BQt1j3ucNgkcAk9oHz%2Be%2FLUalujLdJBWNnty5sRqtPKCF6QEiOoCflWFrvp9TVeWtqU6pCa%2F3M5gaaFk8Bp8CE5MODKqsOJJ%2BlwrZvQf%2BJohPfJBzmRnAc273Cgx7iSuPvskJSEJTyGkzjPIovRBEdHPU6tLd2gVPqRLTv0olIuy4p4qJ9jUK1GuLEtDVYlj6tm8kkIzMDmU08muQJJ5qhJOUYBiYjwqYXm881aJI42T%2BlStSgo5xyVt6QACY5i3oPc9jD%2F0Q1iwDCZDG404ixucYhW0Lv8APiUalAlc4r3E%2BOTphALPKgVOlE06kLSaiELGuWcffPCB%2FerX%2F2Vra2v2z%2F%2FyL%2Fbqq69KOXzw8KHt7%2B%2FbxYsX7cKFC1o5RDn94P337f0PPrD%2F63%2F9L3vrhwvWmp0xBAkGJlZDgfPRhx%2Fa7du35eKccJRE4Pz93%2F%2B9Xb9%2Bze7cvWN%2F%2FMMfrNPpGCZeKLIxsDUbLXvxhRftZz%2F%2Fub3%2B%2Buva8yVlhwEqKa7r6%2Bv29ttv68K9%2Bk9%2F%2BlMpqKFE43WTMhGyyIPi6nvV8MjJMMdqZ6yeVoQRkEi%2FEFDi%2FWnck5jhgxjdehrcKRvzoSQjPY2iHwOmC7g6C5Gxqtaw2oQVboYfV95coogByUH6kBLKHm%2FlBXUVH3sUp7CIdCEQcEcCYZUyCfdJGEOBEQ4SR51OKJykYxh2wSEG5KpoEAX6EMpb4DMlPYgNnBcUr2wlb8SQX%2BTRQB8pY8B3xYdcPmjroUyZVoUdo2h4UjOw44TB8fZa1DUBgUMNV%2FNT%2FZlVFs9CK%2FiayQpEN5%2B0oX0Cq6g5NXa%2BOhpTpnn8J%2FoT2kL9Ck8c1i4JJAkwyXxOyiceaCsWB5RCblG2Sl61PAo7M%2BQ0kvMTjyQjTMFJFOKdcC5fLSvxL2rplU4Rsaoe6RJ%2FSVN1yKIT0alQoSdgXpKDC%2BhxJ4PHK32AF8LeFgWIxNNSLKrZUx6HQvHwxrRwS%2FKCg3mRcFsCkbIgPLwC0a15P0r6ia9eaVUikHxKd2wlMxet48tWnfWlRpnQJtEnCBdtSvXTcwjokYTcehYN9KdQLIMaupNI0c5rnjLKjrjK%2B2M%2BVuGoz1FhZebAU8HxUkbrieBqlNImwGpHPiOAiwcOFXAIllhFSj4RAdX7w%2FSVpTKjVE8jE8gsd6d1%2Bp5VqJcbRYa%2BksosPycSRCKPLON4j%2F7G43w%2BIXAjzFfe3SSW1c1kDSGCpn4OBtZ7%2Bg5UXMLdS0jcA50SlyUkfByHgQruK%2FFNypSUXp6LyQ5PO12rSjZVpVqHSMmd8IjjXn73%2Fi07IT1HmgBN%2FF3kS%2B%2BqcvRxqZ8UKRRfLdNpGzRKlE6BcSM9GDCmMlZQR34J39RJBOZpEC3GI6VMbUAeOTEUMqFoOnwp5MEPXgEvRuUEzino5HZCgWeUAifKZmpYBjGUMc6%2Feu%2F996UY3rhxQwdvY9bJuXystvX7fXu4sqILIXF%2BYcEerqzavfv3NaizGgkcrWDW6%2B7sZn3dPvzwQ%2Fvzn%2F%2Bsd1ZF2bdz984drYIyBnyIgvurX9mZM0t2Ju1R7B30bXt7xwb9oe3vt%2B3lV16RsuhjxkTKIujv7u7aO%2B%2B8Y%2F%2F2b%2F%2BmMlAiP%2FnkE%2Fvtb39rCwsLKU%2BtUDZZ1XzppZfsX%2F7lX%2Bzq1atplRPhshwEXThjPHdxhg7TO%2FWn2DlKfphISUYRP7102pqtppRMFE3KzzNfAZgevJ%2F81%2BnDxGG4xbCThiNmptPKJk4ZJJQkQUgrP5E%2FFAMGs3RpEHdaIvRQH4YoFCpfNQoMuFcHw2IU1jApgUlmPShjabY7Ka7aaVkI5QEviUFqTA2RomsKTYNvEiIkAwQ%2BKUxVckEvauf3EH5483r5Smh6rg6saYB23BnbUx2VM9IDBYWtBAdkzxOSBwEkSFfxHPBKemMGXKonVczh%2BbLMiDkaEjGPeQ%2B84QkpMslBCN5zQV9VSEJWtbDE56pnpSiSgCdOboijqhTBD%2FR5DxEuqlPIiUoU6R0yaSVaqewECZiFMORIeYxXRuVEeu7Cgf6hwMQRSn%2BVNJBJzUhKef4UC1VaRPh7Zcgn8F6soKmEKfwITms1EVkpvVp39WVRL6V1mhV8Wsn3NB5FB0dX9QIVLo62UV3TUTdKpzjoQp%2Fhwr7SUNsKPRI4p1PQ61jkgZTgpXYKfLgnl2ueQu3p%2B5yLJk0whUPgWwmrFhlwIyyRWq%2BKC9pHgkfcSUb7BeschiNchDH0CXX7KDD%2FxsQmHin%2BKdMBp4R9GHvSVcPi2elZ5ivhPdEnLE9q2G%2B4maaPw65oaiIrWRZEP3G4Lv5lgSUxh69UtyIT6bxxvV7%2BLtiRJimeHp9qmixVnEwJBlFFosjsAY5rESkgpCjJHDAiDTmqeEVib3N94%2BlD9%2FoCzbldwIsSSB9XwA5YdJ6MlDFWEE6aKl85zBL%2FgEVxtAk5vOwoXyazWCGxPB2MXCAVOKj2RejJwwkFnmUKnCibdBSTicxn2SeI0vbuu%2B%2Fq%2FL1%2F%2BMd%2FtN2dXXmla7RaOpC50WzYcICp7Z6Uz6WlJa2GPnywYr%2F%2B9W%2Fs%2Fv3PdV7fhYsX7LVXXrVmoyEFE4UVU9Xr16%2FL3PbOZ5%2FZ%2FXv35Jmwd9C1bqcjZxUogS%2B%2F%2FIpWTTns%2BfPPH9inn34mJRcvra70oRhzJhce8%2Fbt%2Ffffs%2F%2F4j%2F%2Bwv%2FzlL0p3Csc69bqcG1Auyi%2F43r17V2e7LS8vCydWP69cuSKYOu4hTGIk1UCXXJvd%2BQDoL93M6%2Bl8Dj6suEkh%2BN%2B4cd0W5xdsYX7e2MvKz%2FfNgEu59%2FTpYONQJRRWCpAAmAaVMJPhzsqZxkTMPHnQWOKKhLLHYKaZ5BjUfHDy4UZ2N0lpYCCLQcjTHFFQU%2Fs4amlATkNeoBs5BSnGtjQwk6YY%2FyphSqYJB2pBPXygd2wCSCohhHe9egqPSSULbjU85dMNWIF3mcvr7asOitcqJMN40s4SuBjYq9CjrVQvylb5QWvuCa8qGsc8P16qYzI%2BMghcvI9JD4ZXSVlMItIkoVoKkXOP6qs6SsBLgNUu0I22iT1DaiWtPjje5CrbiTC98UAMqNCmSWlIoSlVCFdpRbNCL2jqUAXI2y4Jw64BeYscIUGYoym34640JYqOT2odcAyLDafHNESyOes7bxY8nCrq1KjmqRRUDRY%2BXhf%2B%2BjebJgWm0j25l6nPJdWXsusTxNw0GUW7FBc0dcXGMX0ELhWyku5wjb1%2BTldq6vyhL0pp%2BTKCrs5zrgQfDwcI6VdJEGGVIP%2F8Im26U1aJoDOh5wkIngAcA89KiXpU%2BlQQyjhTL%2FwEgceCV51XxPN8Z9FnwjqV4uLR7%2FEmkAkYYYfDI%2F5p3b1O3kM6QzivE%2B58qm0F1B2FT8kDR787KVKYbvzxy6GnWikuQvzu35GXrhqSBuuvKSYmbXxxnlagCCusR0hThKbUXgag%2BNZZ5C%2BYQsprpdyoX4EEbef9l1Oe%2BourvBxN1PEeYdyZgA3lMN3lfI9iwQ1lkH2yoXACOY3Bjrqni%2BcpWAR6fVRPGkn4eOIii9JEOsf85O8JBZ43CjyHyubRjx7FbWdn2z744H373e9%2Bp9XNn%2F%2Fi5%2Fbaa6%2FazZsf2b3796xz0NVh8OTGXAJFEIEIqyu8p27v7Njbv%2Fmt%2FaH5R0OZ%2B%2BnPfiLnNsvLZ7TKCWOdOXPGvv%2F979vPfvozzWpvbW54Z8WgWasp3xuvv2Fv%2Fd1b2ieKN7yLF%2B%2FIKx7mr5jssmLKPk72BqysbNjt27fsd7%2F7vb33%2FntSKBcXF%2ByFF27YD3%2F4lhRJymW19ubNm4Xy%2BfLLL9sLL7wgU1o6SeqBEhsrPK7QplWlb%2FKLSKtwmPhevHBRzpZYpY0Bi7sLIU8aqWme0CBREU6K8UTFuiiUHp12YCiJnMGNgQp4TlfHGQmIuGSqI5MdSolByWexbZJ5DTWoJ5w0IFLvlD6kpzTwK5WfrCCUipoIhSgj8iZJK%2BUlQ2AAWJ79vDmBSpKvu3DX%2BW%2BJECHwFzgpJ%2FXjiro65AQpSJJoA3J%2BBZqCqSwKERyESUcq6BswveQCdoKld1UkaXDKTB6%2F4ol0wesOgzLBvlzZ9%2FCv%2Ftf5gWom4UgrnEwqpImFhBUU4xdiG7g6BarYeopI6fcSNDmAg7Ed%2BQNmetVNRrJeTSdHAZLA4NkQXKME7uXqsqs%2F8IigeVzhQTkxUMoK9qpTasKi0GgfFApnJFWE9FI01QoOxGtT4qJ%2Bqnh1ugJOv7irtom9UoQE9dQMLrSndikypszRVoQrYQFUKb%2FKHweTaAO4VGce3URRT4kbjvJ1Ub9UJbVWUqjUakHDqMsxKAPVg6MFoybOEBEvFc%2BDREW1X4IXYKPrSMkEqPqcCkr5vRzycrGS67zpCkWV3IFRYaoYeKS68kou4YFSIZj%2BDk6BHxFKmwKIcxqqNl6MZ46IQ3UoIBVtIoAFgocfqukPx%2FFOYdWft8V0aMCITjjVYTqbKumUS99rZWVR8PTHYQStSh4DGOU47QRadAtMuCcaFQQt%2BwOUvOJ7DbzUNhDYsfJaOBzvhcCzDI1sKidVOd1SlFv2JCyEDd%2B8Y0hbwz2BL1nIzXv0PUyoUb%2BAyj3SoHSyXz6wqDBNWHQVoImLl4BRyacyvc7gV%2BJ0OC15Ak7kP7mfUOD5pMBzpmzGhx93%2BsmJDUdDW1tblUK2sbFu165dse9%2F%2F015Q%2FXVw1178OCB%2BZlYDR3GzB7I%2BfkF6%2FcHOsaAQ%2BRRAldWVqUI4qUWEwptIK%2Bxv8zlDPLhJRZzW%2Foh9maiaCJoLZ1etAsXztmF8xdktst%2BSx35gatz9o%2FgbGg81grjcDiwW7du2R%2F%2B8Hu7%2Fcktwbh8%2BZJWNHEmdPr0Kbt8%2BbK4GtPf8SgTvlevXrP%2F9k%2F%2F3X7x8%2Fjg%2BSkAACAASURBVH%2BwM2eWlZ7%2B0pVY7yxdEA%2FBuxxwnvYnEt02prMLiwuiD6uY6tCR2vh%2FaH%2Fbl8epGG0ODQRROvEMV4ykJZ%2BU5UQYdwbTuFL%2ByCN0Y%2FBhkKwqmtX9IUDGTLYcCI%2BYhqlI%2FgROiZmSAMD%2BJccadYkf2PvezmJfjmB4rEtfLmLyV%2FJ%2FEsr0LhiYcLFSizMkFI60agvTptl02sZxpz4qICnVLlIKzNSfSAOKPKd3oZwQKNJ7jTyK2vgahucK3IvE3lbQYYruXkKUklgo0cjJGWKrx5Eyyk20qhTxuI%2BFokkGFe7tIxmOiSUpnmEy7VCnS3OBqZB3UsGwlos4AdfRpQhWbqqiWNQicCaNUEk1FGpKVIpmwbpOgypGFAx%2FOl6OQ%2BwjC8AlHMFWOQHDV%2B4crje9O9JKWGmSySfcoj0oS%2FVJE1Cotygr3nhRE6%2Fd9BthMEGUDX5iirLdlQ3hmZRpJZ0qJvoqeyqK%2BK%2F3I%2F8hDKP9aU2VmVKkY0%2FIAR2YeiqqnBQB3lkNp9fxXA5bf6VVVSYNK4gLpmtdRc5EzJTKaxo85%2BbUMWEGQglRUh8hiQc4JiVW0a8oS1I0G0kxYZUs0pewvS2oNT1ZcFTcfRXMFdbgdV%2FdTCgBsKCNV8vpEm3NN5doJ%2BSm8S4QIlgZefA0CgjiJIr5LeIjMN6jdnEvUxMCtYsYDwgAuhdxeksa91SKCp0jvMrziX70RY524OV0FfVTevqjEhrApkv3N2gXyiOw4irzVlo0QaimcSSDr1QG31%2BgpVKjXHCMUp1OJCNsim5FvXlwQI4Nf%2BEQr2t8LZ4kymA8S4WLt0EmxjjqGekSPZgsFiHrvnKrb8lLE40Fyt8dLQIcd0JTSYHxyf2EAs8dBZ4zZZP2rXYi3t6sbHKgd7%2Ffs5deetFefOklrXz88Y9%2FkFK4sDBvrBgOBiN5tmw1Z7RXc2Z2zvdmNlr2s5%2F93Fgx%2FP3vf2dnzy5rVRFPsHREcvaTT2xrc1smunim%2FSScBbH5f4IiOZbCyJ6sbrdjO7u7dvv2p%2Fbxx7ek6J47d16KJ4oXiuFwOLK9vV1rt%2Fft3Llz9r033pBZ7%2F3795X%2Fvffes7W1dTn%2FwbT37r17dv36DfuHf%2FgH%2B%2Bd%2F%2Fmd77bXXFAd%2BDhPBh%2F2QbqJKuP%2FotF20SQFP54Ysw%2FlUdMwq2hUrhaQm4ygYbYH4yhhEnQAQQwD36kVcNd1xhSWEGPxioFJQhJd5fHiMd%2BD6IOgh1XJQDlnhJCzCA17c02CPcEASgmWylEQvBLn07qoH4dX9nlU8PL8GSlaviJIApgcN6y7koW6GAEsqGsqlBOcKn5QoZ9Cr9YvyHCZIR8085vBgDHxXakoakDIpKwVPOhT%2BAtHfAq%2ByTNWpePW2orkCh8hJnUqI5OIt7gWAL%2FkADC8haOMhgA7KAnIaSy8kUnLn52mgluRC0eG4fKRM31BCn5aNdiqqlaBWYQeuU1EFpRLUCn94n%2BA4TPN4QEh4AEOCmbcUtCBGcpuSJkShCZcUWg%2BL9on0ogbNHA%2FKHzQKKkX5lbsmZTw%2BYAob6EhRXo3QNisZv84jeJW4eblR0PFwAxWnNsegUNkSCuFSNEMpFR8FzETXAnRZNkGkKkPKp4jjrtAUxS0g88S%2FABDhcfcs%2Fi0HPG%2BjBDQSJnwdWvqbylM%2FpnRJ4ZQyihdy71%2BIquJUxcc%2FiqjAdDrwKeL1EvHwm6%2BEeZoyf0p2KAAMggZRoUA%2BcvAeYSl9RBV3%2F%2FYdQqQtIvUQ0KdDy%2B%2FIy%2FD2VimJjavphYm%2BNfpjcgRuKXEULRYDJ79URzVeYFG2K3CIiuHHoVYAFTC8xKBF1JWxycc%2FoVTA8rfIk94oKHUSgYG%2Fll%2BwcyicANw0huktJiZjLIpy6QkJAyPCuPjLuOvfmkMTVVN8KJnVPCW1HNtEPwc3BTvKSLU6uZ1Q4LmlwHOobB5ta5RB9l6%2B%2Bf03ZbqJ4vnv%2F%2F5LHX%2Fyf%2F7P%2F2k%2F%2BclPZP6ajb2zwnQWpWxnZ88%2B%2BexTKX54lX3xxRfkmAcnP%2BfPX5BzHs6KJC0K4s7ujq2srtjDhw9tZ2tLHTwrlix7TjLO9RoYZ%2FLt7u7YrVu37Q9%2F%2BKM9ePDQZmbm7Pq1a1rx1KpovWZzc7P24osvaT8jR63gHZf9m%2FTnv%2F3t7%2B1Pf3pH8DBDxeT27Nlz9otf%2FEJ1Yd8oHmtR7liN9T2QR%2BkyrXD6kHE01ZMNQeEdDcc6aoYzSxdmZ%2BWEh0GAmW0EBI1ZX7tYRoavUqdykNJAUkhVFYTSoBNDFjE%2BYFIBN6OsDrrCIw2sMYBO31OZzK4GytwlLJeDpwQBBlDhxGpjXORL4ZIUfGD1sZbwGFCjVKitAtIaQ7nKSYrYN6OVzbTXRbyS2qaoSoUkLmikAZ2VflHfxQSSlYN8JVMhDBAfCqfHBxmqqY97frx0XlevffBFasTjgD5mmLdaajvVBVon8SPdKVm0FgrVMiNfKa5I0SzK9rTQOlLCYxKvotLKkF4CNPeIL2BFGZXIapq0cq6MSThFEZo2qwtzfIB6Yfydwi9QqcIGHb0rdZE3YJT3QNaVBIWnVezg1gJsWjWLsgM87zyHuBoQdS8yk6h4mUrypF%2BixgF3%2Bt0x1acsdHxVjm9P345YyYXcyF%2Bllb4n9tmnOgMCRTV%2B%2BvKwaElfusIr8bw7XWEwcgsJJYsn7mTRPQJTmGhdgUc9KIv1cP7BPyo7pVER%2Fnk4RIqVp%2BniNVBXtxf1ChiAES6JP3kDJXV7CUevU%2FBABe%2FAoSwhPaWIIjwgTAV8My8ikOOseqlOaR%2F2EQxinOAeCpfffeIrNanyOQ8V41PRztMNWpYZhUGbBJt%2BvwIrUpT86JOoXrZDqkBX8qOUrvSVATD1dV4YXwE%2FIGEiG7wIJB%2F3sI0o7D0KHo6SvUSCve4cqxWjUqQJOh7GrvpO2khP%2BOFLqJ38OaHAc0%2BB517ZREjG7PTG9Rs683Jjfd3eefcdHWXCamGr2fTZdp3DmTyOohCNJtbpdm1jY9NwLPTaa6%2FY1atXZOaKIofH2ZmZWRv0e37IL3syzyzb%2BVfP2euvv6aVzQef35dJrGbzJ%2BwD7RpHmKj7yydSWOfnF2Xu%2Buprr0l5ZRUWWajd7milk1VNNwNek0dcvOK2220xNoomZrsolBxvwt7Njz%2F%2BWOd9opyyN5IVW%2FaS4pQHpfWwIlcqnLG69fS%2FmUG%2FLzoszC9YY%2FmstRolm2rLWzqz7GljEkPo8eUcHlQYcAjzgUdDeBKeaK%2BCrkoWeRms%2BcVgRUIGSuLdpEcCvZTKZBoo4SFlk7gmQ9ekvKWVABmhYYjGCYLUgnJQKKMsykNMk6imO%2Bokgiz%2FxH%2F6623OBIB7Qww8HWMfqL3OqhGOm6Rw1mQqGliWuRj8Q2LgaB%2BEEFJ5XYVPMaEduZQgQD3Fu9c71ewJlnMY%2F%2FKdJ2gYNY07zS06JgUbYeiwMChlQavYpEUBc1JiEucioJsUh96koxwSlCiXO0K73sWFtHPV7I6YCoKpbWBBHNsEvsIloABPeAHHuS%2Fq4pMgkJYPI3Iz8RCCo2MOx%2Fo3Q4Es%2BOeu76hVwAnBMH07gBGaDi%2BUC5KGopZqoXSlgkzo3%2FgXtE%2BkAKO4nERlncCUbwdlLUNRS%2Bg7b3gcub2%2FLusGL%2FF10avIDDnxgHIQJ7PW1CTe2gVRKN3NHvU0FVspIeHsfEfmMk7cU%2BCKgjmW9QWKr%2Fc%2BUZjzPHmdmwintwBWhDk1HDptK9cvRX8R03fegwmuZxafBruRj2%2BFX4En78WLx327%2FiaEQUoVoBLwP3VNyIvZ%2BXIqPKDvj%2BO5dKqn%2BhQqGvX3Oga9gcNzedcTY4LazHnO6ejfNhSvTXQiaNH%2FqMWDlonoMr%2FVc0WZS2MN%2BINz%2BfO%2BwWtC%2F8HP%2F4IHfOLHGjF2%2BBimsUyKIvCpgY9rzhGJi6iMft7HOGd6yX6UGZPAmTy6q4hEieCqyH307vRyeMQ6rkfTnYScUOD5pkApxT%2FHdMDb6fz8nHW6LSmOeH%2FlWJMf%2FehHOleT8zU3N7e0gklnz8omq4UcR7KytmYHBwd29%2B49u3jpknEwOEqeViAlK%2FmMP8reufPn7O9%2B9CP7x3%2F4hc3PzVm3w0oknaObxqK0%2Fud%2F%2Fqctnz2rg4CzzMMHg6EUYo4puXjposxk2av50Uc37eCgK%2FNZFMzuQVerla%2B%2B%2Bop973tvKg9Hn2B%2BurG5Ja%2B5v%2F71rw0T28XFReHIESM%2F%2FOEP7K233jL2fLJPtF73TjsUzbg%2FVRbR%2BFmzGs6Xegf28OGKLS8t2cLMrC3MzUppfqrlV4HHwOSjToqJQMZ5Hwo9gkSVAUbt6asIGrolRaFYcbnXu5h5jYEMYRqhD6%2B22ssr4Tvt2JrkSWH0fYu0RZSGfIEwiNA11iqFnynJCjDmZwiZEjOSsOH4Ug8fpH29kmeJsC5s1OE5FAwapKnzxyY5e4ZxwY90zD7kdNYjggLJ0kCPIN8Qz4uj08qXixMuBMDrMdvO8Mxe0CTgyDmSK07gGWKGK0lJKmdjcxJgUqM84Ru0Ceo%2BYdAChyDoypgL8QRW%2BIpnNSrBPLvyrj3dDWjesnE20t5x9i6z8o%2FZvWGKP86klCGINWo1azYbEuiH%2BdjG4q%2BaTXSOrgt35AOuC29eHm1RoDNFZ%2FIkyqgJaDlWVQL3iHXBDh5lr3oDfuZyEdjyse87z7R1ICnD4heq7UIygjFFS3lOYU4lV6iJlCWGmsr5Ar7M%2BGZ0fBA85n1qYKekR5rz%2BNAjyZ5CAF%2BEaF0I9t4TiJya2OELdXqLG%2FWd%2B1eb1Sc2adbNtOd%2FIr8CWMfQJ3E8V13nKWcaE6BVE78BjYbGE6xrMvhk4k6fMvhCsKGXs56cB1BnwsWdwlZPeCMXPto8yZec3rUP2ZVZifJkVC%2FDcaIc3jER79WbdY051qjbKBvLigfLH6AAS9wDLCyH8GdQ9AMJYOJCmRILo8DR%2B42ibO%2BmHFeyFkxe8nCwruqTYMWzY%2F90%2FpZjqRNY6lfx2aV%2BbqroqHs1EEz9cpz5698N%2FYfOFc69n61bwxr1Gf56a2FFpT6XM7q9Hxc%2FxDdpzjPEET7Kx5ZNxpaxn1Eo01rp36RpdWv6VEZOWPqm1XeEBY9%2FzI4ndaHvYGIT3nMrmeJ70L5eMaQU42a9aVx874yR6jdSXr74mrZcQMGxTWpcPpa5Nu0TVmJiTeAy2RphYgrREMd3tcnYJtqTnvKLdxupH6FWVQW12g4nzycUOKHA41LgRNmkY8kn8vh67949ma5%2B%2BuknUhxfefVV29%2Fbs63tbZufm5Vwh%2FDL4I5jIBTLmVbLWktL1ul07OGDB9Y76GkVUaazIbBJgPBBg5VSVj5x%2FIMCShLMWRGYtre3bW19zc4sn7Wr167bhQuXpOCy9xLvt6%2B8%2FKplb%2BCVdmBra2v28a2P1cGjOLI6e%2F78eUN5nJmdtYODno5ouXLlqvZnYo7L0SesbmKuyx3HQSipFy6ctzfeeD3t13Q5V%2BPz43LRE0qngbhWM5RraNHizFINgoxRScj8phArx6NCoqGd%2FMUrjHjk8%2Bs%2BlBKKoOvrdAiHPDektI3zmg1HZuNRbnk20oo2kxLw03AwsMFwZM1m3ebmWI1moKtbPh5pnzB0mJ2ZtZlmqxj2VBZ8UzMbTcwGGQM3PDXjymKO4oeIgbqJMMZstPMgA6uEHMZ1BEg0RMSVWq4VSZQT1kIaE2C1bDjMrdsZW384tkZzRqvhMzMtzQTX6gi6CBZDs8nIWk2zRuFowaUoNZmcZMXA3fSBHHxkVowiS%2FkoMAz4CERgBF5uPu2eSl0pSZHC%2Bdv8Z5pbAlPq5IJZNZ46QwRo5aJcUjStbrPNGbc%2BWFzQ98q30Wy07PzZc3Zm6bQN%2BwPb29yy3sGB6MlxQcvnlq3Ratr2%2Fq7t7O9ZfzTEG5nYl8mC2dk5WQxI4UwKDq1DP4RSiKD5%2F7P3nl2SHFeW4HUtQ6tUpRUKAEE2OXu6Z7ji687vnf2682H27JzpJnco0E0CKK0yK0Vo4dp9z33mUZVVKJAAWQWgDzKqIkN5uHuYmZu9%2B95993E7g2NDJilV31Y3dBRVgbzMlcuiLJHnyllCeCC%2FqdJkXmz4TTSCBjzHk9%2FG2sKcdzbpWkVQZWAyN1FQooIbBbEz3ScadLOO8guOrGSoqHmgxg%2F1ZSfGK4cgEUQ9ls%2B38bblf3SP5wbAG0CT44BGPwElxeGqAgX7hfaybcFvN%2BA3G9Ivy%2FlcGDYOFbyHQ%2FheIG18dnYmwNImy6bVRiMIkMUJJuOxrCUUu8vqecC0LbC0l26ZIsBWknHAG69HAtKS%2FVHBsDib8KlygIkzgS%2BLUpwdyAp5XneL0hYoc6RlAdNx0O53MNzbgeU6mC%2Fm4til5gDHPfdrsPvoGCsqaNwn24DHk3mXp6McHLk41yrkgkvU9ST9LRHwCoZOnQQ6YWSWE4eMzEEK97yaQ7fnKT%2BVf964sXPedeO3vumzd23%2F%2Br03gGa9F7m0Xm%2FyrZ9x3eAPEceL%2FCJd7BIOEkO3JOJY5VyhLPh%2BA57ty1KVJSmKLBeg6bkeLMtEniWIIzKwCOCAwCHjyRNnwHK9RJzFyKsccsWLs4yOJAJBHseEAUvGjTAQxJ5StUFlzq6dScqxxRelmj8q7u31v6zI6rnJlEgsR5pvBgj9ELZpiy2zXC2Rl5lAQeUg5TrFHH%2BWgUvE4cT1Q5wiGlk%2BHAI8Jp2wFnTNlKmM9p4sPVwbCTa1RIFNnSOLa7YC%2FeoqUONLudu%2BdfdcbHjRAhct8FYLXIBNqJqVBHm%2F%2F93v8M%2F%2F%2FM9CRx0MR2g0GlIihJHGk%2BNjMfx13YRhWhLNZI7kerWRsilc3B89eCgA1PdcODYnYqXyykk8iRPJAf3Tn%2F4kiyZLkSwWi9rL%2FNrTTc8zDcGDg0uSJ0rQSPBFbyT%2FEYg0wiZu3bqNJInEU0yw2G530O60BRAfHh3hj3%2F4XMAl%2B%2FtXv%2FqVfH771m3ESSI5oaTrkrZL4Hvp0mX5rdy3LMoySM4vxW%2BNmg%2F4kkelsUm6MBdnRm%2FEyOAx1bx%2F7hw%2F4Il8613XJ1VvL2aiUMQ0FPTIaiYKOIiyCotFjPl8jTQp4dgBfJ%2FGgoHVaoPVagnbMdHpNOG6pDNX2GwynJ2OJQre7%2FbQbtqwaYASFBQ5kixFlKRYxxmilJ5iE5blyULKxZ30Y45BrSyVQcj8YEY1ZDktJHxg2Bo8n8rK%2FC7Pl4CDRocJlDbyzMRstsHRywUWiwiuF2Jnp4FW20NV5tD0AoapwElVZXCrCo6lKQNPRiz7jVbRlhRnArqNqqTnnMfhqM6ljyVCSrBZqigqxyI%2FZUSGfS9RvFdRgG%2FdQT%2FKDbfmqrqqlced17hShhR7SqI9lm6hFbZw69otofqPT8%2Fw6NEjmQeuXb2KywcH2CxXePzgASZnYzGVOA9cvnoJbuDj%2FqMH%2BNNXXyKLZopOpxtwHQ%2F9Th%2FNRkNAIdtV4C%2Fnq6IQJ1RVFDI30KnA%2FmBk2zR0mBYdQDmSNBH6%2FnqzwWy%2BwCZOxIFA4ElDzrE87HR3cfPaTck1Z%2BT16PAQjx49wHQ2kfEtY41uD0Zc9QpZniOi44VWIoXV6iin2JOsR1lHPtTMVEEzdXGU0BCmwJpimCszdOtAURFEBZx%2BlAOBp1YPBs5zvLN9Zb6vpxYCzawsBFwRTPb3d3H5%2BlUBCnQikhHTardx6%2FZtyc2nSBzZOUkUIfR9HOzuYXe0g9WCNZn%2FDYtnz5EmBJuKgRF2WxiMhnDDQCKjBLfidOBx80zuPC%2FXtsVfQfYJHWCmboDjpMxyZFGCaL7EZr5Asonl%2FEu9QkHMZ%2BiwGj6u3L2FT37xGdzQx%2BHRoai%2FgyrvWSZtQFeaTWCQFSiTDMUmRp7mNW1S6QuUmo6MCvIyaxChmuKUoO4Cxy7HGUEC24yzB8eMkDQ4dtSwqttbNa60vcwz29HB99V3VXz5%2FPvb59%2F9ke33%2Fm71uXNSlGuXyvY6dLnTSejItU4fgWV46AQDdFt9NgritXJC05FB%2B8Z1HMTRBkttJk5sOpkG7T563Q7WmxWOsiNU2QxVyRbnmqHDNh14bgDHcKGVJizdBSOo1LTgVJ8msawhdJ6ahloLBGwaBICFsDOyKkNaptikEQpGJit%2BvxCgbMKCY7roB30M%2B0P4ri%2F21lF5hDiN5ILhftTcyYgm2R5rpAVV%2FxPlTNAIvnWgUKwiXacT1xamDgEowTrPiQhcOY0JOkmj5TpKEKucxsphrCKwtc%2Fj%2FXXjxZ4uWuAn1AI%2FebDJNSmKIjx88AC%2F%2Be1vBYj59PiZptxpZP3Lv%2FwL%2Ftt%2F%2B38wPhvDcTxcuXoVv%2F71%2F4r%2F43%2F%2F30BF2t%2F9z%2F%2BJ%2F%2FJf%2Fi88evRQSqZQzCfwAzEGNptKvHKMglIY6PM%2F%2FhH%2F9b%2F%2B38iSBL1eRyEoGlaGAUYhw0YDw9GO5HWyJmea5jg5OZNIarPRRBAGspB%2F%2BuknYpE%2Bf%2F5M8kYJXKlOy9%2Fz%2FPlzPHz4UB4ZxVT5o64cgxFV%2Fl7e%2FuEX%2F4DhcCj03laroUCdRBDf58L47a8mGlgCLOjRrnNlaUDIe1TJlX%2Fffn8fesutScLz4u0VcJDnhFEGiopg00ZW6Tgez%2FDlF4%2BRpBU8r4FG2IZhWFgtV6Iq7Ho2hsMSrVYIx7WwmEe499ULMFJ145oL0%2Bmg1QhgmTryJMJkvMSjJ89xeHyGxSpFnFUwLU9qtPI7tmGizHMkUYyMNVpz5RUWRV%2Fm3ZmAHzgYjTq4dn0Pg0FTAKTt0og0kCQ6FqsCzw%2BXePjwFJPpBkGQoKy6qLQWslR5lTU9hWGmMPQUKz1Gs2Gh4dMw1VHkyljUaAwyuiq0LkeMoySNRF3YthyYFg2kFCiVk0GWeoY7aCkS7NDrTvBRt%2FWH7tv3tX8ZI%2Bcup%2B2YeeNRvP%2FKcCzzCkWewSQlmRFt18VosIu7tz%2FGrRu3UGUF5j%2BfY7PeCFhkdDNPElwdXsZmtUQSM7oJDHYG8BsBirTCsydHmOZzaIUG27Wx39vDzz%2F7Oa5cuYJW2JRrjRY657o0SUG1bEaHCEbpNBMqZJHLe5peibFIsDmejPHw0WN88dVXqJK59G9SZNJHLlwc9C%2Fh5x%2F9AoNeXwDFoNlDN2his1kJaCXBMuWYNDSJsp2cneLw5Uupacxj8pZlGcpc0UwlO0zGEFuPgVpFEWVkzShpVJJqp3K5OG4EZNCgVP%2FlO9%2F0Z9sf3%2FT5h36fQ2Q7TOhs5G%2BhOjrHveFYQp0lldHyXQz2d3D7s0%2FQISOF8%2F5sppgtox04QYDBlQNcv3tbnJmMWLXCBvZ297BeLvFifIKnJy%2BR5ikK0p0NA5duXsc%2F%2Fvo%2ForszhOGQdaCixAQPccSyWRkc14Eb8LqtoBFU8B83TDNxZGWbCEcPH%2BNPf%2Fgc97%2B8J6kejKybrgs39AQgf%2FQPP8P1T%2B%2FK7wl3ezBbPvpHu0ijWICQb7vwTVv2WW4S3P%2FTF3jx6IkASKHoVyYINgtSPC0DmmnC9Dy4vi%2FRL2nDokQaR1gvlgp8ETTwfHmurwSTVGtvQf7rvq17oN5Wvc8XvKnvKCBav%2FUDPXCN51qpcqHJVuAcqcHULDiWC1OzkScS6kfotLHTvYRRfwQDJio6gwrZgfQ9p9jUjdH1BsiyVJyew1Yfg04XU32C5XSDSEtQ8BgoYJo2uu0eRv1dhF4LZmXDNj2JcEo7a8BqtZAIJp2mpOOSbMBrlRHyOGUEskCll1jECzx4ch%2BbeA1b91AapFDrsHUX3aCHUXsPo9YIgRcg8RLYVSDbku0kbAbOD3mKSkuQFytskjGiZIYsjcVxVZa0Gegss1BUzA3XYFkOPMeXdZeAsywSlPlKdS9tDW6lcV1jlytXKP%2By3%2FnWdjT8QF1%2FcdiLFvh32wI%2FebDJniMF9erVa%2FjP%2F%2Bd%2Fxi9%2F%2BUt8%2FsfPxWtPminzYEg1tS0bH310F41GU4Afy5MwL3N%2Ffw%2FLxRwHB%2Ft4%2FPghtnmVpNHyRu%2BZY9tSCuU%2F%2FOpXCIMQ%2FUEPT588wZPHj8TA43YEB6TAkgoVJ6z7eYxebyD74BTHmpmtdusV%2FXa1MsSj%2Fdvf%2FlYiqyyzwhtpaicnp2JoMK%2BU9F5GRlkTlMbrnLTg8VjOh%2Fmcw9FQaJGK0knvHqfU7%2F9G40VyAfUK%2FC17e3toNVuwWJOURuXfV%2FPku%2F8gaYZv0xZqIard5fVqxO%2BRUkjDzUaam1itc0xmGRZc1wwPRhngbEYF4pXQnzStgTwGspME40WJXq8NrQqRlQ1kpYuk8LFOLHHPuxaPaSEtbKyiCuNZguU6Q1YaKJHAjXQF%2BAIHRVZhvSqkzioJtezeosjkTk%2B1H%2BVwwyay0kKSauLcIHtR1yysI%2BDoeImnL2aYzEqsNybWUYokO8SLl2tZqLNiDU2PYZoJNG0Fz81wab%2BLg%2F0BOs1Acm0lF1W3UOY1lZg07nmEo6NjZHmMMHAx6DXRawfwaVjXvcWxKH1PKh5poGIcc8r6Nv3y3bv8Q36jHiW1Ia%2FsQ%2Fmd9Y%2Blo4KGPCP5pMialYXADnCwe4CPbn2Eg50D%2BJYnkbzQDqH1NbiWDc9xgaBA32uLkb1YzLDaLOFbPjzTQ9tvYdgeII8ZCc%2BFls99dxs97A8O0OS8IedA%2F74m0QVGOhj5IEODoIfnxX4wTIJ9GmSFRDbNysDxi2NoaQWkpC8asHjeQQO3rt%2FGp3d%2Bhr3BPlzLQaYluDQ6wE6nj6rKoTMYo5VCkyc9lFTLB48foshK5OkhNkksAmajKyMc7O2h02zDYY7qNkLFzjJ05CiwjFaYLWc4PHmJZ4fPMF1MwciJbhuwXapZayLc9k39K3b0N334Xt8n6j03djmet6Dt3HEI%2Btkp4nCrSFuWmBI6gx7u%2FOwT3P35pxju7wj11Q5cNPsdiUS6QSDzpWn30ey1sJgvMBmfCZ3e9F3YVYHmsIf%2BwS708RSzxRxpkQOOCb%2FTRHfUh%2BXZ4rDkkMiLXKLcpNX6%2FL5nCwVTyxR4K%2FNCh4D2dgAAIABJREFUcuw5NjbTOWZnp7BDD1bgQi8yZKTqFikazT5uffIR9m9ehdMOxbHgGU1c9z7CpVvXxCGmFRVs3YTNFklypIul0DvpQGHkPiOoZdjM0EHKcG9%2FF%2FvXrmG4v4cgbAj4pTOC9zSKMD49xZf%2F%2BiccPX0u44x0SeXsOtfQbzxlv%2FBeX5BvfFa%2F4EfiweDrv7Ddu777gd6T1A46WBh0ZHxRs6CVhjiWXMNFy%2B%2FKPbDb0CsDhm3AZA5jUYljJk9TACYs24PuaDALD4HZgm%2B2kTsV2sESRVlhla2xoiOL0WfdR%2Bi20Qn7AhKZbqFC2CoHvKC%2FSy%2FR8ANJDREHBac3VAhclYybI5OUDM8%2BRrSho9KAJTR%2FDaHdQL%2B5g0FzF02H170Llt32d5pI8lQi%2F5KHzjaVbkuxiSaYzJ7ibKJjHk%2Bke4JGB53OCL5PDQxH2DQEoKbhCOhkNDbLYiznJ9isjxGlxyBGz7VYwDDdXcpXJR3%2Fyjb6cfT8BxpQF7u9aIEP1AI%2FebBJg5aqsSwHQvBFeg8pps%2BePpMJkF5dy7RAytrdjz8Fo4t%2F%2FvOfxSijR7nRUCCv1%2Bui2WyAZU8Cn8BOlTt5RUurKqHB%2Fexnn0otz9%2F85jdYLucCWJk3YZim0Fp4Hi%2BPT4QCy%2FqYnNzp6b51647U0%2BTCToopaWPcluCYkUoC5tlshi%2B%2F%2FFLEjAiKL126hNu3b8v36NEj2ORv%2B93vfieAk9FQRj6VcfOBRth32W3tAWUZmiuXr0jbsMYpz5urikQ%2BpUXUovZddv1dt%2BWCInbh2ysLqVjyIffIJ1xClUGuXpOTRdoorWlGhRhJLvH8cIKHj19ik%2BgY7uxC1z2s1ymijCDNEOM%2BzTKs4gy2zRwn0h1txLmPbA08P15hHVVo%2BKYAMwK0rCC4ZFSwicFOA%2B3ujtBpZ7OFCK7AZKQypS2BIDDRaTURBor%2BulovMZ9PURQpSnBflgBOggBmZK3XOY5ervDk%2BRinkxjrxIRmhfDcJgzbR5KZICuXXuwkXaGsljD0FbodE50ejUxm01AgRhNxEooNMb%2BIBt9yneL5izEePHyBKF6jGbqILu1IdMK1Q0V9Exrc1pjQJSdIjYE37fXv2q%2Ff9%2FZqhKijbofS9r3taxlD5GhR3Mc04BgOHN1Dv93H1YMruHZwBQ03wORkjCIrMOyRWubBNW3YktXG8QPYtobKzaCXFTzXh%2B%2BFuLx7gOofgMlshpPxGI8fP4Wt2bSokK0znMzPJI%2BPIHdnuINGEMLVHDHa9UIX1euT4xNMp2PESQw%2FcLG7N0Kz1YBZ6XLXqE6VlbBsA%2B12F9eu3cTPfvYZrl%2B6jobbqHPuaA3TyCOVLoNtGXA9R6KaaVUgQ4H5bC75qSIklJcy746GI9y%2B9RF2B0P4lgNb02GxXJNiGgtYWscbzNcLPDt6LvmhD58%2BwGw1EyAq2lV1CY3tkJLe2OIKXq5ser7%2Bnm9qfvn6gYUSTMeDadSlqSo4gYO9y5dw7dZ19EcDJGWG6ckpvMCX%2FFyOJdKKORyYf4lch1U68IpQ5W6HLgLPwo2P76DRbQsb5t79%2B5IykpM%2BaACraI3J0XMslks0W010eh1Ijm6ZI85jFEmJs9NTPHv8WLQMLN3ETn%2BA%2FdEOdOZ2mppEHCubg9GEa3nojQa48%2BnHuP3pXTR7bVQ26Y2cHyqUFiPTDlyTTiYXNqmOWQHEKWLLgBN6gOyL8z9zRyt4jQD716%2Fixicf4%2FLNm%2BiNhnA8VyJ7pPdySq6yHOvpXNJN%2FuT%2BAcfPXiBerQGWLpOAeS0UIxFv5QD4ei%2B8azBst3p95b5rq%2B%2F6HvcqY1N2%2F9e4G3TLcg6sz0XJsyul2QrI0wJGqcO1fLTDAYbdXfh2E0VCh0spbBfaO%2Bw7LmSJngqRlM%2FpFK9cA4EVwNFDhE6FUTeHFwRYJEscT88kMmnAAQpT9rlOU2lbx%2FDQbXfhWDbMciHOTGQEcwU2q5UwMTh%2Fk5nlNTwwub%2FIKAhIXQECZIJAC2HYwKA1xKi7h3bQh2cEwlrgdx0CaSOTCKgIWVHkzGDcMYVZAbE5h6PNyCNCqWsInQH6rctodwYyzrgPjiHmbzKvVVF%2FC%2FTCLqJND7NliPHiCebxmThBeU0o7vX5Hq3b%2FfxbF88vWuCiBf5qC%2FzkwSZbiAnlLAPCCZyCBRJh0zgfmoijRIAl8xt2d0YSIWTuEsWACNpOTpV4D3M2N1EkEUnSyxiJoXgQc14ISjertQj4UMSHpUZ4PMuyxbikoSN0Mk1DfzAQY%2BHw6CU%2B%2F%2FyPyPMC%2F%2FiP%2F6gim62WdCgXa%2BZSsYTK3t6u0EzTNMH9%2Bw9wdka641RA8T%2F903%2FEP%2F3TP8kELgZVVUnkkx5zgl3xnG9BnKjQ%2FnATqVBQKXjDWKBtK2DNvEOh03I1lrR9BfQYNN4utn91iL%2BHDbbNIihBGQOKWkPLhW%2FyUfygyhDg34o5RDqiOMfZaYSjF6eYzyOE4QDd7j6ipMJivUBClQvm3RSalNOhArEHG%2BvYRJxW2CSMNOSIDhc4OZ2j3%2FFg0ViwHeQF8x4tGCbL14xw5eodLCMK%2BTwWsZhK81AxB8qsEDQbGO7totdtoyxzzKZTQD%2FCfDFBkpuIEjq7bVH%2FWy5WODya4slTClZtEMUGCriwzAbcBs%2B%2FB9s2EcVzrNMISUTjQgMdA17YhBf0YNghSs1GwX4rSYol5qCBY2K9ifHydInxlPnIGfJMRyOIsejnaIYMtDDeQ1okFVaVYafEUgjit%2F3JJ8q4fP3e9rMfx6MMl3qEvHpen%2F%2Br1%2FXnahy9%2BnEiCDXsj3Bp7xK6zS6qrJIoYp7lYhzZniXGl0WLiAIyIthhA04Ak%2Fl1niuA0%2BiP0AxamK%2FX%2BOrBfUxPZzB0Ezr7JCuxXqzx8sWxAP2210KDOb8iNqXAThHlOHr2Ao8eP8JqvcBg1EfguQg9V9RCHd2AY5oSdey1u7h67SY%2B%2BuhTXL1yA62gDUuzhFJXVjo2ESm6SxFSdZoh5NzFACyxYO772VRy4GkUiwOG4NJxZc5lninBAlkm6SYWG1CnyJptww08eH2KpHniPGOdZALjiPldpA0KyYTX7ev25QhRI%2BvckPpxDBtxqgkdWFLkDFkjun227RWMdneg2SYm8wkePn0sLJmw1xBROI30UkPlfTJfEo4Op%2BkpRU%2FXgF5oEhHtDHtoHx9jup7hyeETEX9hyDjJYhyfvMTp2QlG2Qh%2Bg9FMB2mRICsTOMhxePwcv%2FvX34n%2BQOgH%2BPjOR2h3mghMB5WlIzeAVKtg%2BC72Lh3g7scf4%2BbHdzC8tA%2FT4zZK%2BCmJC4wXM9E4aDWa8pltGwL643WKl2cnOJ6Osc5iREUq8whB5fDKHj76%2Bae4%2FtEdNPtdmVcm0zNsSBkpKhGkajfbaPU6uPvpxzBIR68ggDNariVHXFTV6jzNGrqdGw3vYxBsr%2B5v2td25PFzNSZfjcx6SuPoVHvhJ%2BpOxWa51yNZqLT1p0L8qa9pumJ8Mqg6Q%2FTbIwHz8SpDyTQLz4BmMMWBzmcdupXLeCLa5VpLBwAjombpwDVKdBqA7TswIhubhGXX1rD4XUYzSxPJJsNsvEbDMzBsurDhwKqYw6mDg4F20Hy6wmyi5h2KFjFtgmBX53rA3H0RNTLhuw0532FnF82gB0cPYMGDXhpiB6VxJkJ4mqXDdmzw%2BuelTbErAdMxUKaM6npCKTbKEKbWhKU3xVmZZYmI8RVlAovRTcOHYzoIQjJAGuKMYUQ2neZIkykKihFJ03O1V85u6ZVXnfVN%2FXvx%2FkULXLTA2y1wATalRVTOpJQrqUVyWJuSqrNU71sulmi32yLUQuEWirk8fvQQ08kERy%2BPhKLFfE3Sih48eIAvv%2FgSN65fE0EFUtKm0wnSNBXBDakdSZGh%2BjikqPA4OcUx4riOcDYFTDLySACbUsaUGRMinEMlOUMMMFJfeef5MGL54vAFxuOJUHKvX78u5Uxu3rwpkVvun%2FthlJa1ORkJ5Xe3uZFvD4zv%2FfVWTIlKhxSUqAWWGBkj4ODCSyeA8mh%2B2LNTR1PL%2FZvRza2RoBZ%2F5syo2%2FZ9Pqr3xIipNCSbFGfHYywWa3hOgHZ7ANtm7gnzTAwUzDVjOIL0VkZNDQswHaHH5mmMUnPhOIruk6xW8F1bgTZYQqUlnRaViTzXEccVkoSiHppEVMvKEvBO48JyAthuKNElioMkmSa026K0kOcmspznQQCb4WyyxrMXpzg5WyHNXdhuE2XpoCxtEWGodEfUJYtohYwGjmbBckO0uy5GuwMRKzFtR6USMT%2BnVv8j6OS5zRex5H%2FmhQXdVPk0q02J%2BSJBt13CCEgH05SyJfNn2Kq1HK209Os%2FdZh52%2F51d%2FwIHnhG27OS5zRuawN3%2Bz5P89VzUio5vite5yqq1%2B9SIGME13YRrzbIE%2Ba0kqCtwSbtTKeUBscb1Tx1VCwTYNOIZD6ugTzJZFARFEiWXQGkMSn1qiwJoxCVH4DGOfflMG%2BW%2B8lTJQRC73%2FF%2FOBcxGDI6ui0OuD%2BCP5FhbQshP7mWhYGvS5u37yFSweXhA68Wqzg2o7Mg1KXMy%2FknAhgXMktM0U4bTaf4f7jB%2FjyT19gXEdvLYdzG41iGpS6AODVfIUn9x4INZJSk47HqF4Pl29cw2B3hB5zzboj%2BG4gUQvJ8RVnhSgLfX1UqKb7%2Bvs%2F0DvnxwJPgSI9FODRLQ2NZgOj3RGa7QZyrUSUxtgka2xSD0keQ3fIIiCbks6dSokMmYAV2DA1Xt8p4k0kka2gFcBZOkjLrFYapfgLo%2BoUC3PQaAbwAkdyuineRaObESQqay9WMyw3C1ik3jZ9%2BM0ATkihGB2ZViIm5b0q4RBsXr6Eq7dvojPoC106Wi4UeHAtESIjuI2SCK7vigBSWmRI1iscPXuKLz7%2FAx49f4JVGokjlo5giqddvnkDV2%2FfQGfQRZSlooPw8P4DnBweiaDU7mgP169dx97eAcJuB5evX8dyPBXxIuaGlhQc4hXDa%2FFrtWJf9UA9At5%2BXb%2F9Fx%2F4ne%2Fyve22zMGkEI2c3bkjKKCzBZznPjh3HLUPWaskUKsLTdR1fPBuGy6iPEdVUETIhlYykqjUWSXCSZAvCuQabLOEZbggKKRoj1BOtRy6thY1V5ZR0TUbhkaxOg%2BVlCYDPCuEyYhnbsq%2BCWTp5cnSDbKECNqAZbpwLF%2F2z%2FldVHN1U1RjNd2E7zXQbHThuQ1UuY60qGBZpNe6KFiCJYnFwUrRNB1kXxgoOIY2EVbzJdaLCGnE6LUNnedW8E7g64igHh1V8%2FlYACfPxXPaaPhttIMWAq8BLRwhSldYpUtERSzMHVL9Vca4Wte%2FW9%2B%2B2VsXry5a4KfcAhdgk4asUP04qVeyUBNokq7K%2FMd79%2B5JnuNg0JeIG2tqknpKryIT6hUYXYhR8MknHwvoe3D%2FHh49vCNGGalhzJGkh4%2B1Nan%2BStEL3imewpwogkcej3TY8fhM1ElJiRXPpabh6OgIv%2F%2F976U25t2P7qLdacn2PA%2FmdpLW%2B%2Fs%2F%2FB4s3cIp8caNG%2FjFL36Bg4MD2QfzNmnAyvYnx7I%2Fgk%2BX5Q8oeV%2Fnl76i5vzAVwSpLhTGoPEtdSe3RqFiPH3goCYX7u3C8u6G4DhRHnFG4NSdZp5a8sUHKudomVysSafOYemM3vliUJxSCTiik6EASxOQSiZf4O8jcNCBTRyLyAZpjQMaVmsuphoc14dj%2B7BorBuxGABloWExX%2BHxo2fYJCxTkoizgrBElPfo%2F9UMpGmB6WSOMaPfk4mUTCCYt%2B0QlhUCmiu5plyoDZ1CQwa6%2FQEsu4PFIsV0GmHF8hpnpzBnGparCeI4hWG7Et3YP%2BhhMOwgbNgwDYLEHIy2sGg2vepplmO5SnF6NsN8EcG0VckeigJFSYHZfIP1hteJJ%2BIfFY1cinqQzsQ2l%2Fbhs1fu%2F7%2FaV%2B%2Fuwe%2FvXWU8vjZROEbUOFHnwM85lngN0ngimKTTio%2FMEzdNOhMg4G1%2FZw%2BOaaHheUSkIvdPAEARqIIAkQRog2wAS5SKZ4uFGPGNTkcEyTinkLlBuhxHOAFjp90W6hsFPNphU8AIRAyIZU%2Bk4cUhtb%2B7L7TK7qCDbpcMiwIbqliuVqJwzQg2fwnnE95IvV0u1iIOtDMYwLVNYVvYjIJaJnyH9X8huZYP7z3E5%2F%2F2OZ49fybiRGwT3dahUTUyr5SoSVoiWm7w8tkRHt17JEDXcknTXCFsd9Hu9YVqSqPRtQOpLYgqFoVSgjaZ295xWW%2F74%2Fzj9zc6Xo%2BB8xRfmY%2FpbOF1Q7YHVVYFDhZIsxjgGGiFuHb9KvyQktaVCKewQbk953beSI126FDUNXFuzRZTeHQCocR8OcNsNkaWJ8pho5XwPAd7%2Bzvo9loCAB3HFNBqmIDtUM0TSNIYnk%2B19APs7e6Kyi3PIVoQ%2BMaImVNH1wYVbdnBhoHlZoXTwzGiKsPgYBe9UR%2BOZaDbaSNvhAiDAK5jIok2eP7sKf71j7%2FD%2FS%2F%2BjMnkTERlNMm9ddHbH2H36j5ag67Uf3zx7Bn%2B7fPP8dWfv8T8bALbsHD6%2FCUWZ1Pov6xw6co1hGGATqctkX6u66XUZKyBZl0eg22lrsntAKHI1PYq3eZNqL563395FB6V8746i%2B1x33Wk7fltz3f7yHPkTipxEPDUuX4qOyOHa6hoIp1RVGXNc6r0ilRtLTL0ugSbbXkCMCnellAl2FL5wkmUI4lz0QCoCo5N6ijYCAMHrtaEo7swdUfEmMjo4SJGNdyMVFnNRrvVQ6vZBFNkKH6XVolQbAn4qRJrGgSxqmYndQY2SSKieibLuvk2LN2GbdHx4kI5oig4l4kzfjYdYzadgKWVuMZRb8DQXBEGKkvqJujibFkuJ5jOX4qAENXWLX2Gpd1B3tmFMezDchwEfkvuVjSW308xI%2Bmd80vOu7rm4r2LFrhogb%2FYAhdgs24eGnwEd7xzsaZhRhD3r%2F%2F6b2JsjUY7ko%2FJSCCjhaTCUkCIgjuktP6n%2F%2FQfcevWLVCwh1HGP%2Fz%2B92i3WmLUT2dTMR55qOOTExwdvsA%2F%2F%2FP%2FwOnZGW7fvvXKqKOE%2FX%2F%2Ff%2F%2B7GG%2Bs4%2Fnzn%2F8cruthsVjit7%2F9jSpJUFW4c%2BcWTk6OwTIqjKgymnp6eiI0XeZKffbZz3Ht2nUBx9zmq6%2B%2BwmYTK7B5fCx5nfwd9JYzwslcuu1tC3C3r7%2FvR%2FYDSyAQINMo1gWM1d5PRsgk%2BPOBcza5Wsuav13460c6Jep%2F4oIm%2BqFlXN8Z9aZRK2J%2FBMs6pD7rsN%2BHYTYxnRc4Op4gSmcw3Bb8oAPTDUFsQTEn5uvxOxTw2URLUaNstXwxlAjIitQTBwEBiK4pIFnkHK%2BqdmdRrbBJS%2BIQwNZlnzlr3wnZiNtD6IUsVcGyPXRAdNotdDt9NMKOojShQhh2sLMDBGEJzWggSU3MFpkAGKojb5INStZJKxMYBpUqdVgO1XJ9FJWBOC4Yi5JFmsIPLBfESu1ZXmA6W2EyWyEvDbRbqvxGHC2RRDPMlhFmyxhhSADO%2BB2nJ4IYFd3cmlavnCKvLHQea9tX3%2FeI%2FRbHe20jvrExh03dTMqxwpglBWGKEpt1hJdHx3gaPEMx3EW%2F1cH%2B7p5EMo0SiJZLZJUm4JMRkYICSromESfTNsXopyc%2FKXLYno8oThBFG6VKLLVrOS5UnmXLbEh%2BOgWHRK2S1GdpTiX6w%2FxQ1u6lCFpv0BGDfTw5FuVuKmATdHLOXK7mePHiGXTDQpIUYpjyBxM8mZYtwEcok1IHUdVwZBkFCpewDuBosAOv0cQy2UguJoEmxDBmbJMR11KirKT%2FkuqbabnkqFE1lVFz3jn2ScGm8co7KegsjfDXx0ftyXijh76HF%2FUYUFeLOh7HPiM%2FdEbRUUWwPJtP8eDhA6yRoH9pF73dITqDtgimJBkVoitx7ORkyWSpAE3LV6JOLG1DkZ8sTaS0DjHgajkX4Mg5iyUqWE%2FVsU0YVogw9GUcsQQLKcuks4vADpVxDaDZDLC7uyO0XtZBZI7tfLnAlDU%2Fo42MOSrdThcLocMGSYB1spF8TTqeePcdG67dlX6hU8PUycxg2QqmUZiikM4yQNGaY6sQlfadK%2FsYHOwIrfPs5AzPHj3Cwy%2B%2BxPjoJYokk9JPp%2BsE2ToGY1%2FxYi0zyPjsTDmIebFxguVYqWcWiQbK2s8RUs8hcr3WPXIedH6A4aCmhvPHfX0Q5bZUr%2BstXn%2FIZzVTgk%2FVuXMMaJLXvd6sMZvP4ZkL2FogTkq9tETIh7We6VDiusWxwfmGLAU6Hh3bFXYVwaZcSyxLxHIzdBYmLDHEuYEOVNpLXIeZe23D0VxorGMpdS4dZoaImFhVqXJcDd9Dv9cVhwbrdi5Xa8zny3rdo8ow1yauewlcjXmnBpcMAayk2eqGiSBogYrMZOZD5%2FxCdlAq6yXXI8WIoqCgC01nNJSA1FCaAaJ8vUIUj5GSXl8yX3SJSN%2BIU8tzLDQ7ZHsxIBDCNF3oeSQrJwW63hwbb3bDxauLFrhogb%2FeAhdgk3N2HdmkYUzgKEI%2F7ZZMuiwbcvnyZdy9exfD4UgMAEYnGRl6%2BfKllBchYPv1r3%2BN4XAg4O3zzz8XgKpyK23sjHYk2kAq7nq1wv0HDwSQdtodDAZDiXYGQSBeP1JpKVRE5duPP%2F5U6mPe%2B%2Bo%2BHj9%2BLJ5KgmACx9PTMwHDp6fHcF0Hv%2Fzlr6QuJ8ul7OzsyT4JhAlgv%2FzyK0wnU5XbUBQCSgmMD%2FYPJGGfwJN5q7y9MuT%2F%2Bth5v1vQ1tNVLT3WAmPbUmiJZRPo3WTkRc5PXLjv99Bv701aQuPyogwjdWAFM9UqqtqqtsjV18VqES6w8hYLTauU6NSg14GmpVgsTpElETTNg23So8vFNJNFnMqNRkUqHMu%2FMDeGUT0qc8aIo7UskKxDSXoxo0csJcIz2kZtGmEDrd4uFpsM4%2BlcIhyqJmyJOCF4jwRQFHkitTnzUhU%2F5wItEZQiR5ZqWJMmt2QtUOZSApvFHPN1gcUyQVqkyGl4VswZZi6ZI0C3qFIsVmu8OCqxXtoIPQ0MuDQCA%2B2mgybr98GU8xhPV1isEjhuE93%2BnkTWptNTbOINZqsMk2WMdrcU7zUpmGwPqfPIKKd4weu2f7vT%2Fj2%2Frn0bklfNgvYgYE%2FAGoqBFaLphtjpDiSvspJSILlENmltaqS6sSwQBxNBHOsOGhYcu4IfNGBkqTiTGOUgIBR12TpKzJJCdOowp5zx%2BX6ni8ClgBRr4eXC3KBK9nC4I2I1rPFomTZyniiDVhQz8hwpn0Ol7NHuUEAKyweQfcEcLJZJcD1G4lnztZLyO3Q6SNkKCoI02rh%2B4xb8dguzzRLT9Qqn8wnGs4kYto7tSc1OCh4xOnLl8jX4JulxJXTbRrPfx2i4A57bOl7LvCzCZ3FSXwOsHcuyB1uHBaNaNZCQiCd%2Fywd2Xn3Hsbmdg3meBOqch07HYxQPH6IKLTR3%2BtL%2BolJLxwAvCdISWa5LKPekRaq6lMrZo8O2aKz7okTKccB6y6rMlAK1ZNlEcQRGw6m0HjYb8BueRBa5HVuMa%2BPe3r7oDbBsF9dB1l0lw2cLdknfDhohBv2h1O6kWBEVgRu9FryGj4C0W9OSMcl6nixjwZ0TnJCKfbC3C98wMdm%2FhLOTU0lhobOW6SZUyw07beGQLGYzzM7OEM3mYMK5SZ8UhWHyEuvZHPf%2B%2FIUIKLEW6HI2x2I6Fycm25S%2FhcBKmk0QW81q%2Bo799F02V2Pu%2FDfUGOR5SGfKR9vnwm%2BR92uejPoi20kNV7U1G00qQ3HNKFTdYl3N62zXTRyJg5r5v1w3yox9XSrBKLKpqBXAWtYcYzWNn%2Br7wrIwLJlHKqYx6My7ZloR64Yr8KkZSiCOJdyKOIFnlmgGloj86KYjDilS4H2%2FAdu0JB%2BS44XrTZmWyhYhG4KOKNuW3Gw6LJlGopkWXCeEp7F8nCvRcY5tzoubbCOpHnSAlFohUc9W1QDMLpxQFwZZXnKtoXOVwFOlqBCcagbFkFbIq6Vy7tFZVWpYbTwslg14QReGY8NhyonlQk%2BZU5rXQPMHckadHzIXzy9a4N9xC1yAzbrzuPRwImSdSwI2iqB8dPeuqNAyqkllV4JFTsSkgqzXaxHn4fsEm3fu3JHFl8Yet%2BMasrOzI%2BCUqxsX%2FX6vLws869tx8Se9h8dot1u4ceOmotZWFfr9vpRiuXLlmgDPS5cu48XzF0jSFAf7%2BxJhZZmUa9eu4fLlS%2Bj3e9jZ3ZVaavwuc522dCoaB59%2B8qmIBvHcmZfK8yOAHongEWkzxg8HMs9dPAL6AaHGEGyS4tcMG1KYnMBOI%2BDknM81%2BYPfiABoZHG552H5qFzJAgp4fDmP2gKg7VC%2FJ2OJZSRo8ElcsRJhlMWMkuwFgsAV73ypVYjijXh0uXfaXYzkMbJZ5gkMRgPTCMv5BGWZwjEAqV1mqlIwXIDlTq9vGGI4GsFcbLBYb8Sw4iLO00pXK5yNZ6IyiYp0qI2oGfP4FH05G%2BtoN03obQ%2Fj8SmOj8%2BwXmVIMxtJZiGHLSUVwqYvIIhe5LDpodn0kaZrpNkGqFijLUKyWWKiZ3CsHO2mhYOdnuQMMRq72RSYTNeIogJBq41We4Bmp404y4CzY6zjGNNlhGWUIgzpLWdusy1AgTlnHANiJIrj4VyD1z2kOuDf29%2FawKzzx%2BQVDT86E6i8atlSCogRBxqHFFRi7pJX52vrUqme9DleGzQeDblA2N6tVkcJj%2BmaRDRZQ5MOMBq%2BCtCUWK83ePHiOa1IWDrLqdDxBIkisr0bYShOKV50pL8pam0hKtws4TSc9zGZjdFotIRx0e4MJTLuOoyWOmLcMoqROxSf0oUqyXqPrL1HJxntZYqZXAp8DGkKJhFOZhM8fvZEqeQy8smSGLaLfm8A92Mb8eXrSuHWNGD7Ppq9jgjZLNZKiC1hPnTGyDszVYUZ%2FmpQKKN%2FGxKqUb5s9GqTH%2FwJz1EAXllCtwwUGsQuKswKAAAgAElEQVSpw4hno9lC2GxKDi7TLpjLZtgEBux%2FRccm%2FbokqOC8LvWJ1ThqNdsCQufTqdTPJJuCN85nBCEcW3RK0kHZHXQxMkcSKeP58M4xdengQJyVBA5c9zhOGbVutlsYDFm6ayy5eDdv3Madj%2B4gaDSktqvpmNBNDdFqLfMPa28SoEpaShQJiHJNSwlN9ftS%2F3W0syM1Pg%2BPjnB0%2FFJojkSmSRRhtZgjWq5Qxin0nABKQmmyNlR5geV0hs1iKf1fZoWAUAJw5tlLGi%2FBJqduTuP1cNjOKN%2FHAOCxeOw3jiknImf0asWpF5l3nxK3J9iUVUrBUjogBCzqlmg1EDwyf5LNQ4cCUxkoiiO1L2W8qOikui7UYbhbOjSpUl5QrbbK5EQJWmlXyDpNgFpVYpNEqxSZSceqB89lXWlenmRdOHAcpgGkIipMWjcdWbQ36PholA3oM0bxKzSaTbSDLkK3KfuxNMV4oEMizRM5f4YZWSprna5QaCk0PYOhZ7BcC22rhaBgmbEMm7jCYkEnq3LK8uRJBtYIOPUMmp7IuKXIkSaRUbK%2BIomyOq4htUSpjMv5VtpFnFNypfzF7nh3J128e9ECFy3AFrgAm%2FU44ATKCZaRzJ999pkI%2Buzu7AkAZOkRpR6r8pG4XRiGsi3rQXIGIq2WizvrbhI8clJmvggfKaxBAML90IgIGyGi6K7Uset0OxK1o%2Bd%2Fb39P6IPcFw1FRjhpcNKQY45MIuIerpQd4ALiOLYk0DebLdmWCm2MPIjvtoKAUirWEphuNpEsQgSb3C8jqYxoKlGkH4%2B1xcWXRvF8sZAcV7YXb3yfE78ykutO%2B2APcrTtUV%2BbBNJMtWXyqsnObSuLP2lazFPUZbFiqYr5dIbjoyPMZ1NoGmk6jOiwhqaJlFQdSXGhs0OJxJAWSKU%2B3kupA0bgWcFvh3Ald4qAom4TLuxlKUXa04x5MJl4jdlqFSlQuo6sZHH2CNpK0eEsU43FqkgQxxssFwS9DbRBunKCzWaBxYLUvACm3UWTuXxBA2leYjKdqJI9FgU7GjCMEHlOlb81kmiJPFmBFCxGZB2zUoq5IK2ywnIZY7lgwW1IXTfTVp5sRkh100ZSFJjMl5guSe314VcULaIH3pQ7vdkUaxARGxkR%2FJWvOuKDjYbvY8cq3qKOxLmC%2Bd27O7tSAqjfV4wJjVGb9RrL6QT9dhtmyBqZivLKeYYRPL3IYVL8wzIk95X0NtbHIzAhjZZgky3GoaqcT6yL6TPJS6KPJDiwVQlsLIMUOU9UXmlosmYio1jktzmuK4CT84iah0wZ071%2BD44TgvS5aBVjNlmKSFG72UQjDJAlMU5Oz7Ccz2Xu8kJPRbw6LXh%2BAM21sclTuXZIn9xe%2F5wHCXbNjo7cC%2BuT1AFLF3ounRB04IW%2Bh9DzJQ81l%2BgmoyfKYXTeoD7fp9IeMkP%2FOMYSz5OCLXITQKRJjeUrV6%2Fj8pVraHe6rGwi%2BdKsMUqKs%2BcrNXWTBjVzEanQmalcaQo%2FGYYFPzCRpznyYqLSKmLSizlPcT7RRYzJcXypW%2Bkxim05qHRGowk2FShptjoIwpY4q1gWjFRb5kpyPWy12iDDIlpFIlJHp2aj1RIxIFInp%2BMpXp68hOma2DvYE7C6nC1w9OIQ8WaDkPUzO110Wm0Rxeq4rPNK1e419NNTFHmGPEnAUjslxa8YISfNWgJk7DvODQSRPN9ScgIleieuwm1qxKtmVVMHp%2B8f4Maz5aHPjzg1B9QnxA%2B26rP1Rue3VafM2qEqi0PQGFMrxGml5nc6zrnOcI3n9U6HHddWloixmbIhOyRDhs4GRpg55vjI0iC6pLGQxZBmtXoda11RwI%2BzMoEq88MtE6WnifqrfLuOgos9ZZrwXGai29BIcxXGRAFT0xG4PsIikHNgzUzL4La0s1yYzEMvCBapKB3D0aniHirWRMn1aY5VPAe0HK6rwfE1qYduspJSxjU1RVXFwtbaMrbYADwnJTTHi4p5uWTpUPmaDrgt68NQo0jWcvZRKfmvpPl%2BP7bHDzAYLw550QLfQwv8BMEmp9Y3VxhOIgSK%2FNcIm6BiLBc5WWxrgCMTFScgLmkSWYEslgRuvIkXWfajPL50hm23oxdYFsF60Ws2Q%2FHqcjei2oYKfhhgr9yTBYbRUe6Piyf34%2FuWTMJbryInUAJSGol8zm23x%2BK58FicXKWelmVL%2FU5ltNHzzUmXkTH1W97nBPr1lpWm%2BW5%2Fai%2F6ayNT5dcoQ1Gd83fb4d%2B7NccKzQAeextWVXFOtWf1%2BWt%2Bk2pf9h35bVzcJ2djTCdjiS4ZohaqS15UARtxRtEPemlZaocAgRTIhkRAGdEcn72UaBBzqjTUhr1tijc7KwgsczBn62x8hrQ0EKX0NsegGixzX0nPZXxH%2FN6koZoGGi3Wgw2QbBaI1lMR4DEt5kopxcf5bIE0ZWTWheuRTteA5fqgWuRmrWNZpRLRLPIILEnBe2bR4CiQ6SWYGsR6mf1uiHa7D9P0MF%2BtMJ0uxchlhIG1BKWMRZaC%2BUWMcjC6QjrufLFCnLYFqGYU0JLritF6StGrCJ4yjOo%2Bkb75e%2Fv5hxhb9QiS6UiNLV6PfEkwt7u3h%2F2DAyldxN6nxP98QYGnE7gEk6xTKSJQVCGmyBJzmEpYro1GqyniMaQ%2BVusVFvMFVqw1WM9nvL5oUPa6XRFoodXqM1JF4zLOVPSD9HpGS3XS76jCvcFyM4Pl6TBdlsrIEKexoq7xvCZnaLG%2FKXhFJeY4EdEOUhspDOR7jISx%2F8h8jLDeFEjLFKUBmIErZTNm6yUOD4%2Fw%2FPkLLBZz9DodaSQKnrB8y%2BToVJQniYhJ%2FWN%2BarvXQXfYFdr9zmiE0WiAyeIMaRHJ%2FhWAZrtKQ39toJwfRT%2FcKDh3Wpz06zuNbs00MByMcP36DYxGu3DdQEqCMEp1cnwqkc3RaCTGOqcdQq71ao3VYiEORdY%2F7HUHcC0HzPFO0kz6klRtHsYwVX6r6%2FrY3d1Db9BXDgSK9tBwl1NTOd%2Bs%2FcmcyhWFvk7HIk7Vb3dF8Zbgk04tpm8cHr7A7t6u1AE1LFOU0Kk9wM%2B83BXQS4E6nmsax1jM5ijTDL7twXd9ybfltT6ZTPHkyVP5nXTaMmpJBVWWFbOMbaRdOdzUtaNopLx%2B6AjhWp4lKRazBZIollxf%2BTnvHgrnOuEvP317nJzf3duffdOezm%2B3HZt8rJg6INi4nrdl%2Fq5B5bmdcc4kCBIgJRFsQ1RkuQkjmnRA%2BARvJnPBKR5FRXqWDaqQmYwoUiSWdkYl5d1Ir0ZcqcgjS7M5VEsnkzQThWqtyEX4iY86ChGesgMHoWeLyi3LHPF0lG1BlyDL6HJd0KXMEqOHjFJSXVl36EZUtGDOE5v1CglVz60cLJrJc83oGNnkKAwbts0yLQ50g%2BCQpUk2YHVeiuvZpS22Euco0sOXiwUW8wim1a0BonL%2BigYAHZglc5iVsD3bSq0vXLdV44qzR%2BqX1vWzheGkPqw3OdcLypo83%2F9vfHjx4qIFLlpAWuAnBjY5VXBa2D6%2BHgVb0KWiTJy8lCdLeXTfnGJkUavpKpxYuTBstxeo9%2BbmsuCrLdRfUp7U8RiVUNE65lmp27unLW5PwMGbAl6K6kLjjZMkz2H7G%2BodyXv8XAy87ZvnHtWk%2Bv6jhV9v3XMHfeupLK6vGlAaXaihEkm26zahN1UnJea1kNFbu%2FkAL9kPb%2FaFIipta53xkNttzm%2FHX6%2FOk4ZimqbIuDgbCujRcDdMlYdFCu1iMROhBJFAIT5tNbB%2F8zp290Y4PT5CkbN0TiaiGqyDxnZhtKkqldIr98XAxGq9xIbCDxRGYIYka1zWnmSOSVLdqIzLqGq720Wv18RqzhqNsZTCINCl6mu73RD12zjWMJ9DinEv1oxgUJevVGqYVYpok%2BDZsw1EYETyf1iqJGMtd3RaPg72%2Btjf7aMZumKQkmI7nc2QMxGU4iFTKvKuZWzSq5znkcrNzAuJwlEgJyZm0TPYVin5YsrZrCIU4lDhdcymf%2Bt6%2B%2FsGw3vdmTqV88PjL5ycXL%2B1xaOud0MAoZSyYH5blkrdXhrvzItrtpSwDxuAQPBkPAEph8zhu3z1Mi5duSzCGqwVfHZ6KsXVGUEQ%2FauClDiq1xK0Un1YF8XkjOUhJDqhlLlZlJ2qXFQdHp9NcDp9ibDtyn25WmK5Xkn0gUJUFCkbDffhOQ34roV%2Bt4dm0Bb6LKOfjKZwUmqEPq5fvyp0camBaepIqwKLaC2lLFhf%2BP6jBxKZ5fxA%2F0KSxHj65DH%2Bv%2F%2FxLzh6dlhH4zQBM1euX8Gnn32CvSu70iZMJWieNDHfzFCkOQoReXl3J0hvS2med3%2F%2BF7rrb%2FpIzblqDt%2FOvzJ3cyBvT6EeguwHCvtQp5gUVjo%2FObfQoSBrgKaJcW1TcMd1JS2DdFLe14ulCMexvvOlS1fw6ScunK6aE%2BjcGU%2Bnkq7AY0vfM7fStmGQUZHpMCzOBwao5WnR8NYo3EYaYi71GMmUef78udCtPcuFrZtSCow0fI4DOtnI1Bnu7iB0mdfrS6rH7v4uHArKuKrOY%2BC66LU7UpKHRr%2BASCl5o2O1XOGLP3%2BB3%2FzLbyVSy0g%2FHa78buAH8Hxf6qySZkyKKOcig1Rc20ZvNMTtW7dBcTaKCd3%2F8h6OD18iK9OaPsvZ%2FLtd69x6e2dXbb%2B97TYOCO7z9WfnP3n3cHnTBXJ%2B%2B%2B3et4%2Bvv6%2FOQTkk5FOK4MjIYJpBfV4ESGWBsmKkm8rEtBN4NZUiCEV1YdNiNFvZLxwHRZLi9ORUosJ7uzvo2m2JdJK1kkZrVFks3y%2FzCGVG6jMZCEqAx9QAm%2BWQRKiLmgMseUXarALPnPeX8wWSLILbcMVBzj4jtT5PWYtzCs8K0HBaCGwKF9rwdQ%2BaR3caaeB0UuXQmRva9uGGO%2FJDWRrFtDTkZYTlKsJ8tsR4MsFylSFskFlGdgQjt7rUc0bJRcWrHU8s9cRa546q%2FUktBK0W5aKTVqK9apzQKSJmyte741XHsPfO3199cPHkogUuWuCnSKPlbMEpYfv45ihQgG07o7z2dr251Xlg983bvP2d7evXoPD8d88vNK%2B2lIWiXj62b8qjinyKDSCvaxu13kad%2F5vvvfH1%2Bjvb3%2Fn1z%2F7Wd7atun3kfr72y7bNf25x5qLI38lICqXwSRsm7Y55Xcx33QJN2ZcA67%2F1DL%2Ft97Ztsz17vt56mtXw4dKt%2BHznt1H759Z0RIiRtTNCqXswjudYrKjoyLwhJcCSZbHkrJAeywU6z0gTWsEyd7GzM8LpyRGSmEAsV8aVSZoQBWKoUqmMUdbHGwx7GOxeRpJrOD6diLw9%2B5%2F0QlKdmOvJXBkWtqYi8nwxQRLNYSLB3s4InW5bFnjK25O%2BxNqtyyWZaiWSHKIOqpsVdIOLbwpJEQMkkkGDwtRNya%2FSQK93jmGPESn6skyk%2FE1RLMA6jpfQTQqPbLBarsVoZjuZzD2sMiRRgvHJKU5bDlr%2BCF5DUUJNxxDvOAWVJMKvYrWqI75tl37jdqpvv%2FHjv%2BGD7R4F59Rn%2Beq97Qy0HTZ8XdNU9ZK1M3Xpg8PDQ7T9FordDMN2F4woMJotOVoUktIqAaBsjzhNBPgd09BnmaXAw3BnR3Jt0zQRIaAiV%2FlS%2FDkEGLzNZnOVG6nrGPZ78GxS85WAC73%2FrO0ZR5kIEHW7ffg0FD0grTZYRzHOxhNQ3Zg5khQbYtkVCjsZmgHDsuHZFPbgtcCIk%2FrhlaHDrCgwwmhtDr72LJOl%2BOS84liVLOG4IHUyTRIkNoWtNpiv5lK2g84ZRnq1hYm0StEdddHd60qbMNrJlALmM0Olm31zD4oFyfNSxvs3b%2Fg%2BPtl2uJo5tq9kPaCHgDQ%2FzoHiIDSUQQ7KLUGE5Y6PXsJq%2BWhWPZgec8qoJqrJHOm5rJ9YoKhyUYZm27HGM1XLmcdL%2FYBmoyEOKJarobptljM3PBelVjINmD95cnYiyrLtThvdflfUvxlBNS3mhxuSo8d%2B5v6ZosEoY%2BB4OD06FpC5mM8F%2BMm%2BGT0nY4h0bMsVkEjlW36XoIcrA52sZmACJAgRXBNIc3yapgBsjitGvthGVKZdzpdohm002l2ErTYsRu5cFxbzm21bRfYDD9du38Kn%2F8t%2FkDJBhnFPNA84EAnSCRxk9AtFue5XaXt1ofJYW9D4Tb3OMf2u27ZPFTLhFuqd12v%2B62%2FJPvjxOWeIeq92osmVw%2B3PrTvydX5J7ZdRSrYlq6Cy3IwStMkkB5GOTE%2F34eq%2B5DSTWsw1hs4b9gNfM8qt%2BkgxDuiI4HxB9lXQcJEVGyzmU8TrpUQzHYtOKXF5IM82WEVrJJsKnt1Eu0FWAxkoFCXj%2BeWKgMJccDoyel0ptVOZFWIwRzIVoS%2BW5yFln2MxJ9U3jWUe8RxHBMhElbakw5bsF17QdHiQEkvhIjrhqXbOvmV5LwrbUY2ZzC6q2NLGIlA0RADP0AIELmm6zOPlWPQQBi202x2llFstpO14DoparGwSEeEiRJV5Qo3dugsEuLIXlFDX6%2F69eHbRAhct8LoFfmKRze0P55Qus%2Fz2jXc8ftNy8o5N%2F%2Ba3vs0xvr7Nuxau7eLzLmD6N5%2Fee%2Fji2628Nb63Nt4rzF879kkhItikgBHBEalWCmjWG%2FALX2%2BS93Cm79gF0Zpa0%2BVDeXr%2B2Nvn57bZ7oWLD79OkDcY9gE7xDoB5qszKZJOoSCduW82f2NDcpW4yLNe2Ivnz8AgEHN%2FRXVWN5WRRMPMosIe6U1KAIWgleCVBc%2F390dYrjNMZ3MBlVJXmxFVXUPge0LFXq0WGI9PMJ9T1j3FqMfcY%2Bb8erKIk2LdbnVw%2BZKL%2Fb0QltvDOsrw%2FOgFjk8PkecqEjoYdLC3vyv0K3qzab6RvkSKJ5%2FTQE3SHHGcYbFYCSWSQNfzDPSGXbS6fWVoSh3JEmkSy2%2BfTk6UQi%2FLINQCOVUZC6WKhhSNqm2Am2Np2wXbdv8xPso5coy8Y5zwNyhDhsYSDSOV60vA9fTZU%2BiFJnlpIWmBFHzizpgWDObZxpKLTc891RN39vagW5aAPgrJ8EZARgOMhc836zVMqhnXudrsNSrRUu2aFMgb167iYHdX8qnYyIxkResUk%2Blc8via7RBBy0OuxTiZraR8wXLFfNBE9s86v38M%2F4Bm8BxVYYka7c7OPnZ2hggCRes%2BOzvFs6ePJe9XQJVhIGw1MdrfgxP6inZHhUqJlrNNVM1DGseOa8P1HVGh5LXCcwx9H8PdodBobdfGKlthk7Ae7ApREguNnHw9Um4VM4F%2F65tMKSq%2FTyIw7%2Bif7abf66OwZgxQ2ZXKz3FZYExV8S%2B%2BQKRluKzdQGfUk9qpnEccUwdVpsfLuYD%2BdquNdquBzz77FKPhUIxxRoA4Z%2BRFpgx%2BKkpbBpzAlwgQ5yo6uZ49e4rDo0PsUj%2FA0gWkcKyZLseehheHL2QcXT7Yx3AwEIDIvElGqQg0WZuajirO2Q8ePUCUJkL1JN2z3W7ixo1rGO0Mhe0TbdZ48ew5nj55IuPHsR0Rr9vZ3QFF%2BdI4RcbcTDpT4hgnL08xPptiNNxDs9XGlRs3sFyuUBn3ZM6Li1Ii%2Ftdu38aNjz9CZ38HVZKiZM3HesHh9Ua%2FVq2r9apb2fVsg1dj49WTV5t87ck3bvLGODq%2F1fnn754PeAbcSv7WS965EfvqHNSe1ASofgvFj3IOBxRkImwWmBcWnMpBy%2BsgsAMVbeTMIXmKBGCkVCfSF2Q3eIEvFOr1egnD1lFqdG4lSLMIZZGKU5RrDYEeNQRY23fJuX0aI%2FQScSiEfkMijVxzOEvF8RpRSVEiS8qAcb9JGSNeReLkIoVaUfdjTIszFEmFmT2HZ%2Fhy3n3W5%2FQbAl430Rqnk5eYr6fCFmINTdvxwTzxoMESbjRn2XJcI0gbZppJgqIMxOlp6lRFDyQ9w9Q0eFRwD%2FvY6e6D14xmFlLqJ2IkN02UmBp%2FhqQevWp6ecLZ5NxoedfU%2FuYXLl5dtMBPvAV%2BomCTva6m6x%2B%2B%2F9%2FXebyv%2Fby%2FFtmuuW9Oy%2B%2FYvzj1VRkP2gSUaW%2BaDXH40gtNL7Hso7YG%2BPD93La%2FQB2Nhj7fUUbr9rkyUl5HRmgh1LkesuiR9sX8GVsW4bJKBWzS%2B0svs20pMZhG6GG5pAALa7euURYJOt0uNpu1gArukx5%2BliThjd5sFmRnJNQ0NTRCVwpsEyCYOvMcC1j06pakUFVSNL3Z8KFrOVZLQ8RDLFMXZVwa8ZIKySiJ40gJn1aTeaEhisLD8dkEJ2fEOBmg50K1vXZtD1euXBakRKplGuc4OiLtdia5PKSykRLH7mM%2BznxOcaQcnXaAa1cG2Ds4gGU7ImjFXBvmmB0fUR2QuWZTbJZLyfdrBVRlzQWAmmYpEVCeq9iO24H1Zjd9P0PjOx6FQ%2Fb8nV%2FfDmN5rBVomTdO2iSBwWI5x9nkDIvRroposli5bcKFJwb8ZDGXdvPcAEGjhWGzhUanK6UrLJtlSZSjhsJkFD5jfjmvJDpzVB65LkBxzLJIWY7dnVgiQynz4kiJg4ZNHONsMkFWlKCYj%2BN7UkuPwDiKUwjYjFOhqlHx%2BPd%2F%2BCMcM0Qr7OHypeuguJFGw7TMMJtN8NX9P0sNYjpVSNtkiY2r16%2BjNejCKCwRMZFIDUurMAIqtR8NKYXT63dx9%2BM7aDUCZGkmJRLCVgtXr1%2FDaH8Hum1IjuFys8Q6iUAlS8l%2Fe6uvtsNG3ubl%2BkHGz3anqpfF%2BVSfx6uxu93k7fMj9ZCRP3pViCeqUijQJ0eHcDsB%2BvtDcdgwWtRtNaU9qjwThdY8pRK0JWrqN65fx85wJCqbFPwhAKAR3ia4Hw7lGuPYaDWbEt2S0iezKabTCZrtpuSYm2Rc1FTLJEnx7NlzLJlL226j02yJQ4isC%2FZHEsdyj%2BNIzv3hgwd4cXgElj9hXq1t35DJkpGoJEnw9MlT%2FOF3v8e9r%2B5hvVwJnfvq1auSAz7sDev5X5c5jPU%2Bx6djnJ2Msb60BvNQDy5fEdpsq98X6iRzUClSdOv2HezQWek4OD4%2BwYujQ6k5ScEp3raAU3qmHgyMVW2vx7e64z295N7ffQT1rhoM6u92u%2FPf2b53%2FnQUDFVblRLZludVLs6HqFxhbS5kTWE9So4pXlNM4%2BFaxhx5YQdwnHHu9zwMRgP4a4qCmZKrzW05V%2FAe50ybINAk%2FZaR0UKi51yjLCpPl0o8TNMJ9liLkzm8K6RJBEYpDbMt9GyeB9kXdH4xmkmqK3ODszhDmVRInRSB1YAFC3nYAMuvMFIaxVRVP8bZ5AQJ0zHgImh0YLsubEYr5cKioA%2FXWM45EbjeEhjSGdftjCR3PMsjsCRO4DMa20E7aItY2TqhMN4Yi%2BVE2mzr6PqmfjvfE%2B98vo2Wv%2FPDizcvWuCn1QI%2FYbD50%2Bro7%2FvXbu2oei1%2F5%2BEFO8oaWtfuYgU1Lhg1jUnBOfWX%2Fkr596419517%2F3vf5Jmfv3N%2Faln%2F%2Bp7Pb7d9rihLzEfk9wiYoGWokIHCOlTU20QsrF3BdhrU4EUSr%2BSzMifgLMQrTOojabSM9CyXC5yeHcPz1P426yXiZCOUqDBw4Fq6App6AYN3gjSd4JNZnBmqMhEZel0vYJESqxd1aZUpNm0KSblijPJYuakhXm9wdnaGp88PMRkfQdMydFoeDvb72B11JJeyLCqhQm2yNdbLCeJogVYzhOPqkKBllWITEThOpZRLr%2Btj1A%2FQb7MeJJuYOTIabM1CGfuYnbnYzHIspjOps9cMTTRJpRUhLLa%2FyjXkWPjm%2Fvh6D%2F2o3yHQ5J0EPxZML2golSjJH1NoQ8iUpM1SSMzUAmimjtl0BuZj%2BmEDmmVK9Clg5NK1pW1JK%2BSNZSlu3b6N5XopAkOMBHiuJ8eIWQ6lAhxGNvxQ6l9SHZK0V1W7k%2FnFGlhSQUSc6PjR2LcuPJ8iRC14wUL8K47lCqHPdGwMdoZgLuVwdwDT1rFYz%2FH0xWM8fHwfk9mZ5O5qpibRM7%2FhwwscAYdxGgngJNgmUBQBNTqjDE3KcYTBZ7h7947klTKbUbMtuFRiNXUsNiucTE4xIe0vjeT7jLApwMnr8vWNr76fqeTccWVqkD8yz3Gu47%2B3b%2FKu5GuyzSmIUkErKhHQoZSzzrxFw4TTaMIxCRJsEQVjSRDmazIPjjRRgnmv40j%2FqetF3sTB7h4%2Bun0L68VC2qAlub%2BaREqZP8d2YeqColeaQk3mtMxxSZTC5wQq9KmR7pohl%2FmJpaqofM5Iu%2FqplTgOB8Mhrt28gTsf3ZaIJVv%2B9PgU97%2B6j%2BdPn6HIcmGw2Cbzem1RopVrodRgVJR1Yd2OClSuffr4MbrtDnCNoLmNyzduYLR%2FIJRMCtyQ%2BcFyKyyXMxuPcf%2BLL3Hv3j2MJ2OJ3pvUSFBXmkQ32faCUd4ksbzdJR%2F2NRvra4Nx%2B4aKob12dL55KtyKWyiFWI4VUkMraBw%2FEtljDVTmULJtdPgsu%2BWyDiYFvnjtl2C%2BJecbTscEnKydKuuWXgkTImy2kOQbJBTzqrh22BItrwrOVQrASxS%2BjmZKrihVjBlj5PwuAjtM%2BchFlIi%2FlaJFnu%2FCyRwUaQETJizDFkEjsjiaPtWNQzi%2BJRFWit4t13NROmfNXNJjSe22HY5Tzkl5DTKZV6pySystljVXo7PVctEzhqpSQMExronAFGuAsizKMppjujjC6fQF5sszZAUdJkVNcVYpB2pUv9n%2Bf%2B2V2Cx%2FbaOLzy9a4CfQAhdg8yfQyT%2FUT1RmlTr6dul8%2B1xksZTIZh0Q5AYVRFiHXlSrNnpemWVcdb9pZ2%2Fv%2FO96vT37d3E1lQHw9d2f%2B47kJBUqCir13ZjnSBGLFJvNVHJd0ow02xCu1YFlUIadVCTA9C0xjKLFWuhoPiOAtoU0WuLliydwzFSUY%2BfzM2TpGo2whcDVUaQrpNEcKCIYFfNh1kBWoMrXYC20ZDMBabTJZgVDK1GkESZnSzzV1vCsFPreUB3Ab%2BkAACAASURBVCyvJC4wncU4O93g9GyFCfOwykQBzUsDXN7vQddivHh2pAxO3cZqscF8eiznYGoutCpBGi9Q5gTRCwAJwsBCvxeiGTJ2t4ZeUuWUpQoM2KT6OhW6DQebhiuUXpZPkfwb05UIsG4UksNH4SNlMIpsw%2FczHL7e2e%2FtHRnO9LxIlI11VkmJU1Eo1iaU8hNUf7RNdPpd2KYuwCAuUqTM%2FaXXP09QphR2MaE7LGFTYJPFQg20PRuXrl3GMlqCNNad%2FV0BpJskRpylUqO12WzACTxW7UFJo9E0kBPcNgPsX96H43qwPAdJwfqrsdB1969cRoIcfrOB6XQmJXL2RgdQ9330Oj2Jbi82czx5%2BhD3HnyByWKCnf0Rur2uREva3Q5Ge3uwPBvLzRqbZI0o3cjdik055%2FlqCs%2B3wDqM1FEjIBHwwzItFMkpYslpfHl2jPuP7uHo5BDz1UxyhWkEU5SLV6bcXj3ZvvFhH3meBJXsz62x%2BvYpqM9fvyuRN05zfEvEmhR13NYNoSM6uik5igImbSX08nK5xnq6VCrltifUa5a6oCI5lUnptCKQpDLooNvDzas3sJot5ceP%2BkPolSagjwJSrG3c8APYUo%2BRObeV5GayrubN6zfF%2BdXvDmDpFv5%2F9t5ESW4j2RY8WBK5Z9bG4ipKLbV6ez3vzZiN2fz%2FD4zNvLF73%2B3bt7VQErcia6%2FKFcDYOR4OILOqRFIiRYrMrMoEEKu7RyDCPdzDo5jnPEECLOO%2F%2F%2F2%2Fo5v18M0338nsdXdvHw8%2Bf4h7Dz7Drdv7OoajXJZ48uQp%2FuPf%2FoEfvv8J7VYXD%2F70mfoOj76gxvXO7j6wKHF0cIizoxOU80J1XJ6c4z%2F%2F7T%2BwmCx0rM5Xf%2FwKu3t78jgb9wemreMxUAua9B7hf%2F3P%2Fw%2F%2F9n%2F%2FP3j57BmWUzoGqqTgypSWBNCxFu%2B2G1wpXW3bGLmun9I81K8mlHpPqUMZYt%2BYCzRcnIhKmadGCTXkub6dfgtRj6J7Ah5Fczo506JNlEVICu5pnOt9lanrPJcZOp3ypN02BltbmBY0qZ2j1elKo7ykOXKaoNPvyvN10uZu%2FQUWJRc1U2Qxzd476PQytLnnt03T3BxlnINjErWoi3gGXJQy9%2B21%2B9jZ2sO4v41eNgAdTy2jGY7Oz3ByfIjnB0%2BwLOfYvjXWokKU8BzPAXqjDFG6xBKXWEYT5PEERVIgj84xWxxjMmPf6Gthh2MBzW3D9nFczi4xnRzj7PwZjk6f4vjiGSbzUxQRNac295tBlVHbaX%2BlQW8IcL6lbqsbEm6CNxT4yCmwETY%2F8gb%2BUNHj4FsN3MGUTSv9kZ2zeXx8rKNlyPSAzgN07pydk0UTnd%2FOlPZmCmp6p3aC2gdhwymMDI2dB8n7WOu7XE1fII4WiIsp5pMFZlw0jTJ0h21sD2IM%2Bxkw76FH1%2B8ldFTF82dn2N7awe3925ooj45fYDE9weVZC8sswnJ6gm6ag6am88sj%2FOcP3%2BHg8FSeYulhr5zFKClszi5weUkNonna2xl0tadrMTvH2elLnLx8ihfDBLuDthjJFy9OcPDiFCenc8yXMXrtFOPtMe7c3cGdO7sYb6V4efgcj775X5hMuJenhelkiZOTU3mCHPZjjPo8S42NHOP%2B3W302l%2BgncW4d28P22QOQE%2BGOtVNHgyLMsa4H%2BGrh%2FvY3%2BnLEUS7zTJSoFjIFDAm402GkR%2BzrhbV2Q4fy2TOlXAycPwjR7Skp14uHCQFWt0ESdcc7lzML%2FDs9IW0mxMssT2%2FQKvVrc7Qnc9ppvidND4PH34GOpDZ3t9GZ9jG3bt35azl%2FGKCwbiPrwZfSUjhnjrujVQXTiMskwJpv4VRm3uHedhBgfPpGSaLC0RZie6oj1t393G5nGD3zr6O5bhz6y52xjvotXugSeeTpz%2Fhu%2B%2B%2FwTff%2FlN7hUfDAb786x%2Fw8MFnWkChJiXr9UBfH2dHp3hxeoCLxTmW0Rynk2P841%2F%2FjuOzA4z6A3m71H67MHawJywjyFMymeeLKb2svsDzl88xXVyG8YW9g3qf8FkzbTPNAxnQ99OJWK0c1hAu7tnVH4VTO5qBDoCoUJQHWh6DkpdIqPGLUrTSjs4LJOyLyxxHz46QT3Js9bZk5kgt12Aw1EIBjzN6%2BviJzsHk2dDDdh9b%2FTF4RvP92w9ArWAxK3Dv1j30vxjg9t076I9GmOVLOQdLi1QCyf72bWmnaMK7nC5wdPBCx5GwfW7v7mN6d4o4j6Uhk5C5fweD7bFMNy%2FOz%2FHdd9%2FhH%2F%2F4hzzZ0oTyi4cP8Zc%2F%2FRk7Ozvotjvo9ftoZR0s6O32X4%2F0XV7O0SpoWp5jcTHDsx8eq%2B4fvnuEvVu3sL29I6dWHASm87m8Xr84eIEXT5%2Fi7OAQOfd%2FS3MXSXtHbSnp62OGX72LfGhXCSycI9nvgzacYYSbz%2FzwWR85w2Ec1c4lyiSXwLaIZrI04QIu92CezS9xNDnSvLpIBpiio72xPE6NJrNnsxOZS%2FMQU%2B6zp0CacUBfxIha9B69VL%2FMem10h3b2d9yJsSxmmNF8lfspkxitNvdfp3LYM11OpZks40Ljx2hniHl6C%2BURjzopMOyP5MSq1%2BlqUYWLjcen5zg5PJIJ%2FmRyjp3dMca3%2Bsg6XR17kra4EFtisjjB6ewAZ4uXmOIU9J2%2BnJXIXwLHF9zCQc%2Bz4Yi72M4YpVZ2sZhiueRRX0eYzI4wy8%2B0J537VWk%2BLlfvJGxgOFgG7%2F2PZNd9iFf7SHuulHUns9bZ%2FG4o8MlSYCNsfrJN%2F54RtzHbJlBOlX4EDM%2Fgm1ziyZMnOsg52Yt0eH3LvcJULMJ7hr%2BqnlO%2Bpv0GC2xCJx3ccAk9KbnanCOLC3nCG5BJTDK0233s7m7j1nYH%2FV4L%2FfYOFrOBnG0cPI%2FQTRfguYF7t%2FZ0LuXWoNBkvrPTRasVoRUNcNEBtsYd9LISL%2FMLpOUEW%2F0WhsO%2BmMzLyylaPOy7oHkV91Em2NoeY2d7hHy5hdPjDs5OXqLfjtFOeA5CJDi7KZCO7ZzNwXiA8XYf460e%2BkMekbDEeTKXhpXOYigMdtIY3V2aPo1w99YI28MM3Ta91MboZWNsj7kXMcdwkKEV254imlfR7I%2F0o4aK5pbd7Qxbo5bMukoshSedJdHMS8cbKHnwJynG6kNnFauOcuMN2cSmpoPP1EzyXFMeUD7P55iQQbw80%2F4nvh8HLw7wXz98g%2BcHL%2FDT4XP0%2ByO0M%2B7N3MGtvVuYzib4j%2F%2F175hcXuLo4khnTz57%2FgQvXr7E%2BfwSe7u3dDYnBU4dIdFNkMdLnJyd4%2BT4RNry27coWKQ6m5GCwvMXB3h68FjC5mC7j96oi8vpBC9ODrUHb7S3jTwpcHR5jB%2Bf%2FiSnNk%2BePMbjxz%2Fi%2BcFT7S%2BO2hFmFJ5bJZAB02KKy%2FOpztD8x3%2F9E9%2F%2B%2BC2oCV3SBLws8JJ7qMI%2BYB7wIGcogZLUSNF2wL70xJpjtpjqDM8ysmNddLSKRpmGdvOaMUSKxxtb6JdGqGWVWcKBywNB0Gn2XB9F%2FMpMhFg4k50lgMsS5aLQAlJxOcdsWeiMWjra%2BeFf3%2BHxv37EEwCHPz6X05f%2BYID9%2FX31i8ePn%2BKHRz9id2cX85OpPNEePX6B46dHGGUDaT%2BPnr%2BUWWx%2F1EW7THF5eI6Do0N5OubZm6PxSAtE9DT78vgJnj1%2BgudPn6KbtXH%2F7l2NM5dHZ5ieXEggzsqERybi6PFzPDs4wMuXL0EnUo8efS8nVhRQ4znQiTIMsz7a1FhPc5y8PMCTH37C9%2F%2F4BmcHxygnC2RcedFm7QjzswmeTx%2Fj5OAIz4ZPdJ4kBRoKATz79ZzH8VxOkM9mKGcLJMucMhOo5KOgaSMOKRwaRC3UbA0FfJA%2FZvJrok4lYAbtObGhybj58y2kRczjBWblBOeLE5R5pDMml8tSjpVenh5JgD%2BZ8hgaO2ZpPB%2FpvNrTs1McH1NIKzAc9ZBlCS5nZ2auHC2woDCWc3MGLS5aKNIZLhbctzvD6ewI7TIT3TMejZJD7%2F75xSl43BffzVavhaQd4fj8EGeTU3lUjnVscI6L%2BQmOTl5gejnB%2BemZHM9NJxfS1g6SDHlrTvMG85TM7SeLHGeXL%2FDy4jHOZi8wLSls0vScDn8KnFCDm%2FMYFh6tQxNgegyj52Oa%2BHLRkyb3FyioGY2n3FGqbQtlxH3r7C3%2BCYtSQdT00OaVMicFen382kywud9Q4BOlwEbY%2FEQb%2FoNBm3uBtGpr3lvp8ZCOHg4ODmT6tTMeh9VcE%2Bmqgfy9IKDpfI1JaQLi8dw7Q70L3dFzTwyPdkiwuzXE8sEdpO0e0oxHAfQw6I%2Bk1cyyCONeFzG6Ytw7yRQ74wQ729vo9zLkZYLxaFv7Xro9MgcArU0vLzJ0Oz0510C%2Bg60hV3wzDIYjcNX38oLeQjmL86DvFO2shR4P4h705Jlvsk0T2K6OqBj3O1hmdrbeiBplal4H3JfXRdblHhk6mJhLWzvsRvjszo40m0XOHVYUnulGvgdqrwadGFlizop4AgrN8%2BzIkrnOPCt55AU1wNxfFvYskpPluW0FlZlhxV7OJjSDU4NFLDjhm%2FMaM0109tyvzfb4%2Fdyr53BfZNh%2Fxb1U9Bx6Ob3QcRTffPsvHYNzcUEvsKc4Pj3Gj49%2FwuHxMZ4ev9A%2BKjrB2Nrawc7ONhZznoP6SJrqy%2BUFbr3YlafQZ0%2Bf4qfnT3TmIZXEfNfoOOjw%2FKX6Bh050WHQ1ngHd4%2FumbOiObXWx%2FJS%2Bvj5Y8zLGYY7Q4y5YIEcT54%2BwcXlBLNiIdM8MpeHdOby7ACnp6e4oGfY6aWEp5dnx%2Fjmx%2B8xL3l%2BakvtPM%2BXeHl6gm8fPcLjl09xsZhgGRXm8TIvMFnae8S1ENdssmUpbJJe1LhSFtO9nAJRXZgEbYT1C9L35s%2FPx96c7%2BdjrAubSGCLCatDh2vXaMLK5ZOgC1GhJhqzr1Mbl4DeMyloXhyd49mjJygoeKJQu9BhD49FOfyB51tOcfjDUwmb49EYp%2Fsv1TeePT%2FA4YtDTEYnWB5PJGY9%2B%2FGxzrTF5RLD4RAnp6cSOhcnlzh%2BeoDJfI7nL1%2FIo%2BzebWoQtyRszqdTHDx7ip9%2B%2BAGnx8cYdHs42X8qL8anJ6c4OHipY0hayxjHz16oj%2F7w0084PjnG2emZ%2BgQXjqbzEoc%2FPsGPWQ%2BTF8c67oIaVpbx06MfcPDDT8B0gTTnGhitWYyJLyRwL7CYFzibzHGu8cFWL%2BnwRk5vSMUiR7zMqeDTl31HWs2wOBh0g2HB84a25MJA%2BN6Q4p0Hq2cY6rZ3PXJ7mUbVQchkv6FWkwt1EWaYLC9weH6AyfISyxlN9ClkcUGXeyDNjDaeWOH0Un2xHKJz3gadRXGs4Vt1mXdAh2Oz2UR7rbNZhs60J6sV%2Bunp5We4zI91fNN0MtWcQ0dz06Jve66LUscXcdziIpgLmzzOiotJHOMGxQBxVmK6uJDn8YvTcwmbPK%2BVWym4h5tHnxxzG%2BbpEt0FHZXRCRGPBlrgYnKE4%2FOnuFgeY46LyqnVsjDBMue1iLCg8Ev7Xx0DUyCO6BWejo0mQDRFGfFoKQqhfL%2FYpyqR3paomDW0RYP6gUfhOGLvrOJk9cT9pByfVt%2FvZt7N%2FYYCnwIFNsLmp9DKHyiOHJo5LcoUiJyZBmRgodXpC3nNpIAiIyFGy6wl8JDvECefXuo5xWCoqzQ2xZhDpvIv0%2FET0suchlpNoJOl2N%2FZQo9eIVttnUFIRwstrbTSw99S3iLTmBrNElnUQb7k%2BZh0gGBeNWlqWyA1j4I8wzPtYt6lK%2FpMzkDarW1MZyMdl9Ki9784xXzUwnJJwTGYEKWRTJp4EDa1VuPuAIthqn0%2B3U6CskOz2RbmYxK8pTP7kowHdppzoyheiJkZdCLcv72F5aLU4d1p3BYuFGjp5TZNzUGRCd30brpEQQGc7ZyTtSaZjDES9QIJ6UiJrvB9UVgMZmA0dYA4V5o126uEivahl4j6nlcP%2BvF2qUPey13A0ZBvQuARFhbYHJ2ZeD45x49PfsDlxQlaOudwIs3dVA4zLjCR9uaCBmJIkxaOL0%2Fx9OipvDzyCAqeSzd9PMHB8XPtoyMjfzI5xcuzQ1VG80yeqzl42pfTDp61SM%2FA9F763U%2FfI6bDoiW9Tk7keIfnXObcc3WZoXPUVlOcch%2FwjIztFM9ePtfq0cXpGS7OLsT4m5GftenxxSn%2B%2BegbPD18Jo%2BQfPephTibTnBE77rTKZZ0KkIz6WD9wFGChrBcazCtlL1%2FbFUXOF2jo5aWoMn8oY%2B8qvm1XfZViZrt9ep7jWkUr8mchrHNarDfqvfKdDaMIIryGNZh97SQoPMW7o88ev4C%2FypKPP7hsbRS08tLzCaXuDy%2FwPycjPocC1xKe7M8mWF6dKmjktim1DoVZ3NMj6glinF%2BfqE%2B8Wj2L2m3uR%2BPY%2BzLn56i3eEZi0ucXJxJw%2F78%2Bx91PBL3AuaLBc5OTnBydKS9wxetDNODE5nBsn5qy1n%2B4nyKTq%2BP88tLHB4fqS4KBxQAo6JEkU%2Fwgvu%2Bz6f4iabUXGjKeVzGFCdHx5icnyNd0mzYBE0uSvGjKYFaTmrqeFaoBAfrL1yk4bhMx1IRj5DJ7bRf02rW%2Fcdoy7NqTaznO9dsn1e38NtMYTW%2FTokcD21MrFN7j%2BJVGr2INOCcMcfl4gzPj0uZsuYLCpqcbyGzaZ1z6dsSuBiZp5gVx%2Bo7FO44D5M60zIBBdJCx23liGcJWpMW3Uhpf3k266B13pajOC4W0OFTOmvhaGIm%2FySsHN3NZyqTe9DjhTkH4z7yZbFEfjnHvJhoHzC9BvO8ZcFXcKEprDKhxPFkgSnO0TozTTZFTTpA4nmgs%2FkJZsUlCs1VdHJEoZGOxuYo45YU49T0ikolz4PmHEc6LYBoDh7KS8%2B37E%2B2rkmK%2Bpf0NkrXlF%2B7W4tWTsKuetbSbh43FPjEKLARNj%2BxBv9g0A0Ds43FJmgSNjJm%2FNrB5rGYH%2FOwZ5NskxV7d7gQHnGJ9bWadBozSphHeDG4%2BBu%2BQdDkKjOZnzY1eANqMmlaS6cl1AaSiWJum9SpBaUXwTaZ%2BZ55e6RHPaaVV00xWmSK6CCHR8QA3ZSeWumKvpBb96KXakWWzHdEFVOHU2om6I1RIZFzO1OT7EIWIc5aCuOxKIS1k6YomK%2FkvkEy%2BfRCONOETMdCDKOn2WzQllkWtZpxROaDbcR6l6BGUvZTXE7gmaJ0WMHFAgoMImEixzdy2sGpXQxSEEaJAZlJmdj6GXk0AzYGQ%2F3E61JZoSc0769rr5DsfVxIV%2F9br9%2BoYqFqN74D4XgX7kV8cTQD9%2BuStqbHyyWQcQ8bmSKu8FMyo3Awn8xxOrX3iHt0yajROcr5jB5jc3m4PZ8vcPHyMoBh71VylKh9eJA5mb34NMbjF0%2FUR0nKsihUPveQcoHocjKF%2FIBQ%2BNBe4ALz4wMcnR6pfUuaqJFR1EJBLPNslsOjeS4Pp3h2dFDtVeTeKHrAnQufkmsRaj2%2Bg%2BwyEgQCkTg28JZMMJtbX6UhOk1KhjKq0GYc7%2BvOUt%2Btt8zbe7Y6DGYv1TSbAZ%2BwX9PiKFKbUMBnyljU7C2WS5wfcc%2F2BSIdomtjlM4IpRYvB1qFMfiRnG%2FNcX55LArIqoAapukEi7O52oXQUNN3%2FvIUl0fnoig1Osfxobx90gPxggIGCpwlhzYWqzS5o9WCBj3jFtMZzi%2BXmMSJ%2BgmPnWDDvbjkmMF9fDyOotAiEs2CtYrAIXZOj6jneH420R5TNgnnA%2FY1Cp3cFEghmwspolXYj8gwjnngmZIFhc%2FQnhIcE8FLx0rMw7RKH7SaWq9UY1DjFATN0H9epx%2BwJr7Ha13Nm9SubLBQx2rE%2BtPr1BgWVzUlWV%2FhOMpZhUCohCiM1ZX2jOnYajxWZILZ5dSmMzqqE%2F0DoYkGV0KlxaPsTjNkvqSOni0QLXLaq7MmXxjm2b9h2YdD94LHU1GDaPApN%2FNMia%2FV6TIXPWpr8YXelQvqXxdqoAk13ezXgs%2FakxpBDibVvEV9bTEH924yheFvnmjpyIheaHONkW5yzbkj0EgUo4aRcyfnOfZriuY%2BT9mcyjK1AKGFDWtHCZ4%2BXljFoXZdNj8bCmwo8BoU2Aibr0GkTZK3TwFNXTZTBsGL%2BgvKPEutrA4GAzkI8tVsW80NE0ctm759wEKJYgspOGmW1LxW1WXTfPWoG6LSmIfCk03QhJqHYJM%2F4tSr0LD6LFlTEyGdCrkQaMKXHDwoASc9Ox7G2NCgGeQDJ2NBMLMz7xKWH%2BjkIDrvUz0TAmNXVIRyBE%2BNmu5pWpRWznjMtGhmQjG1CPKuS5zctI01mgt84QA6OTJ8VthrCh6lwc52pTBrQjHh4cTPI1qMZmIkSj4Z81wqn%2BFGhA1n3lR22I7d7%2FDqONuVNBH%2B4gPJMlKgY5h5lSQbyTQFHYD4AoSEFbJO1o7qAaFvMBWZT0mBbHCxgMZCOSVZNAUUMZ4hDYUb2%2BEW8nDhgeaqPDdTTB0ZPaAkw0oGmMIJHWERetm8sr9Tc8C62FbuBEcACBwxlxQY5FnWrsSN5VITTvzYxvrTe2%2FOc1iy8Fjp24apQWu%2F7CfE3vuLXQlKuGvCFMps5n8b95KFDOUAFM3FKeQTNcfHa2pCShwpGFgrUWiiLXmpMxP5QLzsj6a4XKHw9lIX8iauKKCWsbYQrgaHmH%2BOBxTuAw2UlZ5NmZdFL%2Fl%2B2ocQMh01jixRpYb%2ByX5HOOX4dcmeG7qd3lnCF%2BgueEN5Sy6aOLNPmvC4E5Yb9qqyvGrMN3xNvWnmsWxffnj2K28dC4YSHje9FpxCwgRNEdYoHGhi8LzyN6Ag%2Bns%2FamRSdCX4NSJuvHXKXk0gbLWYVIILQTwOiXJdRUfDUNTSsiYrF634xNGAx54YAdXfiCk9soaqSJ%2B69vqO8Z7GuhHjnL6hDQgFiaqUFmdPLLV%2BVlUqzGoTPDL75VjCuY4g13VXWfXeM3doYZURBGUVanHajsExRuMG67UlBuuJzR7NPs4xzbSYJnRWL0nAgukJJz8UWgVceK5hNHQCHTSXhTUUN51Vh2UZoawg0Ffjjsrf%2FGwo8OlQYCNsfjpt%2FUFiahNa%2BCXPGidyDHT%2F3j3tJeOh4zKJ4oCu%2FRk8A44TiuX5LZFijTfWyoh6LgoPDFidzDRxNmCXEKA0FNC4pMxzOZnH8tX1kfESi2eTYAMSlmGODIyJWAHD%2BAybzENhYnAD4Rik6VDcKSdyhlj95ruR8TyyZWHwcRJVMqbzaZnpPR%2Fh55fmSiYsGKsgrkTpVJ8YIqvd8joDZExvYC%2FEMFHQ9A%2FBZByZHHYD05LWDIEYzgZtPN%2Fv4eoMF9vP2oTNYUcYcG8RV%2BUpTto1CGSUtZXa6EeK8t1gfn755%2FdquEbPdLqv0EYFeAjz1osQ7BrqGaZItXrVb1go%2Byd7Ic3aAvyBwRLzL6bNtKgUjPQKeLoAE5uNuNuXkYEiKtd6k%2BFH%2BDylYxW6IIND%2BzMtHx2l9asijBNXXY2SnABv9yoBMwY9zFLY5JWCFeHy35sqZBuyrwsn4Wh4Mp%2FyhnIs9OdKsdqYQhTU%2B667kMmpZJpVanm0f82DOfqE9qBVAtcUAgQqUaCxHW2YqOlfwcc%2BFSpvgOnFN3HxMCULD57Xu50X0cSAEPHZ8%2FNq74Cn5jWkaCZqgiVE6jKaOf2%2BMYx7UHX1YquAG29CRTfFax3H3hvB7MKMCGB42pgd7lmOvzd6W1m%2BCXRGB8PJYL9at8PNmFUae25GeIurtRqQK1eYQyy91WBjFeG3hQ0Baf0v5NabrsHcc3j%2F5LOVa1ZAjeqqW5ZvacxomqMUl0kolVPry4Q2nvh8a0JnON6EyxqlueKypZO6zpUeIOKEON6ryjBoOSzs91ahh%2BiqpCshm4cNBT4tCmyEzU%2BrvT9wbG0Vvd%2Fr6XiGNE3RydrS2BHwehDXqP8b4LLKtKxXuAIFZ5Pq4zFhYtKkb7M3SzR2K8RpkqRG0%2FeNBGFzZaancE2By%2FYh2YToAhjrak76gZkTLAZU%2FWt3jHIIDeQAiyIak2cFA1eDbeXYZlgyIo0SVKxN5iaOuMBJWIgxhWSvo3k1yA1iw8OEZhVoUIZboxsfDFc%2BO9bMWZdhGH1wv4beOuEFplHE%2Br6pcAxPY6ConaDQbgsAtcBphJEpoIR%2FvSDGIYrZJEWsZKNOfW8xjfa7kVhOY6OwSpDAaSwbu4BBYQV4K9Mk2mKs1e2JWnALphaTfKXLOW61wFJkhs3eorINZmv79U7rNfPawIV9VlGGfR1jd%2FWzwUwIDUovxkO8%2FBuJ89oRKyXpVeYZqnSMJUN69WOHayVtqEF9PZgoMr6Zxt8GXYMw6u%2FIOoCWjzXVPaMmnTempbL3iSMNe16dXrmDR1cqpRhvtgpWm9rNmyDA6rhZ3nWo6udmOoayKT2sTmV36%2BHi74lCkzhKSsrUgcxXPzXvaDlifaAOvb6u1TLWIXvTZ8dkvda6HPYV14iprzqSytrMT0y9HF755tFkIbSm2sWIKlzrKozOntXDq6J9rmGEBVo9nqF59YVgpqsKMLjCuMTU7PmCKuDClDbGOQahhiA4K96LY7lNBKp5yhO4ZtNKrZHjOMpxlr8moNpiGtPxS1NgCqg%2Bfjm%2BXi4h968TKaRxeDxpM3pzv6HAhgKyVtmQYUOB904BDf5h1ZZOZgbDoTQldjRGmLakEeC88K5HdJb%2Fc9%2BaXM1UdZ463laVmYqTlGkg5bhEc75PXEvTaMr0lIKah4fSeQlhlUmic1cK93i%2FWn5nsvx6DSfWAJR5%2BCGzQG0WJ1xVHOoOcVUY46jiMiHY7m0F3crxbGT27I%2FhWjAQ7CyfWAWpQ8I0mQTjGI09MvwNiiY81AhZN6j4jKpSy1M9VrR0%2FOqY3%2FrOGcb1etVaQtsETjPdZl8hLkTUmKO6D1j72i9JxswNhULAmbm87ZvYi%2BYBCIVf9z4ZT2qprAF0b%2BWwXC95w%2BTE%2FwAAIABJREFUNUmznlCFLs3UXhzTmqDJO%2BJOjZ%2FlkiltA4%2FVsvzJa1NJHmhl6YmF%2BbcRHW6tL%2FLBOxP7%2FtV0byOEvCi%2FMmEMDq%2BIr76KDKCuVSZwGuhdC15gdA1TT2F9oiquQq1uCd2JhE7HKrW9hqRMIA2vDgbfubD0ZSa0BD30P0%2B3jpJgC33KIWzUtnrb6HuvTBtyko7XYLHSnDeVdV0%2BD6vy8B3h%2FxpZVwF%2Fm0%2BEwKDgHk32G%2FOaFcbQsMXDXl1P24S6Geb33r3XTbcd7gpbvd8KDX3LUjDevwzx%2Bq7m95AqlQZqE%2FQ4djCvjXN1Sj7bApvDax2hhoppw4ukbCHGYdRjgElZ2Sk5jlLgdkis7GaZ9X2Yy1hegLdagajAbMBmhVYxThvzN1CXWs9%2BjaSb2w0FPjEKbDSbn1iDf8jokvkTAxiYTn%2FWldMMmTNOvPU4%2Fo7QYQVeSbj3CU01OsdRi0TXAxImvrA6a6w%2Fw5zz4z31BtRsUlALK6qVh8BVGCw%2FmarA9VQwsnaWw49NhkzVFDauMgZM6zksjz%2FXsATcq5QOD%2FM2hMya5bRqlKwJY8gXGABbwQ7MYVUkV7q9XN55hF0tNfeBMs73fnkaZfyZH8evWe7PJH%2FrUW4GR6ys71g%2FD8JHHJn%2FDUaJuzcATChswm5kYQhLCr3FnvRSNOlhqezXyjOSet%2BlJif0pRDdvLAk7911qcYmMh3LdaaRz0zjTJVfmcqFFaVwk1GZYdp7TAZT6YOwYEsQTM0a%2FGvPVkfgA2ugDGxW1OgzBpvnaGJW30tA4ZgTEHgX40qNgdXLOs2hly%2Bs1PBce%2BeCl1%2BvTVQHiiwrY1WIE5IUeA2imnxNCOtQIwpJav2lESMquymtTKJVhUujISWLbWRitXzU9zr4ahQad2GMaISs3gakVgMlH1TVhyQNUNZS2yOT%2BZch9joZxAazQpVYz2%2Bls7CkAKCBsfobhlD1GeoCedQHvw4o49XvfexfzV5hpDRWD2vkRziE%2B%2BsuSifnOp5y%2Fepw%2B3W9FE%2FvwK5d2QfUJ1RTyMw%2BVGsemUDddb1oPTfLD2VU8ybrciFTg2rAmKOLjZrqWaKLFa4SmvAIrSZsTBfGCo1rob9XlKytFZod37qJ5Vsv7Vq0NoEbCnykFNgImx9pw%2F7u0NJcpBFee4To%2Fp5azSyld1U7d5F7NX%2BzAZuToXEctcmOJsgGG%2Bsw%2ByqoIBUHsEJ%2BTjX6E0PNO8PCWH0TNmNpE5mN%2BSnI8cOrmwTZAdMuANQTWs2FUlBZZdKNnsZ0sDx%2F5j1h8GeWQbhCUAMfn%2BwpmMj5iBIxL78ucPqz08zhZmJO9o141cJ9h6yd4f7x8mrM6hhnEur0OpnQwfeEuhrDshL0nh5IMTGKrsEKDGqpoxqs3dKEXnnj6kgCUsXQ8vbgk32l7eNt6EfqP6LtOoJGby%2Bpjq3pt9qP6vA6rbVDFSNBsXqy3mOAVlnUQ4K5p6WMQzuzP1jfsD7PJzOYZjppNIiHkrCUcNxBoESVJ5StCqu6HSa7qo%2Bqr6rkyvTengxUvSdrwgLbSRoJJgmLXteStsL2F95wr2bK44ts6qWzrZXX4IZiHUtGN%2B%2BV3PneKm9FnCpEN8rIuGa8PzOS97xaDWyJKqhREscEpvA9pJ6zkcRuQzVeoq4iKu9u%2Flg2z3VTOoc1VMI5IoDLHB7LZq5qez1Sq0K9twmPnaKTmAYMrwKrkfTVtzXsdVpbcDU5yCqjs7aI3yKx42HCKM%2F3wj5qqYC1Y84Y3tdfT8UgH9erept0qgKvu2kSw%2BMdDnvWgpluPS1HIv5xrgujvtqC20Jq8nJ8YzxxZ05bDFstW8UqyGgTaqwXaqslOF%2B2ovDKe5VowqYWdr3cIOA6XErnaZnGv3bnv1Zv%2FRsnsd7rOKFn3jq8qtaRUkAjfnO7ocAnQoGNsPmJNPQHj6YGaBul57MZDg8P0c4yjAdDtBIKXDyjm574wj6n5oD%2BTpBjBYFJDhMQmVE6MEJBpwM%2BSYX5iDAwi7gEmy1tWrVJVoJC0EZV843mO1tpZSqbpJxjYmHEm8K2OTso9FzLvvXEFybwQJMKDANI1LEo%2B1W1Xk2gncLEhXiATbImA3hskyNhAZIOKo2WEcDCjHbMRxryI6jCPVedbV%2BeCaJOZ7%2FWzJDp7ygIGJ2Is0Hj5RkiJLtSXGG8Q5Xv4yKHV8aEcP8xv9p%2FSe%2BrRW1yLIZL%2FcmAtFZq9KuAMS9NAYitzrRX07Mcbyujlkpu3F77bNVX5alsdeW6Ft65fFT11wCDaSlZcw0XqzQW0qDkr7eyM5oWE9o1LJjUzkCsb9dlG5DME3p9gwJWs2qvCGUpA2q6UJDgp2aK7SiNJOHxL7Y%2FrobJqdws4dX3XgfLIZ5OejkGEmPKsYRt5DGvLpMpDK5GWmU3GHXri0ZVjXXd9V1491RMs%2F5G6c3gRnXVbUVfT%2Bh5%2FdlSKlkVZNr0qowbbkKL3xB7fTCr0LcxrjntmyNQM3cFVjNQ9wZBmvC84BQJx3y11ZWENwZcV7ZTqM7kqQR51WJa%2BFBL2wIIFyY476zuk7c5xss0DSfDQpm6NJ5Dz%2FEy%2FB2tYGlkc2FJc1KVgDdMxFHWP%2FWY7CGrVxOHfS%2BmP7Ec1h%2FrTNR6x6%2BGQC0UhRSyOnAMvWQ%2BBw9lDPJoZtYc4TCxDHpDDjBzu4dow3huE6lpY0Uwnb%2Bo62NnIM7aiMOyWQyB4JnWaWzjR1PaFE4NMB2LzXVDgU%2BNAhth81Nr8Q8YX02yZYmL83M8evQIg34f6b0YXToJosCplU%2BfXd4lIlfroKDJSZ%2BTihhJcVFr6cLEY3OWTViNIE17xMFYmcYMFDyKVqwyZ3uVb%2B43KGxS0DRX7poSnbVau1ocoXJm1yZbmywdWnty%2BtmTpWNYSFXB4Lm05lxFe27lCEgqpZiFmoGoRQumDBM9j7SojrUI5WvvJ%2B%2F5JXtoboUkODAreYPASJsA2mAh6eqezFhkGgCdMeN4CFC2RagnPDt99PgOf9SnpTULx13UFFatJvCsr%2FgzyjFnbyGB6xa6DlznMZtYGiN0TeoGQ171heqmbmJvDZUZ4tktq3CGhbKa9Sqe7eVVN%2Bpr5m3eMzFxUFi4twIYEioK5THE%2BgMvegqABOACrKKgm8k6LFaDnlyg5TvdSlO0WnblkT40WVz9CLLVoFc%2BWRta17PFJG4DSNIY3JdObYgcPjU1tq8oM6BWp3L0RSOjFHuKho%2BVPuM57arfKm91YwWw9BDkubxCT8nyuehgb2qoN7Sz2H1PGMqSeGFAeVFXrhbNjNbjryS4EkDo%2BLXKvF6HmZpX7QFu9EWPWy%2BKNVprWZl8b1utFrIs01Fcrxovmuh62c26GM%2FnOp3Vo1CNa%2F4c6fxJOzuU%2FTBFmrSQJtRsciHEthCslFO96KHGcFFtIqoFhN4oPH28cFj9WpWruVYUDVA3MfBUHu8V%2BpXxjOPV8zEufP0950ivvm%2FlUZMpE2EBY%2FksxqHjlSGNUBYpZCgohvLDwqTeA2ZhsATMcPWFS4VbHt0yeuXjMIRYlt9oK47dXDSkt2Z2tJj8ARcGgsCsokIdprVtwL1Sz%2BZhQ4GPnwIbYfPjb%2BPfBYY2ERLUErPpFC9fvtAcUuQ87sH%2BNKeEo69%2BPVLXTy%2FNco39IANrrAhZK64w8yiOsqhFgFqOsYnQxSTNfZpfjCVjjcYc2yRGrPSxx1B1YHIl7LmwyTB%2BVZjoss63rWJj6cIsW%2BVbTcPqmiGh3vXJvEoVvDU2GVg5qTCTWLYf8QkQCl6793JZH%2B%2FJhPDTrJtaPnKqFqZymFnPDGumbWZnONsnCJr0d5a2ENFEUVzmFdYkZF4t0alVRQYs6udffkeqUDPfyTLQZHZOX1DUkEeJzpF0loxclvWypqDOeg1%2F720echVm4mr08Di%2FNqEXJeufBqbXpQ45xRyG3mpVNIusyqhKUPmNJMzvketxxNDjPIvXUV3XEgRmtX6%2F2HfW0lSUIwXrOI0zFQxmJZFESdBMcDGJYdYGNVvP%2FHUZDubVK9NUhV%2BNZilkStMEcZaiTHl%2BTw4qufl5nRq80NVa6ifekbElHP53U8Gey68%2FB8SKcBJeVZLc81qN4Tkg4nEGswvAN2Np6UM%2FuwloFdaojYApo41PHnOlJRr9Yx1upykLsneQZyJH0mpSs0ltd7PaGk7rWcLI%2ByQTcr6oOnyd1TGvaclMbHwr0a%2FaIoAYCagtayFrdZCmGZI80aFSMsNnHpmDsj7mD6V7UVZt%2BPXZlVc7bqdKv5KODyzAC2lS0cPWM3h6j2eealRrlFXHOx3WS%2FLnmqo%2Fl9LL8%2Fo9d12ltyXhMaP9kIZZ1D5MEbziin5X62OIFgx1pBPLCb4VJF%2BSH0gRF1yA5kJVB2mSaWy%2Fib4UUG3h4mpdDQw2txsKfHQU2AibH12T%2Fn4RskE91mrhYm5nYEVhotcgHdaefz2GzYnqamli0qQk4Q9NZs3rKs%2BdTJI28nDkuE0oPmmEqS0IpjaJMYXXFZw4kNOpmIPA3IhR0bQWUhtTQOHM2QRCSY2elcZfL3f9anU6VAajp1nHtU5l6RrxymJMg9i%2FikMizMzHBMEUNAiJxmQwdV2u4V8%2FWz32bL8sp%2FmlEyBPH%2BoQWGwD0w7V5TMdGTs6zUiRxymQtBCnrVCGlVu3QU21GlOvq0lpxnp4nfJN7pibLGoaR%2Bi1WxgN%2Bui227hcXqrsIo6xpLDuzrBIXx0lUUjYcUjN%2FJosDpn1MuxL087ENQiJKz%2FeR3jvYX61FNVv0BTb81qawDwbfV0AqHKqblF%2FLVuTbqtR4cnXFMKZnQSR5TDWhYB1Rr2utYGSB6rY0FYqkwE0P2R3scJDiLVp2I%2FJ1jbBMkEatdBtddFv95CJWWQsW49fYanaVIvqC8EOQxVrNV2hO7UfRSEnUGUSIe5miLstFK0Ii6jQokMq4cKGBu%2BJ7BKGWcAvtKeDYFd%2FMmBMptIIJmKtwLwCb%2F3QfD9CKXXk2p1D4sFeO6%2BqtdGn1tMyj6f3%2FOvXV8VbeqvNxtGKSNVY6fV66zkVva6Q2%2FocA5lBmdy80syqO70O%2BsMBWu22lc3%2BxMyVdstKrNvJilG%2FI65BoFnHWlOAshokRreQSg6kEiRlCwkytNIe%2Bt0R2q0uyqk5UcvZhzUe%2B0ho5Xi%2FqetzSjDEYr0up8XVq5fFmIowIdn6czMN8xFp1rCWTosSNSyW0KDkPlvGWK1OMz6H8jzxynU9LjxLo8jS1o8Is3m0zmVmuGwfhhm8PGezCSN7j8W6w7w4plfbHIU83JqJcxy3EJUZ4jhDtzNAtz1EErO%2FsDxaY0Xg2c%2F8M0GTiHg9fl1BbvOwocBHSYGNsPlRNuuHj5SG2TDWanIO5jQM4kpy1mrJfImYaJDmcO0rzG8FPZ96%2FLpeqE13NF2NuW8yaiHhymXaRRlnQJGi5JlcPrGGiU4TmLz4sTybaKSha6x0iweWmVKVO0w%2FnOAsn2lqbJIiXyEmgSVWjE6YCEMOu1iYT2F%2BXUly5cFTrdPByuIvU9jVwlahrqWF5tTNapiaPzz8XXlUFTmPMPl61YKJqS2dB5tcbjXXULDMoMUQXVhrLDNjLgJEnPyTTNpO5tEkv4Zzzex5BMuwWr1uj%2FnFV%2B7XBNCKI%2FQ7beyOxxj2%2Bji6OFZdNL0SoxWcXgW5SIsTcpCjOxeYrPWZnl9%2ByMDow4uawNkzUd3i%2BCumtH5s3llKz9eMsYV%2FwhRacTUyPF1Pq6saLIfIryS14xvIXpXPNPZ1RKuon78RQ%2Bt5rQQjkUWwH1C4LAuJ7eoX1B1Re9SKMwx7Q%2ByMd9Dr9BDRLDv0HebjR78VAteQRQn4w0R%2BNZDVeiXN7YCoFaM96KI97KHIEiz8IHsSpOAube%2BxKrCuO8DhrUXc%2FL6Cr6qZvbkJrMGx%2FlvXwJhXp2%2Fm97yeS1eNaR7STM3SHSLvH6vx9VPoHHXANXcaVASzl6pEeg8cMms56%2F4Gk0PGq74haRUrQYma5gLUdg9HQ%2Bzs7aDb75jPtiBIeTnMvvJ6VRF1wXUbeWR4t7xPOXaEXdlobs9%2BWSKhVjPpYNjbRqfVs5efZthxgmVdRYMOIZBl8rauUg%2F22EjjRHMYGs8uMNdRnm%2Bl0BDdDPN0IarxXjJEsaGJiyCMM8xLqOlV17x%2BZ33faO%2FlWRr2BgqWjqkJlfZGhQWoQBjW42O%2BjdRhaUINSo2ljRUVIaMCMQ%2BW5faPnIsSPJOT5ZM%2FaCGNOuh2xuh2hkjjDFHJFjQNt48hVpbTx6%2Fr2G2eNxT4OCmwETY%2Fznb9XWDlwy2vmh4CB0rHQNvb2%2Bj1emIQpfEM%2ByAsnU%2FMvxZNn%2BJuKoeQcV9VEGLSDpJWG0sKM8tUAg21nqYFqctypsEERoZT6KxXShXviDCW%2B8MkbDscrJdTVJiprQRFuke%2FyoTKs1TTdRXwK27I%2BZiG0dvGJ3Ar1HCye6YQgDXHYCF1uJLU9CHnJgw1sVt%2BNr2laKQT22Cr0j7pK11gVpiS%2BuKi5JEAKYooQ9rqIm51gJjaTZvwLW8TqFV4WQ6h8JoNorX0b%2FjItmOLZ2mCYa%2BH3e0tjAcDpIcp4pyr47bnjR6XzSyOABgkpLVg0Kq%2FsUXSalZsVA0rwRLsUpg7BpLHXwtiy1Hn80yCpO5%2BHrxy%2FTk6rZfoz34l0NX9Sqm%2F4CGUxfL0Ddo1L59kpVU1hU0msMUrc%2FTF51Y7w7i%2FhZ2tXXQ7vWBE%2BwvgUBa1hreKGoceTcmg8t1NeIbweIj%2B9ghJJ8NCfkvMDiLhwBD6gBOnSeMKH%2BHrTwYnnzwt%2B89q7Ovi8nq5VM%2B17Wf5nQLNWh02Xyxpxq3eu9T1c7AwLoivEjCbaVlTYO%2B12sB0ZPqbaaxGKyX0GS7%2BcEEABZb5AglaGAwHGG2NkXXaskDgApGaZxXgujDdOaY2YnqtBpHXaGk8jtkYIg1YyM7RIy5TtJI2Br0huu0B0riNnAud8QJFMRe81uheZwBs7VH1NMOaFXvlIWuApHpavVnPyNjrwlZzrT8ZPD6jvFn%2BZmpbTLoOBiJLituf4VRDYT2n%2BZYYceytYWwBeYlmlopubHsKmbkWGCLO53QUqH20LWTSQA%2FRyTh%2BpDYAM6%2F6TBBsgxa3UWgN1OZuQ4GPnAIbYfMjb%2BDfC3oal01KQ6%2Ffx8OHD%2BWNttPpVB4iNRlwcTHsx3s7uHH6ak5hLNVnGE5IFBkSgAImhZi0I1PNMm6hoCt6eYilYEatnE1jNrUI0FASyxGGgQ1kfZy4rB4yMGJGAv5WP%2BP8S5isBLuzeq7C%2FXYoUpdrdDEo18t2mjVgbCb06Guoyyiavq5%2BRARVzXgrysu2tMoXyiMFJGgiRl5y%2FyOZsA7itI847QFRW5pnCfk8viCUuFrn1ScHu4nK1VSvF8I2bSUphr0Bdrd2MOwPdJwPHUjEXKQgA1yQiQmYsdKgPXHnNSSI%2F1mtATKltRCHmSg2gq%2F06teDuk5VlVsHvdbdq%2FL92vh1IFhes0yjV%2FV66TWTGCGNFffLcgkpQUpnXzmQRil6nT7GwzH63V69R2%2B9otd%2BNkbW5Ua2iqwyolKOgfqjIUbbW8j6XZRphLwokZcFT9uVYyJ2C7ajtXSzRQ0n4sePX5tgWR7P24x53fsmJV83z9V0DofHvFmpr0odxr9AJ6%2FDr6o7nOlKSpBOV%2BAJAaxJiz0kuoYZnpeYSMAcbo0w2Boibbe5UlE1CtvVIOSvRm6vOly9Nr8y%2BFU4hXLCnECvsXRSRRPvdtrFsDtGLxtguTgHokxbOUz4IREa9TRuK6CCuWjz2eeeK4Sp4PSCHG6%2FVqX8opu6lPruTQvynITQ772MujV8zg14XFmQYl7HMeRmH5AVTi3402ZG%2FaMwE1qWyrEjkkBp%2BzXTpI1ee4BeayArCcUHR06F9uLnJvaqnVjnWr0O%2FOa6ocBHTIGNsPkRN%2B7vDrWwJ6%2Fb6WD%2F1i2tJmdpy7y7cbKQPBdm%2BuYE%2B9YRtQmBk5FYlaDZRNJGlPJLgZPCTKa9gjE4mXAOMYGTE5RNKLyaoOOTYD3Buacj51w4bZpQVU1G9dJthaFPU%2BuTbJXgN7%2B5AZIAqBgzcd0GmKFETe86oCEDNdhOEumYXFC0DKbhI9Nt2mJ66aWgWUrQHCBKB0Dcl7DJY2NMi2pSmNXZrNipuQ6LMTE3x15Nf10I25yr3O1WB%2BP%2BGNvDbQzafUwmC8TFUgba5JZ0pI%2BAMxND9pEaSr%2Fza2BvXSC5geGuU18H2ccRVrUPka2YST7UYpju6OUy557JJdK0LWEiLiOZStIBTL%2FTx7A7QK%2FTlVMYd%2BDhNKzqeQOysTlVt9YTeGfqVWo2u4MetnZ3MNoa4aj7EkW%2BlJMgezcCMhKCbPyxFm8gea1W0fosQfwl8L4Bah9M0votqTHWXSVoXgXVeoeFq32ZIYw33kZZu40%2Btc%2BjIbIuLSUSHbnF%2FbbWkqE9VYxpO63eRn1XFtMacVdufXZgKVVH1uhHc94szrAz3MXWYAeXR8co8znikqaaJgipuKpPCCurQUCFMlfq9DBmChRRWibiDectfhplhZAP6%2BLw%2BdVhJg4hLODFJ31r8goVz8l5RYs8Esy5l96sb4qSZtVLoFxqcZDWB%2FLdAPIl3OrTQa%2Fdx6i%2FjW67L4dONHPmQgFHfzkUYiUVfT8sCm6g2VDgt6LARtj8rSi9qednKaBBX1od27PZ7nSqvZqaJHxWoJD5zgVNzkycLMjJc%2F9Woj2bEfdipD3ErT6KZQ9FcYGobIE6Cfm0M2m4mqxlHqspjuZ7JkjWcw7v%2FCkgJ27Tw9bJZWnEEPlEup7kvT1741wFgDFuwmapjGEz9modV3ICxkJajN1bqZZP5YnCNI2jmSzPIc0QJX3ErRGS1giIezRg5Y5JrUCzHazupmS2XvdV2H9NCEuXqBmlaCdtDLsj3Nrex%2B54B6ezCS4Xc3CxXEyO1tidjWVGsShV9QapU6%2BmnNVRJfskbyrakDxhz6AoJabS3hY7o5B8tS0fUbOMnEdMFMiylvZq7u3sab8mdRZmuO0LIipYr6rV1SDzlQCLs5ZqpCNoZD7NX4gczlCzubt%2FCwc%2FHeBieopiaW2uZarG%2FnVWrLcgCFAEnfKBm6PWddld%2Fbxa%2F%2Ft%2BIlxvHTbSX8KSY3dDg3h047oCS9D8aQErLrUYcOvubezc3kfW7yFKg3drpmv0Ky%2FOF9D8uTk%2FrULUnLtqCCwNf238Yzn0iEyNGhdFqN3c6m9jb7iPk7MDnMynSNDW2MEFFJ3du%2BLV1iEJZYZHX%2BhcHUGsh9V0JFyE0%2BCrofQyP7TrdRBynLcXxWN5tXaq4a%2Fi1KbE2ayNOAIQf%2F1RoNe4Yj6q%2BWvOm7hPs4120sewM8b2YAf9dh%2BtuGWLWSwj9E3xAasdoQZic7ehwCdCgY2w%2BYk09IeKpk2HNv3JlIwDdBQhX9KojC7ouRGfwz6NJrnJ%2F12O2g4NhRMKh2biyP2AdAIQxR1EWR9xe4R8cQosL1CUU3D107SZ3M%2FBKSx4aSXRNcNpqruquZSw%2BXP4VNOhmo%2BTHv%2F0%2BblsluI9%2FTrMoXrCGUxDDV2qEchIqTWdpzEGRwnWwXbamWAmCojp415anj%2FaQokOorSPpDVGlIyAiMJmh95YpNkM7FRNO1URBM8K3LdNUMMvLhO0ojaGnSHu7t3Fnd07eHr4AqfTMyzzUo5H5IxCe2TV4ypBwilBEAmdIAzwNu89Ha8VOs3Aj%2FjeliOIdXg3GkyyL3KQyCZwst%2BR5eZ%2BK9Mot3tt7O%2Fs487eHXmjDb3y2p64QsYbuotBstoOHLMqRjcGkjQFTTTv3L%2BHZ4%2Be4vL4Enm0kD6pPruSJYVKXNAMDextTIHT7y21Pdn9CrTv9cFhfPtAvE7J16S5ru2C860iBtr9Hm7dv4vdu7clbCJNuD1P76WPwFV7SitKk34%2Fbem6wok55y4X99YpwTwuaLIHurBJz%2BzQkUmDbIjd4S286O5iMr9ACR4Jxm48A6Jl6AeukfTya1jqmq0uzaMaAvnMWLt6ThZY4Vj1sir2Pd%2FUeN0MCKljOPGOuFzTE0K4LWSqrDB%2BkAfR9gatD9C7LSlE7Sf3evPMU%2B6n7aCXDjDubmHcHaOTdpFErXB0UoRlXkjDaeduvg7MN2OzidlQ4PdOgY2w%2BXtvwY8B%2FuY8VwJ5UeBycmlHE7Tp7IVMIhENK5bvHGdjOTVJSeik8EkNWguIu4izIZJsiHx5jrK4RJHTWcNC%2B%2FEEWljRNHMkIkfB1RkBn3TCVXh5mPOXzWmxdnNv0yVpYJC9czL84gqa8LMQeyaWztYwtJrXxRQ0aFDVa7habhOzyTTYXk1O%2FdQ4c68mTd3YJiPENKONugDa0khLsGiWt36vFXAGspbrYKgyvPGNGJQiQlIm6Gd93Nu7g%2Fv79%2FDNT9%2Fj8PwY83yJKLU9YstyibJ0BvJ6SF4F3TrV3xjg31kGFzT96u%2BHC5nWY7jWwcUfLh9Rm5mjyKmdSJBEKUb9MW7v3cHe1h46WccWtNQTWKqx6FfWt25oCNL%2FShswbdW1Ijke4Z7z4XCI%2B599hqffP8HLp4e4nJ5B1nqBKa7LMTGAxfB94ZVCppbCwnBoh92sAlXn%2F5016lsBdx379efVSiSIBLrHrRZ64xF29vcx2B4jabdM0KR4p0UzH4%2FrMpQ%2FmOJ6K1ypMUSsh3t6K80FztDW6rYRoiJBlrQx7m5jb7SP88kp8nkOiphchLWjOKxzmNjb6HJhzCWM6j12Y6EMC33qmp4bOi4hXoe6xv1DvqvHgRrKFUwaxNebzsVc0YONmWs%2FPZPIJDZM4UUeIVrQ2qmFNOmin40w6u2g3xkjS7raNiHnQaFsCvUu2NdQbO42FPj0KLARNj%2B9Nv%2BgMebAvJhOcHBwgC73y4xjreyK4eMcoH2djVnirWPTLFtTjTkI0plZPFajgyTrA9kA5byLctlGGY5BMXbW8zenNa17B4GT8aHcauK%2FDgnmJ7fBvC5SvYbPAAAgAElEQVSoOmfQLPu6vO8z7HrYyLpLhGe0fwMlDNr1fHy2YyocG5KLgiavLI0nUspTcNJB2hrIjBbJQFpNLQyEc85IbWoCVuth%2BRZjV6%2FlLV65Gl7QGVAk86rxYIyH9z7Dw6c%2F4uXFMaZnNKWlmVZRHWmjLhHA4sU%2FvLe1dYPWBQ%2BP96tj5c8f95XYrn5NwOR7YuHqMwUtDujMy3hIvU4l5OXzwb3PcP%2FOfYyHW9pvxQWClf4QJM1mW1xHU9Z202cljpqSOEa728Gt27fw8IvPZUr70%2BkU%2BXwW%2BjetOQIceuVtH7NDRjwo%2BPBD8Kxf8PlVUN4E4ccU7tR2WvjzVRwthQnzJHcZRxiNx7j%2F8DPs37uL7nCAqJXYCRduVumNsF4c87vAKW1YncAh8GsdE5rMh3WPYEL5K7JxwxYTUvTaQ%2ByO93E6Ocb06BIL7t2MlohAU1qOiOz9QSpSEQasvRMsfBUCPfE9qer3%2BADAyrvlwH0oV%2BLm8K7DZBh7iiupNH94HpuZ%2BCJxlq2OFitKmdmzjDRJdUgSrXHKZYSkaCNL%2B%2Bi3t7E12Mf26Db6nS1kXPTU1g0zxNfvlcq93s11Q4FPiwIbYfPTau8PEltNiTrM2szczi8u8MOjRxjwqIg4QbfdRiulSSQ37jP12%2Fx4eeuzAp%2BNEeFVWjQ5nOH%2BwC6iFvcIDlFIuzmRZjOSOS0nf%2BZ1AZGw8vm68q2Om%2BNYRvB062CuoH5t4EqK3%2F5hFSaZFZOTk%2BMfixNDH5hpT23UcRq59oD4m0kyY8ROaZ%2BmnaspE9qog4TeZxN%2Buyijjgn%2FdNARm9dXEzzW28FK9DZ2OJxe688e%2FqZX9lc7zbFEr93Fg7v38ec%2Ffo0nR89xMb3ExfICi3wGnmhAjVe1Gk8AVphAEzjcETOjQ5IKpJp6FldFfLQ3V1vJ3j0i3GzfwF0WpQR%2FMoHcW3X%2F9j389eu%2F4MGdBzKhpTjaLLF5LxKuBTi9ryMvhyk7C5VjFlNwLOEZiZH8ViEv0RsM8ODzz%2FH8xwMcPTvE2WwOHuGXcE8me34Bwct66qprTll1NMaV1XTXQfWxhdVUccxEAwZX1iUW423FaxhVJM8XUYk8fJcxsHV7D1%2F86Y%2FYu3dbWs0lteKUx1imvl6S11j3tKqRAlgCo0529Y6mmlWm0MZyGJYjXyxte0ZCjSo3d5doJ12M%2BzvYHd%2FG6eUpZpMZFuUS1HFyjJPZp8ZLLausjBDVIowh0YDlKj428DDcBNhG4iu31%2BW%2Bkug1AwLZXjM1a%2Fb5mVmuQmIY1KK2k9pS1iPFaoX2nsZJYmbP3DObZto3y2agTQGFymF3D3vju9jbuqs26SQ9pBGdNqXBTJ%2FvurPXb4bZKjybpw0FPg4K%2BNvwcWCzweJ3RQGZrFTjsE2WnDBn8zlOT0%2FRarXCBMoJw%2FSGnDB%2BjbzpE41Vy98wSVELpVv%2BkMu3OD0xTt49%2BLqY51O0BihpSrs4Q5lPUZZLOzhRLuvnWm2WVlLFkGHxZW9volCPWB8P8yvjgpDJKw%2BS9qiKWTAMmmxoleQDuDFaEhDSLlzXYRcHxzhnyO3eGoKeFnP7hvzQ%2Fl3TZlZOgdojpJ0txJ2RtM7Gydv5mpaNlDP20tgLo2R1XxOWlevjlPXnX3xlQWIorf1bSYLt4Qif332AP9z7DIfHL7A4mXDtXCo3guJHwvA9EJvUcGpDLMj1ytmMYleBf2tw%2F2KE307Gn8ODXYZYs3%2BRpWbTklYF3xFmpBMesXvGcBe0Oc0pwEVIyxgx7wvg1s4Ovv78Szy8cx9b%2FREyOvZQTo4DaglbIFEPvorXKuUtfjXM%2Br3JPK49Mm%2FDeh%2BSWOdsblO4%2BfMf8fLFMf7rcoKL41NQAOpEHGusl1L4JAvLc0KJm4Nn%2FXoVtlUY6jgTROz57S%2FY1fW8u7smZuG%2BGj9YKxvf55DQByp6hfGT2qsIWFBrxeRxBAqTk%2BUCyBLs3tnHwz9%2FhVuf30Nnq48yi1Ek3Fdtkw4vK1WyVkaFvybubDlCyWr4ve5jixHqxSFahWlBldrvmIsjKoBetbWbBIP2GDvD2zifXmDJvZoz9q1ceNiIwQy0lLCK6bwupycyQWOLtTTzdJh8HLR%2B6qEBbhu4rwNdYc0WuTHRa0Z4zX79uWxX0zRDeG%2BQ6cgS4WCUIY40ieUeeX4kSmve5ztvtFdolEhQjHQsFRd8MiRlVh15QtPZce%2BW2mF7sIc%2BjzyJUnm31gDkZbHu0GHqPtKE9eew3MRtKPBxUWAjbH5c7fm7xIZTQzVxcXwuS%2B3bJFMUa7Z9O2hVdYSJphr2pUGyaZc1VROwqrVpwlhbTvrct8nzNs1RUJxTq8lV6AJLmtnwSAUJnMzHSZ8iApEyr3a8t%2FmPlZJTrqAwJAmkm85GuUws5adSZlw%2BeXGyZPkf8segq36FZ4BYDd645y05AUmoZJ5MOBSz4CybhLag0Swz0Z97NNPuDtLuNuL2AGXCfZrUaPIsxUTOd9SzjJNaoZdqb3SIAM3bJ6hwY7F0LlEii1PsjXfwpy%2B%2BwvHZMWbzCY4uF8ip0hIQZs4lcoRWZn8Ro0unNjQJ9XciMFJvH%2BgPs8RGc9krRUYxdB11KfYVvnukD7XaZLu5VlPGaJUpkoJ7NWOMeyPR%2F89ffq226CQZaCiXarwx3FmumuMaUqzA0Yi%2Fmt5CvC3VDb0vJrH263YGPdx9eB9fvjzGyckxflzMMZsuQCsJmnVqia2wPsH3QvsGJbs6c0wATIhtgLJ6q4WL1aAbkVtL9mE8Wuuuw8LQmubWKhKk9V6EUbxs7mmMsSyBBXc6xpGOM1nStVucoDPu4%2BGfvsLnf%2F4Ko70txN0UhfyLhQ2yoXLW5%2B1f170OmT3%2FXLyX0cTAS6GgmXD9Sf2bTvLYrSkoR8iSPsbdHdzZmUmjWZwsUU4XmBX0Scs8nDM4RpiAxfIpVHF%2B4lfjkI5l4Tzk2ATa%2BUJGoJ8NvT%2BHhUP8dq5vVFNFQObyLwP55btB%2FN3JD59trNB5tyG8CM7CUnmcN6sq5Q4O7LhZl1YpUZ7KKVCSt9Fp9THu7WF7sI9xbxeD9pY0zkzH1E7vStonaOIvwsKEaPt26LUpZUOB3xMFNsLm76m1PnJYOflJYxHFaLfbjTPvDHEy2W80Ib0WvbxEv4ZMYW%2BozWmMM8bPVCcmcCbZGDGPqUhiLMkMTOiAhPupeORzjJTaTtnemCsHMZ2qhniEiTE865FVu8BlrIOpbny%2FkOJdA%2FtayL2fREGwFGq8NyIGWBrPCg%2FCJfE2blxOLyhgk1ngeRFRTK%2BzPM20hRxtFHEPabaFVmcHaYeC5ghIOtq%2FyfYxV%2FOqPTAfxo4Yn2%2BMh4V4mt%2BKTHZQ%2B7A3wFef%2FwGzfI6zy1NcfHuGOZlBCpOBBuwhXIGnJ0PJlgxX52KaolqdfwcvxG9FjF9dj8aLIFRykYHaTYXpICIWz2MjIiTcc7VMEJexjif4w2ef4%2B9%2F%2BW%2F4%2FMFnGPUHaCcpyHDSxFVHGDmzfQOE7DUrXfqGdBbM9mOfr5l%2FhbNRkxJJlmK0PcbDLz%2BXNcdsPsPLH59iPpkLfo55zF%2FmObDk4hSZ1hhxwuMZ%2BLgKCWEjDUwzHgCTk5KfBfJ3F0msRdYG5JodhKstxvFoG1%2Bw4nvFhRrZiyQxyoRaywhxmmI0GOHuF%2Ffx5d%2B%2Bxp3P7qE94jYJCqNmcWEUrul8ZdRoDGneHFfSNOC0259JoSGK8VouCddE2rc0KtHNRtge5ljwr5iiKBbArMBcPm2WJpjSERaxjenzIJZ5trTbGmcpdDY%2BEoYMHvad%2BtNErA7VXTPZWtSveqzJ%2FJrFEBAHhlcWEAqhUC0B294J12jS031Ot89cGNbapJ2LyVyF9mqyCDO1p2ks8hhYxEjjDkbdHext3cHu1m2M%2Bjtot3rap4nSDk2yNiPoNVzr7%2BhrIrZJtqHAR0WBjbD5UTXn7wuZiqcLm%2FF9Cmx32tjb28NoNEKrlZnZ4Mok%2BOvw5KTi05OV5BNDmKQaxVfpFEUGzzzRad9mXGp1nCvOKEos8gjLpfSZdq5muUBULCRY2qoy3dtQu2IASK5UXa7V8opJCf%2BGubMilsPqV%2BapoPQCPoBrE76bwCEhGhrNBqNgZ2jSZDZGGacokCAvW8ijLpL2NlrdPaSdPSStLSDpo%2BSmxyBoimGS7Eq6BmI3Jn%2FRq6lpvQm8txIecAwOP7j%2B3Wm1cWt7D3%2F%2BssDJ%2BQkuJud4evgE03wm8z72MBO1bY%2BfKTJpUleCB2TwiCDSzRhDLluwjk%2FvQ8aQ7x3pkKQJ0tg0OPmSWhzSK0IraSHlPqoiQrfVxcM7D%2FD3P%2F83fPn5H7A1GKGdZqaToOzn2o%2BVN6pJ2%2Fo9q%2B9ej%2B5aOOGCQVjE0nITh5M0Rrvfxf79O%2FhqOsX5%2BRlml5c4OzjEcl4gKnIs8wWwyNGKErSzTA5LCJVpq5rwEfDrIdPbuC6Evh7oH2yqNcztPWC7a6EmaLjTlvrHsiiwXC707hT0v5RShijR7rZw9%2FP7%2BD%2F%2Br%2F8Tf%2FjLV%2Bhv0dEYvVybyGKLgrxfr22VLB4r8rOZV%2FrQatr66bq2Yk6zEa%2BdVXFE4CfWgkg75gJniR0Km%2FnMnJ%2BdlDi7BJblDGWZSOsZ0TKmKOx4pYSae3q75v5P26IhL82OV0DABNLr4Aog%2BOX1EPTUr3cNMLw6cRO%2B5j1z1s80mTXP5YW8QEvwVB0UHCnIx%2FJIzUUomRaH6SIu6DU6RgpaPLSAJe87GHW2cWvrLm7v3Mf28BY69H4e0ZomRUSzdwm3Xj%2FfcL93sBrPr0Zyk2JDgY%2BKAhth86Nqzt8RMkHB5PMLZQJN1HGEfr%2BP%2B%2Ffvo9vpoNfvIUlsstVqfWAI3wam1XxJxiIwCFW5YV6omQ0GhCNQohYineMYVky5pyovdHQBXaMX0xiLIkVRzBBHUzEPhD1CbloOnrXHCunwiFd9%2FMoHF8B4z3qN87HJy1btLZz3H%2BZHzLXvZboyx5LYLggSb%2BJLPOgghxQnsxchF9OUoMh5zl0LRUSNwxhp95a%2BSbYNpEMgsjM16YrHTEyb9HP6NGilhr8ClCd8y1drV2M9Iu3r4SE6KVJs97fwv%2F3p79K4%2FL%2F%2F8T%2Fx0%2FPHOJ9eSohgn4%2BSCMUix7KgZrzQe9BKU8RBS8a9faKdVfGW4f7wizMNn70fJReslhTRSzGQ0jMU3PeW2NEzrR4e3L6P%2F%2FG3%2F4G%2F%2F%2BlvuDXesX1W3AvJZYqgQV5lEZ2wvLIev%2F5S2nDQYyl2ZftSqiG%2F2tvq4%2F4XDyRY5ssF%2Fmv577g4PEG0LNGihjuh2WMC7lteliWWy6WAqEyqVWpDoym51uEn%2BJ%2FGogTH2bxYmiZP4w9px%2FGjRJlwfImR0%2BlOlKPd70uj%2Bdf%2F%2Fe%2F48q9%2FxJjmsx2%2Bd2wj0k5ENDo3mlzrVI3nm25ft7dUreRDkrRuplVVu%2Bl959zDD3toJi1br72FvXEuK4c0biGL2ji7PMZseQlwoZNn9ybU6HL8qM3vJVCyJM15Mqeou3alVbWgm3B7f%2BFOJL9eB4nNl6IV32ttb7EphwIovctKOKS5bA7k8q8UyRlhyjO1edQaT8vMaQ2RohV3Meru4vbOA9zZ%2FQzbo1vSLifcTsNtNZx39LU2svWeGr5VbfF18G7CNhT4%2BCmwETY%2F%2Fjb%2BMDHUROegRToOwNmhLMuwu7ODtNUCnapw8NYEydlW%2B5huXMD3Aq%2B9cvj3iZ3XlWefn0I4JwifLkxwsiLNK21LJkoUFPkXxwXQypFy7kGCZdTCcnaMvDiXRo7aTE1udFFPIau0oy64%2Fmz7NpvQOIRWO1e3KXgZNAwL37IhPF2L7fsMNBhJN8LuH4UGIbs2FzZ8paSSDpgMNQXLFMsikdCea%2BW4i7hNQXMXaXcfcWcPSMdANLA9tJr0WYPpx1V31YK2mMDFgjVoAj0dwnd3JRnI9NAkmG2Y5yXypIN7e%2FdQ%2Ftncj7bTDn589gRHZ6cSJrTvlJpdWdAuzFMtyRPzLFp2ZtLO%2B4v1DMegDvWQj%2Bvqjj6okRAZSBCeacq9l3Gqo0747lCo3%2BqP8fntB%2FjLV3%2FGX%2F%2F4V9zdu4NuqyNTd2sNM7GMyWAG5yE1XZ2SvNa9542oyawC0krlmKHFNb7VdGikbYEpBrsj%2FCH50t6CCPj%2BP%2F%2BFsxfHWM6XMoXkfkOZTPq4Exwh6b0iQJJhXeD0BZwA6S8E%2FY3w%2FI0Tc4w2wcnOR%2FTqZTLLxT%2BdrZrIq6uWa0ifLEXSStAZdnH388%2Fwl7%2F%2FDV%2F97WuMbm0h7WU8PpErD2HfvI38NoRVVNYb9zoCp4SM0O4O201X72WmfaM%2Bjh%2F7tTiqwTlDMoybNNpoRTl6WYFoQJPPDN20h%2BeHT3Byfojp4hKLgkfpLM0FAOdNesfSApW8aql8LmAIP4VzvPaeb3XfBO%2F7DSdsTfia9w6Zzc1azIloJst3UDOxzsKE1NvUaBJhbk0x4ZIeZBPSt9RGGJnJjvu72Nu%2Bi%2F3xPWxRo9kaIuYCJ9XjNHXmGK23tm4zh2Jz3VBgQwGjwEbY3PSE90YBWQOGecPFKRPEImTttrwvar8TB3IKaCsTzC8HW%2FPOCptuIkqTnfRp3aZe5vAJhTHcQ0jtJpkcnU%2BgBU6aSMbUekb0WJsin7dQ5PRyydeMHmtpUksTJu6n4REpZG%2BXNtmLGMSJdTWvNiEGtmctvmJRQp4P5WLaV4PZmReCztV60%2BaSdkZ1mj6SKtL7SudXFDSXzbBEhgXVPkkXaXuIpEdB8xaSzg6ibAuI%2BwDaKOkwSDRmqcZQ2eTPPTvk86vepVqNwvxd%2F747%2BlU1lZA5JJJM%2FZlH%2BjzYu4%2Fy61KMTbc9wrc%2Ffo%2FD0yNzkkUteNi3J%2BNanctZt%2Fs608t66th3h8%2F7Llm9h0IXhcyS8gE1Fi3QBE7aTLTQTtryNPv53c%2Fw16%2F%2BhD9%2B%2FiXu79%2FFoN03PYT6hb3DXATima31%2B0cM1ynpz6Ty63%2FE9mrfNUtkGdb7uVilRS2Z00JC8iAd4w%2FxV3pPsnaGR%2F%2F1LY6evcDicorFgu5suN4Wac%2Bml8RxxOEWhCYdrQDokK8E%2FsYPb0a1VwAnCV0H78pEkgImBU%2Ftc672swJFHOtoEwqbUZYg63fQ2x7j9sN7%2BPKvX%2BOLr%2F%2BI3fu3gqAZjqWJjVoUUHhXj70Gk%2BNxI02D0P8KDBTNsq038NEEJI6Rak9drRQt2gXHPhwHopLm4R10CHI7RZZ05KgmjTpyInR6cYiL2SnmxQTLco68XEioArd%2BCAH2GVv0NHysZ3LRj8NiuATcb8DEE90Q%2FUbBLOu1Pk59T8zn9TDGuVbaWo%2BLUxL%2BOVwsTejk2btcjtIRJRo3IsR5ilaUod3qS3gf9raxt809mnek3exmQ8RxW4JmFLSa1IKyfawmg%2Bs6iBzizXVDgU%2BRAhth81Ns9Q8JZ59kODoHbScdOyzzHGWShPM1OZ2E4ZsT%2Ba8YyUM1Ks2r5lVfr0IRVWio21kC7smk4EljSE4vxjDSYQf1KjzUmSZNUZJiPqWGM0WZ07kD3QvOURY0f6OWao4SYoFsZVVCqO3Fq2d7AkTdizOTTcQFZID8Q2pQ0pJwGsxOV2OjnNHR9FyxWeb8h3syw77MMkMedVAkA6A1RNIeodXZllaT%2BzXjjA6B%2BmY%2B66vLqo9115pNa1XCYTAZ9ZyGfn33tGN%2FdYGXDDF5yIyr7WmMKF%2Bg3%2Brj4e3P0Eo76HQGaGddfPvTIxydn2C6nMhpBflMmsUti4WWKpzEvx0W755Ob1ID6ShnHjmXfhIkrZa0mHTkzGNM%2Bu0h9sZ7%2BOz2A3z9xVf4%2BuEX2N%2B9hUGnJ70Q6UahTWbsOhrCmX722MBt89pg%2BN8EvjqtjyOBJ%2FbXlqOHVyNYuB3cTGX7u2N5RU1bKTr9Lr7%2Fz2%2Fw4skzTE%2FPkM8WpvziW1aaQzL2r3UwxVjXQKzcmTZwJeh39aAWCh2fNOQbb156bUGSZrNyoMRwEiaOQGuZzrCH8a1d3PniAb7481e4%2F%2BVDbO3vSQDlWhVNbU2e8zbjSGYVVc0WKCV6N9pvlYCv%2B1Y201mdajfvl1Wh9dyjkayk31OagrLvR8iilvDL4rZMPjvZEIcnQxydv8DF%2FAST5QXmOTWd3NLBfhjLkgj0WivEwrxDDbu5H9CIWVvUVIBUN06P9X5XJfiVN03K3FiUVtquT8nzii3GmAo%2BcWnXtZgmaJqZbMzzMXl0SRyjHWcaj%2Bn8Z9TbxtZgR9pMCp2dtI%2BE5zhz7qdGWG3Aq7VPRRNxE4T6ethuxGcTsaHAR0yBjbD5ETfu7wq1sDJNRogr%2BGdnZ8iyFga9PuKMWqDwCQLprxE4vaiVKysIZdsaL6eOhvCnxC70UdgM6gil4l5Bvkr2jWnGl6YoYzvvsVzY3rGymAHRAijo1EFiahDMWDmFVa8vTFsylWWd%2FnUq%2BJ5Eh3EFk%2Ff8QBgNTsfRdtJxng%2FwaxXYhUA7zoSeZouI5sltFDRRigdy%2FpN0dtHq7iLr7CBujRAnQyDuQhvdylTWiaSChDhxPnoKMLCNSA7%2B0NzSWUc%2BB1iq67snm62sl3LaIS%2BRMVlGc%2FjTbw9w91YLWaeH%2FnCE8c4uvv3xOzw%2BeIyTc5pkW5uzDJ2YQwxcrfmuOL53T5JfXAPbmxaKNDVOk0x7YSVoJhm2%2B9u4d%2Bs%2BvvzsS3z14A86S3NvtCXHTNybCQqoMfdoUVjLkefc90amMXzC62dPDF0JsOBrgjx78%2Bo97ubkQaOkamwxJkljDLbH%2BPzrL9Hr9bA1GuHRv77Fsx8e4%2BTFIeaXMw1NZR7GEI5bDTAdDxc4Xbi0d8Rjm1D%2BNvc30%2BDN62fbk3IymaXQR4GbJuqJ7fdWXRSe0hjdbhv97TF27%2B7j7sMHePD1F7jzxX1QqI87LZR0uEPNcxDaJbwHYWWVWm62%2B%2Bbw3pij0W6epq7TKFbTzecHpuTSJucb9jA6%2F0mQtjK0Rj102gN0OwP0ekMcXbzA2fQY59MTTBbnWJYTFJhrTyc9qKojyYuzTX4m7JKuGlQdpJuvNbA3p3ndmICoF%2BnX1ewMvT6mmY5DYk29oMmU5RFNahNEMqO1RWCeo0nNcL%2FdxbAzxHZ%2FBzvDPQy7W%2Bi3x%2Bi2B8hoXRNMZ7XYLEeBYVsG%2B40q95byKwNfDWsT7s39hgIfKwU2wubH2rLvES8fXnn1%2B%2BvBaQzKnByKQiur%2BWKBFwfP0el05Lgjo1MUMhHBay0ZxV%2Bj3iRMrNlha0ChMAtvhq5Cb%2FFmoslSKHgWNMmhtooMTziuww5jpyKzBSzaKKilWk5R0KSWDoRAE1uaxtGkNmcpQeC0%2BmxtNgi2K9CanrAWhtdhJYSO3Srsv8UTodFXQqXdi5mjMO1niFYtkJiQWWYSNJH0kKRDRK0RkvYeMjoDoqCZjoCoi5KOmZChpKCpQ7ettlLlkmJX8RYDJRI5Xfz6W1DD6iADS2GXTDLP1CzzElyfIJMoRz9ljk7Sxu2dfYzGW9jfv4Pb%2B%2Fv457f%2FxI9PfsDhyUtcTk%2BxzHlGIM24zeOqsA%2BMdxMbl0ObYb%2BrewqTawCr1ei8g1rNnI5zUmmBM3qULRO0ohb2Rjv48sGX%2BPqLr%2FGHe1%2BInoOsK6N3ep0MFpLS6NC0jt1FJrTsSyv1eT9iqN8zwY3qrJXc1YMaaK2IKtIWSVix6haCHE9oFwy0Bx3c%2B8Nn2Lu1h4dfPMS%2F%2FuOf%2BOYf%2F8TLp88xvZhieTHDcp6jDHgxu203oOBFs0GrSIIZf3wxpolOA5Z3frtK4DeozmGvsxBPCZqkFaeD1I6D4fmZ9LnKT9puSTM82tvBvS8%2Bwxdff4V7XzzEYH8b6aCDqG3v3rLktgY2gjmT8SVFH0uMXDXRKjRYdR1cA%2Fcmd1VhzUzsA6u9LvQQjayskgtNFDJtbKOGnmNLgozH%2FHQzdLIeBv0Rhpfb0nCenL%2BU86Dp4hyL4hLL3I5MKUpqN7nIYf2f44bTdf2NaELI%2Bwr0X0sDLzgU%2BOriRAHP9VpXiptJTPq0kHKrC7XfsnHgsUcdDDpD7Ix29N3q72DQHqGd9JBGbURoIUEmqyUuKmufeNhWw1byfkJArOVeC6RNog0FPikKbITNT6q5f1tkTXcV6jRu25ycNIJqiHhUgTFfi9kUxy9fotNpY9BuY9TtanLg9KaJ6FfP8DaR%2B2TJMrlGyWfXAlgKxjDUJjf9yit9WNFUOO%2BpFeHUnEibyWd6jeQKapa2geUAWJ4jp9OG2SWKJb8meMprYEmBk5M%2Bdy4G5w1iDu1cRp%2FVdfak9pbx%2FDhBa8yHAONP%2BAixxrOHv%2Btrgw8XCFo3D0wMhYfQvjRxEpcmxwo8OT2TIBmnPSStIVrtEdL2NtL2DqJ0jIjmtFpVppt5pg8r%2BlpR5l47FzKJs2m8DFVWGOhAjSC%2FoS3XSeHtLuZtPfKXPqtqMoHcl0rnLhS2I5l8skjqKWjK2cna4K5T7r%2FKI6AfFehnHWz1%2Bvj89j08e%2FEMP%2F70Pb778Ru8OHqO6XKGOY9xKEod5bDk8Rg81J19w5lU9Q%2BWbwJVLZj%2FUmR%2Bw3xaS1JnWamUbcP9VWmaIskS8zobJRh2B7i9dxuf3X2Ah3cf4u7ubewMtzDsDtFrddCKaHbIYw74rvIvmL4zPGXfiaXdXC65n5rnclLj4x%2FrU%2F6ka%2BhSK2E3PYTsPCeT7W9C4KogaIJO1XBge1IwJI7UzCVxia1kH38b9%2FHgj5%2Fj%2BU%2FP8PjRj3j26DEuj8%2BRz5fI5wvki6U8axbcggCa63ufbwgGN8EZwinE6V3wF%2FgV6d8oWu%2FrG%2BVYSWwg2TjCCL7aMj2W%2BbEddULvvK1WisFggDv37%2BHe55%2Fh9v272Lmzj9HuNtrjIaJuak6A1MzsDwlQ5CY4hm7HXhFmG5tzfBD2ZvLrtXSyMe%2FnuonFeQ3ExkKq8ScsDKh4DhT88Jgfa1Wz6FBb0WGYzTUJ82ibRowsjjHqtNBOexh1tjAd35WX2un8HJezM8zmF5jOJpjNuIgh%2F9YAABHPSURBVBd4YR5rqwUe0xj7At61KAaQ3s%2Fl5yjbhCgsG%2FBoE9ItitFKUrRbbXTbPXQ7PXSzLnpZH91WH%2F1OX89Z2jVNZtyRoMktMNKG8gglLuxUfcNagx2xhqi%2B9zna2rRO0YRwc7%2BhwKdCgah0LutTwXiD53ulwM91N62o5jmOj4%2Fx6IcfxPTt7e5id3cX7XbbmDU6x4jJRK2Isr8KJ59MCRv%2FOC1Q8F1l0Wrmg%2BlN1tOd6masiQ8LQJrKOcpyhih8kV%2BiXEyQL2coFhN9c2o58znKfK6rGAX6Ytdh5JwcCQtX3F31QcGKrGkehHaDXKC%2BRXr8GmK6bOfUcwrZ1bQQJK5Wlmn%2BmHYQJz3EaR9pawAJnNwb0xoAyRBl1EMJEzK5wmymyiY0sH1IH2Pt3MTMayRVml8y%2BN5nRLFfg%2BYb5VW%2FoiZGtmkmYLIA9nd%2BqLUnqHb6HXtRgUW5xDyfY7ac42JygaOTl3h%2B%2BAyHpy9xcnaKl8dHODo50f3ZxQUms6kEUJYoPlWaOitfzI66kD2%2FEfDvIbHYtbUmolCeZW0dhTToDzDsDzEaDDHuD7G3tSthc393HzujLfSyrvZttmJqO%2BlV0hhE0sFZQfWMsGjF9qEpLa90MJPQwUyDffy1JGC5FDS9%2FEqg0DjCOKuB4LA%2FSyilCMzFGC4oLJaIcu7RjFEslpicnuP44BDHzw5xdniCk8NjHB28xPHREf7%2F9s5DuY0cCcOgRCX7vGv5fHXv%2F4C3q3JYBQZdfR0GmMiRRFIzVMtFDwax%2B0fqRgOYXz9%2FpoeHx7R6epJz7zpQjeOAfkQbhc5CtxqXeGQs75Ejo1fRaLnyEwucnq08v1gmvsl8cX2Zbm6u05cvX9Lt7W369u1buv12m77%2F9z%2Fp9vu%2F082ff6Tlp5t0drlM6fJchxByxoqHcil9kcty8PMWoi1A20xFxpEd2l%2B1OtRdEsBOIOpK2g27SBhDWHTiLgC%2Bqbng9vNVWvPbckkQbeIhPa7v5fucq9WTfnt0vUkbObesuct4KgtXOt%2BUZc7HTcWW9x1Qn3qxFgrn5cVlumKR7%2FwyXS%2BvE%2Bddzxkr5Obai3R2dpHOOcvJuUxZTNa8Gq3D4GgMVuYr%2FagBWNn3G0HxGgicNAKhbJ509U6Tua5B2ClF0Lq%2Fv5czm8yi8q3NT5%2FEmiFCGOdwZIuYKw6e8u1Pn85VcezLrwg1ZSHHRGpEZeDDXXw8G8WTG2i5CZCzmuuUNitRLp83j6JgbtePabNZpe3a4qBsyudRkK64dVCVKLU46DZUtQxSjv%2BpBcPf3vPpGFY0mACHv%2FwQqOW7gct0vrxK58ubdHbO71NanF%2FLj%2FOYiwVnN6%2FS1rbMIiEy8asN2laq3fZgVgAroSraxEVTHFwg8GcR7UjOdrsHEa27Ch9ZspBNsrK1j21uCIJcDHS%2Fekj%2FPN6nH79%2Fpr%2Fu%2Fk53P%2B7S3Y%2Bf6cfvX%2Bn%2B8VGVC2OPW1o5j3gqfyheXPLCN3j%2F9eWLnOX%2B%2BvmP9P3PW1EwP998kttcZXMcl31whg3LJVvaBZMsJnZh4nVzCGHQ86bcrvwJZyiplAYUCOsv2mm0Jcv%2FKIPrbdo8bdP2YZVWvx7ST5TN%2F%2F2V7v6%2BS79%2F%2FUqPD4%2Fp6ekpPYnFCiW6i%2BPsJ%2BXaK%2BshQu%2BuRDn5i1yv7X0%2BdlAYyhAWzeXlMnFj78XVRbq5uUlfv36VhUkUzusvn9Py5jqdL%2FluplzprCuI6AwQYUqmL455HZX1Y9FexN8xIzvNiggl69wkO2DkYLd88EUUT8YRFim3LFQ%2B47%2BWelbF0lAt2onkIXsvbCXkmIztrSxXNusZMhJwGZB8p3fBrMKClF70k%2ByeBL1VnvT4M990LUCNb83UVdm26hTFWyBw%2BgiEsnn6dTxJDvNEWScPf6wM%2FtFyFEu2zTFQq7KJZZOJYvxAXy%2FhkG%2BuMiDk61Y2JnbcfvkPW2UTfqwcb1eifPJlablFVc4dqmVTJUTZe6nKp66%2F65lHYV2VUOFmklgYzk6bVRdiNMqmfCxyQb2ygdR%2BZ2ynxXp5IZ%2Bh2HJ9jkz%2BrmTquVigIDv96cq%2BKpp9dWuFS4q%2BOO%2Fvr63HLEuI1CIQuwT4nFbPm%2FS4eRIL5nrDh%2Bu3abVZy7ZLtdCYsInygoXDTGZVXzmQAnE05BZ8BmaZLrh5lvNXZ%2Bfp88V1ulpy9nmRtijYcjvtmdwIzXZY3aFgjeVohOaCxgiZPhZW9WTJK3%2BagPcjH2Lo%2Fgwj8Lzaps16nbZr%2BLft1LQBPgtjFttMUcPF4o%2FnLf2DtnM4y2ZVunfJymO3w%2FsHfR0FUm5ztjVHUT4vbIs132ZmjLFPoAh27qYYGzy8Z%2BFVuj1K%2BcQ91T%2FaidIvpnEhk8VJPR%2FvCxe6gKWcMj%2FVlchmdWiOPsc00ZkqEiVdcNRWEDNSvvjE0%2F%2BRnjPhjCbsNmkqmU2UyvLCHQgEAkMIhLI5hE6EHQ0BJkyEYxewKBilkj%2BEIZlQsfTZ97KygHQ0EkcWxMTMjxVkfroVybfEynQllkuUTvsx8WOd4x3LKEqBWTTVTX52llPmUISKhgBQCYwjyTxUtAZZWkzpaffri8SnEzuX%2FYiSeaZKpqwmL7hASb%2FByVlYJETZziQCgLOvglSlUAzyNA9BQZFyhdMYEhmS5Ypt4jKTtWzJZTu12h%2FEOsPFObQ8Fmu2W7GG0oywCOq283nw31eFwhvjg21FxjJxfX6RrjjDKYqmWvD0bBULGmbtN72p2kHdV4Bh9x7jio95zbIrf2hu9m%2FWpFYbsXKKhUYuJsvtxfRGOefX0qQGMNBGZGPNULw9hJWjwujswIGxj0e1GENP0H%2FMIbR%2Fxk1ZlGQXxZKzr3aZTkOxdBpkjhHQlBJ6yxx6DG1Eaa8jqHzp%2F%2FABOjov2dwiC5ukUUWrnpqYYMgIzJ%2Bj1Iw15feu2qPd2OqEL7xpIxJGtP%2B5gupP8unKa8q8B22BwPQQiAuCplcnH5IiJk0UM84MMei79RJ%2FLJ38udCsk8JUYfKJyfdrqeAj%2FNkZQ1E85ZIbJnFfZdaLblAqCZcJXiZEEw4EH6xdJmWZ0j2leVDIdvZ7q6cUXLi8Bn7MYimY8OkCFCeb5Ktzdp5xTi9JbeuYh%2FYWO5MA5UP%2F9zOeIh8Bk53jY9B%2BNg3bWooawhG%2BOYd2RjvBQmxbt4pzaDOBoUWmdAXhyxROGMeSx7k0djpUF3dp%2FwArZOTcWlpZtjwmO67Q0Ms%2FmILNpe4SEF4Jb0ST9zErMQIS%2FzlgZNTMrCTg9e5mfTTfR%2BdcKZpKajW%2Bni3kZmLJR5oCi1u8qbql%2BbMQ4S6ebX4Pw72Wuc%2F%2Fvc1CbxtL5UL9tZWIjwzUdctmkya17JGynWsz7vTfnQ%2BeVrMKhJJeuj28o01Mn8%2BgMBCYLgKhbE63bj4MZapo6kSAQunvum1WlUzAyBe8TB0am9BUyrEJWydtRB75kDxRZNJHEsKiq5Yq5cwmR78giAm%2F0uSIj5LmCplIUu8OCOz4%2BScnRlBQtgsMzEP4YeqHfrZ%2FsmUJCVK3SKuyWYkGliW%2BOYT4jrSXeTJPg0mULORCFC1RBmg%2F4JI5d9x9sV7wzMGnIS96xS648Vktv9py1JoreBQKCFiIIA6O0%2BgizkHr6QpDM6DPv6j66nbvBZYqNKhqS2Uzt%2Fq7NA%2FXuAiSdFVnrUfe4xsleCn%2BfGn22rQ1Jz%2BlSB4yHlTKtYZI3iSo%2BoMrmpVHVXzbpwqahQP6HdPS7cTnMEKHOoXHJOWcUdE24vzXeSn5wt18JxXp8fdnzilcgUAg8DIEQtl8GV4R%2ByAI6Lk7Fa5QNlG%2BVIhksNfttGr5JE4lSB6Eln1l6pOXiECFGMDUpRYEsWBithKGVJHS6VHd%2BVxNtjigcMu2UvmotJexL5pfn0%2FXtA4XUJip9FhbvXFXiuMWRbVGSUwioz1JIuLzp0%2FNSzSKE7NnGpvFw1Vqay3aRiw846keprcXqU%2FVqZxrezHerXV5S1GFS%2Fsc3Yq%2FJl7qO%2Ff%2FbQs120WlY6gSJUsSzngHi9IjtQtV%2FUqiHQEkqoOuLc8O2sZ4QSbpdWTJKbTG7V3qXUApKt%2Feq9ZwBIYzeUdz7ZerQmE%2FGgf7KkgaQZFZNzLZ1%2BNnn5y4yy%2BHhisQCAR2IxDK5m6MIsYBEXArJk8%2Fj6mrrqpwlqv7yFDE06Occ5kAnE6exYQmlgQTmUy3IlRj40Ld0DOsPuUTWy4vwLojF%2BccsGJek7WxqlwqbwXHRY5YcXUbl4RXkSyN5OOqqlr08JKfxNV4VlyR72k4K12B7a8srtg%2FbRPDPKrVczjOnEOpfrfkMk7o4pMs35gKoi2FeN5m5sxvH%2B2yGCGLNI5HPufr3amZFjwydjlUxli3ilaNL4e%2F2VUomGX99dHZV17V323tzd91NMijqw6iufbzHKJ%2BzXI9n75y5%2BoPX928uq8%2FuzkcDu1OM03f%2FhqGR59fffbNPFg6jZS9wxUIBAIvRiCUzRdDFgn2iwBCkhtu6hZO3eWl4ZSpCimu%2Fsljv7S9NTdmKZupXMqrJACVwPBePOs30rQ0T0NKhOn8nsVnSfRW4g6aHqqhl3%2FqzsWhKD87HoS6IdPqVdQrEpnJDsg0l1zvEpyzPBlXJesbJqYDpC14lYEdHDctnBmtjsgz9PJ2BJ%2FSb4yHUpnoahenhoNXnfDNxVB2ntv9%2FSm6qA6i7mVPXcRoeMo23IxlK%2FRVHl5nVWJr1131VMXpcXg9%2Brwg0apxpJ6oezmqOYrU05zim2OWefMa8WcOOS2Xc%2B7PPu524NDTvvpyC%2F9AIBDoRiBuo%2B3GJXyPhEAWlHYM%2BgU92QJaeE7QCW%2F5rzHptYJKj9JNDuWmSn1vr1nnkiRGrex62Gvexgihbl%2FS%2FOEXkY9twno%2BqESgRh7ag0iQ8K28izVPtKcSCzOR2CY6aOoWKl%2FD4fumKduKu0vOlTr1KXHso7qdti%2Fm9PybSnOLwgKAOp9lgLYM0rJTfUz7bZUzYQ%2FtP2rN9GMHwivKXKeCKaEDYYdj1uuIp7iLanpxqbo2VZ1fLtPDtte6P4XrDjycJgkvM%2FkQ7pL7YYbHxxzOZ6qh2hThkh9vZeMs3VPlIOgKBOaBQCib86ink6bSheuXMNkvUL0kl2nFHcbBp322n%2FLzCbKfh%2BH8%2BtO1Q%2FxSjXZIzadSDlEKmahRMvOvVCKcG0lfm9M1RBXXuvpaK4ucRYjUxKVw2Yw3l%2Fdd9aXhNeQ6WdvdMjqTTcaTGq01iTdSNpfFqZeyWbaX7O5vHzpm7hPZ8RTvu0129QXnzzmUdtShaI6nOmIGAoFAIBAI7AOB2Ea7DxQjjzchcIqKYxuQfiFQ47qI1E6Zw0slkyX%2BgTwlaCC8r5guf5HaugKafpRnZZJGzC%2Fux6ddmvH9vR2A8riLej%2FVSS7Ebefi%2Bc%2FjST%2FISkObZhem2yHZxzGbOxZwdAo85Jo5rMvHULd4Hra098%2B9ry84Du9PYVAQCAQCgUAg4AiEsulIxDMQOBgCrnD1FYBYvSsOacfE6SvjLf6UO1b093hOK0%2B9DKhOgcfzJ6Glu%2Bu9nkM7fjN8fu8Iy0MK5y6OHEFQjz9FIBSQ02wJffXqfcCfp8l9cBUIBAKBwHwQCGVzPnUVlJ4sAq4a%2BHOIUUQoi9dvKtyvrU%2BKe6no5vE3PUok4c6Lu%2BHb0w1hcNphfUL0GK6pqrkj6PT7cwzfEUcR0LbzsZHzUdT7wsdGI3pGIBAIBALvj0Aom%2B9fB0HBh0AAkcfFoC6GCRsKL9OQ1y4RamxeZb5D7l3ledqyXHNXZzmJ47eqOg9d%2BXb5ef7xbCLQtISCelkLzfhzeKcF7OLhLUr5HDAIGocRaLb7vvZAOxozopBfXx7DlERoIBAIBAKBwBACoWwOoRNhgcBeEHDReUjkcdHan30Fk8dQPmW6XXmVcYfcY8sr86Bsfn7O1MPsOkleB8l7TZleRjznjIA3i10tIJSDOdfy%2FmlvKp9SgtxYvbuszrS7k0WMQCAQCAQCgREIhLI5AqSIEgi8HYEh0RnxmnAXs%2FtKI07564un%2FvqNzuE440KHaO%2FKAT74oWja50q6ssDiWWPZI7mnv3eVEX6BQCAQCAQCgUAgEAgEAlNH4P%2FwfFe7fdASWAAAAABJRU5ErkJggg%3D%3D)%0A%0A%23%23%23%23%23%23%208.1.3%20Spring%20WebFlux%0A%0A%3E%20%E4%BC%A0%E7%BB%9F%E7%9A%84web%E6%A1%86%E6%9E%B6%EF%BC%8C%20%E5%A6%82struts2%2C%20SpringMvc%E7%AD%89%E9%83%BD%E6%98%AF%E5%9F%BA%E4%BA%8EServlet%20API%E5%B9%B6%E5%9C%A8servlet%E5%AE%B9%E5%99%A8%E4%B8%8A%E8%BF%90%E8%A1%8C%E7%9A%84%0A%3E%0A%3E%20%E5%9C%A8Servlet3.1%E4%B9%8B%E5%90%8E%E5%87%BA%E7%8E%B0%E4%BA%86%E5%BC%82%E6%AD%A5%E9%9D%9E%E9%98%BB%E5%A1%9E%E6%94%AF%E6%8C%81%EF%BC%8CWebFlux%E6%98%AF%E4%B8%80%E4%B8%AA%E5%85%B8%E5%9E%8B%E7%9A%84%E5%BC%82%E6%AD%A5%E9%9D%9E%E9%98%BB%E5%A1%9E%E6%A1%86%E6%9E%B6%EF%BC%8C%E5%AE%83%E7%9A%84%E6%A0%B8%E5%BF%83%E6%98%AF%E5%9F%BA%E4%BA%8EReactor%E7%9A%84%E7%9B%B8%E5%85%B3API%E5%AE%9E%E7%8E%B0%E7%9A%84%0A%3E%0A%3E%20%E5%8F%AF%E4%BB%A5%E8%BF%90%E8%A1%8C%E5%9C%A8%E5%A6%82Netty%EF%BC%8CUndertow%E5%8F%8A%E6%94%AF%E6%8C%81Servlet3.1%E7%9A%84%E5%AE%B9%E5%99%A8%E4%B8%8A%E3%80%82%0A%0A%23%23%23%23%23%23%208.1.4%20%E4%B8%89%E5%A4%A7%E6%A0%B8%E5%BF%83%0A%0A1.%20Route%0A%0A%20%20%20%3E%20%E8%B7%AF%E7%94%B1%E6%98%AF%E6%9E%84%E5%BB%BA%E7%BD%91%E5%85%B3%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%A8%A1%E5%9D%97%EF%BC%8C%E5%AE%83%E7%94%B1ID%EF%BC%8C%E7%9B%AE%E6%A0%87URI%EF%BC%8C%E4%B8%80%E7%B3%BB%E5%88%97%E7%9A%84%E6%96%AD%E8%A8%80%E5%92%8C%E8%BF%87%E6%BB%A4%E5%99%A8%E7%BB%84%E6%88%90%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%96%AD%E8%A8%80%E4%B8%BAtrue%E5%88%99%E5%8C%B9%E9%85%8D%E8%AF%A5%E8%B7%AF%E7%94%B1%0A%0A2.%20Predicate%0A%0A%20%20%20%3E%20%E5%8F%82%E8%80%83%E7%9A%84%E6%98%AFJava8%E7%9A%84java.util.function.Predicate%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%BC%80%E5%8F%91%E4%BA%BA%E5%91%98%E5%8F%AF%E4%BB%A5%E5%8C%B9%E9%85%8DHTTP%E8%AF%B7%E6%B1%82%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E5%86%85%E5%AE%B9%E4%BE%8B%E5%A6%82%E6%B6%88%E6%81%AF%E5%A4%B4%E5%92%8C%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AF%B7%E6%B1%82%E4%B8%8E%E6%96%AD%E8%A8%80%E7%9B%B8%E5%8C%B9%E9%85%8D%E5%88%99%E8%BF%9B%E8%A1%8C%E8%B7%AF%E7%94%B1%0A%0A3.%20Filter%0A%0A%20%20%20%3E%20Filter%E6%98%AF%E7%9A%84%E6%98%AFSpring%E6%A1%86%E6%9E%B6%E4%B8%AD%E7%9A%84GateWayFilter%E7%9A%84%E5%AE%9E%E4%BE%8B%EF%BC%8C%E4%BD%BF%E7%94%A8%E8%BF%87%E8%99%91%E5%99%A8%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%AF%B7%E6%B1%82%E8%A2%AB%E8%B7%AF%E7%94%B1%E5%89%8D%E6%88%96%E8%B7%AF%E7%94%B1%E5%90%8E%E5%AF%B9%E8%AF%B7%E6%B1%82%E8%BF%9B%E8%A1%8C%E4%BF%AE%E6%94%B9%0A%0A4.%20%E6%80%BB%E7%BB%93%0A%0A%20%20%20%3E%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91SpringCloud%20GateWay%E5%8F%91%E5%87%BA%E8%AF%B7%E6%B1%82%2C%E7%84%B6%E5%90%8E%E7%94%B1**GateWay%20Handler%20Mapping**%E4%B8%AD%E6%89%BE%E5%88%B0%E8%AF%B7%E6%B1%82%E7%9B%B8%E5%8C%B9%E9%85%8D%E7%9A%84%E8%B7%AF%E7%94%B1%EF%BC%8C%E5%B0%86%E5%85%B6%E5%8F%91%E9%80%81%E5%88%B0**Gateway%20Web%20Handler**%2C%20%E5%86%8D%E9%80%9A%E8%BF%87%E6%8C%87%E5%AE%9A%E7%9A%84%E8%BF%87%E6%BB%A4%E5%99%A8%E9%93%BE%E5%B0%86%E8%AF%B7%E6%B1%82%E5%8F%91%E9%80%81%E5%88%B0%E5%AE%9E%E7%8E%B0%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%89%A7%E8%A1%8C%E9%80%BB%E8%BE%91%EF%BC%8C%E7%84%B6%E5%90%8E%E8%BF%94%E5%9B%9E%E3%80%82%0A%20%20%20%3E%0A%20%20%20%3E%20%E8%BF%87%E6%BB%A4%E5%89%8D%E5%8F%AF%E4%BB%A5%E8%BF%9B%E8%A1%8C%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%EF%BC%8C%E6%B5%81%E9%87%8F%E7%9B%91%E6%8E%A7%EF%BC%8C%E6%97%A5%E5%BF%97%E8%BE%93%E5%87%BA%EF%BC%8C%E5%8D%8F%E8%AE%AE%E8%BD%AC%E6%8D%A2%E7%AD%89%0A%20%20%20%3E%0A%20%20%20%3E%20%E8%BF%87%E6%BB%A4%E5%90%8E%E5%8F%AF%E4%BB%A5%E5%81%9A%E5%93%8D%E5%BA%94%E5%86%85%E5%AE%B9%E5%92%8C%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E4%BF%AE%E6%94%B9%EF%BC%8C%E6%B5%81%E9%87%8F%E7%9B%91%E6%8E%A7%EF%BC%8C%E6%97%A5%E5%BF%97%E8%BE%93%E5%87%BA%E7%AD%89%0A%0A%0A%23%23%23%23%23%23%208.1.5%20%E9%80%9A%E8%BF%87YML%E9%85%8D%E7%BD%AE%E7%BD%91%E5%85%B3%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20cloud-gateway-gateway9527%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-devtools%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-test%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Etest%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%20SpringCloud%20GateWay--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-gateway%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%0A%20%20%20%20%20%20%20eureka%20client%0A%20%20%20%20%20%20%20%E7%BD%91%E5%85%B3%E4%BD%9C%E4%B8%BA%E4%B8%80%E7%A7%8D%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%B9%9F%E5%9C%A8%E6%B3%A8%E5%86%8C%E5%88%B0%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C%2Fdependencies%3E%0A%20%20%20%60%60%60%0A%20%20%20%0A3.%20%E5%BB%BAyml%0A%20%20%20%0A%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%209527%0A%20%20%20%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-gateway%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20gateway%3A%0A%20%20%20%20%20%20%20%20%20routes%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E8%B7%AF%E7%94%B1%E7%9A%84ID%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%9B%BA%E5%AE%9A%E8%A7%84%E5%88%99%E4%BD%86%E8%A6%81%E6%B1%82%E5%94%AF%E4%B8%80%EF%BC%8C%E7%AE%80%E6%98%93%E9%85%8D%E5%90%88%E6%9C%8D%E5%8A%A1%E5%90%8D%0A%20%20%20%20%20%20%20%20%20%20%20-%20id%3A%20payment_8001_routh1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E5%8C%B9%E9%85%8D%E6%8F%90%E4%BE%9B%E6%9C%8D%E5%8A%A1%E7%9A%84%E8%B7%AF%E7%94%B1%E5%9C%B0%E5%9D%80%0A%20%20%20%20%20%20%20%20%20%20%20%20%20uri%3A%20http%3A%2F%2Flocalhost%3A8001%0A%20%20%20%20%20%20%20%20%20%20%20%20%20predicates%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E6%96%AD%E8%A8%80%EF%BC%8C%E8%B7%AF%E5%BE%84%E7%9B%B8%E5%8C%B9%E9%85%8D%E7%9A%84%E8%BF%9B%E8%A1%8C%E8%B7%AF%E7%94%B1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20Path%3D%2Fapi%2Fpayment%2Fget%2F**%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%E8%B7%AF%E7%94%B1%E7%9A%84ID%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%9B%BA%E5%AE%9A%E8%A7%84%E5%88%99%E4%BD%86%E8%A6%81%E6%B1%82%E5%94%AF%E4%B8%80%EF%BC%8C%E7%AE%80%E6%98%93%E9%85%8D%E5%90%88%E6%9C%8D%E5%8A%A1%E5%90%8D%0A%20%20%20%20%20%20%20%20%20%20%20-%20id%3A%20payment_8001_routh2%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%E5%8C%B9%E9%85%8D%E6%8F%90%E4%BE%9B%E6%9C%8D%E5%8A%A1%E7%9A%84%E8%B7%AF%E7%94%B1%E5%9C%B0%E5%9D%80%0A%20%20%20%20%20%20%20%20%20%20%20%20%20uri%3A%20http%3A%2F%2Flocalhost%3A8001%0A%20%20%20%20%20%20%20%20%20%20%20%20%20predicates%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E6%96%AD%E8%A8%80%EF%BC%8C%E8%B7%AF%E5%BE%84%E7%9B%B8%E5%8C%B9%E9%85%8D%E7%9A%84%E8%BF%9B%E8%A1%8C%E8%B7%AF%E7%94%B1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20Path%3D%2Fapi%2Fpayment%2Flb%2F**%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20instance-id%3A%20cloud-gateway-9527%0A%20%20%20%20%20%20%20prefer-ip-address%3A%20true%0A%60%60%60%0A%0A%20%20%20%0A%0A%0A%23%23%23%23%23%23%208.1.6%20%E9%80%9A%E8%BF%87%E9%85%8D%E7%BD%AE%E7%B1%BB%E9%85%8D%E7%BD%AE%E7%BD%91%E5%85%B3%0A%0A1.%20%E5%BB%BA%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A%20%20%20%3E%20%E9%80%9A%E8%BF%87RouteLocatorBuilder%E7%B1%BB%E5%88%9B%E5%BB%BA%E8%B7%AF%E7%94%B1%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.springcloud.config%3B%0A%20%20%20%0A%20%20%20import%20org.springframework.cloud.gateway.route.RouteLocator%3B%0A%20%20%20import%20org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder%3B%0A%20%20%20import%20org.springframework.context.annotation.Bean%3B%0A%20%20%20import%20org.springframework.context.annotation.Configuration%3B%0A%20%20%20%0A%20%20%20%40Configuration%0A%20%20%20public%20class%20GateWayConfig%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20*%20%E5%BD%93%E8%AE%BF%E9%97%AE%E5%9C%B0%E5%9D%80http%3A%2F%2Flocalhost%3A9527%2Fguonei%E6%97%B6%E4%BC%9A%E8%87%AA%E5%8A%A8%E8%BD%AC%E5%8F%91%E5%88%B0https%2F%2Fnews.baidu.com%2Fguonei%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20public%20RouteLocator%20customRouteLocator_guoji(RouteLocatorBuilder%20routeLocatorBuilder)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20RouteLocatorBuilder.Builder%20routes%20%3D%20routeLocatorBuilder.routes()%3B%0A%20%20%20%20%20%20%20%20%20%20%20routes.route(%22guoji_news%22%2C%20r%20-%3E%20r.path(%22%2Fguonei%22).uri(%22http%3A%2F%2Fnews.baidu.com%2Fguonei%22)).build()%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20routes.build()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20*%20%E5%BD%93%E8%AE%BF%E9%97%AE%E5%9C%B0%E5%9D%80http%3A%2F%2Flocalhost%3A9527%2Fmil%20%E6%97%B6%E4%BC%9A%E8%87%AA%E5%8A%A8%E8%BD%AC%E5%8F%91%E5%88%B0https%2F%2Fnews.baidu.com%2Fmil%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20public%20RouteLocator%20customRouteLocator_mil(RouteLocatorBuilder%20routeLocatorBuilder)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20RouteLocatorBuilder.Builder%20routes%20%3D%20routeLocatorBuilder.routes()%3B%0A%20%20%20%20%20%20%20%20%20%20%20routes.route(%22guoji_news%22%2C%20r%20-%3E%20r.path(%22%2Fmil%22).uri(%22http%3A%2F%2Fnews.baidu.com%2Fmil%22)).build()%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20routes.build()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%208.1.7%20%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE%0A%0A1.%20%E6%94%B9yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-gateway%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20gateway%3A%0A%20%20%20%20%20%20%20%20%20discovery%3A%0A%20%20%20%20%20%20%20%20%20%20%20locator%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20enabled%3A%20true%20%23%E5%BC%80%E5%90%AF%E4%BB%8E%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%8A%A8%E6%80%81%E5%88%9B%E5%BB%BA%E8%B7%AF%E7%94%B1%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%88%A9%E7%94%A8%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%E8%BF%9B%E8%A1%8C%E8%B7%AF%E7%94%B1%0A%20%20%20%20%20%20%20%20%20routes%3A%0A%20%20%20%20%20%20%20%20%20%20%20%23%20%E8%B7%AF%E7%94%B1%E7%9A%84ID%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%9B%BA%E5%AE%9A%E8%A7%84%E5%88%99%E4%BD%86%E8%A6%81%E6%B1%82%E5%94%AF%E4%B8%80%EF%BC%8C%E7%AE%80%E6%98%93%E9%85%8D%E5%90%88%E6%9C%8D%E5%8A%A1%E5%90%8D%0A%20%20%20%20%20%20%20%20%20%20%20-%20id%3A%20payment_8001_routh1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AFuri%E7%9A%84%E5%8D%8F%E8%AE%AE%E4%B8%BAlb%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%90%AF%E7%94%A8gateway%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%8A%9F%E8%83%BD%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20lb%3A%2F%2FserviceName%E6%98%AFspring%20cloud%20gateway%E5%9C%A8%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%B8%AD%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BA%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1uri%0A%20%20%20%20%20%20%20%20%20%20%20%20%20uri%3A%20lb%3A%2F%2Fcloud-payment-service%0A%20%20%20%20%20%20%20%20%20%20%20%20%20predicates%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E6%96%AD%E8%A8%80%EF%BC%8C%E8%B7%AF%E5%BE%84%E7%9B%B8%E5%8C%B9%E9%85%8D%E7%9A%84%E8%BF%9B%E8%A1%8C%E8%B7%AF%E7%94%B1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20Path%3D%2Fapi%2Fpayment%2Fget%2F**%0A%20%20%20%20%20%20%20%20%20%20%20-%20id%3A%20payment_8001_routh2%0A%20%20%20%20%20%20%20%20%20%20%20%20%20uri%3A%20lb%3A%2F%2Fcloud-payment-service%0A%20%20%20%20%20%20%20%20%20%20%20%20%20predicates%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20Path%3D%2Fapi%2Fpayment%2Flb%2F**%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%208.1.8%20Predicates%0A%0A%E2%80%8B%09https%3A%2F%2Fcloud.spring.io%2Fspring-cloud-static%2Fspring-cloud-gateway%2F2.2.1.RELEASE%2Freference%2Fhtml%2F%23gateway-request-predicates-factories%0A%0A1.%20spring%20gateway%20%E5%90%AF%E5%8A%A8%E6%97%A5%E5%BF%97%0A%0A%20%20%20%60%60%60%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BAfter%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BBefore%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BBetween%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BCookie%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BHeader%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BHost%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BMethod%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BPath%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BQuery%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BReadBodyPredicateFactory%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BRemoteAddr%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BWeight%5D%0A%20%20%20%5B%20%20restartedMain%5D%20o.s.c.g.r.RouteDefinitionRouteLocator%20%20%20%20%3A%20Loaded%20RoutePredicateFactory%20%5BCloudFoundryRouteService%5D%0A%20%20%20%60%60%60%0A%0A2.%20%E9%85%8D%E7%BD%AEyml%0A%0A%20%20%20%60%60%60%0A%20%20%20predicates%3A%0A%20%20%20%20%20%23%20%E6%96%AD%E8%A8%80%EF%BC%8C%E8%B7%AF%E5%BE%84%E7%9B%B8%E5%8C%B9%E9%85%8D%E7%9A%84%E8%BF%9B%E8%A1%8C%E8%B7%AF%E7%94%B1%0A%20%20%20%20%20-%20Path%3D%2Fapi%2Fpayment%2Flb%2F**%0A%20%20%20%20%20-%20After%3D2020-09-11T13%3A40%3A01.365%2B08%3A00%5BAsia%2FShanghai%5D%0A%20%20%20%20%20-%20Cookie%3Dusername%2Czzyy%20%20%20%20%20%23%E8%AF%B7%E6%B1%82%E8%A6%81%E8%BF%98%E6%9C%89cookie%E5%B9%B6%E4%B8%94%E5%B8%A6%E6%9C%89username%3Dzzyy%E7%9A%84%E9%94%AE%E5%80%BC%E5%AF%B9%0A%20%20%20%20%20-%20Header%3DX-Request-Id%2C%5Cd%2B%20%20%23%E8%AF%B7%E6%B1%82%E5%A4%B4%E8%A6%81%E6%9C%89X-Request-Id%E5%B1%9E%E6%80%A7%E5%B9%B6%E4%B8%94%E5%80%BC%E4%B8%BA%E6%95%B4%E6%95%B0%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%20%20%20%20%20%23-%20Host%3D**.chris.com%0A%20%20%20%20%20-%20Method%3DGET%0A%20%20%20%20%20-%20Query%3Did%2C%20%5Cd%2B%20%23%E8%A6%81%E6%9C%89%E5%8F%82%E6%95%B0%E5%90%8Did%E5%B9%B6%E4%B8%94%E5%80%BC%E8%BF%98%E8%A6%81%E5%95%A5%E6%95%B4%E6%95%B0%E6%89%8D%E8%83%BD%E8%B7%AF%E7%94%B1%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20curl%20http%3A%2F%2Flocalhost%3A9527%2Fapi%2Fpayment%2Flb%20--cookie%20%22username%3Dzzyy%22%20%0A%20%20%20curl%20http%3A%2F%2Flocalhost%3A9527%2Fapi%2Fpayment%2Flb%20--cookie%20%22username%3Dzzyy%22%20-H%20%22X-Request-Id%3A5%22%0A%20%20%20curl%20http%3A%2F%2Flocalhost%3A9527%2Fapi%2Fpayment%2Flb%20--cookie%20%22username%3Dzzyy%22%20-H%20%22X-Request-Id%3A5%2CHost%3Awww.chris.com%22%0A%20%20%20curl%20http%3A%2F%2Flocalhost%3A9527%2Fapi%2Fpayment%2Flb%3Fid%3D15%20--cookie%20%22username%3Dzzyy%22%20-H%20%22X-Request-Id%3A5%22%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%0A%0A%23%23%23%23%23%23%208.1.9%20Filter%0A%0A1.%20%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%0A%0A%20%20%20%60%60%60%0A%20%20%201.%20pro%0A%20%20%202.%20post%0A%20%20%20%60%60%60%0A%0A2.%20%E7%A7%8D%E7%B1%BB%0A%0A%20%20%20%60%60%60%0A%20%20%201.%20%E5%8D%95%E4%B8%80%E7%9A%84GateWayFilter%0A%20%20%202.%20%E5%85%A8%E5%B1%80%E7%9A%84GlobalFilter%0A%20%20%20%60%60%60%0A%20%20%20%0A%0A3.%20%E8%87%AA%E5%AE%9A%E4%B9%89%E5%85%A8%E5%B1%80%E8%BF%87%E8%99%91%E5%99%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%20%40Component%0A%20%20%20%20%40Slf4j%0A%20%20%20%20public%20class%20MyLogGateWayFilter%20implements%20GlobalFilter%2C%20Ordered%20%7B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20Mono%3CVoid%3E%20filter(ServerWebExchange%20exchange%2C%20GatewayFilterChain%20chain)%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22**************%20come%20in%20MyLogGateWayFilter%20%3A%22%20%2B%20new%20Date())%3B%0A%20%20%20%20%20%20%20%20%20%20%20String%20uname%20%3D%20exchange.getRequest().getQueryParams().getFirst(%22uname%22)%3B%0A%20%20%20%20%20%20%20%20if%20(StrUtil.isEmpty(uname))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22**************%20illegal%20uname%20%3A%22%20%2B%20new%20Date())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20exchange.getResponse().setComplete()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20return%20chain.filter(exchange)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20*%20%E5%8A%A0%E8%BD%BD%E8%BF%87%E8%99%91%E5%99%A8%E7%9A%84%E9%A1%BA%E5%BA%8F%0A%20%20%20%20%20%20%20%20*%20%E4%B8%80%E8%88%AC%E6%95%B0%E5%AD%97%E6%88%96%E5%B0%8F%EF%BC%8C%E4%BC%98%E5%85%88%E7%BA%A7%E8%B6%8A%E9%AB%98%0A%20%20%20%20%20%20%20%20*%20%E5%85%A8%E5%B1%80%E9%83%BD%E6%98%AF0%EF%BC%8C%E6%94%BE%E5%9C%A8%E7%AC%AC%E4%B8%80%E4%BD%8D%E5%8A%A0%E8%BD%BD%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20int%20getOrder()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%200%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%20%20%20%0A%20%20%20%0A%20%20%0A%23%23%23%23%209.%20%E5%88%86%E5%B8%83%E5%BC%8F%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%0A%0Ahttps%3A%2F%2Fdocs.spring.io%2Fspring-cloud-config%2Fdocs%2F2.2.5.RELEASE%2Freference%2Fhtml%2F%0A%0A%3E%20%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%84%8F%E5%91%B3%E7%9D%80%E5%B0%86%E5%8D%95%E4%BD%93%E5%BA%94%E7%94%A8%E4%B8%AD%E7%9A%84%E4%B8%9A%E5%8A%A1%E6%8B%86%E5%88%86%E4%B8%80%E4%B8%AA%E4%B8%AA%E5%AD%90%E6%9C%8D%E5%8A%A1%EF%BC%8C%E6%AF%8F%E4%B8%AA%E6%9C%8D%E5%8A%A1%E7%9A%84%E7%B2%92%E5%BA%A6%E7%9B%B8%E5%AF%B9%E8%BE%83%E5%B0%8F%EF%BC%8C%E5%9B%A0%E6%AD%A4%E7%B3%BB%E7%BB%9F%E4%B8%AD%E4%BC%9A%E5%87%BA%E7%8E%B0%E5%A4%A7%E9%87%8F%E7%9A%84%E6%9C%8D%E5%8A%A1%E3%80%82%0A%3E%0A%3E%20%E7%94%B1%E4%BA%8E%E6%AF%8F%E4%B8%AA%E6%9C%8D%E5%8A%A1%E9%9C%80%E8%A6%81%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E6%89%8D%E8%83%BD%E8%BF%90%E8%A1%8C%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%80%E5%A5%97%E9%9B%86%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E7%9A%84%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86%E6%98%AF%E5%BF%85%E4%B8%8D%E5%8F%AF%E5%B0%91%E7%9A%84%E3%80%82%0A%0A%23%23%23%23%23%209.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20SpringCloud%E6%8F%90%E4%BE%9B%E4%BA%86ConfigServer%E6%9D%A5%E8%A7%A3%E5%86%B3%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%0A%3E%0A%3E%20Config%E4%B8%BA%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E4%BA%86%E9%9B%86%E4%B8%AD%E5%8C%96%E7%9A%84%E5%A4%96%E9%83%A8%E9%85%8D%E7%BD%AE%E6%94%AF%E6%8C%81%EF%BC%8C%E9%85%8D%E7%BD%AE%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%BA%E5%90%84%E4%B8%AA%E4%B8%8D%E5%90%8C%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%BA%94%E7%94%A8%E7%9A%84%E6%89%80%E6%9C%89%E7%8E%AF%E5%A2%83%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E4%B8%AA%E4%B8%AD%E5%BF%83%E5%8C%96%E7%9A%84%E5%A4%96%E9%83%A8%E9%85%8D%E7%BD%AE%0A%0A!%5Bd7b84eb6458c1e92e4764a326f9065b7.png%5D(en-resource%3A%2F%2Fdatabase%2F939%3A1)%0A%0A%0A%3E%20SpringCloud%20Config%20%E5%88%86%E4%B8%BA%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%92%8C%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A%3E%20ConfigServer%20%E7%A7%B0%E4%B8%BA%E5%88%86%E5%B8%83%E5%BC%8F%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%98%AF%E4%B8%80%E7%8B%AC%E7%AB%8B%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%BA%94%E7%94%A8%EF%BC%8C%E7%94%A8%E6%9D%A5%E8%BF%9E%E6%8E%A5%E9%85%8D%E7%BD%AE%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%B9%B6%E4%B8%BA%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%8F%90%E4%BE%9B%E8%8E%B7%E5%8F%96%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%8A%A0%E5%AF%86%E8%A7%A3%E5%AF%86%E7%AD%89%E8%AE%BF%E9%97%AE%E6%8E%A5%E5%8F%A3%0A%3E%0A%3E%20%E9%85%8D%E7%BD%AE%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%BB%98%E8%AE%A4%E9%87%87%E7%94%A8git%E6%9D%A5%E5%AD%98%E5%82%A8%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%B0%B1%E6%9C%89%E5%8A%A9%E4%BA%8E%E5%AF%B9%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E8%BF%9B%E8%A1%8C%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87git%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%B7%A5%E5%85%B7%E6%9D%A5%E6%96%B9%E4%BE%BF%E7%9A%84%E7%AE%A1%E7%90%86%E5%92%8C%E6%9F%A5%E7%9C%8B%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E5%86%85%E5%AE%B9%0A%0A%3E%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E4%B8%AA%E5%BE%AE%E6%9C%8D%E5%8A%A1%EF%BC%8C%E9%80%9A%E8%BF%87%E6%8C%87%E5%AE%9A%E7%9A%84%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E6%9D%A5%E7%AE%A1%E7%90%86%E5%BA%94%E7%94%A8%E8%B5%84%E6%BA%90%EF%BC%8C%E4%BB%A5%E5%8F%8A%E4%B8%8E%E4%B8%9A%E5%8A%A1%E7%9B%B8%E5%85%B3%E7%9A%84%E9%85%8D%E7%BD%AE%E5%86%85%E5%AE%B9%E3%80%82%E5%B9%B6%E5%9C%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E4%BB%8E%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E8%8E%B7%E5%8F%96%E5%92%8C%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E3%80%82%0A%0A%23%23%23%23%23%209.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A1.%20%E9%9B%86%E4%B8%AD%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86%0A%0A2.%20%E4%B8%8D%E5%90%8C%E7%9A%84%E7%8E%AF%E5%A2%83%E4%B8%8D%E5%90%8C%E7%9A%84%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%88%86%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E4%BE%8B%E5%A6%82dev%2Ftest%2Fprod%2Fbeta%2Frelease%0A%0A3.%20%E5%8A%A8%E6%80%81%E5%8C%96%E6%9B%B4%E6%96%B0%E9%85%8D%E7%BD%AE%2C%E6%9C%8D%E5%8A%A1%E4%B8%8D%E9%9C%80%E8%A6%81%E9%87%8D%E5%90%AF%E5%B0%B1%E5%8F%AF%E6%84%9F%E7%9F%A5%E5%88%B0%E9%85%8D%E7%BD%AE%E7%9A%84%E5%8F%98%E5%8C%96%E5%B9%B6%E5%8A%A0%E8%BD%BD%E6%96%B0%E7%9A%84%E9%85%8D%E7%BD%AE%0A%0A4.%20%E5%B0%86%E9%85%8D%E7%BD%AE%E4%BB%A5rest%E6%8E%A5%E5%8F%A3%E5%BD%A2%E5%BC%8F%E6%9A%B4%E9%9C%B2%0A%0A%23%23%23%23%23%209.3%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%23%23%209.3.1%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloud-config-center-3344%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--config%20server--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-config-server%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C!--eureka%20client--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%86%99yam%0A%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%203344%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20utf-8%0A%20%20%20%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-config-center%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20config%3A%0A%20%20%20%20%20%20%20%20%20server%3A%0A%20%20%20%20%20%20%20%20%20%20%20git%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20uri%3A%20https%3A%2F%2Fgithub.com%2FChrisLi716%2Fspringcloud-config.git%20%20%23git%E4%BB%93%E5%BA%93%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20search-paths%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20springcloud-config%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20label%3A%20master%20%20%23%E8%AF%BB%E5%8F%96%E5%88%86%E6%94%AF%0A%20%20%20%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20instance-id%3A%20configcenter3344%0A%20%20%20%20%20%20%20prefer-ip-address%3A%20true%0A%20%20%20%20%20%20%20%23%20Eureka%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA30%E7%A7%92%0A%20%20%20%20%20%20%20lease-renewal-interval-in-seconds%3A%201%0A%20%20%20%20%20%20%20%23%20Eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%94%B6%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%BF%83%E8%B7%B3%E5%90%8E%E7%AD%89%E5%BE%85%E7%9A%84%E6%97%B6%E9%97%B4%E4%B8%8A%E9%99%90%EF%BC%8C%E8%B6%85%E6%97%B6%E5%B0%86%E6%B3%A8%E9%94%80%E6%9C%8D%E5%8A%A1%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92%0A%20%20%20%20%20%20%20lease-expiration-duration-in-seconds%3A%202%0A%20%20%20%60%60%60%0A%0A%0A%0A4.%20%E5%90%AF%E5%8A%A8%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableConfigServer%0A%20%20%20public%20class%20ConfigCenterMain3344%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(ConfigCenterMain3344.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A5.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%E5%9C%A8hosts%E6%96%87%E4%BB%B6%E4%B8%AD%E9%85%8D%E7%BD%AE%20%60127.0.0.1%20%20config-3344.com%60%0A%0A%20%20%20http%3A%2F%2Fconfig-3344.com%3A3344%2Fmaster%2Fconfig-dev.yml%0A%0A%20%20%20%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%0A%20%20%20%60%60%60%0A%20%20%20config%3A%0A%20%20%20%20%20info%3A%20master%20branch%2Cspringcloud-config%2Fconfig-dev.yml%20version%3D1%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%209.3.2%20%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloud-config-client-3355%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--config%20client--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-config%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C!--eureka%20client--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%86%99yml%0A%0A%20%20%20%3E%20application.yml%E6%98%AF%E7%94%A8%E6%88%B7%E7%BA%A7%E7%9A%84%E8%B5%84%E6%BA%90%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%20%20%20%3E%0A%20%20%20%3E%20bootstrap.yml%E6%98%AF%E7%B3%BB%E7%BB%9F%E7%BA%A7%E7%9A%84%E8%B5%84%E6%BA%90%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%EF%BC%8C%E4%BC%98%E5%85%88%E7%BA%A7%E6%9B%B4%E9%AB%98%EF%BC%8C%E6%9B%B4%E5%85%88%E5%8A%A0%E8%BD%BD%E3%80%82%0A%20%20%20%3E%0A%20%20%20%3E%20SpringCloud%E4%BC%9A%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AABootStrap%20Context%E4%BD%9C%E4%B8%BASpring%E5%BA%94%E7%94%A8%E7%9A%84Application%20Context%E7%9A%84%E7%88%B6%E4%B8%8A%E4%B8%8B%E6%96%87%EF%BC%8C%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6BootStrap%20Context%E8%B4%9F%E8%B4%A3%E4%BB%8E%E5%A4%96%E9%83%A8%E6%BA%90%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%EF%BC%8C%E8%BF%99%E4%B8%A4%E4%B8%AA%E4%B8%8A%E4%B8%8B%E6%96%87%E5%85%B1%E4%BA%AB%E4%B8%80%E4%B8%AA%E4%BB%8E%E5%A4%96%E9%83%A8%E8%8E%B7%E5%8F%96%E7%9A%84Environment%E3%80%82%0A%20%20%20%3E%0A%20%20%20%3E%20BootStrap%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%E6%9B%B4%E9%AB%98%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%8D%E4%BC%9A%E8%A2%AB%E6%9C%AC%E5%9C%B0%E9%85%8D%E7%BD%AE%E8%A6%86%E7%9B%96%0A%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%203355%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20clound-config-client%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20config%3A%0A%20%20%20%20%20%20%20%20%20label%3A%20master%20%20%23%E5%88%86%E6%94%AF%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20name%3A%20config%20%20%20%23%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20profile%3A%20dev%20%20%20%23%E7%8E%AF%E5%A2%83%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20uri%3A%20http%3A%2F%2Flocalhost%3A3344%20%23%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E5%9C%B0%E5%9D%80%0A%20%20%20%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20instance-id%3A%20configcenter3344%0A%20%20%20%20%20%20%20prefer-ip-address%3A%20true%0A%20%20%20%20%20%20%20%23%20Eureka%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA30%E7%A7%92%0A%20%20%20%20%20%20%20lease-renewal-interval-in-seconds%3A%201%0A%20%20%20%20%20%20%20%23%20Eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%94%B6%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%BF%83%E8%B7%B3%E5%90%8E%E7%AD%89%E5%BE%85%E7%9A%84%E6%97%B6%E9%97%B4%E4%B8%8A%E9%99%90%EF%BC%8C%E8%B6%85%E6%97%B6%E5%B0%86%E6%B3%A8%E9%94%80%E6%9C%8D%E5%8A%A1%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92%0A%20%20%20%20%20%20%20lease-expiration-duration-in-seconds%3A%202%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%23%209.3.3%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%8A%A8%E6%80%81%E5%88%B7%E6%96%B0%E9%85%8D%E7%BD%AE%0A%0A1.%20%E5%BC%95%E5%85%A5actuator%E5%9B%BE%E5%BD%A2%E5%8C%96%E7%9B%91%E6%8E%A7%E6%A8%A1%E5%9D%97%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-actuator%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%BF%AE%E6%94%B9yml%E6%9A%B4%E9%9C%B2%E7%9B%91%E6%8E%A7%E7%AB%AF%E7%82%B9%0A%0A%20%20%20%60%60%60yml%0A%20%20%20%23%20%E6%9A%B4%E9%9C%B2%E7%9B%91%E6%8E%A7%E7%AB%AF%E7%82%B9%0A%20%20%20management%3A%0A%20%20%20%20%20endpoints%3A%0A%20%20%20%20%20%20%20web%3A%0A%20%20%20%20%20%20%20%20%20exposure%3A%0A%20%20%20%20%20%20%20%20%20%20%20include%3A%20%22*%22%0A%20%20%20%60%60%60%0A%0A3.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%E4%B8%AD%E6%B7%BB%E5%8A%A0%40RefreshScope%E6%B3%A8%E8%A7%A3%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RefreshScope%0A%20%20%20public%20class%20ConfigClientController%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Value(%22%24%7Bconfig.info%7D%22)%0A%20%20%20%20%20%20%20private%20String%20configInfo%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2FconfigInfos%22)%0A%20%20%20%20%20%20%20public%20String%20getConfigInfo()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20configInfo%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A4.%20%E4%BF%AE%E6%94%B9%E5%AE%8Cgithub%E4%B8%8A%E4%B8%AD%E7%9A%84%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E5%90%8E%E5%8F%91post%E8%AF%B7%E6%B1%82%E5%88%B7%E6%96%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A%20%20%20%60%60%60%0A%20%20%20curl%20-X%20POST%20http%3A%2F%2Flocalhost%3A3355%2Factuator%2Frefresh%0A%20%20%20%60%60%60%0A%0A%0A%23%23%23%23%23%209.4%20%20%E9%85%8D%E7%BD%AE%E8%AF%BB%E5%8F%96%E8%A7%84%E5%88%99%0A%0A%60%60%60%0A%2F%7Bapplication%7D%2F%7Bprofile%7D%5B%2F%7Blabel%7D%5D%0A%2F%7Bapplication%7D-%7Bprofile%7D.yml%0A%2F%7Blabel%7D%2F%7Bapplication%7D-%7Bprofile%7D.yml%0A%2F%7Bapplication%7D-%7Bprofile%7D.properties%0A%2F%7Blabel%7D%2F%7Bapplication%7D-%7Bprofile%7D.properties%0A%60%60%60%0A%0A%23%23%23%23%23%23%209.4.1%20%2F%7Blabel%7D%2F%7Bapplication%7D-%7Bprofile%7D.yml%0A%0A1.%20%E8%AF%BB%E5%8F%96master%E5%88%86%E6%94%AF%E7%9A%84dev%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%20%20%20http%3A%2F%2Fconfig-3344.com%3A3344%2Fmaster%2Fconfig-dev.yml%0A%0A2.%20%E8%AF%BB%E5%8F%96dev%E5%88%86%E6%94%AF%E7%9A%84config-dev%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%20%20%20http%3A%2F%2Fconfig-3344.com%3A3344%2Fdev%2Fconfig-dev.yml%0A%0A%23%23%23%23%23%23%209.4.2%20%2F%7Bapplication%7D%2F%7Bprofile%7D%5B%2F%7Blabel%7D%5D%0A%0A1.%20%20%E8%AF%BB%E5%8F%96master%E5%88%86%E6%94%AF%E7%9A%84config-dev%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%20%20%20%20http%3A%2F%2Fconfig-3344.com%3A3344%2Fconfig%2Fdev.yml%2Fmaster%0A%20%20%20%20%0A%20%20%20%20%0A%0A%23%23%23%23%2010.%20SpringCloud%20Bus%E6%B6%88%E6%81%AF%E6%80%BB%E7%BA%BF%0A%0A%23%23%23%23%23%2010.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%23%23%23%23%23%23%2010.1.1%20%E6%80%BB%E7%BA%BF%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E5%9C%A8%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84%E7%B3%BB%E7%BB%9F%E4%B8%AD%EF%BC%8C%E9%80%9A%E5%B8%B8%E4%BC%9A%E4%BD%BF%E7%94%A8%60%E8%BD%BB%E9%87%8F%E7%BA%A7%E7%9A%84%E6%B6%88%E6%81%AF%E4%BB%A3%E7%90%86%60%E6%9D%A5%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%60%E5%85%B1%E7%94%A8%E7%9A%84%E6%B6%88%E6%81%AF%E4%B8%BB%E9%A2%98%60%EF%BC%8C%E5%B9%B6%E8%AE%A9%E7%B3%BB%E7%BB%9F%E6%89%80%E6%9C%89%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%AE%9E%E7%8E%B0%E6%9D%A5%E8%AE%A2%E9%98%85%EF%BC%8C%E7%94%B1%E4%BA%8E%E8%AF%A5%E4%B8%BB%E9%A2%98%E4%B8%AD%E4%BA%A7%E7%94%9F%E7%9A%84%E6%B6%88%E6%81%AF%E4%BC%9A%E8%A2%AB%E6%89%80%E6%9C%89%E7%9A%84%E5%AE%9E%E4%BE%8B%E6%B6%88%E8%B4%B9%EF%BC%8C%E6%89%80%E4%BB%A5%E7%A7%B0%E5%AE%83%E4%B8%BA%E6%B6%88%E6%81%AF%E6%80%BB%E7%BA%BF%E3%80%82%0A%3E%0A%3E%20%E5%9C%A8%E6%80%BB%E7%BA%BF%E4%B8%8A%E7%9A%84%E5%90%84%E4%B8%AA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E9%83%BD%E5%8F%AF%E4%BB%A5%E6%96%B9%E4%BE%BF%E5%9C%B0%E5%B9%BF%E6%92%AD%E4%B8%80%E4%BA%9B%E9%9C%80%E8%A6%81%E5%85%B6%E4%BB%96%E8%BF%9E%E6%8E%A5%E5%9C%A8%E8%AF%A5%E4%B8%BB%E9%A2%98%E4%B8%8A%E7%9A%84%E5%AE%9E%E4%BE%8B%E9%83%BD%E7%9F%A5%E9%81%93%E7%9A%84%E6%B6%88%E6%81%AF%E3%80%82%0A%0A%23%23%23%23%23%23%2010.1.2%20Bus%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20Bus%E6%98%AF%E5%AF%B9Config%E7%9A%84%E5%8A%A0%E5%BC%BA%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%E5%88%86%E5%B8%83%E5%BC%8F%E7%9A%84%E8%87%AA%E5%8A%A8%E5%88%B7%E6%96%B0%E9%85%8D%E7%BD%AE%E5%8A%9F%E8%83%BD%0A%3E%0A%3E%20%E6%94%AF%E6%8C%81%E4%B8%A4%E7%A7%8D%E6%B6%88%E6%81%AF%E4%BB%A3%E7%90%86%EF%BC%8CRabbitMQ%E5%92%8CKafka%0A%0A%23%23%23%23%23%23%2010.1.3%20%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86%0A%0A%3E%20ConfigClient%E5%AE%9E%E4%BE%8B%E9%83%BD%E7%9B%91%E5%90%ACMQ%E4%B8%AD%E5%90%8C%E4%B8%80%E4%B8%AAtopic(%E9%BB%98%E8%AE%A4%E6%98%AFspringCloudBus)%2C%20%E5%BD%93%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%88%B7%E6%96%B0%E6%95%B0%E6%8D%AE%E6%97%B6%EF%BC%8C%E5%AE%83%E4%BC%9A%E5%B0%86%E8%BF%99%E4%B8%AA%E4%BF%A1%E6%81%AF%E6%94%BE%E5%85%A5%E5%88%B0Topic%E4%B8%AD%2C%E8%BF%99%E6%A0%B7%E5%85%B6%E5%AE%83%E7%9B%91%E5%90%AC%E5%90%8C%E4%B8%80Topic%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%B0%B1%E8%83%BD%E5%BE%97%E5%88%B0%E9%80%9A%E7%9F%A5%EF%BC%8C%E7%84%B6%E5%90%8E%E5%8E%BB%E6%9B%B4%E6%96%B0%E8%87%AA%E8%BA%AB%E7%9A%84%E9%85%8D%E7%BD%AE%0A%0A!%5Ba5aa97914fd7e1a622050b234d6485db.png%5D(en-resource%3A%2F%2Fdatabase%2F942%3A1)%0A%0A%0A%0A%23%23%23%23%23%2010.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%20%E5%8A%A8%E6%80%81%E5%88%B7%E6%96%B0%E5%85%A8%E5%B1%80%E5%B9%BF%E6%92%AD%0A%3E%0A%3E%20%E5%8A%A8%E6%80%81%E5%88%B7%E6%96%B0%E5%AE%9A%E7%82%B9%E9%80%9A%E7%9F%A5%0A%0A%0A%0A%3E%20%E6%B6%88%E6%81%AF%E6%9B%B4%E6%96%B0%E6%8E%A8%E7%BB%99configserver%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%2C%E5%86%8D%E7%94%B1%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E5%B9%BF%E6%92%AD%E7%BB%99%E5%85%B6%E5%AE%83%E5%BE%AE%E6%9C%8D%E5%8A%A1%E8%8A%82%E7%82%B9%0A%0A!%5B0506e02b63100440bdeb5121b6d52057.png%5D(en-resource%3A%2F%2Fdatabase%2F940%3A1)%0A%0A%3E%20%E6%B6%88%E6%81%AF%E6%9B%B4%E6%96%B0%E6%8E%A8%E7%BB%99configClient%EF%BC%8C%E5%86%8D%E7%94%B1A%E5%8E%BB%E4%BC%A0%E6%92%AD%E5%85%B6%E5%AE%83%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%E8%8A%82%E7%82%B9%0A%0A!%5B1f12f9bf674be14ba27baf30bc1e357c.png%5D(en-resource%3A%2F%2Fdatabase%2F941%3A1)%0A%0A%0A%0A%23%23%23%23%23%2010.3%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%23%23%2010.3.1%20%E5%AE%89%E8%A3%85RabbitMQ%0A%0A%23%23%23%23%23%23%2010.3.2%20%E5%88%9B%E5%BB%BA%E6%96%B0%E7%9A%84module%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20%20cloud-config-client-3366%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-actuator%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-devtools%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--config%20client--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-config%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--eureka%20client--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C%2Fdependencies%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BAYML%0A%0A%20%20%20%3E%20bootstrap.yml%0A%0A%20%20%20%60%60%60YML%0A%20%20%20%23%20%E6%9A%B4%E9%9C%B2%E7%9B%91%E6%8E%A7%E7%AB%AF%E7%82%B9%0A%20%20%20management%3A%0A%20%20%20%20%20endpoints%3A%0A%20%20%20%20%20%20%20web%3A%0A%20%20%20%20%20%20%20%20%20exposure%3A%0A%20%20%20%20%20%20%20%20%20%20%20include%3A%20%22*%22%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%2010.3.3%20%E9%80%9A%E8%BF%87configClient%E5%88%B7%E6%96%B0%E6%89%80%E6%9C%89%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A%3E%20%E5%88%A9%E7%94%A8%E6%B6%88%E6%81%AF%E6%80%BB%E7%BA%BF%E8%A7%A6%E5%8F%91%E4%B8%80%E4%B8%AA%E5%AE%A2%E6%88%B7%E7%AB%AF%2Fbus%2Frefresh%EF%BC%8C%E8%80%8C%E5%88%B7%E6%96%B0%E6%89%80%E6%9C%89%E7%9A%84%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E9%85%8D%E7%BD%AE%0A%0A%20%E4%B8%8D%E5%BB%BA%E8%AE%AE%E4%BD%BF%E7%94%A8%E8%BF%99%E4%B8%80%E7%A7%8D%0A%0A1.%20%E7%A0%B4%E5%9D%8F%E4%BA%86%E5%BE%AE%E6%9C%8D%E5%8A%A1%E7%9A%84%E8%B4%A3%E4%BB%BB%E5%8D%95%E4%B8%80%E6%80%A7%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9C%AC%E5%90%91%E5%8D%B3%E6%98%AF%E4%B8%9A%E5%8A%A1%E6%A8%A1%E5%9D%97%E5%8F%88%E6%89%BF%E6%8B%85%E4%BA%86%E9%85%8D%E7%BD%AE%E5%88%B7%E6%96%B0%E7%9A%84%E8%81%8C%E8%B4%A3%0A%0A2.%20%E7%A0%B4%E5%9D%8F%E4%BA%86%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%90%84%E4%B8%AA%E8%8A%82%E7%82%B9%E7%9A%84%E5%AF%B9%E7%AD%89%E6%80%A7%EF%BC%8C%E4%BE%8B%E5%A6%82%E8%AE%A2%E5%8D%95%E6%A8%A1%E5%9D%97%E6%9C%89%E4%B8%89%E4%B8%AA%E9%9B%86%E7%BE%A4%E8%8A%82%E7%82%B9%EF%BC%8C%E5%85%B6%E4%B8%AD%E4%B8%80%E4%B8%AA%E6%9C%89%E9%85%8D%E7%BD%AE%E5%88%B7%E6%96%B0%E5%8A%9F%E8%83%BD%E8%80%8C%E5%85%B6%E5%AE%83%E4%B8%A4%E4%B8%AA%E6%B2%A1%E6%9C%89%E9%85%8D%E7%BD%AE%E5%88%B7%E6%96%B0%E5%8A%9F%E8%83%BD%0A%0A%0A%0A%23%23%23%23%23%23%2010.3.4%20%E9%80%9A%E8%BF%87configServer%E5%88%B7%E6%96%B0%E6%89%80%E6%9C%89%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A%3E%20%E5%88%A9%E7%94%A8%E6%B6%88%E6%81%AF%E6%80%BB%E7%BA%BF%E8%A7%A6%E5%8F%91%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E7%AB%AF%2Fbus%2Frefresh%EF%BC%8C%E8%80%8C%E5%88%B7%E6%96%B0%E6%89%80%E6%9C%89%E7%9A%84%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E9%85%8D%E7%BD%AE%0A%0A1.%20%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE%E6%9C%8D%E5%8A%A1%E7%AB%AFconfigServer%0A%0A%20%20%20%3E%20cloud-config-center-3344%0A%20%20%20%3E%0A%20%20%20%0A%20%20%20pom%0A%20%20%20%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%E6%B7%BB%E5%8A%A0%E6%B6%88%E6%81%AF%E6%80%BB%E7%BA%BFRabbitMQ%E6%94%AF%E6%8C%81--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-bus-amqp%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%20%20%20%0A%20%20%20application.yml%0A%20%20%20%0A%20%20%20%60%60%60yml%0A%20%20%20%20%20%23rabbitmq%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%0A%20%20%20%20%20rabbitmq%3A%0A%20%20%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20%20%20port%3A%205672%0A%20%20%20%20%20%20%20username%3A%20chris%0A%20%20%20%20%20%20%20password%3A%20123456%0A%20%20%20%0A%20%20%20%23%20%E6%9A%B4%E9%9C%B2bus%E5%88%B7%E6%96%B0%E9%85%8D%E7%BD%AE%E7%9B%91%E6%8E%A7%E7%AB%AF%E7%82%B9%0A%20%20%20management%3A%0A%20%20%20%20%20endpoints%3A%0A%20%20%20%20%20%20%20web%3A%0A%20%20%20%20%20%20%20%20%20exposure%3A%0A%20%20%20%20%20%20%20%20%20%20%20include%3A%20%22bus-refresh%22%0A%20%20%20%60%60%60%0A%0A%0A%0A2.%20%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE%E5%AE%A2%E6%88%B7%E7%AB%AFconfigClient%0A%0A%20%20%20%3E%20cloud-config-client-3355%0A%20%20%20%3E%0A%20%20%20%3E%20cloud-config-client-3366%0A%0A%20%20%20bootstrap.yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20%23rabbitmq%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%0A%20%20%20rabbitmq%3A%0A%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20port%3A%205672%0A%20%20%20%20%20username%3A%20chris%0A%20%20%20%20%20password%3A%20123456%0A%20%20%20%23%E6%9A%B4%E9%9C%B2%E7%9B%91%E6%8E%A7%E7%AB%AF%E7%82%B9%0A%20%20%20management%3A%0A%20%20%20%20%20endpoints%3A%0A%20%20%20%20%20%20%20web%3A%0A%20%20%20%20%20%20%20%20%20exposure%3A%0A%20%20%20%20%20%20%20%20%20%20%20include%3A%20%22*%22%0A%20%20%20%60%60%60%0A%0A%20%20%20pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%E6%B7%BB%E5%8A%A0%E6%B6%88%E6%81%AF%E6%80%BB%E7%BA%BFRabbitMQ%E6%94%AF%E6%8C%81--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-bus-amqp%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20http%3A%2F%2Fconfig-3344.com%3A3344%2Fmaster%2Fconfig-test.yml%0A%20%20%20http%3A%2F%2Flocalhost%3A3355%2FconfigInfos%0A%20%20%20http%3A%2F%2Flocalhost%3A3366%2FconfigInfos%0A%0A%20%20%20%0A%0A%20%20%20%E5%8A%A8%E6%80%81%E5%88%B7%E6%96%B0%E5%85%A8%E5%B1%80%E5%B9%BF%E6%92%AD%0A%0A%20%20%20curl%20-X%20POST%20http%3A%2F%2Flocalhost%3A3344%2Factuator%2Fbus-refresh%0A%0A%0A%0A%23%23%23%23%23%23%2010.3.5%20%E5%8A%A8%E6%80%81%E5%88%B7%E6%96%B0%E5%AE%9A%E7%82%B9%E9%80%9A%E7%9F%A5%0A%0A%3E%20%E5%9C%A8github%E4%B8%AD%E4%BF%AE%E6%94%B9%E4%BA%86%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E5%90%8E%EF%BC%8C%E5%8F%AA%E5%88%B7%E6%96%B0%E5%BE%AE%E6%9C%8D%E5%8A%A13355%E4%B8%8D%E5%88%B7%E6%96%B0%E5%BE%AE%E6%9C%8D%E5%8A%A13366%0A%0A1.%20%E5%9C%A8github%E4%B8%8A%E4%BF%AE%E6%94%B9%E5%AF%B9%E5%BA%94%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%0A2.%20%E5%8F%91%E9%80%81post%E8%AF%B7%E6%B1%82%E5%88%B7%E6%96%B0%E5%AF%B9%E5%BA%94%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A13355%0A%0A%20%20%20%3E%20%E5%91%BD%E4%BB%A4%EF%BC%9Acurl%20-X%20POST%20http%3A%2F%2Fconfig-3344.com%3A3344%2Factuator%2Fbus-refresh%2Fapplication-name%3Aport%0A%0A%20%20%20%60%60%60%0A%20%20%20curl%20-X%20POST%20http%3A%2F%2Fconfig-3344.com%3A3344%2Factuator%2Fbus-refresh%2Fcloud-config-client%3A3355%0A%20%20%20%60%60%60%0A%0A%0A%23%23%23%23%2011%20%E6%B6%88%E6%81%AF%E9%A9%B1%E5%8A%A8%20Stream%20%0A%0A%23%23%23%23%23%2011.1%20%E5%AE%98%E7%BD%91%0A%0A%23%23%23%23%23%23%2011.1.1%20%E5%A4%A7%E7%BA%B2%0A%0Ahttps%3A%2F%2Fspring.io%2Fprojects%2Fspring-cloud-stream%23overview%0A%0A%23%23%23%23%23%23%2011.1.2%20API%0A%0Ahttps%3A%2F%2Fcloud.spring.io%2Fspring-cloud-static%2Fspring-cloud-stream%2F3.0.1.RELEASE%2Freference%2Fhtml%2F%0A%0A%23%23%23%23%23%23%2011.1.3%20%E4%B8%AD%E6%96%87%E6%8C%87%E5%AF%BC%E6%89%8B%E5%86%8C%0A%0Ahttps%3A%2F%2Fm.wang1314.com%2Fdoc%2Fwebapp%2Ftopic%2F20971999.html%0A%0A%0A%0A%23%23%23%23%23%2011.2%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20Spring%20Cloud%20Stream%E6%98%AF%E4%B8%80%E4%B8%AA%E6%9E%84%E5%BB%BA%E6%B6%88%E6%81%AF%E9%A9%B1%E5%8A%A8%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%A1%86%E6%9E%B6%0A%3E%0A%3E%20%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E9%80%9A%E8%BF%87inputs%E6%88%96outputs%E6%9D%A5%E4%B8%8ESpring%20Cloud%20Stream%E4%B8%AD%E7%9A%84binder%E5%AF%B9%E8%B1%A1%E4%BA%A4%E4%BA%92%0A%3E%0A%3E%20input%20%20%E5%AF%B9%E5%BA%94%E4%BA%8E%E6%B6%88%E6%81%AF%E8%80%85%2Coutput%20%E5%AF%B9%E5%BA%94%E4%BA%8E%E7%94%9F%E4%BA%A7%E8%80%85%0A%3E%0A%3E%20%E9%80%9A%E8%BF%87%E9%85%8D%E7%BD%AE%E6%9D%A5%E7%BB%91%E5%AE%9Abinding%EF%BC%88%E7%BB%91%E5%AE%9A%EF%BC%89%EF%BC%8C%E8%80%8CSpring%20Cloud%20Stream%E7%9A%84binder%E5%AF%B9%E8%B1%A1%E8%B4%9F%E8%B4%A3%E4%B8%8E%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6%E4%BA%A4%E4%BA%92%0A%3E%0A%3E%20Spring%20Cloud%20Stream%20%E4%B8%BA%E4%B8%80%E4%BA%9B%E4%BE%9B%E5%BA%94%E5%95%86%E7%9A%84%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6%E4%BA%A7%E5%93%81%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%AA%E6%80%A7%E5%8C%96%E7%9A%84%E8%87%AA%E5%8A%A8%E5%8C%96%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%BC%95%E7%94%A8%20%E4%BA%86%EF%BC%8C%E5%8F%91%E5%B8%83-%E8%AE%A2%E9%98%85%EF%BC%8C%E6%B6%88%E8%B4%B9%E7%BB%84%EF%BC%8C%E5%88%86%E5%8C%BA%E4%B8%89%E4%B8%AA%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%0A%3E%0A%3E%20%E7%9B%AE%E5%89%8DSpring%20Cloud%20Stream%E5%8F%AA%E6%94%AF%E6%8C%81%20RabbitMQ%20%E5%92%8C%20Kafka%0A%0A!%5B1b3bd0cd5a44772a4ab26a27c2a5f2da.png%5D(en-resource%3A%2F%2Fdatabase%2F950%3A1)%0A%0A%0A%23%23%23%23%23%2011.3%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%20%E5%B1%8F%E8%94%BD%E5%BA%95%E5%B1%82%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E5%B7%AE%E5%BC%82%EF%BC%8C%E9%99%8D%E4%BD%8E%E5%88%87%E6%8D%A2%2C%E5%BC%80%E5%8F%91%E5%92%8C%E7%BB%B4%E6%8A%A4%E6%88%90%E6%9C%AC%EF%BC%8C%E7%BB%9F%E4%B8%80%E6%B6%88%E6%81%AF%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B%0A%3E%0A%3E%20%E4%B8%8D%E9%9C%80%E8%A6%81%E5%85%B3%E6%B3%A8%E5%85%B7%E4%BD%93MQ%E7%9A%84%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%82%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E7%94%A8%E4%B8%80%E7%A7%8D%E9%80%82%E9%85%8D%E7%BB%91%E5%AE%9A%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E8%87%AA%E5%8A%A8%E7%9A%84%E5%9C%A8%E5%90%84MQ%E4%B9%8B%E9%97%B4%E8%BF%9B%E8%A1%8C%E5%88%87%E6%8D%A2%0A%0A%23%23%23%23%23%2011.4%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%23%23%2011.4.1%20Stream%20%E6%A0%87%E5%87%86%E6%B5%81%E7%A8%8B%0A%0A%3E%20binder%20%E5%8F%AF%E4%BB%A5%E5%BE%88%E6%96%B9%E4%BE%BF%E7%9A%84%E8%BF%9E%E6%8E%A5%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6%0A%3E%20channel%20%E9%80%9A%E9%81%93%EF%BC%8C%E6%98%AFQueue%E9%98%9F%E5%88%97%E7%9A%84%E4%B8%80%E7%A7%8D%E6%8A%BD%E8%B1%A1%EF%BC%8C%E5%9C%A8%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6%E4%B8%AD%E6%98%AF%E5%AE%9E%E7%8E%B0%E6%B6%88%E6%81%AF%E5%AD%98%E5%82%A8%E5%92%8C%E8%BD%AC%E5%8F%91%E7%9A%84%E5%AA%92%E4%BB%8B%0A%3E%20Source%E5%92%8CSink%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BA%E6%B6%88%E6%81%AF%E7%9A%84%E8%BE%93%E5%87%BA%E5%92%8C%E8%BE%93%E5%85%A5%EF%BC%8C%E4%BB%8EStream%E7%94%9F%E4%BA%A7%E6%B6%88%E6%81%AF%E5%B0%B1%E6%98%AF%E8%BE%93%E5%87%BA%EF%BC%8C%E6%B6%88%E8%B4%B9%E6%B6%88%E6%81%AF%E5%B0%B1%E6%98%AF%E8%BE%93%E5%85%A5%0A%0A!%5Baf8c62dc70a2248a622d27bd45e0b439.png%5D(en-resource%3A%2F%2Fdatabase%2F946%3A1)%0A%0A%0A%0A%0A%0A%0A%23%23%23%23%23%23%2011.4.2%20%E4%BD%BF%E7%94%A8%E5%88%B0%E7%9A%84%E6%B3%A8%E8%A7%A3%0A%0A%60%60%60%0AmiddleWare%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6%EF%BC%8C%E7%9B%AE%E5%89%8D%E5%8F%AA%E6%94%AF%E6%8C%81rabbitMQ%E5%92%8Ckafka%0A%40Input%20%E6%A0%87%E8%AF%86%E8%BE%93%E5%85%A5%E9%80%9A%E9%81%93%EF%BC%8C%E9%80%9A%E8%BF%87%E8%BE%93%E5%85%A5%E9%80%9A%E9%81%93%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%E8%BF%9B%E5%85%A5%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%0A%40Output%E6%A0%87%E8%AF%86%E8%BE%93%E5%87%BA%E9%80%9A%E9%81%93%EF%BC%8C%E7%94%9F%E4%BA%A7%E7%9A%84%E6%B6%88%E6%81%AF%E9%80%9A%E8%BF%87%E8%BE%93%E5%87%BA%E9%80%9A%E9%81%93%E7%A6%BB%E5%BC%80%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%0A%40StreamListener%EF%BC%8C%E7%9B%91%E5%90%AC%E9%98%9F%E5%88%97%EF%BC%8C%E7%94%A8%E4%BA%8E%E6%B6%88%E8%B4%B9%E8%80%85%E7%9A%84%E9%98%9F%E5%88%97%E7%9A%84%E6%B6%88%E6%81%AF%E6%8E%A5%E6%94%B6%0A%40EnableBinding%20%E6%8C%87%E5%AE%9A%E4%BF%A1%E9%81%93channel%E5%92%8Cexchange%E7%BB%91%E5%AE%9A%E5%9C%A8%E4%B8%80%E8%B5%B7%0A%60%60%60%0A%0A!%5B337eabf1287fc453f441ba1a86e4eb7d.png%5D(en-resource%3A%2F%2Fdatabase%2F943%3A1)%0A%0A%23%23%23%23%23%23%2011.4.3%20%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E8%80%85%E9%A9%B1%E5%8A%A8%E5%AE%9E%E7%8E%B0%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloud-stream-rabbitmq-provider8801%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%3C!--boot%20web%20actuator--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-actuator%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--eureka%20client--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--stream%20rabbitmq--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-stream-rabbit%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--%20%E4%B8%80%E8%88%AC%E9%80%9A%E7%94%A8%E9%85%8D%E7%BD%AE%20--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-devtools%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecn.hutool%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ehutool-all%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C%2Fdependencies%3E%3C%2Fdependencies%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A3.%20%E5%BB%BAyml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%208801%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-stream-provider%0A%20%20%20%20%20rabbitmq%3A%0A%20%20%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20%20%20port%3A%205672%0A%20%20%20%20%20%20%20username%3A%20chris%0A%20%20%20%20%20%20%20password%3A%20123456%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20stream%3A%0A%20%20%20%20%20%20%20%20%20binders%3A%20%23%E5%9C%A8%E6%AD%A4%E5%A4%84%E9%85%8D%E7%BD%AE%E8%A6%81%E7%BB%91%E5%AE%9A%E7%9A%84rabbitmq%E7%9A%84%E6%9C%8D%E5%8A%A1%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%20%20%20%20%20defaultRabbit%3A%20%23%E5%AE%9A%E4%B9%89%E7%9A%84%E5%90%8D%E7%A7%B0%EF%BC%8C%E7%94%A8%E4%BA%8Ebinding%E6%95%B4%E5%90%88%0A%20%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20rabbit%20%23%E6%B6%88%E6%81%AF%E7%BB%84%E4%BB%B6%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20%20%20bindings%3A%20%23%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%95%B4%E5%90%88%E5%A4%84%E7%90%86%0A%20%20%20%20%20%20%20%20%20%20%20output%3A%20%23%E4%B8%80%E4%B8%AA%E9%80%9A%E9%81%93%E7%9A%84%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20destination%3A%20studyExchange%20%23%E8%A6%81%E4%BD%BF%E7%94%A8%E7%9A%84Exchange%E7%9A%84%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20content-type%3A%20application%2Fjson%20%23%E8%AE%BE%E7%BD%AE%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%EF%BC%8C%E6%96%87%E6%9C%AC%E8%AE%BE%E7%BD%AE%E4%B8%BA%20text%2Fplain%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20binder%3A%20defaultRabbit%0A%20%20%20%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20instance-id%3A%20stream-provider8801%0A%20%20%20%20%20%20%20prefer-ip-address%3A%20true%0A%20%20%20%20%20%20%20%23%20Eureka%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA30%E7%A7%92%0A%20%20%20%20%20%20%20lease-renewal-interval-in-seconds%3A%201%0A%20%20%20%20%20%20%20%23%20Eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%94%B6%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%BF%83%E8%B7%B3%E5%90%8E%E7%AD%89%E5%BE%85%E7%9A%84%E6%97%B6%E9%97%B4%E4%B8%8A%E9%99%90%EF%BC%8C%E8%B6%85%E6%97%B6%E5%B0%86%E6%B3%A8%E9%94%80%E6%9C%8D%E5%8A%A1%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92%0A%20%20%20%20%20%20%20lease-expiration-duration-in-seconds%3A%202%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A4.%20%E5%90%AF%E5%8A%A8%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableEurekaClient%0A%20%20%20public%20class%20StreamMQMain8801%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(StreamMQMain8801.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A5.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20interface%20IMessageProvider%20%7B%0A%20%20%20%20%20%20%20String%20send()%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20import%20cn.hutool.core.lang.UUID%3B%0A%20%20%20import%20com.chris.springcloud.service.IMessageProvider%3B%0A%20%20%20import%20lombok.extern.slf4j.Slf4j%3B%0A%20%20%20import%20org.springframework.cloud.stream.annotation.EnableBinding%3B%0A%20%20%20import%20org.springframework.cloud.stream.messaging.Source%3B%0A%20%20%20import%20org.springframework.messaging.MessageChannel%3B%0A%20%20%20import%20org.springframework.messaging.support.MessageBuilder%3B%0A%20%20%20%0A%20%20%20import%20javax.annotation.Resource%3B%0A%20%20%20%0A%20%20%20%2F%2F%E5%AE%9A%E4%B9%89%E6%B6%88%E6%81%AF%E7%9A%84%E6%8E%A8%E9%80%81%E4%BF%A1%E9%81%93%0A%20%20%20%40EnableBinding(Source.class)%0A%20%20%20%40Slf4j%0A%20%20%20public%20class%20MessageProviderImpl%20implements%20IMessageProvider%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%2F%2F%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E4%BF%A1%E9%81%93%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20MessageChannel%20output%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20String%20send()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20String%20uuid%20%3D%20UUID.randomUUID().toString()%3B%0A%20%20%20%20%20%20%20%20%20%20%20output.send(MessageBuilder.withPayload(uuid).build())%3B%0A%20%20%20%20%20%20%20%20%20%20%20log.info(%22uuid%3A%22%20%2B%20uuid)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20uuid%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20public%20class%20SendMsgController%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20IMessageProvider%20messageProvider%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2FsendMsg%22)%0A%20%20%20%20%20%20%20public%20String%20sendMessage()%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20messageProvider.send()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A6.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20http%3A%2F%2Flocalhost%3A8801%2FsendMsg%0A%0A%0A%0A%23%23%23%23%23%23%2011.4.4%20%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E8%80%85%E9%A9%B1%E5%8A%A8%E5%AE%9E%E7%8E%B0%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloud-stream-rabbitmq-consumer8802%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%3C!--boot%20web%20actuator--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-actuator%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--eureka%20client--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-netflix-eureka-client%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--stream%20rabbitmq--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-stream-rabbit%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--%E4%B8%80%E8%88%AC%E9%80%9A%E7%94%A8%E9%85%8D%E7%BD%AE--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-devtools%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Cscope%3Eruntime%3C%2Fscope%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecn.hutool%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ehutool-all%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C%2Fdependencies%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%BB%BAyml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%208802%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20%0A%20%20%20%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-stream-provider%0A%20%20%20%20%20rabbitmq%3A%0A%20%20%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20%20%20port%3A%205672%0A%20%20%20%20%20%20%20username%3A%20chris%0A%20%20%20%20%20%20%20password%3A%20123456%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20stream%3A%0A%20%20%20%20%20%20%20%20%20binders%3A%20%23%E5%9C%A8%E6%AD%A4%E5%A4%84%E9%85%8D%E7%BD%AE%E8%A6%81%E7%BB%91%E5%AE%9A%E7%9A%84rabbitmq%E7%9A%84%E6%9C%8D%E5%8A%A1%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%20%20%20%20%20defaultRabbit%3A%20%23%E5%AE%9A%E4%B9%89%E7%9A%84%E5%90%8D%E7%A7%B0%EF%BC%8C%E7%94%A8%E4%BA%8Ebinding%E6%95%B4%E5%90%88%0A%20%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20rabbit%20%23%E6%B6%88%E6%81%AF%E7%BB%84%E4%BB%B6%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20%20%20bindings%3A%20%23%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%95%B4%E5%90%88%E5%A4%84%E7%90%86%0A%20%20%20%20%20%20%20%20%20%20%20input%3A%20%23%E4%B8%80%E4%B8%AA%E9%80%9A%E9%81%93%E7%9A%84%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20destination%3A%20studyExchange%20%23%E8%A6%81%E4%BD%BF%E7%94%A8%E7%9A%84Exchange%E7%9A%84%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20content-type%3A%20application%2Fjson%20%23%E8%AE%BE%E7%BD%AE%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%EF%BC%8C%E6%96%87%E6%9C%AC%E8%AE%BE%E7%BD%AE%E4%B8%BA%20text%2Fplain%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20binder%3A%20defaultRabbit%0A%20%20%20%0A%20%20%20eureka%3A%0A%20%20%20%20%20client%3A%0A%20%20%20%20%20%20%20%23%20%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E5%B0%86%E8%87%AA%E5%B7%B1%E6%B3%A8%E5%86%8C%E5%88%B0eureka-server%2C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%0A%20%20%20%20%20%20%20register-with-eureka%3A%20true%0A%20%20%20%20%20%20%20%23%20%E6%98%AF%E5%90%A6%E4%BB%8Eeureka-server%E6%8A%93%E5%8F%96%E8%87%AA%E5%B7%B1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%EF%BC%8C%E5%8D%95%E8%8A%82%E7%82%B9%E6%97%A0%E6%89%80%E8%B0%93%EF%BC%8C%E9%9B%86%E7%BE%A4%E5%BF%85%E9%9C%80%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%E4%BB%A5%E9%85%8D%E5%90%88ribbon%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%20%20%20%20%20%20%20fetch-registry%3A%20true%0A%20%20%20%20%20%20%20service-url%3A%0A%20%20%20%20%20%20%20%20%20defaultZone%3A%20http%3A%2F%2Feureka7001.com%3A7001%2Feureka%2Chttp%3A%2F%2Feureka7002.com%3A7002%2Feureka%20%23%20%E9%9B%86%E7%BE%A4%E7%89%88%0A%20%20%20%20%20instance%3A%0A%20%20%20%20%20%20%20instance-id%3A%20stream-consumer8802%0A%20%20%20%20%20%20%20prefer-ip-address%3A%20true%0A%20%20%20%20%20%20%20%23%20Eureka%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA30%E7%A7%92%0A%20%20%20%20%20%20%20lease-renewal-interval-in-seconds%3A%201%0A%20%20%20%20%20%20%20%23%20Eureka%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%94%B6%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E5%BF%83%E8%B7%B3%E5%90%8E%E7%AD%89%E5%BE%85%E7%9A%84%E6%97%B6%E9%97%B4%E4%B8%8A%E9%99%90%EF%BC%8C%E8%B6%85%E6%97%B6%E5%B0%86%E6%B3%A8%E9%94%80%E6%9C%8D%E5%8A%A1%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA90%E7%A7%92%0A%20%20%20%20%20%20%20lease-expiration-duration-in-seconds%3A%202%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableEurekaClient%0A%20%20%20public%20class%20StreamMQMain8802%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(StreamMQMain8802.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A5.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Component%0A%20%20%20%40EnableBinding(Sink.class)%0A%20%20%20%40Slf4j%0A%20%20%20public%20class%20ConsumMsgListener%20%7B%0A%20%20%20%20%20%20%20%40Value(%22%24%7Bserver.port%7D%22)%0A%20%20%20%20%20%20%20private%20String%20serverPort%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%2F%2F%E7%9B%91%E5%90%AC%E9%98%9F%E5%88%97%EF%BC%8C%E7%94%A8%E4%BA%8E%E6%B6%88%E8%B4%B9%E8%80%85%E7%9A%84%E9%98%9F%E5%88%97%E7%9A%84%E6%B6%88%E6%81%AF%E6%8E%A5%E6%94%B6%0A%20%20%20%20%20%20%20%40StreamListener(Sink.INPUT)%0A%20%20%20%20%20%20%20public%20void%20input(Message%3CString%3E%20message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20log.info(%22%E6%B6%88%E8%B4%B9%E8%80%851%E5%8F%B7%2C%E6%8E%A5%E6%94%B6%E5%88%B0%E7%9A%84%E6%B6%88%E6%81%AF------%3E%22%20%2B%20message.getPayload()%20%2B%20%22%2C%20port%3A%20%22%20%2B%20serverPort)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%2011.4.5%20%E5%88%86%E7%BB%84%0A%0A%3E%20%E8%AE%A2%E5%8D%95%E6%9C%8D%E5%8A%A1%E5%81%9A%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E8%AE%A2%E5%8D%95%E8%A2%AB%E4%B8%A4%E4%B8%AA%E6%9C%8D%E5%8A%A1%E8%8E%B7%E5%8F%96%E5%88%B0%EF%BC%8C%E5%B0%B1%E4%BC%9A%E9%80%A0%E6%88%90%E6%95%B0%E6%8D%AE%E9%94%99%E8%AF%AF%2C%E7%94%9A%E8%87%B3%E9%87%8D%E5%A4%8D%E6%89%A3%E6%AC%BE%0A%0A!%5B8b5279edc17816f16964a1ede259b76d.png%5D(en-resource%3A%2F%2Fdatabase%2F945%3A1)%0A%0A%0A%0A%0A%3E%20%E5%88%86%E7%BB%84%E8%A7%A3%E5%86%B3%E4%B8%A4%E4%B8%AA%E9%97%AE%E9%A2%98%0A%3E%0A%3E%201.%20%E6%B6%88%E6%81%AF%E9%87%8D%E5%A4%8D%E6%B6%88%E6%81%AF%E9%97%AE%E9%A2%98%0A%3E%0A%3E%20%20%20%20%20%E5%A4%84%E4%BA%8E%E5%90%8C%E4%B8%80%E4%B8%AA%E5%88%86%E7%BB%84%E7%9A%84%E5%A4%9A%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E6%98%AF%E7%AB%9E%E4%BA%89%E5%85%B3%E7%B3%BB%EF%BC%8C%E8%83%BD%E5%A4%9F%E4%BF%9D%E8%AF%81%E6%B6%88%E6%81%AF%E8%A2%AB%E5%85%B6%E4%B8%AD%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E5%8F%AA%E6%B6%88%E8%B4%B9%E4%B8%80%E6%AC%A1%E3%80%82%0A%3E%0A%3E%20%20%20%20%E4%BD%86%E4%B8%8D%E5%90%8C%E7%BB%84%E6%98%AF%E5%8F%AF%E4%BB%A5%E9%87%8D%E5%A4%8D%E6%B6%88%E8%B4%B9%0A%3E%0A%3E%202.%20%E6%B6%88%E6%81%AF%E6%8C%81%E4%B9%85%E5%8C%96%0A%3E%0A%3E%20%20%20%20%E6%9C%AA%E5%88%86%E7%BB%84%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%9C%A8%E9%87%8D%E5%90%AF%E5%90%8E%E6%97%A0%E6%B3%95%E6%AD%A3%E5%B8%B8%E6%B6%88%E8%B4%B9%E9%82%A3%E4%BA%9B%E6%9C%AA%E8%A2%AB%E6%B6%88%E8%B4%B9%E7%9A%84%E6%B6%88%E6%81%AF%0A%3E%0A%3E%20%20%20%20%E8%80%8C%E6%9C%89%E5%88%86%E7%BB%84%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%E9%87%8D%E5%90%AF%E5%90%8E%E5%8F%AF%E4%BB%A5%E6%AD%A3%E5%B8%B8%E6%B6%88%E8%B4%B9%E9%82%A3%E4%BA%9B%E6%9C%AA%E8%A2%AB%E6%B6%88%E8%B4%B9%E7%9A%84%E6%B6%88%E6%81%AF%0A%0A1.%20%E4%B8%8D%E5%90%8C%E5%88%86%E7%BB%84%0A%0A%20%20%20%3E%20group%3A%20Group-Consumer8803%0A%0A%20%20%20%60%60%60%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-stream-provider%0A%20%20%20%20%20rabbitmq%3A%0A%20%20%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20%20%20port%3A%205672%0A%20%20%20%20%20%20%20username%3A%20chris%0A%20%20%20%20%20%20%20password%3A%20123456%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20stream%3A%0A%20%20%20%20%20%20%20%20%20binders%3A%20%23%E5%9C%A8%E6%AD%A4%E5%A4%84%E9%85%8D%E7%BD%AE%E8%A6%81%E7%BB%91%E5%AE%9A%E7%9A%84rabbitmq%E7%9A%84%E6%9C%8D%E5%8A%A1%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%20%20%20%20%20defaultRabbit%3A%20%23%E5%AE%9A%E4%B9%89%E7%9A%84%E5%90%8D%E7%A7%B0%EF%BC%8C%E7%94%A8%E4%BA%8Ebinding%E6%95%B4%E5%90%88%0A%20%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20rabbit%20%23%E6%B6%88%E6%81%AF%E7%BB%84%E4%BB%B6%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20%20%20bindings%3A%20%23%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%95%B4%E5%90%88%E5%A4%84%E7%90%86%0A%20%20%20%20%20%20%20%20%20%20%20input%3A%20%23%E4%B8%80%E4%B8%AA%E9%80%9A%E9%81%93%E7%9A%84%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20destination%3A%20studyExchange%20%23%E8%A6%81%E4%BD%BF%E7%94%A8%E7%9A%84Exchange%E7%9A%84%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20content-type%3A%20application%2Fjson%20%23%E8%AE%BE%E7%BD%AE%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%EF%BC%8C%E6%96%87%E6%9C%AC%E8%AE%BE%E7%BD%AE%E4%B8%BA%20text%2Fplain%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20binder%3A%20defaultRabbit%0A%20%20%20%20%20%20%20%20%20%20%20%20%20group%3A%20Group-Consumer8803%0A%20%20%20%60%60%60%0A%0A%20%20%20%20!%5B8a7ae456e4266ba3d277f94e0cfd88f6.png%5D(en-resource%3A%2F%2Fdatabase%2F944%3A1)%0A%0A%0A%0A2.%20%E7%9B%B8%E5%90%8C%E5%88%86%E7%BB%84%0A%0A%20%20%20%3E%20%E5%B0%86cloud-stream-rabbitmq-consumer8802%E5%92%8Ccloud-stream-rabbitmq-consumer8803%E7%9A%84%E5%88%86%E7%BB%84%E6%94%B9%E4%B8%BA%E7%9B%B8%E5%90%8C%E5%90%8D%E7%A7%B0%0A%20%20%20%3E%0A%20%20%20%3E%20group%3A%20Group-Consumer-A%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%B6%88%E6%81%AF%E5%8F%AA%E4%BC%9A%E8%A2%AB%E7%9B%B8%E5%90%8C%E5%88%86%E7%BB%84%E4%B8%AD%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E4%B8%80%E6%AC%A1%0A%0A%20%20%20%60%60%60%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20cloud-stream-provider%0A%20%20%20%20%20rabbitmq%3A%0A%20%20%20%20%20%20%20host%3A%20master%0A%20%20%20%20%20%20%20port%3A%205672%0A%20%20%20%20%20%20%20username%3A%20chris%0A%20%20%20%20%20%20%20password%3A%20123456%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20stream%3A%0A%20%20%20%20%20%20%20%20%20binders%3A%20%23%E5%9C%A8%E6%AD%A4%E5%A4%84%E9%85%8D%E7%BD%AE%E8%A6%81%E7%BB%91%E5%AE%9A%E7%9A%84rabbitmq%E7%9A%84%E6%9C%8D%E5%8A%A1%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%20%20%20%20%20defaultRabbit%3A%20%23%E5%AE%9A%E4%B9%89%E7%9A%84%E5%90%8D%E7%A7%B0%EF%BC%8C%E7%94%A8%E4%BA%8Ebinding%E6%95%B4%E5%90%88%0A%20%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20rabbit%20%23%E6%B6%88%E6%81%AF%E7%BB%84%E4%BB%B6%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20%20%20bindings%3A%20%23%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%95%B4%E5%90%88%E5%A4%84%E7%90%86%0A%20%20%20%20%20%20%20%20%20%20%20input%3A%20%23%E4%B8%80%E4%B8%AA%E9%80%9A%E9%81%93%E7%9A%84%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20destination%3A%20studyExchange%20%23%E8%A6%81%E4%BD%BF%E7%94%A8%E7%9A%84Exchange%E7%9A%84%E5%90%8D%E7%A7%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20content-type%3A%20application%2Fjson%20%23%E8%AE%BE%E7%BD%AE%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%EF%BC%8C%E6%96%87%E6%9C%AC%E8%AE%BE%E7%BD%AE%E4%B8%BA%20text%2Fplain%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20binder%3A%20defaultRabbit%0A%20%20%20%20%20%20%20%20%20%20%20%20%20group%3A%20Group-Consumer-A%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%2012%20%E6%9C%8D%E5%8A%A1%E9%93%BE%E8%B7%AF%E8%B7%9F%E8%B8%AA%20Sleuth%0A%0A%23%23%23%23%23%2012.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E5%9C%A8%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%A1%86%E6%9E%B6%E4%B8%AD%EF%BC%8C%E4%B8%80%E4%B8%AA%E7%94%B1%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%8F%91%E8%B5%B7%E7%9A%84%E8%AF%B7%E6%B1%82%E5%9C%A8%E5%90%8E%E7%AB%AF%E7%B3%BB%E7%BB%9F%E4%B8%AD%E4%BC%9A%E7%BB%8F%E8%BF%87%E5%A4%9A%E4%B8%AA%E4%B8%8D%E5%90%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E8%8A%82%E7%82%B9%E8%B0%83%E7%94%A8%E6%9D%A5%E5%8D%8F%E5%90%8C%E4%BA%A7%E7%94%9F%E6%9C%80%E5%90%8E%E7%9A%84%E8%AF%B7%E6%B1%82%E7%BB%93%E6%9E%9C%EF%BC%8C%E8%BF%99%E6%98%AF%E5%BD%A2%E6%88%90%E4%BA%86%E4%B8%80%E4%B8%AA%E5%A4%8D%E6%9D%82%E7%9A%84%E5%88%86%E6%AD%A5%E5%BC%8F%E8%B0%83%E7%94%A8%E9%93%BE%E8%B7%AF%EF%BC%8C%E9%93%BE%E8%B7%AF%E4%B8%AD%E4%BB%BB%E4%BD%95%E4%B8%80%E4%B8%AA%E8%8A%82%E7%82%B9%E5%87%BA%E7%8E%B0%E5%BB%B6%E6%97%B6%E6%88%96%E9%94%99%E8%AF%AF%E9%83%BD%E4%BC%9A%E5%BC%95%E8%B5%B7%E6%95%B4%E4%B8%AA%E8%AF%B7%E6%B1%82%E6%9C%80%E5%90%8E%E7%9A%84%E5%A4%B1%E8%B4%A5%0A%3E%0A%3E%20Sleuth%20%E7%94%A8%E4%BA%8E%E5%88%86%E6%AD%A5%E5%BC%8F%E8%AF%B7%E6%B1%82%E9%93%BE%E8%B7%AF%E8%B7%9F%E8%B8%AA%E5%B9%B6%E4%B8%94%E5%85%BC%E5%AE%B9%E6%94%AF%E6%8C%81zipkin%0A%0A%23%23%23%23%23%2012.2%20%E5%AE%98%E7%BD%91%09%0A%0A%3E%20https%3A%2F%2Fgithub.com%2Fspring-cloud%2Fspring-cloud-sleuth%0A%0A%23%23%23%23%23%2012.3%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%20Sleuth%20%E8%B4%9F%E8%B4%A3%E8%AF%B7%E6%B1%82%E9%93%BE%E8%B7%AF%E7%9A%84%E6%95%B0%E6%8D%AE%E6%94%B6%E9%9B%86%0A%3E%0A%3E%20Zipkin%20%E8%B4%9F%E8%B4%A3%E6%95%B0%E6%8D%AE%E5%B1%95%E7%A4%BA%0A%0A%0A%0A%23%23%23%23%23%2012.4%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%23%23%2012.4.1%20zipkin%E5%AE%89%E8%A3%85%0A%0ASpringCloud%E4%BB%8EF%E7%89%88%E8%B5%B7%E5%B0%B1%E4%B8%8D%E9%9C%80%E8%A6%81%E8%87%AA%E5%B7%B1%E6%9E%84%E5%BB%BAZipkin%20Server%E4%BA%86%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E8%B0%83%E7%94%A8jar%E5%8C%85%E5%8D%B3%E5%8F%AF%0A%0Ahttps%3A%2F%2Fdl.bintray.com%2Fopenzipkin%2Fmaven%2Fio%2Fzipkin%2Fjava%2Fzipkin-server%2F%0A%0A%E4%B8%8B%E8%BD%BDzipkin-server-2.12.9-exec.jar%0A%0A%E5%88%87%E6%8D%A2%E5%88%B0%E4%B8%8B%E8%BD%BD%E7%9B%AE%E5%BD%95%E4%B8%8B%0A%0A%60%60%60%0Ajava%20-jar%20zipkin-server-2.12.9-exec.jar%0Ahttp%3A%2F%2F127.0.0.1%3A9411%2F%0A%60%60%60%0A%0A%3E%20%E4%B8%80%E4%B8%AA%E9%93%BE%E8%B7%AF%E9%80%9A%E8%BF%87%E4%B8%80%E4%B8%AAtraceId%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86%EF%BC%8Cspan%E6%A0%87%E8%AF%86%E5%8F%91%E8%B5%B7%E7%9A%84%E8%AF%B7%E6%B1%82%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%90%84span%E9%80%9A%E8%BF%87parentId%E6%9D%A5%E5%85%B3%E8%81%94%0A%3E%0A%3E%20span%3A%E8%A1%A8%E7%A4%BA%E8%B0%83%E7%94%A8%E9%93%BE%E8%B7%AF%E6%9D%A5%E6%BA%90%EF%BC%8C%20%E9%80%9A%E4%BF%97%E7%9A%84%E8%AF%B4span%E5%B0%B1%E6%98%AF%E4%B8%80%E6%AC%A1%E8%AF%B7%E6%B1%82%E4%BF%A1%E6%81%AF%0A%0A!%5B678780f5c2ccb2cf6ba7e6dc68ea6669.png%5D(en-resource%3A%2F%2Fdatabase%2F948%3A1)%0A%0A%0A%E6%95%B4%E4%B8%AA%E9%93%BE%E8%B7%AF%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E5%A6%82%E4%B8%8B%0A%0A!%5B517005a9a0cafbd4e09b5e867fcb0439.png%5D(en-resource%3A%2F%2Fdatabase%2F947%3A1)%0A%0A%0A%0A%0A%23%23%23%23%23%23%2012.4.2%20%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E5%BC%95%E5%85%A5Sleuth%0A%0A%3E%20%E5%90%91%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%858001%E5%BC%95%E5%85%A5%E9%93%BE%E8%B7%AF%E8%B7%9F%E8%B8%AA%0A%0A1.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5Sleuth%E5%92%8CZipkin--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-zipkin%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A2.%20%E6%94%B9yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20zipkin%3A%0A%20%20%20%20%20base-url%3A%20http%3A%2F%2Flocalhost%3A9411%20%23%E9%93%BE%E8%B7%AF%E8%B7%9F%E8%B8%AA%E6%95%B0%E6%8D%AE%E7%9A%84%E5%B1%95%E7%A4%BA%E5%9C%B0%E5%9D%80%0A%20%20%20sleuth%3A%0A%20%20%20%20%20sampler%3A%0A%20%20%20%20%20%20%20probability%3A%201%20%23%E9%87%87%E6%A0%B7%E7%8E%87%EF%BC%8C%E4%BB%8B%E4%BA%8E0%E5%88%B01%E4%B9%8B%E9%97%B4%EF%BC%8C1%E8%A1%A8%E7%A4%BA%E5%85%A8%E9%83%A8%E9%87%87%E6%A0%B7%EF%BC%8C%E4%B8%80%E6%A0%B7%E7%94%A80.5%E8%A1%A8%E7%A4%BA%E4%B8%80%E5%8D%8A%E9%87%87%E6%A0%B7%0A%20%20%20%60%60%60%0A%0A%0A%0A3.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%3E%20com.chris.springcloud.payment.controller.PaymentController%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40GetMapping(%22%2Fzipkin%22)%0A%20%20%20public%20String%20invokeZipkin()%20%7B%0A%20%20%20%20%20%20%20return%20%22Hi%2C%20test%20sleuth%20and%20zipkin!%20port%3A%22%20%2B%20serverPort%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%2012.4.3%20%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E5%BC%95%E5%85%A5Sleuth%0A%0A%3E%20%E5%90%91%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%8580%E5%BC%95%E5%85%A5%E9%93%BE%E8%B7%AF%E8%B7%9F%E8%B8%AA%0A%0A1.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5Sleuth%E5%92%8CZipkin--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-zipkin%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E6%94%B9yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20zipkin%3A%0A%20%20%20%20%20base-url%3A%20http%3A%2F%2Flocalhost%3A9411%20%23%E9%93%BE%E8%B7%AF%E8%B7%9F%E8%B8%AA%E6%95%B0%E6%8D%AE%E7%9A%84%E5%B1%95%E7%A4%BA%E5%9C%B0%E5%9D%80%0A%20%20%20sleuth%3A%0A%20%20%20%20%20sampler%3A%0A%20%20%20%20%20%20%20probability%3A%201%20%23%E9%87%87%E6%A0%B7%E7%8E%87%EF%BC%8C%E4%BB%8B%E4%BA%8E0%E5%88%B01%E4%B9%8B%E9%97%B4%EF%BC%8C1%E8%A1%A8%E7%A4%BA%E5%85%A8%E9%83%A8%E9%87%87%E6%A0%B7%EF%BC%8C%E4%B8%80%E6%A0%B7%E7%94%A80.5%E8%A1%A8%E4%B8%80%E5%8D%8A%E9%87%87%E6%A0%B7%0A%20%20%20%60%60%60%0A%0A3.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%3E%20com.springcloud.order.controller.OrderController%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40GetMapping(%22%2Fpayment%2Fzipkin%22)%0A%20%20%20public%20String%20testPaymentZipkin()%20%7B%0A%20%20%20%20%20%20%20return%20restTemplate.getForObject(PAYMENT_URL%20%2B%20%22%2Fapi%2Fpayment%2Fzipkin%22%2C%20String.class)%3B%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%2012.4.4%20%E6%B5%8B%E8%AF%95%0A%0Ahttp%3A%2F%2Flocalhost%2Fconsumer%2Fpayment%2Fzipkin%0A%0Ahttp%3A%2F%2F127.0.0.1%3A9411%2Fzipkin%2F%0A!%5Baa0fcb098d0720d9fb70b0b623bfe781.png%5D(en-resource%3A%2F%2Fdatabase%2F949%3A1)%0A%0A%0A%23%23%23%23%2013%20Spring%20Cloud%20Alibaba%0A%0A%23%23%23%23%23%2013.1%20%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%23%23%23%23%23%23%2013.1.1%20%E5%AE%98%E7%BD%91%0A%0Ahttps%3A%2F%2Fgithub.com%2Falibaba%2Fspring-cloud-alibaba%2Fblob%2Fmaster%2FREADME-zh.md%0A%0Ahttps%3A%2F%2Fgithub.com%2Falibaba%2Fspring-cloud-alibaba%0A%0Ahttps%3A%2F%2Fspring-cloud-alibaba-group.github.io%2Fgithub-pages%2Fgreenwich%2Fspring-cloud-alibaba.html%0A%0Ahttps%3A%2F%2Fspring.io%2Fprojects%2Fspring-cloud-alibaba%23overview%0A%0A%0A%0A%23%23%23%23%23%2013.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A1.%20%E6%9C%8D%E5%8A%A1%E9%99%90%E6%B5%81%E5%92%8C%E9%99%8D%E7%BA%A7%EF%BC%9A%0A%0A%20%20%20%3E%20%E9%BB%98%E8%AE%A4%E6%94%AF%E6%8C%81Servlet%2C%20Feign%2C%20RestTemplate%2CDubbo%E5%92%8CRocketMQ%E9%99%90%E6%B5%81%E9%99%8D%E7%BA%A7%E5%8A%9F%E8%83%BD%E7%9A%84%E6%8E%A5%E5%85%A5%0A%0A2.%20%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0%EF%BC%9A%0A%0A%20%20%20%3E%20%E9%80%82%E9%85%8DSpringCloud%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0%E6%A0%87%E5%87%86%EF%BC%8C%E9%BB%98%E8%AE%A4%E9%9B%86%E6%88%90%E4%BA%86Ribbon%E7%9A%84%E6%94%AF%E6%8C%81%E3%80%82%0A%0A3.%20%E5%88%86%E5%B8%83%E5%BC%8F%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86%EF%BC%9A%0A%0A%20%20%20%3E%20%E6%94%AF%E6%8C%81%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E5%A4%96%E9%83%A8%E5%8C%96%E9%85%8D%E7%BD%AE%EF%BC%8C%E9%85%8D%E7%BD%AE%E6%9B%B4%E6%96%B0%E6%97%B6%E8%87%AA%E5%8A%A8%E5%88%B7%E6%96%B0%E3%80%82%0A%0A4.%20%E6%B6%88%E6%81%AF%E9%A9%B1%E5%8A%A8%EF%BC%9A%0A%0A%20%20%20%3E%20%E5%9F%BA%E4%BA%8EStream%E4%B8%BA%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%BA%94%E7%94%A8%E6%9E%84%E5%BB%BA%E6%B6%88%E6%81%AF%E9%A9%B1%E5%8A%A8%E8%83%BD%E5%8A%9B%0A%0A5.%20%E9%98%BF%E9%87%8C%E4%BA%91%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8%EF%BC%9A%0A%0A%20%20%20%3E%20%E9%98%BF%E9%87%8C%E4%BA%91%E6%8F%90%E4%BE%9B%E6%B5%B7%E9%87%8F%EF%BC%8C%E5%AE%89%E5%85%A8%EF%BC%8C%E4%BD%8E%E6%88%90%E6%9C%AC%EF%BC%8C%E9%AB%98%E5%8F%AF%E7%94%A8%E7%9A%84%E4%BA%91%E5%AD%98%E5%82%A8%E6%9C%8D%E5%8A%A1%EF%BC%8C%E6%94%AF%E6%8C%81%E5%9C%A8%E4%BB%BB%E4%BD%95%E6%97%B6%E9%97%B4%EF%BC%8C%E4%BB%BB%E4%BD%95%E5%9C%B0%E7%82%B9%EF%BC%8C%E9%80%9A%E8%BF%87%E4%BB%BB%E4%BD%95%E5%BA%94%E7%94%A8%E5%AD%98%E5%82%A8%E5%92%8C%E8%AE%BF%E9%97%AE%E4%BB%BB%E4%BD%95%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A6.%20%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%EF%BC%9A%0A%0A%20%20%20%3E%20%E6%8F%90%E4%BE%9B%E7%A7%92%E7%BA%A7%EF%BC%8C%E7%B2%BE%E5%87%86%E9%AB%98%E5%8F%AF%E7%94%A8%E7%9A%84%E7%9A%84%20%5B%E5%9F%BA%E4%BA%8ECron%E8%A1%A8%E8%BE%BE%E5%BC%8F%5D%20%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E6%9C%8D%E5%8A%A1.%0A%0A7.%20%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%EF%BC%9A%0A%0A%20%20%20%3E%20%E4%BD%BF%E7%94%A8%20%40GlobalTransactional%20%E6%B3%A8%E8%A7%A3%EF%BC%8C%20%E9%AB%98%E6%95%88%E5%B9%B6%E4%B8%94%E5%AF%B9%E4%B8%9A%E5%8A%A1%E9%9B%B6%E4%BE%B5%E5%85%A5%E5%9C%B0%E8%A7%A3%E5%86%B3%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E9%97%AE%E9%A2%98%E3%80%82%0A%0A%23%23%23%23%23%2013.3%20%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E5%92%8C%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%20Nacos%0A%0A%23%23%23%23%23%23%2013.1.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20Naming%20Configuration%20Services%0A%3E%0A%3E%20%E6%98%AF%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%92%8C%E5%88%86%E5%B8%83%E5%BC%8F%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E7%9A%84%E7%BB%84%E5%90%88%EF%BC%8C%E7%9B%B8%E5%BD%93%E4%BA%8EEureak%2BConfig%2BBus%0A%0A%23%23%23%23%23%23%2013.3.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%20%E6%9B%BF%E4%BB%A3Eureka%E4%BD%9C%E4%B8%BA%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A%3E%0A%3E%20%E6%9B%BF%E4%BB%A3Config%E4%BD%9C%E4%B8%BA%E5%88%86%E5%B8%83%E5%BC%8F%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%0A%3E%0A%3E%20%E6%9B%BF%E4%BB%A3Bus%E4%BD%9C%E4%B8%BA%E6%9C%8D%E5%8A%A1%E6%80%BB%E7%BA%BF%0A%0A%23%23%23%23%23%23%2013.3.3%20%E5%8E%BB%E5%93%AA%E4%B8%8B%0A%0A%E5%AE%98%E7%BD%91%3A%20%5Bhttp%3A%2F%2Fnacos.io%5D(http%3A%2F%2Fnacos.io%2F)%0A%0Ahttps%3A%2F%2Fnacos.io%2Fzh-cn%2Findex.html%0A%0Ahttps%3A%2F%2Fgithub.com%2Falibaba%2FNacos%0A%0A%E4%B8%8B%E8%BD%BD%E5%9C%B0%E5%9D%80%EF%BC%9A%0A%0Ahttps%3A%2F%2Fgithub.com%2Falibaba%2Fnacos%2Freleases%2Ftag%2F%0A%0A%0A%0A%23%23%23%23%23%23%2013.3.4%20%E5%AE%89%E8%A3%85%0A%0A1.%20%E4%B8%8B%E8%BD%BD%0A%0A%20%20%20%3E%20nacos-server-1.3.2.tar.gz%0A%0A2.%20%E9%85%8D%E7%BD%AE%0A%0A%20%20%20%3E%20cd%20%2Fopt%0A%20%20%20%3E%0A%20%20%20%3E%20tar%20-zxvf%20%20nacos-server-1.3.2.tar.gz%0A%20%20%20%3E%0A%20%20%20%3E%20cd%20nacos%2Fconf%2F%0A%20%20%20%3E%0A%20%20%20%3E%20vi%20application.poperties%0A%0A%20%20%20%60%60%60%0A%20%20%20%23%23%23%20If%20use%20MySQL%20as%20datasource%3A%0A%20%20%20%20spring.datasource.platform%3Dmysql%0A%20%20%20%20%0A%20%20%20%23%23%23%20Count%20of%20DB%3A%0A%20%20%20db.num%3D1%0A%20%20%20db.url.0%3Djdbc%3Amysql%3A%2F%2Flocalhost%3A3306%2Fnacos%3FuseSSL%3Dfalse%26characterEncoding%3Dutf8%26zeroDateTimeBehavior%3DconvertToNull%26allowMultiQueries%3Dtrue%26serverTimezone%3DUTC%0A%20%20%20db.user%3Droot%0A%20%20%20db.password%3D65536%0A%20%20%20%60%60%60%0A%0A%20%20%20%E6%96%B0%E5%BB%BAnaocs%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B9%B6%E5%9C%A8nacos%E4%B8%AD%E6%89%A7%E8%A1%8CSQL%0A%0A%20%20%20SQL%E4%BD%8D%E7%BD%AE%E5%9C%A8.%2Fconf%2Fnacos-mysql.sql%0A%0A3.%20%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%E5%9C%A8nacos%E7%9A%84bin%E7%9B%AE%E5%BD%95%E4%B8%8B%E6%89%A7%E8%A1%8C%0A%0A%20%20%20%60%60%60%0A%20%20%20.%2Fstartup.sh%20%20-m%20standalone%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A4.%20%E6%9F%A5%E7%9C%8B%0A%0A%20%20%20http%3A%2F%2Fmaster%3A8848%2Fnacos%2Findex.html%0A%0A%20%20%20%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E5%AF%86%E7%A0%81%E4%B8%BA%3Anacos%0A%0A%0A%0A%23%23%23%23%23%23%2013.3.5%20%E5%9F%BA%E4%BA%8ENacos%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloudalibaba-provider-payment9001%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--springcloud%20alibaba%20nacos--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-alibaba-nacos-discovery%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%86%99yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%209001%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20%20%20servlet%3A%0A%20%20%20%20%20%20%20context-path%3A%20%2Fapi%0A%20%20%20%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20nacos-payment-provider%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20nacos%3A%0A%20%20%20%20%20%20%20%20%20discovery%3A%0A%20%20%20%20%20%20%20%20%20%20%20server-addr%3A%20master%3A8848%20%20%23%E9%85%8D%E7%BD%AENacos%E4%BD%9C%E4%B8%BA%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%9C%B0%E5%9D%80%0A%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20management%3A%0A%20%20%20%20%20endpoints%3A%0A%20%20%20%20%20%20%20web%3A%0A%20%20%20%20%20%20%20%20%20exposure%3A%0A%20%20%20%20%20%20%20%20%20%20%20include%3A%20'*'%20%20%23%E7%9B%91%E6%8E%A7%E6%89%80%E6%9C%89%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableDiscoveryClient%0A%20%20%20public%20class%20PaymentMain9001%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(PaymentMain9001.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%E2%80%8B%09%0A%0A5.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fpayment%22)%0A%20%20%20public%20class%20PaymentController%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Value(%22%24%7Bserver.port%7D%22)%0A%20%20%20%20%20%20%20private%20String%20serverPort%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2Fnacos%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20getPayment(%40PathVariable(%22id%22)%20Integer%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20%22Nacos%20registry%2C%20server%20port%3A%22%20%2B%20serverPort%20%2B%20%22%2C%20id%3A%22%20%2B%20id%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%2013.3.6%20%E5%9F%BA%E4%BA%8ENacos%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20cloudalibaba-consumer-nacos-order83%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--springcloud%20alibaba%20nacos--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba.cloud%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-cloud-starter-alibaba-nacos-discovery%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%86%99yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%2083%0A%20%20%20%20%20tomcat%3A%0A%20%20%20%20%20%20%20uri-encoding%3A%20UTF-8%0A%20%20%20%0A%20%20%20spring%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20nacos-order-consumer%0A%20%20%20%20%20cloud%3A%0A%20%20%20%20%20%20%20nacos%3A%0A%20%20%20%20%20%20%20%20%20discovery%3A%0A%20%20%20%20%20%20%20%20%20%20%20server-addr%3A%20master%3A8848%20%20%23%E9%85%8D%E7%BD%AENacos%E5%9C%B0%E5%9D%80%0A%20%20%20%0A%20%20%20%23%E6%B6%88%E8%B4%B9%E8%80%85%E5%B0%86%E8%A6%81%E5%8E%BB%E8%AE%BF%E9%97%AE%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%88%E6%88%90%E5%8A%9F%E6%B3%A8%E5%86%8C%E5%88%B0nacos%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%EF%BC%89%0A%20%20%20service-url%3A%0A%20%20%20%20%20nacos-user-service%3A%20http%3A%2F%2Fnacos-payment-provider%2Fapi%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableDiscoveryClient%0A%20%20%20public%20class%20OrderNacosMain83%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(OrderNacosMain83.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A5.%20%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A%20%20%20%3E%20nacos-discovery%20%E9%9B%86%E6%88%90ribbon%E5%AE%9E%E7%8E%B0%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%92%8C%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Configuration%0A%20%20%20public%20class%20ApplicationContextConfig%20%7B%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20%40LoadBalanced%0A%20%20%20%20%20%20%20public%20RestTemplate%20getRestTemplate()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20new%20RestTemplate()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A6.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fconsumer%22)%0A%20%20%20public%20class%20OrderNacosController%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Value(%22%24%7Bservice-url.nacos-user-service%7D%22)%0A%20%20%20%20%20%20%20private%20String%20PAYMENT_SERVICE_NAME%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20RestTemplate%20restTemplate%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22payment%2Fnacos%2F%7Bid%7D%22)%0A%20%20%20%20%20%20%20public%20String%20getPaymentInfo(%40PathVariable(%22id%22)%20Long%20id)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20restTemplate.getForObject(PAYMENT_SERVICE_NAME%20%2B%20%22%2Fpayment%2Fnacos%2F%22%20%2B%20id%2C%20String.class)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A7.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20http%3A%2F%2Flocalhost%3A83%2Fconsumer%2Fpayment%2Fnacos%2F45%0A%0A%0A%0A%23%23%23%23%23%23%2013.3.7%20Nacos%E6%94%AF%E6%8C%81AP%E5%92%8CCP%E7%9A%84%E5%88%87%E6%8D%A2%0A%0A!%5B243f9078800143283dba04691f5d6f36.png%5D(en-resource%3A%2F%2Fdatabase%2F951%3A1)%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E4%B8%8D%E9%9C%80%E8%A6%81%E5%AD%98%E5%82%A8%E6%9C%8D%E5%8A%A1%E7%BA%A7%E5%88%AB%E7%9A%84%E4%BF%A1%E6%81%AF%E5%88%99%E5%8F%AF%E4%BB%A5%E9%80%89%E6%8B%A9AP%E6%A8%A1%E5%BC%8F%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E5%9C%A8%E6%9C%8D%E5%8A%A1%E7%BA%A7%E5%88%AB%E4%B8%8A%E7%BC%96%E8%BE%91%E6%88%96%E5%AD%98%E5%82%A8%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%EF%BC%8C%E9%9C%80%E8%A6%81%E9%80%89%E6%8B%A9CP%E6%A8%A1%E5%BC%8F%0A%0A%60%60%60%0Acurl%20-X%20PUT%20'%24NACOS_SERVER%3A8848%2Fnacos%2Fv1%2Fns%2Foperator%2Fswitchs%3Fentry%3DserverModl%26value%3DCP'%0A%60%60%60%0A%0A%23%23%23%23%23%23%2013.3.8%20Nacos%E6%94%AF%E6%8C%81%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%E6%97%B6%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%3E%20Nacos%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%98%AF%E6%8C%87%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%E6%97%B6%E8%BF%9B%E8%A1%8C%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%EF%BC%8C%E6%AD%A3%E5%B8%B8%E6%83%85%E5%86%B5%E4%B8%8B%E5%9C%A8%E8%BF%9B%E8%A1%8C%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%E6%97%B6%E4%BC%9A%E6%A0%B9%E6%8D%AE%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%E4%BB%8ENacos%E6%8B%89%E5%8F%96%E6%89%80%E6%9C%89%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%AE%9E%E4%BE%8B%E5%88%B0%E5%AE%A2%E6%88%B7%E6%9C%AC%E5%9C%B0%E8%BF%9B%E7%A8%8B%E4%B8%AD%EF%BC%8C%E4%BD%86Nacos%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E4%B8%AA%E5%8A%9F%E8%83%BD%E5%B0%B1%E6%98%AF%E5%9C%A8%E6%8B%89%E5%8F%96%E6%9C%8D%E5%8A%A1%E6%97%B6%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E9%9A%8F%E6%9C%BA%E7%AD%96%E7%95%A5%E5%8F%AA%E6%8B%89%E5%8F%96%E5%88%B0%E6%89%80%E6%9C%89%E5%AE%9E%E4%BE%8B%E4%B8%AD%E7%9A%84%E6%9F%90%E4%B8%80%E4%B8%AA%EF%BC%8C%E8%BF%99%E5%B0%B1%E6%98%AFNacos%E4%B8%AD%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E3%80%82%0A%E8%BF%99%E6%A0%B7%E5%9C%A8%E6%B6%88%E8%B4%B9%E8%80%85%E6%9C%AC%E5%9C%B0%E5%AD%98%E5%82%A8%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%AE%9E%E4%BE%8B%E5%B0%B1%E4%BC%9A%E6%AF%94%E8%BE%83%E5%B0%91%EF%BC%8C%E5%8F%AF%E8%83%BD%E5%B0%B1%E5%AD%98%E4%BA%86%E9%80%89%E6%8B%A9%E5%87%BA%E7%9A%84%E9%82%A3%E5%94%AF%E4%B8%80%E4%B8%80%E4%B8%AA.%0A%0A%3E%20%E5%AE%83%E6%A0%B9Ribbon%E4%B8%AD%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E4%B8%8D%E5%86%B2%E7%AA%81%EF%BC%8CRibbon%E6%98%AF%E5%9C%A8%E6%B6%88%E6%81%AF%E8%80%85%E6%9C%AC%E5%9C%B0%E8%B0%83%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%97%B6%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BARibbon%E4%B8%AD%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%98%AF%E5%8F%91%E7%94%9F%E5%9C%A8Nacos%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E4%B9%8B%E5%90%8E%E3%80%82%0A%0A%0A%0A%0A

Spring Utils

创建时间:2022/4/14 15:01
更新时间:2022/4/14 15:03
作者:Chris

BeanFactoryUtils

beansOfTypeIncludingAncestors

org.springframework.beans.factory.BeanFactoryUtils#beansOfTypeIncludingAncestors(org.springframework.beans.factory.ListableBeanFactory, java.lang.Class<T>, boolean, boolean)
%5Btoc%5D%0A%0A%23%23%20BeanFactoryUtils%0A%23%23%23%23%20beansOfTypeIncludingAncestors%0A%60%60%60java%0Aorg.springframework.beans.factory.BeanFactoryUtils%23beansOfTypeIncludingAncestors(org.springframework.beans.factory.ListableBeanFactory%2C%20java.lang.Class%3CT%3E%2C%20boolean%2C%20boolean)%0A%60%60%60

启动时自动执行代码

创建时间:2022/1/4 10:46
更新时间:2022/4/13 22:12
作者:Chris
来源:https://www.php.cn/java-article-416423.html

java自身的启动时加载方式

static代码块

static静态代码块,在类加载的时候即自动执行。

构造方法

构造方法在对象初始化时执行。执行顺序在static静态代码块之后。

Spring启动时加载方式

@PostConstruct注解

PostConstruct注解使用在方法上,这个方法在对象依赖注入初始化之后执行。

自动调用

1 自动调用概述

CommandLineRunnerApplicationRunner 是SpringBoot所提供的接口,他们都有一个run()方法。所有实现他们的Bean都会在Spring Boot服务启动之后自动地被调用。由于这个特性,它们是一个理想地方去做一些初始化的工作

2 CommandLineRuner

package com.chris.springboot2022.init;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @Author Lilun
 * @Date 2022-01-04 10:33
 * @Description
 **/
@Component
@Order(2)
@Slf4j
public class CommandLineRunnerTest implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {

        log.info("CommandLineRunnerTest is running");
        log.info("args:{}", JSONUtil.toJsonStr(args));
        log.info("CommandLineRunnerTest end");
    }
}

3 ApplicationRuner

ApplicationRunnerCommandLineRunner 做的事情是一样的,也是在服务启动之后其run()方法会被自动地调用,唯一不同的是ApplicationRunner 会封装命令行参数,可以很方便地获取到命令行参数和参数值

package com.chris.springboot2022.init;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;

/**
 * @Author Lilun
 * @Date 2022-01-04 10:38
 * @Description
 **/
@Component
@Slf4j
@Order(1)
public class ApplicationRunnerTest implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("ApplicationRunnerTest is running");
        String[] sourceArgs = args.getSourceArgs();
        log.info("sourceArgs:{}", JSONUtil.toJsonStr(sourceArgs));

        Set<String> optionNames = args.getOptionNames();
        for (String optionName : optionNames) {
            List<String> optionValues = args.getOptionValues(optionName);
            log.info("optionValues of optionName:{} is {}", optionName, JSONUtil.toJsonStr(optionValues));
        }

        log.info("ApplicationRunnerTest end");
    }
}

4 总结

无论是CommandLineRunner 还是 ApplicationRunner,它们的目的都是在服务启动之后执行一些 初始化操作。
如果需要获取命令行参数时则建议使用 ApplicationRunner
另一种场景是我们在服务器上需要执行某个操作,比如修正数据库用户的数据,而又找不到合适的执行入口,那么这就是它们理想的使用场景了。

加载顺序

加载顺序为static>constructer>@PostConstruct>CommandLineRunner和ApplicationRunner.

%5Btoc%5D%0A%0A%23%23%20java%E8%87%AA%E8%BA%AB%E7%9A%84%E5%90%AF%E5%8A%A8%E6%97%B6%E5%8A%A0%E8%BD%BD%E6%96%B9%E5%BC%8F%0A%0A%23%23%23%23%20static%E4%BB%A3%E7%A0%81%E5%9D%97%0A%3E%20static%E9%9D%99%E6%80%81%E4%BB%A3%E7%A0%81%E5%9D%97%EF%BC%8C%E5%9C%A8%E7%B1%BB%E5%8A%A0%E8%BD%BD%E7%9A%84%E6%97%B6%E5%80%99%E5%8D%B3%E8%87%AA%E5%8A%A8%E6%89%A7%E8%A1%8C%E3%80%82%0A%0A%23%23%23%23%20%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%0A%3E%20%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E5%9C%A8%E5%AF%B9%E8%B1%A1%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%E6%89%A7%E8%A1%8C%E3%80%82%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E5%9C%A8static%E9%9D%99%E6%80%81%E4%BB%A3%E7%A0%81%E5%9D%97%E4%B9%8B%E5%90%8E%E3%80%82%0A%0A%0A%23%23%20Spring%E5%90%AF%E5%8A%A8%E6%97%B6%E5%8A%A0%E8%BD%BD%E6%96%B9%E5%BC%8F%0A%23%23%23%23%20%40PostConstruct%E6%B3%A8%E8%A7%A3%0A%3E%20PostConstruct%E6%B3%A8%E8%A7%A3%E4%BD%BF%E7%94%A8%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%8A%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E5%9C%A8%E5%AF%B9%E8%B1%A1%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B9%8B%E5%90%8E%E6%89%A7%E8%A1%8C%E3%80%82%0A%0A%0A%23%23%20%E8%87%AA%E5%8A%A8%E8%B0%83%E7%94%A8%0A%0A%23%23%23%23%201%20%E8%87%AA%E5%8A%A8%E8%B0%83%E7%94%A8%E6%A6%82%E8%BF%B0%0A%0A%3E%20%20%60CommandLineRunner%60%20%E5%92%8C%20%60ApplicationRunner%60%20%E6%98%AFSpringBoot%E6%89%80%E6%8F%90%E4%BE%9B%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E4%BB%96%E4%BB%AC%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AArun()%E6%96%B9%E6%B3%95%E3%80%82%E6%89%80%E6%9C%89%E5%AE%9E%E7%8E%B0%E4%BB%96%E4%BB%AC%E7%9A%84Bean%E9%83%BD%E4%BC%9A%E5%9C%A8Spring%20Boot%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E4%B9%8B%E5%90%8E%E8%87%AA%E5%8A%A8%E5%9C%B0%E8%A2%AB%E8%B0%83%E7%94%A8%E3%80%82%E7%94%B1%E4%BA%8E%E8%BF%99%E4%B8%AA%E7%89%B9%E6%80%A7%EF%BC%8C%E5%AE%83%E4%BB%AC%E6%98%AF%E4%B8%80%E4%B8%AA%E7%90%86%E6%83%B3%E5%9C%B0%E6%96%B9%E5%8E%BB%E5%81%9A%E4%B8%80%E4%BA%9B%E5%88%9D%E5%A7%8B%E5%8C%96%E7%9A%84%E5%B7%A5%E4%BD%9C%0A%0A%23%23%23%23%202%20CommandLineRuner%0A%0A%60%60%60java%0Apackage%20com.chris.springboot2022.init%3B%0A%0Aimport%20cn.hutool.json.JSONUtil%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.boot.CommandLineRunner%3B%0Aimport%20org.springframework.core.annotation.Order%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0A%2F**%0A%20*%20%40Author%20Lilun%0A%20*%20%40Date%202022-01-04%2010%3A33%0A%20*%20%40Description%0A%20**%2F%0A%40Component%0A%40Order(2)%0A%40Slf4j%0Apublic%20class%20CommandLineRunnerTest%20implements%20CommandLineRunner%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20run(String...%20args)%20throws%20Exception%20%7B%0A%0A%20%20%20%20%20%20%20%20log.info(%22CommandLineRunnerTest%20is%20running%22)%3B%0A%20%20%20%20%20%20%20%20log.info(%22args%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(args))%3B%0A%20%20%20%20%20%20%20%20log.info(%22CommandLineRunnerTest%20end%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%203%20ApplicationRuner%0A%3E%20%60ApplicationRunner%60%20%E4%B8%8E%20%60CommandLineRunner%60%20%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%E6%98%AF%E4%B8%80%E6%A0%B7%E7%9A%84%EF%BC%8C%E4%B9%9F%E6%98%AF%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E4%B9%8B%E5%90%8E%E5%85%B6run()%E6%96%B9%E6%B3%95%E4%BC%9A%E8%A2%AB%E8%87%AA%E5%8A%A8%E5%9C%B0%E8%B0%83%E7%94%A8%EF%BC%8C%E5%94%AF%E4%B8%80%E4%B8%8D%E5%90%8C%E7%9A%84%E6%98%AF%60ApplicationRunner%60%20%E4%BC%9A%E5%B0%81%E8%A3%85%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%BE%88%E6%96%B9%E4%BE%BF%E5%9C%B0%E8%8E%B7%E5%8F%96%E5%88%B0%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E5%92%8C%E5%8F%82%E6%95%B0%E5%80%BC%0A%0A%60%60%60java%0Apackage%20com.chris.springboot2022.init%3B%0A%0Aimport%20cn.hutool.json.JSONUtil%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.boot.ApplicationArguments%3B%0Aimport%20org.springframework.boot.ApplicationRunner%3B%0Aimport%20org.springframework.core.annotation.Order%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0Aimport%20java.util.List%3B%0Aimport%20java.util.Set%3B%0A%0A%2F**%0A%20*%20%40Author%20Lilun%0A%20*%20%40Date%202022-01-04%2010%3A38%0A%20*%20%40Description%0A%20**%2F%0A%40Component%0A%40Slf4j%0A%40Order(1)%0Apublic%20class%20ApplicationRunnerTest%20implements%20ApplicationRunner%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20run(ApplicationArguments%20args)%20throws%20Exception%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22ApplicationRunnerTest%20is%20running%22)%3B%0A%20%20%20%20%20%20%20%20String%5B%5D%20sourceArgs%20%3D%20args.getSourceArgs()%3B%0A%20%20%20%20%20%20%20%20log.info(%22sourceArgs%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(sourceArgs))%3B%0A%0A%20%20%20%20%20%20%20%20Set%3CString%3E%20optionNames%20%3D%20args.getOptionNames()%3B%0A%20%20%20%20%20%20%20%20for%20(String%20optionName%20%3A%20optionNames)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20List%3CString%3E%20optionValues%20%3D%20args.getOptionValues(optionName)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22optionValues%20of%20optionName%3A%7B%7D%20is%20%7B%7D%22%2C%20optionName%2C%20JSONUtil.toJsonStr(optionValues))%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20log.info(%22ApplicationRunnerTest%20end%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%0A!%5B020bce7c702e02f0a3b74f1df251e77e.png%5D(en-resource%3A%2F%2Fdatabase%2F577%3A1)%0A%0A!%5B87fa9e48ab2586f7340f6649e0affbe1.png%5D(en-resource%3A%2F%2Fdatabase%2F576%3A1)%0A%0A%0A%23%23%23%23%204%20%E6%80%BB%E7%BB%93%0A%3E%20%E6%97%A0%E8%AE%BA%E6%98%AF%60CommandLineRunner%60%20%E8%BF%98%E6%98%AF%20%60ApplicationRunner%60%EF%BC%8C%E5%AE%83%E4%BB%AC%E7%9A%84%E7%9B%AE%E7%9A%84%E9%83%BD%E6%98%AF%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E4%B9%8B%E5%90%8E%E6%89%A7%E8%A1%8C%E4%B8%80%E4%BA%9B%20%60%E5%88%9D%E5%A7%8B%E5%8C%96%60%E6%93%8D%E4%BD%9C%E3%80%82%0A%3E%20%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E8%8E%B7%E5%8F%96%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E6%97%B6%E5%88%99%E5%BB%BA%E8%AE%AE%E4%BD%BF%E7%94%A8%20%60ApplicationRunner%60%20%E3%80%82%0A%3E%20%E5%8F%A6%E4%B8%80%E7%A7%8D%E5%9C%BA%E6%99%AF%E6%98%AF%E6%88%91%E4%BB%AC%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E9%9C%80%E8%A6%81%E6%89%A7%E8%A1%8C%E6%9F%90%E4%B8%AA%E6%93%8D%E4%BD%9C%EF%BC%8C%E6%AF%94%E5%A6%82%E4%BF%AE%E6%AD%A3%E6%95%B0%E6%8D%AE%E5%BA%93%E7%94%A8%E6%88%B7%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%80%8C%E5%8F%88%E6%89%BE%E4%B8%8D%E5%88%B0%E5%90%88%E9%80%82%E7%9A%84%E6%89%A7%E8%A1%8C%E5%85%A5%E5%8F%A3%EF%BC%8C%E9%82%A3%E4%B9%88%E8%BF%99%E5%B0%B1%E6%98%AF%E5%AE%83%E4%BB%AC%E7%90%86%E6%83%B3%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%E4%BA%86%E3%80%82%0A%0A%23%23%20%E5%8A%A0%E8%BD%BD%E9%A1%BA%E5%BA%8F%0A%3E%20%E5%8A%A0%E8%BD%BD%E9%A1%BA%E5%BA%8F%E4%B8%BAstatic%3Econstructer%3E%40PostConstruct%3ECommandLineRunner%E5%92%8CApplicationRunner%0A

canal

创建时间:2022/4/6 22:50
更新时间:2022/4/13 10:44
作者:Chris
来源:https://www.codeleading.com/article/10112032162/

Canal 是什么

  • Canal 是用 Java开发的基于数据库增量日志解析,提供增量数据订阅&消费的中间件。
  • Canal 主要支持了MySQL的Binlog解析,解析完成后才利用Canal Client来处理获得的相关数据。
  • 数据库同步需要阿里的 Otter中间件,基于Canal。

MySQL的Binlog

Binlog是什么

  • MySQL的二进制日志可以说 MySQL最重要的日志了,它记录了所有的 DDL和DML(除
    了数据查询语句)语句
  • 事件 形式记录,还包含语句所执行的消耗的时间,
  • MySQL的二进制日志是 事务安全型 的,即数据和日志的写入是同步完成的。

二进制日志包括两类文件:

  • 二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件,

  • 二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据查询语句)语句事件。

Binlog的使用场景

二进制有两个最重要的使用场景:

主从集群节点间的数据同步

MySQL Replication在Master端开启Binlog,Master把它的二进制日志传递给 Slaves来达到 Master-Slave 数据一致的目的。

数据恢复

通过使用 MySQL Binlog 工具来使恢复数据。

Binlog 的分类

MySQL Binlog 的格式有三种,分别是 STATEMENT,MIXED,ROW

在配置文件中可以选择配置 binlog_format= statement|mixed|row

三种格式的区别:

Statement:语句级
  • binlog 会记录每次一执行写操作的语句。相对 row 模式节省空间
  • 但是可能产生不一致性,比如“update tt set create_date=now()” 或者里面有随机函数,如果用 binlog 日志进行恢复,由于执行时间不同可能产生的数据就不同。
  • 优点:节省空间。
    缺点:有可能造成数据不一致。
Row:行级
  • binlog 会记录每次操作后每行记录的变化。
  • 优点:保持数据的绝对一致性。因为不管 sql 是什么,引用了什么函数,他只记录
    执行后的结果。
    缺点:占用较大空间。
Mixed:Statement的升级版
  • 一定程度上解决了,因为一些情况而造成的 statement
    模式下数据不一致问题
  • 默认还是 statement,在某些情况下譬如:当函数中包含 UUID() 时;包含
    AUTO_INCREMENT 字段的表被更新时;执行 INSERT DELAYED 语句时;用 UDF 时;会按照 ROW 的方式进行处理
  • 优点:节省空间,同时兼顾了一定的一致性。
    缺点:还有些极个别情况依旧会造成不一致,另外 statement 和 mixed 对于需要对
    binlog 的监控的情况都不方便。
  • 综合上面对比,Canal 想做监控分析,选择 row 格式比较合适。

MySQL主从复制过程

  1. Master 主库将改变记录,写到二进制日志(Binary Log)中;
  2. Slave 从库向 MySQL Master 发送 dump 协议,将 Master 主库的 binary log events 拷贝
    到它的中继日志(relay log)
  3. Slave 从库读取并重做中继日志中的事件,将改变的数据同步到自己的数据库。

Canal 的工作原理

  • Canal模拟MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump协议
  • MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 Canal )
  • Canal 解析 binary log 对象(原始为 byte 流)

使用场景

阿里Otter中间件的一部分

原始场景: 阿里 Otter 中间件的一部分

Otter 是阿里用于进行异地数据库之间的同步框架,Canal 是其中一部分。

更新缓存

实时统计

抓取业务表的新增变化数据,用于制作实时统计

Canal安装

mysql 配置

Binlog配置

配置完之后需要重启mysql

[root@master]# systemctl restart mysqld

[root@master etc]# vi /etc/my.cnf
[mysqld]
server_id=1 # 配置 MySQL replaction 需要定义,不要和 canal 的 slaveId 重复
log-bin=mysql-bin # 开启 binlog
binlog-format=ROW # 选择 ROW 模式

##如果需要指定多个库可以配置为
binlog-do-db=canal
binlog-do-db=mysql
## 如果要指定所有库包括后面新增的库则可以不配置binlog-do-db

查看binlog文件

[root@master mysql]# cd /var/lib/mysql

写入一条记录后再查看会发现binlog文件大小有变化,说明配置生效了

insert into user_info values ('001', 'chris', 'male');

创建用户并授权

create user canal identified by '65536';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%' ;

下载

https://github.com/alibaba/canal/releases/tag/canal-1.1.5

安装

[root@master opt]# tar -tvf canal.deployer-1.1.5.tar.gz
[root@master opt]# cd /opt
[root@master opt]# mkdir canal
[root@master opt]# tar -zxvf  canal.deployer-1.1.5.tar.gz -C canal/

配置

修改基本通用配置
  • 这个文件是 canal 的基本通用配置,canal 端口号默认就是 11111,修改 canal 的
    输出 model,默认 tcp,改为输出到 kafka
  • 多实例配置,一个 canal 服务中可以有多个 instance,conf/下的每一个 example 即是一个实例,每个实例下面都有独立的配置文件。默认只有一个实例 example,如果需要多个实例处理不同的 MySQL 数据的话,直
    接拷贝出多个 example,并对其重新命名,命名和配置文件中指定的名称一致,然后修改
    canal.properties 中的 canal.destinations=实例 1,实例 2,实例 3。
[root@master]# cd opt/canal/conf
[root@master conf]# vi canal.properties 
# tcp, kafka, rocketMQ, rabbitMQ
# tcp是通过服务端和客户端的方式来实现,可能通过代码来获取监控的数据
canal.serverMode = tcp

# 配置需要监控的数据库实例,可以配置多个
canal.destinations = example
配置监控实例
[root@master]# /opt/canal/conf/example
[root@master example]# vi instance.properties

# 配置canal实例ID,不要和mysql的master节点ID一样
canal.instance.mysql.slaveId=20
# 配置mysql的master节点地址
canal.instance.master.address=master:3306
# 配置连接 MySQL 的用户名和密码,默认就是我们前面授权的 canal
canal.instance.dbUsername=canal
canal.instance.dbPassword=65536

启动

[root@master bin]# ./startup.sh
[root@master bin]# jps
6659 Jps
6649 CanalLauncher
查看 server 日志
vi logs/canal/canal.log
查看 instance 的日志
vi logs/example/example.log

Canal数据结构

Message 包含多个SQL的执行结果
Entry 包含一个SQL的执行结果
StoreValue 包含了当前SQL影响的已经序列化的数据
RowChange 是StoreValue 反序列化后得到的数据
从RowChange可以获取列名和列值,当前的数据类型EventType和数据本身RowDataList
EventType=update 时,数据包含更新前和更新后的数据
EventType=Insert 时,只有写入后的数据
EventType=Delete 时,只有删除前的数据

Java实现

package com.chris.canal.tcp.autoinvoke;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.alibaba.otter.canal.protocol.Message;
import com.google.protobuf.ByteString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author Chris
 * @date 2022-04-04 12:12 PM
 */
@Component
@Slf4j
public class CanalClientListener implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {

        InetSocketAddress socketAddress = new InetSocketAddress("master", 11111);
        String canalMysqlInstance = "example";
        // 获取 canal 连接对象
        CanalConnector canalConnector = CanalConnectors.newSingleConnector(socketAddress, canalMysqlInstance, "", "");

        while (true) {
            // 获取连接
            canalConnector.connect();
            // 指定要订阅的数据库和表
            canalConnector.subscribe("canal.*");

            // 获取 Message, 设置为一次性获取100个SQL的变化数据,超过100条返回100条,没有100则不需要等待立即返回现有的条数
            Message message = canalConnector.get(100);

            List<CanalEntry.Entry> entries = message.getEntries();
            if (CollUtil.isNotEmpty(entries)) {
                log.info("get entries");
                for (CanalEntry.Entry entry : entries) {
                    String tableName = entry.getHeader().getTableName();
                    CanalEntry.EntryType entryType = entry.getEntryType();

                    if (CanalEntry.EntryType.ROWDATA.equals(entryType)) {
                        ByteString storeValue = entry.getStoreValue();
                        CanalEntry.RowChange rowChange = CanalEntry.RowChange.parseFrom(storeValue);

                        CanalEntry.EventType eventType = rowChange.getEventType();
                        List<CanalEntry.RowData> rowDatasList = rowChange.getRowDatasList();
                        for (CanalEntry.RowData rowData : rowDatasList) {

                            List<CanalEntry.Column> beforeColumnsList = rowData.getBeforeColumnsList();
                            JSONObject beforeData = JSONUtil.createObj();
                            beforeColumnsList.forEach(row -> beforeData.set(row.getName(), row.getValue()));

                            List<CanalEntry.Column> afterColumnsList = rowData.getAfterColumnsList();
                            JSONObject afterData = JSONUtil.createObj();
                            afterColumnsList.forEach(row -> afterData.set(row.getName(), row.getValue()));

                            log.info("tableName:{},entryType:{},eventType:{},beforeData:{}, afterData:{}", tableName,
                                    entryType, eventType, beforeData, afterData);
                        }
                    }
                }
            } else {
                System.out.println("没有数据,休息一会");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}

启动应用

2022-04-04 16:37:29.309  INFO 40204 --- [  restartedMain] c.c.canal.tcp.Canalcloud2022Application  : Started Canalcloud2022Application in 8.573 seconds (JVM running for 14.349)
没有数据,休息一会
没有数据,休息一会
没有数据,休息一会
没有数据,休息一会
没有数据,休息一会
没有数据,休息一会
没有数据,休息一会
没有数据,休息一会

更新表数据

  • update
tableName:user_info,entryType:ROWDATA,eventType:UPDATE,beforeData:{"id":"002","name":"John","sex":"male"}, afterData:{"id":"002","name":"John-01","sex":"male"}
tableName:user_info,entryType:ROWDATA,eventType:UPDATE,beforeData:{"id":"001","name":"Chris","sex":"male"}, afterData:{"id":"001","name":"Chris-01","sex":"male"}
  • insert
tableName:user_info,entryType:ROWDATA,eventType:INSERT,beforeData:{}, afterData:{"id":"003","name":"Rose","sex":"female"}
tableName:user_info,entryType:ROWDATA,eventType:INSERT,beforeData:{}, afterData:{"id":"004","name":"Petter","sex":"male"}
tableName:user_info,entryType:ROWDATA,eventType:INSERT,beforeData:{}, afterData:{"id":"005","name":"Fiona","sex":"female"}
  • delete
tableName:user_info,entryType:ROWDATA,eventType:DELETE,beforeData:{"id":"002","name":"John-01","sex":"male"}, afterData:{}
tableName:user_info,entryType:ROWDATA,eventType:DELETE,beforeData:{"id":"003","name":"Rose","sex":"female"}, afterData:{}

MQ

参数名参数说明默认值
canal.instance.filter.regex过滤出需要监控的表
canal.instance.filter.black.regex加入黑名单,不需要监控的表

canal可以通过在instance.properties设置canal.instance.filter.regex,来忽略不关心的数据变更的parse和sink处理,优化性能,同时减少不必要的存储开销。

canal instance启动时,默认加载 instance.propertiescanal.instance.filter.regex 参数,之后会根据conf/canal/meta.dat文件filter值更新过滤规则。
当客户端调用CanalConnector.subscribe(String filter)方法时,instance再次用filter参数更新过滤规则。meta.dat文件如下:

{
    "clientDatas":[
        {
            "clientIdentity":{
                "clientId":1001,
                "destination":"hm-test",
                "filter":"xxx.*"
            },
            "cursor":{
                "identity":{
                    "slaveId":-1,
                    "sourceAddress":{
                        "address":"xxxx",
                        "port":3306
                    }
                },
                "postion":{
                    "gtid":"",
                    "included":false,
                    "journalName":"mysql-bin.xxx",
                    "position":xxx,
                    "serverId":xxx,
                    "timestamp":1567062470000
                }
            }
        }
    ],
    "destination":"hm-test"
}

所以当你只关心部分库表更新时,设置了canal.instance.filter.regex,一定不要在客户端调 CanalConnector.subscribe(".\…"),不然等于没设置canal.instance.filter.regex

如果一定要调用 CanalConnector.subscribe(".\…"),那么可以设置instance.propertiescanal.instance.filter.black.regex 参数添加黑名单,过滤非关注库表。

%5Btoc%5D%0A%0A%23%23%20Canal%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20-%20Canal%20%E6%98%AF%E7%94%A8%20Java%E5%BC%80%E5%8F%91%E7%9A%84%E5%9F%BA%E4%BA%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A2%9E%E9%87%8F%E6%97%A5%E5%BF%97%E8%A7%A3%E6%9E%90%EF%BC%8C%E6%8F%90%E4%BE%9B%E5%A2%9E%E9%87%8F%E6%95%B0%E6%8D%AE%E8%AE%A2%E9%98%85%26%E6%B6%88%E8%B4%B9%E7%9A%84%E4%B8%AD%E9%97%B4%E4%BB%B6%E3%80%82%0A%3E%20-%20Canal%20%E4%B8%BB%E8%A6%81%E6%94%AF%E6%8C%81%E4%BA%86MySQL%E7%9A%84Binlog%E8%A7%A3%E6%9E%90%EF%BC%8C%E8%A7%A3%E6%9E%90%E5%AE%8C%E6%88%90%E5%90%8E%E6%89%8D%E5%88%A9%E7%94%A8%60Canal%20Client%60%E6%9D%A5%E5%A4%84%E7%90%86%E8%8E%B7%E5%BE%97%E7%9A%84%E7%9B%B8%E5%85%B3%E6%95%B0%E6%8D%AE%E3%80%82%0A%3E%20-%20%E6%95%B0%E6%8D%AE%E5%BA%93%E5%90%8C%E6%AD%A5%E9%9C%80%E8%A6%81%E9%98%BF%E9%87%8C%E7%9A%84%20%60Otter%E4%B8%AD%E9%97%B4%E4%BB%B6%60%EF%BC%8C%E5%9F%BA%E4%BA%8ECanal%E3%80%82%0A%0A%23%23%20MySQL%E7%9A%84Binlog%0A%0A%23%23%23%23%20Binlog%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20-%20MySQL%E7%9A%84%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%97%A5%E5%BF%97%E5%8F%AF%E4%BB%A5%E8%AF%B4%20MySQL%E6%9C%80%E9%87%8D%E8%A6%81%E7%9A%84%E6%97%A5%E5%BF%97%E4%BA%86%EF%BC%8C%E5%AE%83%E8%AE%B0%E5%BD%95%E4%BA%86%E6%89%80%E6%9C%89%E7%9A%84%20DDL%E5%92%8CDML(%E9%99%A4%0A%3E%20%20%20%E4%BA%86%E6%95%B0%E6%8D%AE%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5)%E8%AF%AD%E5%8F%A5%0A%3E%20-%20%E4%BB%A5%20%60%E4%BA%8B%E4%BB%B6%60%20%E5%BD%A2%E5%BC%8F%E8%AE%B0%E5%BD%95%EF%BC%8C%E8%BF%98%E5%8C%85%E5%90%AB%E8%AF%AD%E5%8F%A5%E6%89%80%E6%89%A7%E8%A1%8C%E7%9A%84%E6%B6%88%E8%80%97%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%8C%0A%3E%20-%20MySQL%E7%9A%84%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%97%A5%E5%BF%97%E6%98%AF%20%60%E4%BA%8B%E5%8A%A1%E5%AE%89%E5%85%A8%E5%9E%8B%60%20%E7%9A%84%EF%BC%8C%E5%8D%B3%E6%95%B0%E6%8D%AE%E5%92%8C%E6%97%A5%E5%BF%97%E7%9A%84%E5%86%99%E5%85%A5%E6%98%AF%E5%90%8C%E6%AD%A5%E5%AE%8C%E6%88%90%E7%9A%84%E3%80%82%0A%0A%3E%20%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%97%A5%E5%BF%97%E5%8C%85%E6%8B%AC%E4%B8%A4%E7%B1%BB%E6%96%87%E4%BB%B6%EF%BC%9A%0A%3E%0A%3E%20-%20%60%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%97%A5%E5%BF%97%E7%B4%A2%E5%BC%95%E6%96%87%E4%BB%B6%60%EF%BC%88%E6%96%87%E4%BB%B6%E5%90%8D%E5%90%8E%E7%BC%80%E4%B8%BA.index%EF%BC%89%E7%94%A8%E4%BA%8E%E8%AE%B0%E5%BD%95%E6%89%80%E6%9C%89%E7%9A%84%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6%EF%BC%8C%0A%3E%0A%3E%20-%20%60%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%60%EF%BC%88%E6%96%87%E4%BB%B6%E5%90%8D%E5%90%8E%E7%BC%80%E4%B8%BA.00000*%EF%BC%89%E8%AE%B0%E5%BD%95%E6%95%B0%E6%8D%AE%E5%BA%93%E6%89%80%E6%9C%89%E7%9A%84DDL%E5%92%8CDML(%E9%99%A4%E4%BA%86%E6%95%B0%E6%8D%AE%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5)%E8%AF%AD%E5%8F%A5%E4%BA%8B%E4%BB%B6%E3%80%82%0A%0A%23%23%23%23%20Binlog%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%0A%0A%3E%20%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%9C%89%E4%B8%A4%E4%B8%AA%E6%9C%80%E9%87%8D%E8%A6%81%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%3A%20%0A%3E%0A%0A%23%23%23%23%23%20%E4%B8%BB%E4%BB%8E%E9%9B%86%E7%BE%A4%E8%8A%82%E7%82%B9%E9%97%B4%E7%9A%84%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5%0A%0A%3E%20MySQL%20Replication%E5%9C%A8Master%E7%AB%AF%E5%BC%80%E5%90%AFBinlog%EF%BC%8CMaster%E6%8A%8A%E5%AE%83%E7%9A%84%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%97%A5%E5%BF%97%E4%BC%A0%E9%80%92%E7%BB%99%20Slaves%E6%9D%A5%E8%BE%BE%E5%88%B0%20Master-Slave%20%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E7%9A%84%E7%9B%AE%E7%9A%84%E3%80%82%0A%0A%23%23%23%23%23%20%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D%0A%0A%3E%20%E9%80%9A%E8%BF%87%E4%BD%BF%E7%94%A8%20MySQL%20Binlog%20%E5%B7%A5%E5%85%B7%E6%9D%A5%E4%BD%BF%E6%81%A2%E5%A4%8D%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A%23%23%23%23%20Binlog%20%E7%9A%84%E5%88%86%E7%B1%BB%0A%0A%3E%20MySQL%20Binlog%20%E7%9A%84%E6%A0%BC%E5%BC%8F%E6%9C%89%E4%B8%89%E7%A7%8D%EF%BC%8C%E5%88%86%E5%88%AB%E6%98%AF%20%60STATEMENT%2CMIXED%2CROW%60%0A%3E%0A%3E%20%E5%9C%A8%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E5%8F%AF%E4%BB%A5%E9%80%89%E6%8B%A9%E9%85%8D%E7%BD%AE%20%60binlog_format%3D%20statement%7Cmixed%7Crow%60%0A%0A%3E%20%E4%B8%89%E7%A7%8D%E6%A0%BC%E5%BC%8F%E7%9A%84%E5%8C%BA%E5%88%AB%EF%BC%9A%0A%0A%23%23%23%23%23%20%20Statement%EF%BC%9A%E8%AF%AD%E5%8F%A5%E7%BA%A7%0A%3E%20-%20binlog%20%E4%BC%9A%E8%AE%B0%E5%BD%95%E6%AF%8F%E6%AC%A1%E4%B8%80%E6%89%A7%E8%A1%8C%E5%86%99%E6%93%8D%E4%BD%9C%E7%9A%84%E8%AF%AD%E5%8F%A5%E3%80%82%E7%9B%B8%E5%AF%B9%20row%20%E6%A8%A1%E5%BC%8F%E8%8A%82%E7%9C%81%E7%A9%BA%E9%97%B4%0A%3E%20-%20%E4%BD%86%E6%98%AF%E5%8F%AF%E8%83%BD%E4%BA%A7%E7%94%9F%E4%B8%8D%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%8C%E6%AF%94%E5%A6%82%E2%80%9Cupdate%20tt%20set%20create_date%3Dnow()%E2%80%9D%20%E6%88%96%E8%80%85%E9%87%8C%E9%9D%A2%E6%9C%89%E9%9A%8F%E6%9C%BA%E5%87%BD%E6%95%B0%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%94%A8%20binlog%20%E6%97%A5%E5%BF%97%E8%BF%9B%E8%A1%8C%E6%81%A2%E5%A4%8D%EF%BC%8C%E7%94%B1%E4%BA%8E%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E4%B8%8D%E5%90%8C%E5%8F%AF%E8%83%BD%E4%BA%A7%E7%94%9F%E7%9A%84%E6%95%B0%E6%8D%AE%E5%B0%B1%E4%B8%8D%E5%90%8C%E3%80%82%0A%3E%20-%20%E4%BC%98%E7%82%B9%EF%BC%9A%E8%8A%82%E7%9C%81%E7%A9%BA%E9%97%B4%E3%80%82%0A%3E%20%20%20%E7%BC%BA%E7%82%B9%EF%BC%9A%E6%9C%89%E5%8F%AF%E8%83%BD%E9%80%A0%E6%88%90%E6%95%B0%E6%8D%AE%E4%B8%8D%E4%B8%80%E8%87%B4%E3%80%82%0A%0A%23%23%23%23%23%20%20Row%EF%BC%9A%E8%A1%8C%E7%BA%A7%20%0A%3E%20-%20binlog%20%E4%BC%9A%E8%AE%B0%E5%BD%95%E6%AF%8F%E6%AC%A1%E6%93%8D%E4%BD%9C%E5%90%8E%E6%AF%8F%E8%A1%8C%E8%AE%B0%E5%BD%95%E7%9A%84%E5%8F%98%E5%8C%96%E3%80%82%0A%3E%20-%20%E4%BC%98%E7%82%B9%EF%BC%9A%E4%BF%9D%E6%8C%81%E6%95%B0%E6%8D%AE%E7%9A%84%E7%BB%9D%E5%AF%B9%E4%B8%80%E8%87%B4%E6%80%A7%E3%80%82%E5%9B%A0%E4%B8%BA%E4%B8%8D%E7%AE%A1%20sql%20%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%8C%E5%BC%95%E7%94%A8%E4%BA%86%E4%BB%80%E4%B9%88%E5%87%BD%E6%95%B0%EF%BC%8C%E4%BB%96%E5%8F%AA%E8%AE%B0%E5%BD%95%0A%3E%20%20%20%E6%89%A7%E8%A1%8C%E5%90%8E%E7%9A%84%E7%BB%93%E6%9E%9C%E3%80%82%0A%3E%20%20%20%E7%BC%BA%E7%82%B9%EF%BC%9A%E5%8D%A0%E7%94%A8%E8%BE%83%E5%A4%A7%E7%A9%BA%E9%97%B4%E3%80%82%0A%0A%23%23%23%23%23%20%20Mixed%EF%BC%9AStatement%E7%9A%84%E5%8D%87%E7%BA%A7%E7%89%88%0A%3E%20-%20%E4%B8%80%E5%AE%9A%E7%A8%8B%E5%BA%A6%E4%B8%8A%E8%A7%A3%E5%86%B3%E4%BA%86%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%B8%80%E4%BA%9B%E6%83%85%E5%86%B5%E8%80%8C%E9%80%A0%E6%88%90%E7%9A%84%20statement%0A%3E%20%20%20%20%20%20%E6%A8%A1%E5%BC%8F%E4%B8%8B%E6%95%B0%E6%8D%AE%E4%B8%8D%E4%B8%80%E8%87%B4%E9%97%AE%E9%A2%98%0A%3E%20-%20%E9%BB%98%E8%AE%A4%E8%BF%98%E6%98%AF%20statement%EF%BC%8C%E5%9C%A8%E6%9F%90%E4%BA%9B%E6%83%85%E5%86%B5%E4%B8%8B%E8%AD%AC%E5%A6%82%EF%BC%9A%E5%BD%93%E5%87%BD%E6%95%B0%E4%B8%AD%E5%8C%85%E5%90%AB%20UUID()%20%E6%97%B6%EF%BC%9B%E5%8C%85%E5%90%AB%0A%3E%20%20%20%20%20%20AUTO_INCREMENT%20%E5%AD%97%E6%AE%B5%E7%9A%84%E8%A1%A8%E8%A2%AB%E6%9B%B4%E6%96%B0%E6%97%B6%EF%BC%9B%E6%89%A7%E8%A1%8C%20INSERT%20DELAYED%20%E8%AF%AD%E5%8F%A5%E6%97%B6%EF%BC%9B%E7%94%A8%20UDF%20%E6%97%B6%EF%BC%9B%E4%BC%9A%E6%8C%89%E7%85%A7%20ROW%20%E7%9A%84%E6%96%B9%E5%BC%8F%E8%BF%9B%E8%A1%8C%E5%A4%84%E7%90%86%0A%3E%20-%20%E4%BC%98%E7%82%B9%EF%BC%9A%E8%8A%82%E7%9C%81%E7%A9%BA%E9%97%B4%EF%BC%8C%E5%90%8C%E6%97%B6%E5%85%BC%E9%A1%BE%E4%BA%86%E4%B8%80%E5%AE%9A%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%E3%80%82%0A%3E%20%20%20%20%20%20%E7%BC%BA%E7%82%B9%EF%BC%9A%E8%BF%98%E6%9C%89%E4%BA%9B%E6%9E%81%E4%B8%AA%E5%88%AB%E6%83%85%E5%86%B5%E4%BE%9D%E6%97%A7%E4%BC%9A%E9%80%A0%E6%88%90%E4%B8%8D%E4%B8%80%E8%87%B4%EF%BC%8C%E5%8F%A6%E5%A4%96%20statement%20%E5%92%8C%20mixed%20%E5%AF%B9%E4%BA%8E%E9%9C%80%E8%A6%81%E5%AF%B9%0A%3E%20%20%20%20%20%20binlog%20%E7%9A%84%E7%9B%91%E6%8E%A7%E7%9A%84%E6%83%85%E5%86%B5%E9%83%BD%E4%B8%8D%E6%96%B9%E4%BE%BF%E3%80%82%0A%3E%20-%20%60%E7%BB%BC%E5%90%88%E4%B8%8A%E9%9D%A2%E5%AF%B9%E6%AF%94%EF%BC%8CCanal%20%E6%83%B3%E5%81%9A%E7%9B%91%E6%8E%A7%E5%88%86%E6%9E%90%EF%BC%8C%E9%80%89%E6%8B%A9%20row%20%E6%A0%BC%E5%BC%8F%E6%AF%94%E8%BE%83%E5%90%88%E9%80%82%E3%80%82%60%0A%0A%23%23%23%23%20MySQL%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%E8%BF%87%E7%A8%8B%0A%0A%3E%201.%20Master%20%E4%B8%BB%E5%BA%93%E5%B0%86%E6%94%B9%E5%8F%98%E8%AE%B0%E5%BD%95%EF%BC%8C%E5%86%99%E5%88%B0%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%97%A5%E5%BF%97(Binary%20Log)%E4%B8%AD%EF%BC%9B%0A%3E%202.%20Slave%20%E4%BB%8E%E5%BA%93%E5%90%91%20MySQL%20Master%20%E5%8F%91%E9%80%81%20dump%20%E5%8D%8F%E8%AE%AE%EF%BC%8C%E5%B0%86%20Master%20%E4%B8%BB%E5%BA%93%E7%9A%84%20binary%20log%20events%20%E6%8B%B7%E8%B4%9D%0A%3E%20%20%20%20%E5%88%B0%E5%AE%83%E7%9A%84%60%E4%B8%AD%E7%BB%A7%E6%97%A5%E5%BF%97(relay%20log)%60%EF%BC%9B%0A%3E%203.%20Slave%20%E4%BB%8E%E5%BA%93%E8%AF%BB%E5%8F%96%E5%B9%B6%E9%87%8D%E5%81%9A%E4%B8%AD%E7%BB%A7%E6%97%A5%E5%BF%97%E4%B8%AD%E7%9A%84%E4%BA%8B%E4%BB%B6%EF%BC%8C%E5%B0%86%E6%94%B9%E5%8F%98%E7%9A%84%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5%E5%88%B0%E8%87%AA%E5%B7%B1%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E3%80%82%0A%0A!%5B7f46d216665d6f2765707c4dc96d2cd2.png%5D(en-resource%3A%2F%2Fdatabase%2F1589%3A1)%0A%0A%23%23%20Canal%20%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%0A%0A%3E%20-%20Canal%E6%A8%A1%E6%8B%9FMySQL%20slave%20%E7%9A%84%E4%BA%A4%E4%BA%92%E5%8D%8F%E8%AE%AE%EF%BC%8C%E4%BC%AA%E8%A3%85%E8%87%AA%E5%B7%B1%E4%B8%BA%20MySQL%20slave%20%EF%BC%8C%E5%90%91%20MySQL%20master%20%E5%8F%91%E9%80%81dump%E5%8D%8F%E8%AE%AE%0A%3E%20-%20MySQL%20master%20%E6%94%B6%E5%88%B0%20dump%20%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%BC%80%E5%A7%8B%E6%8E%A8%E9%80%81%20binary%20log%20%E7%BB%99%20slave%20(%E5%8D%B3%20Canal%20)%0A%3E%20-%20Canal%20%E8%A7%A3%E6%9E%90%20binary%20log%20%E5%AF%B9%E8%B1%A1(%E5%8E%9F%E5%A7%8B%E4%B8%BA%20byte%20%E6%B5%81)%0A%0A!%5B3a48d8cf36d1fd715e34e1dd5771ea5d.png%5D(en-resource%3A%2F%2Fdatabase%2F1586%3A1)%0A%0A%0A%23%23%20%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%0A%0A%23%23%23%23%20%20%E9%98%BF%E9%87%8COtter%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%0A%0A%3E%20%E5%8E%9F%E5%A7%8B%E5%9C%BA%E6%99%AF%EF%BC%9A%20%E9%98%BF%E9%87%8C%20Otter%20%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%0A%3E%0A%3E%20Otter%20%E6%98%AF%E9%98%BF%E9%87%8C%E7%94%A8%E4%BA%8E%E8%BF%9B%E8%A1%8C%E5%BC%82%E5%9C%B0%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B9%8B%E9%97%B4%E7%9A%84%E5%90%8C%E6%AD%A5%E6%A1%86%E6%9E%B6%EF%BC%8CCanal%20%E6%98%AF%E5%85%B6%E4%B8%AD%E4%B8%80%E9%83%A8%E5%88%86%E3%80%82%0A%0A!%5B724faa1d9b239ee6e73bae3358e367b2.png%5D(en-resource%3A%2F%2Fdatabase%2F1588%3A1)%0A%0A%23%23%23%23%20%E6%9B%B4%E6%96%B0%E7%BC%93%E5%AD%98%0A!%5B451d49bd05744baaaa611bb6a6edccba.png%5D(en-resource%3A%2F%2Fdatabase%2F1587%3A1)%0A%0A%0A%23%23%23%23%20%E5%AE%9E%E6%97%B6%E7%BB%9F%E8%AE%A1%0A%0A%3E%20%E6%8A%93%E5%8F%96%E4%B8%9A%E5%8A%A1%E8%A1%A8%E7%9A%84%E6%96%B0%E5%A2%9E%E5%8F%98%E5%8C%96%E6%95%B0%E6%8D%AE%EF%BC%8C%E7%94%A8%E4%BA%8E%E5%88%B6%E4%BD%9C%E5%AE%9E%E6%97%B6%E7%BB%9F%E8%AE%A1%0A%0A%23%23%20Canal%E5%AE%89%E8%A3%85%0A%0A%0Amysql%20%E9%85%8D%E7%BD%AE%0A%0A%23%23%23%23%20Binlog%E9%85%8D%E7%BD%AE%0A%0A%3E%20%E9%85%8D%E7%BD%AE%E5%AE%8C%E4%B9%8B%E5%90%8E%E9%9C%80%E8%A6%81%E9%87%8D%E5%90%AFmysql%0A%3E%0A%3E%20%60%5Broot%40master%5D%23%20systemctl%20restart%20mysqld%60%0A%0A%60%60%60mysql%0A%5Broot%40master%20etc%5D%23%20vi%20%2Fetc%2Fmy.cnf%0A%5Bmysqld%5D%0Aserver_id%3D1%20%23%20%E9%85%8D%E7%BD%AE%20MySQL%20replaction%20%E9%9C%80%E8%A6%81%E5%AE%9A%E4%B9%89%EF%BC%8C%E4%B8%8D%E8%A6%81%E5%92%8C%20canal%20%E7%9A%84%20slaveId%20%E9%87%8D%E5%A4%8D%0Alog-bin%3Dmysql-bin%20%23%20%E5%BC%80%E5%90%AF%20binlog%0Abinlog-format%3DROW%20%23%20%E9%80%89%E6%8B%A9%20ROW%20%E6%A8%A1%E5%BC%8F%0A%0A%23%23%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E6%8C%87%E5%AE%9A%E5%A4%9A%E4%B8%AA%E5%BA%93%E5%8F%AF%E4%BB%A5%E9%85%8D%E7%BD%AE%E4%B8%BA%0Abinlog-do-db%3Dcanal%0Abinlog-do-db%3Dmysql%0A%23%23%20%E5%A6%82%E6%9E%9C%E8%A6%81%E6%8C%87%E5%AE%9A%E6%89%80%E6%9C%89%E5%BA%93%E5%8C%85%E6%8B%AC%E5%90%8E%E9%9D%A2%E6%96%B0%E5%A2%9E%E7%9A%84%E5%BA%93%E5%88%99%E5%8F%AF%E4%BB%A5%E4%B8%8D%E9%85%8D%E7%BD%AEbinlog-do-db%0A%60%60%60%0A%0A%3E%20%E6%9F%A5%E7%9C%8Bbinlog%E6%96%87%E4%BB%B6%0A%3E%0A%3E%20%60%5Broot%40master%20mysql%5D%23%20cd%20%2Fvar%2Flib%2Fmysql%60%0A%0A!%5B77691f9cd2562bb697bd76f6a7912470.png%5D(en-resource%3A%2F%2Fdatabase%2F1592%3A1)%0A%0A%0A%3E%20%E5%86%99%E5%85%A5%E4%B8%80%E6%9D%A1%E8%AE%B0%E5%BD%95%E5%90%8E%E5%86%8D%E6%9F%A5%E7%9C%8B%E4%BC%9A%E5%8F%91%E7%8E%B0binlog%E6%96%87%E4%BB%B6%E5%A4%A7%E5%B0%8F%E6%9C%89%E5%8F%98%E5%8C%96%EF%BC%8C%E8%AF%B4%E6%98%8E%E9%85%8D%E7%BD%AE%E7%94%9F%E6%95%88%E4%BA%86%0A%60%60%60sql%0Ainsert%20into%20user_info%20values%20('001'%2C%20'chris'%2C%20'male')%3B%0A%60%60%60%0A!%5Be5346645ef908163c2f317e3849dc740.png%5D(en-resource%3A%2F%2Fdatabase%2F1593%3A1)%0A%0A%0A%23%23%23%23%20%E5%88%9B%E5%BB%BA%E7%94%A8%E6%88%B7%E5%B9%B6%E6%8E%88%E6%9D%83%0A%0A%60%60%60sql%0Acreate%20user%20canal%20identified%20by%20'65536'%3B%0AGRANT%20SELECT%2C%20REPLICATION%20SLAVE%2C%20REPLICATION%20CLIENT%20ON%20*.*%20TO%20'canal'%40'%25'%20%3B%0A%60%60%60%0A%0A%23%23%23%23%20%E4%B8%8B%E8%BD%BD%0A%0A%3E%20https%3A%2F%2Fgithub.com%2Falibaba%2Fcanal%2Freleases%2Ftag%2Fcanal-1.1.5%0A%0A%23%23%23%23%20%E5%AE%89%E8%A3%85%0A%0A%60%60%60shell%0A%5Broot%40master%20opt%5D%23%20tar%20-tvf%20canal.deployer-1.1.5.tar.gz%0A%5Broot%40master%20opt%5D%23%20cd%20%2Fopt%0A%5Broot%40master%20opt%5D%23%20mkdir%20canal%0A%5Broot%40master%20opt%5D%23%20tar%20-zxvf%20%20canal.deployer-1.1.5.tar.gz%20-C%20canal%2F%0A%60%60%60%0A%0A%23%23%23%23%20%E9%85%8D%E7%BD%AE%0A%0A%23%23%23%23%23%20%E4%BF%AE%E6%94%B9%E5%9F%BA%E6%9C%AC%E9%80%9A%E7%94%A8%E9%85%8D%E7%BD%AE%0A%0A%3E%20-%20%E8%BF%99%E4%B8%AA%E6%96%87%E4%BB%B6%E6%98%AF%20canal%20%E7%9A%84%E5%9F%BA%E6%9C%AC%E9%80%9A%E7%94%A8%E9%85%8D%E7%BD%AE%EF%BC%8Ccanal%20%E7%AB%AF%E5%8F%A3%E5%8F%B7%E9%BB%98%E8%AE%A4%E5%B0%B1%E6%98%AF%2011111%EF%BC%8C%E4%BF%AE%E6%94%B9%20canal%20%E7%9A%84%0A%3E%20%20%20%E8%BE%93%E5%87%BA%20model%EF%BC%8C%E9%BB%98%E8%AE%A4%20tcp%EF%BC%8C%E6%94%B9%E4%B8%BA%E8%BE%93%E5%87%BA%E5%88%B0%20kafka%0A%3E%20-%20%E5%A4%9A%E5%AE%9E%E4%BE%8B%E9%85%8D%E7%BD%AE%EF%BC%8C%E4%B8%80%E4%B8%AA%20canal%20%E6%9C%8D%E5%8A%A1%E4%B8%AD%E5%8F%AF%E4%BB%A5%E6%9C%89%E5%A4%9A%E4%B8%AA%20instance%EF%BC%8Cconf%2F%E4%B8%8B%E7%9A%84%E6%AF%8F%E4%B8%80%E4%B8%AA%20example%20%E5%8D%B3%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E6%AF%8F%E4%B8%AA%E5%AE%9E%E4%BE%8B%E4%B8%8B%E9%9D%A2%E9%83%BD%E6%9C%89%E7%8B%AC%E7%AB%8B%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E3%80%82%E9%BB%98%E8%AE%A4%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%20example%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E5%A4%9A%E4%B8%AA%E5%AE%9E%E4%BE%8B%E5%A4%84%E7%90%86%E4%B8%8D%E5%90%8C%E7%9A%84%20MySQL%20%E6%95%B0%E6%8D%AE%E7%9A%84%E8%AF%9D%EF%BC%8C%E7%9B%B4%0A%3E%20%20%20%E6%8E%A5%E6%8B%B7%E8%B4%9D%E5%87%BA%E5%A4%9A%E4%B8%AA%20example%EF%BC%8C%E5%B9%B6%E5%AF%B9%E5%85%B6%E9%87%8D%E6%96%B0%E5%91%BD%E5%90%8D%EF%BC%8C%E5%91%BD%E5%90%8D%E5%92%8C%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E6%8C%87%E5%AE%9A%E7%9A%84%E5%90%8D%E7%A7%B0%E4%B8%80%E8%87%B4%EF%BC%8C%E7%84%B6%E5%90%8E%E4%BF%AE%E6%94%B9%0A%3E%20%20%20canal.properties%20%E4%B8%AD%E7%9A%84%20canal.destinations%3D%E5%AE%9E%E4%BE%8B%201%EF%BC%8C%E5%AE%9E%E4%BE%8B%202%EF%BC%8C%E5%AE%9E%E4%BE%8B%203%E3%80%82%0A%0A%60%60%60shell%0A%5Broot%40master%5D%23%20cd%20opt%2Fcanal%2Fconf%0A%5Broot%40master%20conf%5D%23%20vi%20canal.properties%20%0A%23%20tcp%2C%20kafka%2C%20rocketMQ%2C%20rabbitMQ%0A%23%20tcp%E6%98%AF%E9%80%9A%E8%BF%87%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%92%8C%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E6%96%B9%E5%BC%8F%E6%9D%A5%E5%AE%9E%E7%8E%B0%EF%BC%8C%E5%8F%AF%E8%83%BD%E9%80%9A%E8%BF%87%E4%BB%A3%E7%A0%81%E6%9D%A5%E8%8E%B7%E5%8F%96%E7%9B%91%E6%8E%A7%E7%9A%84%E6%95%B0%E6%8D%AE%0Acanal.serverMode%20%3D%20tcp%0A%0A%23%20%E9%85%8D%E7%BD%AE%E9%9C%80%E8%A6%81%E7%9B%91%E6%8E%A7%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%85%8D%E7%BD%AE%E5%A4%9A%E4%B8%AA%0Acanal.destinations%20%3D%20example%0A%60%60%60%0A%0A%23%23%23%23%23%20%E9%85%8D%E7%BD%AE%E7%9B%91%E6%8E%A7%E5%AE%9E%E4%BE%8B%0A%0A%60%60%60shell%0A%5Broot%40master%5D%23%20%2Fopt%2Fcanal%2Fconf%2Fexample%0A%5Broot%40master%20example%5D%23%20vi%20instance.properties%0A%0A%23%20%E9%85%8D%E7%BD%AEcanal%E5%AE%9E%E4%BE%8BID%EF%BC%8C%E4%B8%8D%E8%A6%81%E5%92%8Cmysql%E7%9A%84master%E8%8A%82%E7%82%B9ID%E4%B8%80%E6%A0%B7%0Acanal.instance.mysql.slaveId%3D20%0A%23%20%E9%85%8D%E7%BD%AEmysql%E7%9A%84master%E8%8A%82%E7%82%B9%E5%9C%B0%E5%9D%80%0Acanal.instance.master.address%3Dmaster%3A3306%0A%23%20%E9%85%8D%E7%BD%AE%E8%BF%9E%E6%8E%A5%20MySQL%20%E7%9A%84%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E5%AF%86%E7%A0%81%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%B0%B1%E6%98%AF%E6%88%91%E4%BB%AC%E5%89%8D%E9%9D%A2%E6%8E%88%E6%9D%83%E7%9A%84%20canal%0Acanal.instance.dbUsername%3Dcanal%0Acanal.instance.dbPassword%3D65536%0A%60%60%60%0A%0A%23%23%23%23%20%E5%90%AF%E5%8A%A8%0A%0A%60%60%60%0A%5Broot%40master%20bin%5D%23%20.%2Fstartup.sh%0A%5Broot%40master%20bin%5D%23%20jps%0A6659%20Jps%0A6649%20CanalLauncher%0A%60%60%60%0A%0A%23%23%23%23%23%20%E6%9F%A5%E7%9C%8B%20server%20%E6%97%A5%E5%BF%97%0A%0A%60%60%60%0Avi%20logs%2Fcanal%2Fcanal.log%0A%60%60%60%0A%0A%23%23%23%23%23%20%E6%9F%A5%E7%9C%8B%20instance%20%E7%9A%84%E6%97%A5%E5%BF%97%0A%0A%60%60%60%0Avi%20logs%2Fexample%2Fexample.log%0A%60%60%60%0A%0A%23%23%20Canal%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%0A%3E%20%60Message%60%20%E5%8C%85%E5%90%AB%E5%A4%9A%E4%B8%AASQL%E7%9A%84%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%0A%3E%20%60Entry%60%20%E5%8C%85%E5%90%AB%E4%B8%80%E4%B8%AASQL%E7%9A%84%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%0A%3E%20%60StoreValue%60%20%E5%8C%85%E5%90%AB%E4%BA%86%E5%BD%93%E5%89%8DSQL%E5%BD%B1%E5%93%8D%E7%9A%84%E5%B7%B2%E7%BB%8F%E5%BA%8F%E5%88%97%E5%8C%96%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20%60RowChange%60%20%E6%98%AFStoreValue%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%90%8E%E5%BE%97%E5%88%B0%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20%E4%BB%8ERowChange%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%8F%96%E5%88%97%E5%90%8D%E5%92%8C%E5%88%97%E5%80%BC%EF%BC%8C%E5%BD%93%E5%89%8D%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8BEventType%E5%92%8C%E6%95%B0%E6%8D%AE%E6%9C%AC%E8%BA%ABRowDataList%0A%3E%20%60EventType%3Dupdate%60%20%E6%97%B6%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%8C%85%E5%90%AB%E6%9B%B4%E6%96%B0%E5%89%8D%E5%92%8C%E6%9B%B4%E6%96%B0%E5%90%8E%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20%60EventType%3DInsert%60%20%E6%97%B6%EF%BC%8C%E5%8F%AA%E6%9C%89%E5%86%99%E5%85%A5%E5%90%8E%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20%60EventType%3DDelete%60%20%E6%97%B6%EF%BC%8C%E5%8F%AA%E6%9C%89%E5%88%A0%E9%99%A4%E5%89%8D%E7%9A%84%E6%95%B0%E6%8D%AE%0A%0A!%5Bec5eb06bc8303113e66b5d11d55d5e89.png%5D(en-resource%3A%2F%2Fdatabase%2F1590%3A1)%0A%0A!%5Bae6d2d0edbd860385676eab4bb61b1f2.png%5D(en-resource%3A%2F%2Fdatabase%2F1608%3A1)%0A%0A%0A%23%23%20Java%E5%AE%9E%E7%8E%B0%0A%0A%60%60%60java%0Apackage%20com.chris.canal.tcp.autoinvoke%3B%0A%0Aimport%20cn.hutool.core.collection.CollUtil%3B%0Aimport%20cn.hutool.json.JSONArray%3B%0Aimport%20cn.hutool.json.JSONObject%3B%0Aimport%20cn.hutool.json.JSONUtil%3B%0Aimport%20com.alibaba.otter.canal.client.CanalConnector%3B%0Aimport%20com.alibaba.otter.canal.client.CanalConnectors%3B%0Aimport%20com.alibaba.otter.canal.protocol.CanalEntry%3B%0Aimport%20com.alibaba.otter.canal.protocol.Message%3B%0Aimport%20com.google.protobuf.ByteString%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.boot.CommandLineRunner%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0Aimport%20java.net.InetSocketAddress%3B%0Aimport%20java.util.List%3B%0Aimport%20java.util.concurrent.TimeUnit%3B%0A%0A%2F**%0A%20*%20%40author%20Chris%0A%20*%20%40date%202022-04-04%2012%3A12%20PM%0A%20*%2F%0A%40Component%0A%40Slf4j%0Apublic%20class%20CanalClientListener%20implements%20CommandLineRunner%20%7B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20run(String...%20args)%20throws%20Exception%20%7B%0A%0A%20%20%20%20%20%20%20%20InetSocketAddress%20socketAddress%20%3D%20new%20InetSocketAddress(%22master%22%2C%2011111)%3B%0A%20%20%20%20%20%20%20%20String%20canalMysqlInstance%20%3D%20%22example%22%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%20canal%20%E8%BF%9E%E6%8E%A5%E5%AF%B9%E8%B1%A1%0A%20%20%20%20%20%20%20%20CanalConnector%20canalConnector%20%3D%20CanalConnectors.newSingleConnector(socketAddress%2C%20canalMysqlInstance%2C%20%22%22%2C%20%22%22)%3B%0A%0A%20%20%20%20%20%20%20%20while%20(true)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%E8%BF%9E%E6%8E%A5%0A%20%20%20%20%20%20%20%20%20%20%20%20canalConnector.connect()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E6%8C%87%E5%AE%9A%E8%A6%81%E8%AE%A2%E9%98%85%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E5%92%8C%E8%A1%A8%0A%20%20%20%20%20%20%20%20%20%20%20%20canalConnector.subscribe(%22canal.*%22)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%20Message%2C%20%E8%AE%BE%E7%BD%AE%E4%B8%BA%E4%B8%80%E6%AC%A1%E6%80%A7%E8%8E%B7%E5%8F%96100%E4%B8%AASQL%E7%9A%84%E5%8F%98%E5%8C%96%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%B6%85%E8%BF%87100%E6%9D%A1%E8%BF%94%E5%9B%9E100%E6%9D%A1%EF%BC%8C%E6%B2%A1%E6%9C%89100%E5%88%99%E4%B8%8D%E9%9C%80%E8%A6%81%E7%AD%89%E5%BE%85%E7%AB%8B%E5%8D%B3%E8%BF%94%E5%9B%9E%E7%8E%B0%E6%9C%89%E7%9A%84%E6%9D%A1%E6%95%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%20message%20%3D%20canalConnector.get(100)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20List%3CCanalEntry.Entry%3E%20entries%20%3D%20message.getEntries()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(CollUtil.isNotEmpty(entries))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22get%20entries%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(CanalEntry.Entry%20entry%20%3A%20entries)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20String%20tableName%20%3D%20entry.getHeader().getTableName()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CanalEntry.EntryType%20entryType%20%3D%20entry.getEntryType()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(CanalEntry.EntryType.ROWDATA.equals(entryType))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ByteString%20storeValue%20%3D%20entry.getStoreValue()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CanalEntry.RowChange%20rowChange%20%3D%20CanalEntry.RowChange.parseFrom(storeValue)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CanalEntry.EventType%20eventType%20%3D%20rowChange.getEventType()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20List%3CCanalEntry.RowData%3E%20rowDatasList%20%3D%20rowChange.getRowDatasList()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(CanalEntry.RowData%20rowData%20%3A%20rowDatasList)%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20List%3CCanalEntry.Column%3E%20beforeColumnsList%20%3D%20rowData.getBeforeColumnsList()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20JSONObject%20beforeData%20%3D%20JSONUtil.createObj()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20beforeColumnsList.forEach(row%20-%3E%20beforeData.set(row.getName()%2C%20row.getValue()))%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20List%3CCanalEntry.Column%3E%20afterColumnsList%20%3D%20rowData.getAfterColumnsList()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20JSONObject%20afterData%20%3D%20JSONUtil.createObj()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20afterColumnsList.forEach(row%20-%3E%20afterData.set(row.getName()%2C%20row.getValue()))%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22tableName%3A%7B%7D%2CentryType%3A%7B%7D%2CeventType%3A%7B%7D%2CbeforeData%3A%7B%7D%2C%20afterData%3A%7B%7D%22%2C%20tableName%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entryType%2C%20eventType%2C%20beforeData%2C%20afterData)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%0A%7D%0A%60%60%60%0A%0A%3E%20%E5%90%AF%E5%8A%A8%E5%BA%94%E7%94%A8%0A%0A%60%60%60%0A2022-04-04%2016%3A37%3A29.309%20%20INFO%2040204%20---%20%5B%20%20restartedMain%5D%20c.c.canal.tcp.Canalcloud2022Application%20%20%3A%20Started%20Canalcloud2022Application%20in%208.573%20seconds%20(JVM%20running%20for%2014.349)%0A%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%0A%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%0A%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%0A%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%0A%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%0A%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%0A%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%0A%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BC%91%E6%81%AF%E4%B8%80%E4%BC%9A%0A%60%60%60%0A%0A%3E%20%E6%9B%B4%E6%96%B0%E8%A1%A8%E6%95%B0%E6%8D%AE%0A%3E%0A%3E%20-%20update%0A%60%60%60java%0AtableName%3Auser_info%2CentryType%3AROWDATA%2CeventType%3AUPDATE%2CbeforeData%3A%7B%22id%22%3A%22002%22%2C%22name%22%3A%22John%22%2C%22sex%22%3A%22male%22%7D%2C%20afterData%3A%7B%22id%22%3A%22002%22%2C%22name%22%3A%22John-01%22%2C%22sex%22%3A%22male%22%7D%0AtableName%3Auser_info%2CentryType%3AROWDATA%2CeventType%3AUPDATE%2CbeforeData%3A%7B%22id%22%3A%22001%22%2C%22name%22%3A%22Chris%22%2C%22sex%22%3A%22male%22%7D%2C%20afterData%3A%7B%22id%22%3A%22001%22%2C%22name%22%3A%22Chris-01%22%2C%22sex%22%3A%22male%22%7D%0A%20%60%60%60%0A%3E%20-%20insert%0A%60%60%60java%0AtableName%3Auser_info%2CentryType%3AROWDATA%2CeventType%3AINSERT%2CbeforeData%3A%7B%7D%2C%20afterData%3A%7B%22id%22%3A%22003%22%2C%22name%22%3A%22Rose%22%2C%22sex%22%3A%22female%22%7D%0AtableName%3Auser_info%2CentryType%3AROWDATA%2CeventType%3AINSERT%2CbeforeData%3A%7B%7D%2C%20afterData%3A%7B%22id%22%3A%22004%22%2C%22name%22%3A%22Petter%22%2C%22sex%22%3A%22male%22%7D%0AtableName%3Auser_info%2CentryType%3AROWDATA%2CeventType%3AINSERT%2CbeforeData%3A%7B%7D%2C%20afterData%3A%7B%22id%22%3A%22005%22%2C%22name%22%3A%22Fiona%22%2C%22sex%22%3A%22female%22%7D%0A%60%60%60%20%0A%3E%20-%20delete%0A%20%60%60%60java%0AtableName%3Auser_info%2CentryType%3AROWDATA%2CeventType%3ADELETE%2CbeforeData%3A%7B%22id%22%3A%22002%22%2C%22name%22%3A%22John-01%22%2C%22sex%22%3A%22male%22%7D%2C%20afterData%3A%7B%7D%0AtableName%3Auser_info%2CentryType%3AROWDATA%2CeventType%3ADELETE%2CbeforeData%3A%7B%22id%22%3A%22003%22%2C%22name%22%3A%22Rose%22%2C%22sex%22%3A%22female%22%7D%2C%20afterData%3A%7B%7D%0A%60%60%60%0A%0A%0A%0A%0A%23%23%20MQ%0A%0A%0A%7C%20%E5%8F%82%E6%95%B0%E5%90%8D%20%7C%20%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E%20%7C%20%E9%BB%98%E8%AE%A4%E5%80%BC%20%7C%0A%7C%20---%20%7C%20---%20%7C%20---%20%7C%0A%7C%20canal.instance.filter.regex%20%7C%20%E8%BF%87%E6%BB%A4%E5%87%BA%E9%9C%80%E8%A6%81%E7%9B%91%E6%8E%A7%E7%9A%84%E8%A1%A8%20%7C%20%E6%97%A0%20%7C%0A%7C%20canal.instance.filter.black.regex%20%7C%20%E5%8A%A0%E5%85%A5%E9%BB%91%E5%90%8D%E5%8D%95%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E7%9B%91%E6%8E%A7%E7%9A%84%E8%A1%A8%20%20%7C%20%E6%97%A0%20%20%7C%0A%0A%3E%20canal%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%9C%A8instance.properties%E8%AE%BE%E7%BD%AE%60canal.instance.filter.regex%60%EF%BC%8C%E6%9D%A5%E5%BF%BD%E7%95%A5%E4%B8%8D%E5%85%B3%E5%BF%83%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E7%9A%84parse%E5%92%8Csink%E5%A4%84%E7%90%86%EF%BC%8C%E4%BC%98%E5%8C%96%E6%80%A7%E8%83%BD%EF%BC%8C%E5%90%8C%E6%97%B6%E5%87%8F%E5%B0%91%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E5%AD%98%E5%82%A8%E5%BC%80%E9%94%80%E3%80%82%0A%0A%3E%20canal%20instance%E5%90%AF%E5%8A%A8%E6%97%B6%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%8A%A0%E8%BD%BD%20%60instance.properties%60%20%E7%9A%84%60canal.instance.filter.regex%60%20%E5%8F%82%E6%95%B0%EF%BC%8C%E4%B9%8B%E5%90%8E%E4%BC%9A%E6%A0%B9%E6%8D%AEconf%2Fcanal%2Fmeta.dat%E6%96%87%E4%BB%B6filter%E5%80%BC%E6%9B%B4%E6%96%B0%E8%BF%87%E6%BB%A4%E8%A7%84%E5%88%99%E3%80%82%0A%E5%BD%93%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%B0%83%E7%94%A8%60CanalConnector.subscribe(String%20filter)%60%E6%96%B9%E6%B3%95%E6%97%B6%EF%BC%8Cinstance%E5%86%8D%E6%AC%A1%E7%94%A8filter%E5%8F%82%E6%95%B0%E6%9B%B4%E6%96%B0%E8%BF%87%E6%BB%A4%E8%A7%84%E5%88%99%E3%80%82meta.dat%E6%96%87%E4%BB%B6%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60json%0A%7B%0A%20%20%20%20%22clientDatas%22%3A%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22clientIdentity%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22clientId%22%3A1001%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22destination%22%3A%22hm-test%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22filter%22%3A%22xxx.*%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22cursor%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22identity%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22slaveId%22%3A-1%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22sourceAddress%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22address%22%3A%22xxxx%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22port%22%3A3306%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22postion%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22gtid%22%3A%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22included%22%3Afalse%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22journalName%22%3A%22mysql-bin.xxx%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22position%22%3Axxx%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22serverId%22%3Axxx%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22timestamp%22%3A1567062470000%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%2C%0A%20%20%20%20%22destination%22%3A%22hm-test%22%0A%7D%0A%60%60%60%0A%0A%0A%3E%20%E6%89%80%E4%BB%A5%E5%BD%93%E4%BD%A0%E5%8F%AA%E5%85%B3%E5%BF%83%E9%83%A8%E5%88%86%E5%BA%93%E8%A1%A8%E6%9B%B4%E6%96%B0%E6%97%B6%EF%BC%8C%E8%AE%BE%E7%BD%AE%E4%BA%86%60canal.instance.filter.regex%60%EF%BC%8C%E4%B8%80%E5%AE%9A%E4%B8%8D%E8%A6%81%E5%9C%A8%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%B0%83%20%60CanalConnector.subscribe(%22.%5C%E2%80%A6%22)%60%EF%BC%8C%E4%B8%8D%E7%84%B6%E7%AD%89%E4%BA%8E%E6%B2%A1%E8%AE%BE%E7%BD%AE%60canal.instance.filter.regex%60%E3%80%82%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E4%B8%80%E5%AE%9A%E8%A6%81%E8%B0%83%E7%94%A8%20%60CanalConnector.subscribe(%22.%5C%E2%80%A6%22)%60%EF%BC%8C%E9%82%A3%E4%B9%88%E5%8F%AF%E4%BB%A5%E8%AE%BE%E7%BD%AE%60instance.properties%60%E7%9A%84%60canal.instance.filter.black.regex%60%20%E5%8F%82%E6%95%B0%E6%B7%BB%E5%8A%A0%E9%BB%91%E5%90%8D%E5%8D%95%EF%BC%8C%E8%BF%87%E6%BB%A4%E9%9D%9E%E5%85%B3%E6%B3%A8%E5%BA%93%E8%A1%A8%E3%80%82

循环重试@Retryable

创建时间:2022/4/11 15:30
更新时间:2022/4/11 22:03
作者:Chris

是什么

spring系列的spring-retry是另一个实用程序模块,可以帮助我们以标准方式处理任何特定操作的重试。
在spring-retry中,所有配置都是基于简单注释的。

能干什么

在实际工作中,重处理是一个非常常见的场景,比如:

  • 发送消息失败。
  • 调用远程服务失败。
  • 争抢锁失败。

这些错误可能是因为网络波动造成的,等待过后重处理就能成功。通常来说,会用try/catch,while循环之类的语法来进行重处理,但是这样的做法缺乏统一性,并且不是很方便,要多写很多代码。
然而spring-retry却可以通过注解,在不入侵原有业务逻辑代码的方式下,优雅的实现重处理功能。

import com.mail.elegant.service.TestRetryService;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import java.time.LocalTime;
 
@Service
public class TestRetryServiceImpl implements TestRetryService {
    @Override
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 2))
    public int test(int code) throws Exception{
        System.out.println("test被调用,时间:"+ LocalTime.now());
          if (code==0){
              throw new Exception("情况不对头!");
          }
        System.out.println("test被调用,情况对头了!");
        return 200;
    }
}

使用步骤

POM依赖

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
</dependency>

启用@Retryable

@EnableRetry
@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

在方法上添加@Retryable

import com.mail.elegant.service.TestRetryService;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import java.time.LocalTime;
 
@Service
public class TestRetryServiceImpl implements TestRetryService {
    @Override
    @Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 3000, multiplier = 1.5))
    public int test(int code) throws Exception{
        System.out.println("test被调用,时间:"+ LocalTime.now());
          if (code==0){
              throw new Exception("情况不对头!");
          }
        System.out.println("test被调用,情况对头了!");
 
        return 200;
    }
}

value:抛出指定异常才会重试
include:和value一样,默认为空,当exclude也为空时,默认所有异常
exclude:指定不处理的异常
maxAttempts:最大重试次数,默认3次
backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000,我们设置为3000;
multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为2,则第一次重试为3秒,第二次为6秒,第三次为12秒。

test被调用,时间:21:34:18.402
test被调用,时间:21:34:21.404
test被调用,时间:21:34:27.420
test被调用,时间:21:34:39.432
test被调用,时间:21:35:03.444

重试耗尽

当重试耗尽时还是失败,会出现什么情况呢?
当重试耗尽时,RetryOperations 可以将控制传递给另一个回调,即RecoveryCallback
Spring-Retry还提供了@Recover 注解,用于@Retryable重试失败后处理方法。如果不需要回调方法,可以直接不写回调方法,那么实现的效果是,重试次数完了后,如果还是没成功没符合业务判断,就抛出异常。

@Recover
public int recover(Exception e, int code){
   System.out.println("回调方法执行!!!!");
   //记日志到数据库 或者调用其余的方法
    return 400;
}

可以看到传参里面写的是 Exception e,这个是作为回调的接头暗号(重试次数用完了,还是失败,我们抛出这个Exception e通知触发这个回调方法)。

对于@Recover注解的方法,需要特别注意的是:

  • 方法的返回值必须与@Retryable方法一致
  • 方法的第一个参数,必须是Throwable类型的,建议是与@Retryable配置的异常一致,其他的参数,需要哪个参数,写进去就可以了(@Recover方法中有的)
  • 该回调方法与重试方法写在同一个实现类里面

注意事项

由于是基于AOP实现,所以不支持类里自调用方法 , 在注解中配置 recover ="recover"没用

@Retryable(value = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 2000, multiplier = 1), recover =  "recover")

如果重试失败需要给@Recover注解的方法做后续处理,那这个重试的方法不能有返回值,只能是void
方法内不能使用try catch,只能往外抛异常
@Recover 注解来开启重试失败后调用的方法(注意,需跟重处理方法在同一个类中),此注解注释的方法参数一定要是@Retryable抛出的异常,否则无法识别,可以在该方法中进行日志处理。

%5Btoc%5D%0A%23%23%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20spring%E7%B3%BB%E5%88%97%E7%9A%84spring-retry%E6%98%AF%E5%8F%A6%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%94%A8%E7%A8%8B%E5%BA%8F%E6%A8%A1%E5%9D%97%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%B8%AE%E5%8A%A9%E6%88%91%E4%BB%AC%E4%BB%A5%E6%A0%87%E5%87%86%E6%96%B9%E5%BC%8F%E5%A4%84%E7%90%86%E4%BB%BB%E4%BD%95%E7%89%B9%E5%AE%9A%E6%93%8D%E4%BD%9C%E7%9A%84%E9%87%8D%E8%AF%95%E3%80%82%0A%3E%20%E5%9C%A8spring-retry%E4%B8%AD%EF%BC%8C%E6%89%80%E6%9C%89%E9%85%8D%E7%BD%AE%E9%83%BD%E6%98%AF%E5%9F%BA%E4%BA%8E%E7%AE%80%E5%8D%95%E6%B3%A8%E9%87%8A%E7%9A%84%E3%80%82%0A%0A%23%23%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%3E%20%E5%9C%A8%E5%AE%9E%E9%99%85%E5%B7%A5%E4%BD%9C%E4%B8%AD%EF%BC%8C%E9%87%8D%E5%A4%84%E7%90%86%E6%98%AF%E4%B8%80%E4%B8%AA%E9%9D%9E%E5%B8%B8%E5%B8%B8%E8%A7%81%E7%9A%84%E5%9C%BA%E6%99%AF%EF%BC%8C%E6%AF%94%E5%A6%82%3A%0A%3E%20-%20%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E5%A4%B1%E8%B4%A5%E3%80%82%0A%3E%20-%20%E8%B0%83%E7%94%A8%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%A4%B1%E8%B4%A5%E3%80%82%0A%3E%20-%20%E4%BA%89%E6%8A%A2%E9%94%81%E5%A4%B1%E8%B4%A5%E3%80%82%0A%3E%20%0A%3E%20%E8%BF%99%E4%BA%9B%E9%94%99%E8%AF%AF%E5%8F%AF%E8%83%BD%E6%98%AF%E5%9B%A0%E4%B8%BA%E7%BD%91%E7%BB%9C%E6%B3%A2%E5%8A%A8%E9%80%A0%E6%88%90%E7%9A%84%EF%BC%8C%E7%AD%89%E5%BE%85%E8%BF%87%E5%90%8E%E9%87%8D%E5%A4%84%E7%90%86%E5%B0%B1%E8%83%BD%E6%88%90%E5%8A%9F%E3%80%82%E9%80%9A%E5%B8%B8%E6%9D%A5%E8%AF%B4%EF%BC%8C%E4%BC%9A%E7%94%A8try%2Fcatch%EF%BC%8Cwhile%E5%BE%AA%E7%8E%AF%E4%B9%8B%E7%B1%BB%E7%9A%84%E8%AF%AD%E6%B3%95%E6%9D%A5%E8%BF%9B%E8%A1%8C%E9%87%8D%E5%A4%84%E7%90%86%EF%BC%8C%E4%BD%86%E6%98%AF%E8%BF%99%E6%A0%B7%E7%9A%84%E5%81%9A%E6%B3%95%E7%BC%BA%E4%B9%8F%E7%BB%9F%E4%B8%80%E6%80%A7%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%B8%8D%E6%98%AF%E5%BE%88%E6%96%B9%E4%BE%BF%EF%BC%8C%E8%A6%81%E5%A4%9A%E5%86%99%E5%BE%88%E5%A4%9A%E4%BB%A3%E7%A0%81%E3%80%82%0A%3E%20%E7%84%B6%E8%80%8Cspring-retry%E5%8D%B4%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%9C%A8%E4%B8%8D%E5%85%A5%E4%BE%B5%E5%8E%9F%E6%9C%89%E4%B8%9A%E5%8A%A1%E9%80%BB%E8%BE%91%E4%BB%A3%E7%A0%81%E7%9A%84%E6%96%B9%E5%BC%8F%E4%B8%8B%EF%BC%8C%E4%BC%98%E9%9B%85%E7%9A%84%E5%AE%9E%E7%8E%B0%E9%87%8D%E5%A4%84%E7%90%86%E5%8A%9F%E8%83%BD%E3%80%82%0A%0A%60%60%60java%0Aimport%20com.mail.elegant.service.TestRetryService%3B%0Aimport%20org.springframework.retry.annotation.Backoff%3B%0Aimport%20org.springframework.retry.annotation.Retryable%3B%0Aimport%20org.springframework.stereotype.Service%3B%0Aimport%20java.time.LocalTime%3B%0A%20%0A%40Service%0Apublic%20class%20TestRetryServiceImpl%20implements%20TestRetryService%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20%40Retryable(value%20%3D%20Exception.class%2C%20maxAttempts%20%3D%203%2C%20backoff%20%3D%20%40Backoff(delay%20%3D%202000%2Cmultiplier%20%3D%202))%0A%20%20%20%20public%20int%20test(int%20code)%20throws%20Exception%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22test%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%97%B6%E9%97%B4%EF%BC%9A%22%2B%20LocalTime.now())%3B%0A%20%20%20%20%20%20%20%20%20%20if%20(code%3D%3D0)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Exception(%22%E6%83%85%E5%86%B5%E4%B8%8D%E5%AF%B9%E5%A4%B4%EF%BC%81%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20System.out.println(%22test%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%83%85%E5%86%B5%E5%AF%B9%E5%A4%B4%E4%BA%86%EF%BC%81%22)%3B%0A%20%20%20%20%20%20%20%20return%20200%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%20%E4%BD%BF%E7%94%A8%E6%AD%A5%E9%AA%A4%0A%3E%20POM%E4%BE%9D%E8%B5%96%0A%60%60%60xml%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Eorg.springframework.retry%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Espring-retry%3C%2FartifactId%3E%0A%3C%2Fdependency%3E%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Eorg.springframework%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Espring-aspects%3C%2FartifactId%3E%0A%3C%2Fdependency%3E%0A%60%60%60%0A%0A%0A%3E%20%E5%90%AF%E7%94%A8%40Retryable%0A%60%60%60java%0A%40EnableRetry%0A%40SpringBootApplication%0Apublic%C2%A0class%C2%A0HelloApplication%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0public%C2%A0static%C2%A0void%C2%A0main(String%5B%5D%C2%A0args)%C2%A0%7B%0A%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0SpringApplication.run(HelloApplication.class%2C%C2%A0args)%3B%0A%C2%A0%C2%A0%C2%A0%C2%A0%7D%0A%7D%0A%60%60%60%0A%3E%20%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%8A%E6%B7%BB%E5%8A%A0%40Retryable%0A%60%60%60java%0Aimport%20com.mail.elegant.service.TestRetryService%3B%0Aimport%20org.springframework.retry.annotation.Backoff%3B%0Aimport%20org.springframework.retry.annotation.Retryable%3B%0Aimport%20org.springframework.stereotype.Service%3B%0Aimport%20java.time.LocalTime%3B%0A%20%0A%40Service%0Apublic%20class%20TestRetryServiceImpl%20implements%20TestRetryService%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20%40Retryable(value%20%3D%20Exception.class%2C%20maxAttempts%20%3D%203%2Cbackoff%20%3D%20%40Backoff(delay%20%3D%203000%2C%20multiplier%20%3D%201.5))%0A%20%20%20%20public%20int%20test(int%20code)%20throws%20Exception%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22test%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%97%B6%E9%97%B4%EF%BC%9A%22%2B%20LocalTime.now())%3B%0A%20%20%20%20%20%20%20%20%20%20if%20(code%3D%3D0)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Exception(%22%E6%83%85%E5%86%B5%E4%B8%8D%E5%AF%B9%E5%A4%B4%EF%BC%81%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20System.out.println(%22test%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%83%85%E5%86%B5%E5%AF%B9%E5%A4%B4%E4%BA%86%EF%BC%81%22)%3B%0A%20%0A%20%20%20%20%20%20%20%20return%20200%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%60value%60%EF%BC%9A%E6%8A%9B%E5%87%BA%E6%8C%87%E5%AE%9A%E5%BC%82%E5%B8%B8%E6%89%8D%E4%BC%9A%E9%87%8D%E8%AF%95%0A%3E%20%60include%60%EF%BC%9A%E5%92%8Cvalue%E4%B8%80%E6%A0%B7%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA%E7%A9%BA%EF%BC%8C%E5%BD%93exclude%E4%B9%9F%E4%B8%BA%E7%A9%BA%E6%97%B6%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%89%80%E6%9C%89%E5%BC%82%E5%B8%B8%0A%3E%20%60exclude%60%EF%BC%9A%E6%8C%87%E5%AE%9A%E4%B8%8D%E5%A4%84%E7%90%86%E7%9A%84%E5%BC%82%E5%B8%B8%0A%3E%20%60maxAttempts%60%EF%BC%9A%E6%9C%80%E5%A4%A7%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%EF%BC%8C%E9%BB%98%E8%AE%A43%E6%AC%A1%0A%3E%20%60backoff%60%EF%BC%9A%E9%87%8D%E8%AF%95%E7%AD%89%E5%BE%85%E7%AD%96%E7%95%A5%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%BD%BF%E7%94%A8%40Backoff%EF%BC%8C%40Backoff%E7%9A%84value%E9%BB%98%E8%AE%A4%E4%B8%BA1000%EF%BC%8C%E6%88%91%E4%BB%AC%E8%AE%BE%E7%BD%AE%E4%B8%BA3000%EF%BC%9B%0A%3E%20%60multiplier%60%EF%BC%88%E6%8C%87%E5%AE%9A%E5%BB%B6%E8%BF%9F%E5%80%8D%E6%95%B0%EF%BC%89%E9%BB%98%E8%AE%A4%E4%B8%BA0%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%9B%BA%E5%AE%9A%E6%9A%82%E5%81%9C1%E7%A7%92%E5%90%8E%E8%BF%9B%E8%A1%8C%E9%87%8D%E8%AF%95%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%8A%8Amultiplier%E8%AE%BE%E7%BD%AE%E4%B8%BA2%EF%BC%8C%E5%88%99%E7%AC%AC%E4%B8%80%E6%AC%A1%E9%87%8D%E8%AF%95%E4%B8%BA3%E7%A7%92%EF%BC%8C%E7%AC%AC%E4%BA%8C%E6%AC%A1%E4%B8%BA6%E7%A7%92%EF%BC%8C%E7%AC%AC%E4%B8%89%E6%AC%A1%E4%B8%BA12%E7%A7%92%E3%80%82%0A%60%60%60%0Atest%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%97%B6%E9%97%B4%EF%BC%9A21%3A34%3A18.402%0Atest%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%97%B6%E9%97%B4%EF%BC%9A21%3A34%3A21.404%0Atest%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%97%B6%E9%97%B4%EF%BC%9A21%3A34%3A27.420%0Atest%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%97%B6%E9%97%B4%EF%BC%9A21%3A34%3A39.432%0Atest%E8%A2%AB%E8%B0%83%E7%94%A8%2C%E6%97%B6%E9%97%B4%EF%BC%9A21%3A35%3A03.444%0A%60%60%60%0A%0A%23%23%20%E9%87%8D%E8%AF%95%E8%80%97%E5%B0%BD%0A%3E%20%E5%BD%93%E9%87%8D%E8%AF%95%E8%80%97%E5%B0%BD%E6%97%B6%E8%BF%98%E6%98%AF%E5%A4%B1%E8%B4%A5%EF%BC%8C%E4%BC%9A%E5%87%BA%E7%8E%B0%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%E5%91%A2%EF%BC%9F%0A%3E%20%E5%BD%93%E9%87%8D%E8%AF%95%E8%80%97%E5%B0%BD%E6%97%B6%EF%BC%8C%60RetryOperations%60%20%E5%8F%AF%E4%BB%A5%E5%B0%86%E6%8E%A7%E5%88%B6%E4%BC%A0%E9%80%92%E7%BB%99%E5%8F%A6%E4%B8%80%E4%B8%AA%E5%9B%9E%E8%B0%83%EF%BC%8C%E5%8D%B3%60RecoveryCallback%60%E3%80%82%0A%3E%20Spring-Retry%E8%BF%98%E6%8F%90%E4%BE%9B%E4%BA%86%60%40Recover%60%20%E6%B3%A8%E8%A7%A3%EF%BC%8C%E7%94%A8%E4%BA%8E%40Retryable%E9%87%8D%E8%AF%95%E5%A4%B1%E8%B4%A5%E5%90%8E%E5%A4%84%E7%90%86%E6%96%B9%E6%B3%95%E3%80%82%E5%A6%82%E6%9E%9C%E4%B8%8D%E9%9C%80%E8%A6%81%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E4%B8%8D%E5%86%99%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%EF%BC%8C%E9%82%A3%E4%B9%88%E5%AE%9E%E7%8E%B0%E7%9A%84%E6%95%88%E6%9E%9C%E6%98%AF%EF%BC%8C%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%E5%AE%8C%E4%BA%86%E5%90%8E%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%98%E6%98%AF%E6%B2%A1%E6%88%90%E5%8A%9F%E6%B2%A1%E7%AC%A6%E5%90%88%E4%B8%9A%E5%8A%A1%E5%88%A4%E6%96%AD%EF%BC%8C%E5%B0%B1%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E3%80%82%0A%0A%60%60%60java%0A%40Recover%0Apublic%C2%A0int%C2%A0recover(Exception%C2%A0e%2C%C2%A0int%C2%A0code)%7B%0A%C2%A0%C2%A0%C2%A0System.out.println(%22%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%EF%BC%81%EF%BC%81%EF%BC%81%EF%BC%81%22)%3B%0A%C2%A0%C2%A0%C2%A0%2F%2F%E8%AE%B0%E6%97%A5%E5%BF%97%E5%88%B0%E6%95%B0%E6%8D%AE%E5%BA%93%C2%A0%E6%88%96%E8%80%85%E8%B0%83%E7%94%A8%E5%85%B6%E4%BD%99%E7%9A%84%E6%96%B9%E6%B3%95%0A%C2%A0%C2%A0%C2%A0%C2%A0return%C2%A0400%3B%0A%7D%0A%60%60%60%0A%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E4%BC%A0%E5%8F%82%E9%87%8C%E9%9D%A2%E5%86%99%E7%9A%84%E6%98%AF%20Exception%20e%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%98%AF%E4%BD%9C%E4%B8%BA%E5%9B%9E%E8%B0%83%E7%9A%84%E6%8E%A5%E5%A4%B4%E6%9A%97%E5%8F%B7%EF%BC%88%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%E7%94%A8%E5%AE%8C%E4%BA%86%EF%BC%8C%E8%BF%98%E6%98%AF%E5%A4%B1%E8%B4%A5%EF%BC%8C%E6%88%91%E4%BB%AC%E6%8A%9B%E5%87%BA%E8%BF%99%E4%B8%AAException%20e%E9%80%9A%E7%9F%A5%E8%A7%A6%E5%8F%91%E8%BF%99%E4%B8%AA%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%EF%BC%89%E3%80%82%0A%0A%E5%AF%B9%E4%BA%8E%40Recover%E6%B3%A8%E8%A7%A3%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E9%9C%80%E8%A6%81%E7%89%B9%E5%88%AB%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%EF%BC%9A%0A%3E%20-%20%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E5%BF%85%E9%A1%BB%E4%B8%8E%40Retryable%E6%96%B9%E6%B3%95%E4%B8%80%E8%87%B4%0A%3E%20-%20%E6%96%B9%E6%B3%95%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%BF%85%E9%A1%BB%E6%98%AFThrowable%E7%B1%BB%E5%9E%8B%E7%9A%84%EF%BC%8C%E5%BB%BA%E8%AE%AE%E6%98%AF%E4%B8%8E%40Retryable%E9%85%8D%E7%BD%AE%E7%9A%84%E5%BC%82%E5%B8%B8%E4%B8%80%E8%87%B4%EF%BC%8C%E5%85%B6%E4%BB%96%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%8C%E9%9C%80%E8%A6%81%E5%93%AA%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%86%99%E8%BF%9B%E5%8E%BB%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BA%86%EF%BC%88%40Recover%E6%96%B9%E6%B3%95%E4%B8%AD%E6%9C%89%E7%9A%84%EF%BC%89%0A%3E%20-%20%E8%AF%A5%E5%9B%9E%E8%B0%83%E6%96%B9%E6%B3%95%E4%B8%8E%E9%87%8D%E8%AF%95%E6%96%B9%E6%B3%95%E5%86%99%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%B1%BB%E9%87%8C%E9%9D%A2%0A%0A%0A%0A%23%23%20%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9%0A%3E%20%E7%94%B1%E4%BA%8E%E6%98%AF%E5%9F%BA%E4%BA%8EAOP%E5%AE%9E%E7%8E%B0%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%8D%E6%94%AF%E6%8C%81%E7%B1%BB%E9%87%8C%E8%87%AA%E8%B0%83%E7%94%A8%E6%96%B9%E6%B3%95%20%2C%20%E5%9C%A8%E6%B3%A8%E8%A7%A3%E4%B8%AD%E9%85%8D%E7%BD%AE%20%60recover%20%3D%22recover%22%60%E6%B2%A1%E7%94%A8%0A%3E%20%0A%60%60%60java%0A%40Retryable(value%20%3D%20Exception.class%2C%20maxAttempts%20%3D%205%2C%20backoff%20%3D%20%40Backoff(delay%20%3D%202000%2C%20multiplier%20%3D%201)%2C%20recover%20%3D%C2%A0%20%22recover%22)%0A%60%60%60%0A%3E%20%E5%A6%82%E6%9E%9C%E9%87%8D%E8%AF%95%E5%A4%B1%E8%B4%A5%E9%9C%80%E8%A6%81%E7%BB%99%40Recover%E6%B3%A8%E8%A7%A3%E7%9A%84%E6%96%B9%E6%B3%95%E5%81%9A%E5%90%8E%E7%BB%AD%E5%A4%84%E7%90%86%EF%BC%8C%E9%82%A3%E8%BF%99%E4%B8%AA%E9%87%8D%E8%AF%95%E7%9A%84%E6%96%B9%E6%B3%95%E4%B8%8D%E8%83%BD%E6%9C%89%E8%BF%94%E5%9B%9E%E5%80%BC%EF%BC%8C%E5%8F%AA%E8%83%BD%E6%98%AFvoid%0A%3E%20%E6%96%B9%E6%B3%95%E5%86%85%E4%B8%8D%E8%83%BD%E4%BD%BF%E7%94%A8try%20catch%EF%BC%8C%E5%8F%AA%E8%83%BD%E5%BE%80%E5%A4%96%E6%8A%9B%E5%BC%82%E5%B8%B8%0A%3E%20%40Recover%20%E6%B3%A8%E8%A7%A3%E6%9D%A5%E5%BC%80%E5%90%AF%E9%87%8D%E8%AF%95%E5%A4%B1%E8%B4%A5%E5%90%8E%E8%B0%83%E7%94%A8%E7%9A%84%E6%96%B9%E6%B3%95(%E6%B3%A8%E6%84%8F%2C%E9%9C%80%E8%B7%9F%E9%87%8D%E5%A4%84%E7%90%86%E6%96%B9%E6%B3%95%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%AD)%EF%BC%8C%E6%AD%A4%E6%B3%A8%E8%A7%A3%E6%B3%A8%E9%87%8A%E7%9A%84%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E4%B8%80%E5%AE%9A%E8%A6%81%E6%98%AF%40Retryable%E6%8A%9B%E5%87%BA%E7%9A%84%E5%BC%82%E5%B8%B8%EF%BC%8C%E5%90%A6%E5%88%99%E6%97%A0%E6%B3%95%E8%AF%86%E5%88%AB%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%AF%A5%E6%96%B9%E6%B3%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E6%97%A5%E5%BF%97%E5%A4%84%E7%90%86%E3%80%82%0A%0A

拦截器

创建时间:2022/2/20 15:59
更新时间:2022/4/11 9:44
作者:Chris

1 是什么

拦截器是spring中的概念,和过滤器类似,可以对用户的请求进行拦截处理。
但是相对于过滤器而言,拦截器要控制的更加细节
拦截器可以在三个地方执行:

2 能干什么

拦截器本质上是AOP,符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景如下:

  • 登录验证,判断用户是否登录
  • 权限验证,判断用户是否有权限访问资源,如校验token
  • 日志记录,记录请求操作日志,用户IP,访问时间,方法签名等
  • 处理cookie,本地化,国际化,主题等
  • 性能监控,监控请求处理时长等。

3 与过滤器的区别

  1. 过滤器只能在容器初始化时被调用一次,在action的生命周期中,拦截器可以被多次调用
  2. 过滤器可以对几乎所有的请求起作用,而拦截器只对action请求起作用
  3. 过滤器不能访问action上下文,堆栈中的对象,而拦截器可以访问
  4. 过滤器依赖于servlet容器,而拦截器不依赖于servlet容器
  5. 过滤器是基于函数回调,而拦截器是基于java的反射机制的。
  6. 过滤器不能获取IOC中的bean,而拦截器可以,这点很重要,在拦截器中注入一个service可以调用业务逻辑
  7. 拦截器是在DispatcherServlet这个servlet中执行的,因此所有的请求最先进入Filter,最后离开Filter, 其顺序如下:
Filter -> Interceptor.preHandler -> Handler -> Interceptor.postHandle -> Interceptor.afterCompletion -> Filter

4 怎么玩

  1. 实现HandlerInterceptor接口并将实现类注入到spring容器中
  2. 实现WebMvcConfigurer配置器接口,添加拦截路径和放行路径,并把实现类注入到spring容器中

4.1 单个拦截器

4.1.1 Controller
@RestController
@RequestMapping("/error")
@Slf4j
public class ErrorController {

    @GetMapping("/showError")
    public String showError() {
        log.info("ErrorController.showError executed");
        return "the error happended";
    }
}

@RestController
@RequestMapping("/hello")
@Slf4j
public class HelloController {

    @GetMapping("/sayHello")
    public String sayHello() {
        log.info("HelloController.sayHello executed");
        return "hello My HandlerInterceptor";
    }
}

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @GetMapping("/getUserInfo/{userName}")
    public String sayHello(@PathVariable("userName") String userName) {
        log.info("UserController.getUserInfo executed");
        return userName;
    }
}
4.1.2 自定义拦截器
@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {

    /**
     * 前置处理,可以中断请求继续
     * true  请求继续
     * false 中断请求
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("begin myInterceptor");
        return true;
    }

    /**
     * 后置处理,即afterReturning通知
     * 在controller执行之后,能过拦截器执行一段代码,此时只是controller很乖完毕,视图还没有渲染
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        log.info("controller has executed");
    }

    /**
     * 整个请求结束后执行
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                Exception ex) throws Exception {
        log.info("response result:{}", JSONUtil.toJsonStr(response));
        log.info("request done");
    }
}
4.1.3 注册拦截器
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Autowired
    MyInterceptor myInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor).addPathPatterns("/hello/*").excludePathPatterns("/error/*");
    }
}

http://localhost:8081/hello/sayHello
http://localhost:8081/error/showError

4.2 多拦截器

4.2.1 注册拦截器
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Autowired
    MyInterceptor1 myInterceptor1;

    @Autowired
    MyInterceptor2 myInterceptor2;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor1).addPathPatterns("/hello/*").excludePathPatterns("/error/*");
        registry.addInterceptor(myInterceptor2).addPathPatterns("/hello/*", "/user/**").excludePathPatterns("/error/*");
    }
}

http://localhost:8081/hello/sayHello

修改MyInterceptor2的preHandle,返回false

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    log.info("MyInterceptor2 preHandle: begin myInterceptor");
    return false;
}

http://localhost:8081/hello/sayHello

4.2.2 拦截器执行顺序

4.3 设置多拦截器顺序

多个拦截器的执行顺序和注册顺序有关,先注册先执行
可以通过Order方法来设置执行的顺序,值越小越先执行

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(myInterceptor1).addPathPatterns("/hello/*").excludePathPatterns("/error/*").order(2);
    registry.addInterceptor(myInterceptor2).addPathPatterns("/hello/*", "/user/**").excludePathPatterns("/error" + "/*").order(1);
}

%5Btoc%5D%0A%0A%23%23%201%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20%E6%8B%A6%E6%88%AA%E5%99%A8%E6%98%AFspring%E4%B8%AD%E7%9A%84%E6%A6%82%E5%BF%B5%EF%BC%8C%E5%92%8C%E8%BF%87%E6%BB%A4%E5%99%A8%E7%B1%BB%E4%BC%BC%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%AF%B9%E7%94%A8%E6%88%B7%E7%9A%84%E8%AF%B7%E6%B1%82%E8%BF%9B%E8%A1%8C%E6%8B%A6%E6%88%AA%E5%A4%84%E7%90%86%E3%80%82%20%20%0A%3E%20%E4%BD%86%E6%98%AF%E7%9B%B8%E5%AF%B9%E4%BA%8E%E8%BF%87%E6%BB%A4%E5%99%A8%E8%80%8C%E8%A8%80%EF%BC%8C%E6%8B%A6%E6%88%AA%E5%99%A8%E8%A6%81%E6%8E%A7%E5%88%B6%E7%9A%84%E6%9B%B4%E5%8A%A0%E7%BB%86%E8%8A%82%0A%3E%20%E6%8B%A6%E6%88%AA%E5%99%A8%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%B8%89%E4%B8%AA%E5%9C%B0%E6%96%B9%E6%89%A7%E8%A1%8C%EF%BC%9A%0A-%201.%20%E8%AF%B7%E6%B1%82%E5%88%B0%E8%BE%BEcontroller%E4%B9%8B%E5%89%8D%EF%BC%8C%E9%80%9A%E8%BF%87%E6%8B%A6%E6%88%AA%E5%99%A8%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AE%B5%E4%BB%A3%E7%A0%81%0A-%202.%20%E5%8F%AF%E4%BB%A5%E5%9C%A8controller%E6%89%A7%E8%A1%8C%E4%B9%8B%E5%90%8E%EF%BC%8C%E8%83%BD%E8%BF%87%E6%8B%A6%E6%88%AA%E5%99%A8%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AE%B5%E4%BB%A3%E7%A0%81%EF%BC%8C%E6%AD%A4%E6%97%B6%E5%8F%AA%E6%98%AFcontroller%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%EF%BC%8C%E8%A7%86%E5%9B%BE%E8%BF%98%E6%B2%A1%E6%9C%89%E6%B8%B2%E6%9F%93%0A-%203.%20%E6%9C%80%E5%90%8E%E5%9C%A8%E6%95%B4%E4%B8%AA%E8%AF%B7%E6%B1%82%E7%BB%93%E6%9D%9F%E6%97%B6%E8%BF%98%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E6%8B%A6%E6%88%AA%E5%99%A8%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AE%B5%E4%BB%A3%E7%A0%81%0A%0A%0A%23%23%202%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%3E%20%E6%8B%A6%E6%88%AA%E5%99%A8%E6%9C%AC%E8%B4%A8%E4%B8%8A%E6%98%AFAOP%EF%BC%8C%E7%AC%A6%E5%90%88%E6%A8%AA%E5%88%87%E5%85%B3%E6%B3%A8%E7%82%B9%E7%9A%84%E5%8A%9F%E8%83%BD%E9%83%BD%E5%8F%AF%E4%BB%A5%E6%94%BE%E5%9C%A8%E6%8B%A6%E6%88%AA%E5%99%A8%E4%B8%AD%E6%9D%A5%E5%AE%9E%E7%8E%B0%EF%BC%8C%E4%B8%BB%E8%A6%81%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%3E%20-%20%E7%99%BB%E5%BD%95%E9%AA%8C%E8%AF%81%EF%BC%8C%E5%88%A4%E6%96%AD%E7%94%A8%E6%88%B7%E6%98%AF%E5%90%A6%E7%99%BB%E5%BD%95%0A%3E%20-%20%E6%9D%83%E9%99%90%E9%AA%8C%E8%AF%81%EF%BC%8C%E5%88%A4%E6%96%AD%E7%94%A8%E6%88%B7%E6%98%AF%E5%90%A6%E6%9C%89%E6%9D%83%E9%99%90%E8%AE%BF%E9%97%AE%E8%B5%84%E6%BA%90%EF%BC%8C%E5%A6%82%E6%A0%A1%E9%AA%8Ctoken%0A%3E%20-%20%E6%97%A5%E5%BF%97%E8%AE%B0%E5%BD%95%EF%BC%8C%E8%AE%B0%E5%BD%95%E8%AF%B7%E6%B1%82%E6%93%8D%E4%BD%9C%E6%97%A5%E5%BF%97%EF%BC%8C%E7%94%A8%E6%88%B7IP%EF%BC%8C%E8%AE%BF%E9%97%AE%E6%97%B6%E9%97%B4%EF%BC%8C%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D%E7%AD%89%0A%3E%20-%20%E5%A4%84%E7%90%86cookie%EF%BC%8C%E6%9C%AC%E5%9C%B0%E5%8C%96%EF%BC%8C%E5%9B%BD%E9%99%85%E5%8C%96%EF%BC%8C%E4%B8%BB%E9%A2%98%E7%AD%89%0A%3E%20-%20%E6%80%A7%E8%83%BD%E7%9B%91%E6%8E%A7%EF%BC%8C%E7%9B%91%E6%8E%A7%E8%AF%B7%E6%B1%82%E5%A4%84%E7%90%86%E6%97%B6%E9%95%BF%E7%AD%89%E3%80%82%0A%0A%0A%23%23%203%20%E4%B8%8E%E8%BF%87%E6%BB%A4%E5%99%A8%E7%9A%84%E5%8C%BA%E5%88%AB%0A%3E%201.%20%E8%BF%87%E6%BB%A4%E5%99%A8%E5%8F%AA%E8%83%BD%E5%9C%A8%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%E8%A2%AB%E8%B0%83%E7%94%A8%E4%B8%80%E6%AC%A1%EF%BC%8C%E5%9C%A8action%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E4%B8%AD%EF%BC%8C%E6%8B%A6%E6%88%AA%E5%99%A8%E5%8F%AF%E4%BB%A5%E8%A2%AB%E5%A4%9A%E6%AC%A1%E8%B0%83%E7%94%A8%0A%3E%202.%20%E8%BF%87%E6%BB%A4%E5%99%A8%E5%8F%AF%E4%BB%A5%E5%AF%B9%E5%87%A0%E4%B9%8E%E6%89%80%E6%9C%89%E7%9A%84%E8%AF%B7%E6%B1%82%E8%B5%B7%E4%BD%9C%E7%94%A8%EF%BC%8C%E8%80%8C%E6%8B%A6%E6%88%AA%E5%99%A8%E5%8F%AA%E5%AF%B9action%E8%AF%B7%E6%B1%82%E8%B5%B7%E4%BD%9C%E7%94%A8%0A%3E%203.%20%E8%BF%87%E6%BB%A4%E5%99%A8%E4%B8%8D%E8%83%BD%E8%AE%BF%E9%97%AEaction%E4%B8%8A%E4%B8%8B%E6%96%87%EF%BC%8C%E5%A0%86%E6%A0%88%E4%B8%AD%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%80%8C%E6%8B%A6%E6%88%AA%E5%99%A8%E5%8F%AF%E4%BB%A5%E8%AE%BF%E9%97%AE%0A%3E%204.%20%E8%BF%87%E6%BB%A4%E5%99%A8%E4%BE%9D%E8%B5%96%E4%BA%8Eservlet%E5%AE%B9%E5%99%A8%EF%BC%8C%E8%80%8C%E6%8B%A6%E6%88%AA%E5%99%A8%E4%B8%8D%E4%BE%9D%E8%B5%96%E4%BA%8Eservlet%E5%AE%B9%E5%99%A8%0A%3E%205.%20%E8%BF%87%E6%BB%A4%E5%99%A8%E6%98%AF%E5%9F%BA%E4%BA%8E%E5%87%BD%E6%95%B0%E5%9B%9E%E8%B0%83%EF%BC%8C%E8%80%8C%E6%8B%A6%E6%88%AA%E5%99%A8%E6%98%AF%E5%9F%BA%E4%BA%8Ejava%E7%9A%84%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6%E7%9A%84%E3%80%82%0A%3E%206.%20%E8%BF%87%E6%BB%A4%E5%99%A8%E4%B8%8D%E8%83%BD%E8%8E%B7%E5%8F%96IOC%E4%B8%AD%E7%9A%84bean%EF%BC%8C%E8%80%8C%E6%8B%A6%E6%88%AA%E5%99%A8%E5%8F%AF%E4%BB%A5%EF%BC%8C%E8%BF%99%E7%82%B9%E5%BE%88%E9%87%8D%E8%A6%81%EF%BC%8C%E5%9C%A8%E6%8B%A6%E6%88%AA%E5%99%A8%E4%B8%AD%E6%B3%A8%E5%85%A5%E4%B8%80%E4%B8%AAservice%E5%8F%AF%E4%BB%A5%E8%B0%83%E7%94%A8%E4%B8%9A%E5%8A%A1%E9%80%BB%E8%BE%91%0A%3E%207.%20%E6%8B%A6%E6%88%AA%E5%99%A8%E6%98%AF%E5%9C%A8DispatcherServlet%E8%BF%99%E4%B8%AAservlet%E4%B8%AD%E6%89%A7%E8%A1%8C%E7%9A%84%EF%BC%8C%E5%9B%A0%E6%AD%A4%E6%89%80%E6%9C%89%E7%9A%84%E8%AF%B7%E6%B1%82%E6%9C%80%E5%85%88%E8%BF%9B%E5%85%A5Filter%EF%BC%8C%E6%9C%80%E5%90%8E%E7%A6%BB%E5%BC%80Filter%EF%BC%8C%20%E5%85%B6%E9%A1%BA%E5%BA%8F%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60java%0AFilter%20-%3E%20Interceptor.preHandler%20-%3E%20Handler%20-%3E%20Interceptor.postHandle%20-%3E%20Interceptor.afterCompletion%20-%3E%20Filter%0A%60%60%60%0A%0A%23%23%204%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%3E%201.%20%E5%AE%9E%E7%8E%B0%60HandlerInterceptor%60%E6%8E%A5%E5%8F%A3%E5%B9%B6%E5%B0%86%E5%AE%9E%E7%8E%B0%E7%B1%BB%E6%B3%A8%E5%85%A5%E5%88%B0spring%E5%AE%B9%E5%99%A8%E4%B8%AD%0A%3E%202.%20%E5%AE%9E%E7%8E%B0%60WebMvcConfigurer%60%E9%85%8D%E7%BD%AE%E5%99%A8%E6%8E%A5%E5%8F%A3%EF%BC%8C%E6%B7%BB%E5%8A%A0%E6%8B%A6%E6%88%AA%E8%B7%AF%E5%BE%84%E5%92%8C%E6%94%BE%E8%A1%8C%E8%B7%AF%E5%BE%84%EF%BC%8C%E5%B9%B6%E6%8A%8A%E5%AE%9E%E7%8E%B0%E7%B1%BB%E6%B3%A8%E5%85%A5%E5%88%B0spring%E5%AE%B9%E5%99%A8%E4%B8%AD%0A%0A%23%23%23%23%204.1%20%E5%8D%95%E4%B8%AA%E6%8B%A6%E6%88%AA%E5%99%A8%0A%0A%23%23%23%23%23%204.1.1%20Controller%0A%60%60%60java%0A%40RestController%0A%40RequestMapping(%22%2Ferror%22)%0A%40Slf4j%0Apublic%20class%20ErrorController%20%7B%0A%0A%20%20%20%20%40GetMapping(%22%2FshowError%22)%0A%20%20%20%20public%20String%20showError()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22ErrorController.showError%20executed%22)%3B%0A%20%20%20%20%20%20%20%20return%20%22the%20error%20happended%22%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%40RestController%0A%40RequestMapping(%22%2Fhello%22)%0A%40Slf4j%0Apublic%20class%20HelloController%20%7B%0A%0A%20%20%20%20%40GetMapping(%22%2FsayHello%22)%0A%20%20%20%20public%20String%20sayHello()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22HelloController.sayHello%20executed%22)%3B%0A%20%20%20%20%20%20%20%20return%20%22hello%20My%20HandlerInterceptor%22%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%40RestController%0A%40RequestMapping(%22%2Fuser%22)%0A%40Slf4j%0Apublic%20class%20UserController%20%7B%0A%0A%20%20%20%20%40GetMapping(%22%2FgetUserInfo%2F%7BuserName%7D%22)%0A%20%20%20%20public%20String%20sayHello(%40PathVariable(%22userName%22)%20String%20userName)%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22UserController.getUserInfo%20executed%22)%3B%0A%20%20%20%20%20%20%20%20return%20userName%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%204.1.2%20%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8B%A6%E6%88%AA%E5%99%A8%0A%60%60%60java%0A%40Slf4j%0A%40Component%0Apublic%20class%20MyInterceptor%20implements%20HandlerInterceptor%20%7B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%89%8D%E7%BD%AE%E5%A4%84%E7%90%86%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%B8%AD%E6%96%AD%E8%AF%B7%E6%B1%82%E7%BB%A7%E7%BB%AD%0A%20%20%20%20%20*%20true%20%20%E8%AF%B7%E6%B1%82%E7%BB%A7%E7%BB%AD%0A%20%20%20%20%20*%20false%20%E4%B8%AD%E6%96%AD%E8%AF%B7%E6%B1%82%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20boolean%20preHandle(HttpServletRequest%20request%2C%20HttpServletResponse%20response%2C%20Object%20handler)%20throws%20Exception%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20myInterceptor%22)%3B%0A%20%20%20%20%20%20%20%20return%20true%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%90%8E%E7%BD%AE%E5%A4%84%E7%90%86%EF%BC%8C%E5%8D%B3afterReturning%E9%80%9A%E7%9F%A5%0A%20%20%20%20%20*%20%E5%9C%A8controller%E6%89%A7%E8%A1%8C%E4%B9%8B%E5%90%8E%EF%BC%8C%E8%83%BD%E8%BF%87%E6%8B%A6%E6%88%AA%E5%99%A8%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AE%B5%E4%BB%A3%E7%A0%81%EF%BC%8C%E6%AD%A4%E6%97%B6%E5%8F%AA%E6%98%AFcontroller%E5%BE%88%E4%B9%96%E5%AE%8C%E6%AF%95%EF%BC%8C%E8%A7%86%E5%9B%BE%E8%BF%98%E6%B2%A1%E6%9C%89%E6%B8%B2%E6%9F%93%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20postHandle(HttpServletRequest%20request%2C%20HttpServletResponse%20response%2C%20Object%20handler%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ModelAndView%20modelAndView)%20throws%20Exception%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22controller%20has%20executed%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%95%B4%E4%B8%AA%E8%AF%B7%E6%B1%82%E7%BB%93%E6%9D%9F%E5%90%8E%E6%89%A7%E8%A1%8C%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20afterCompletion(HttpServletRequest%20request%2C%20HttpServletResponse%20response%2C%20Object%20handler%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Exception%20ex)%20throws%20Exception%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22response%20result%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(response))%3B%0A%20%20%20%20%20%20%20%20log.info(%22request%20done%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%204.1.3%20%E6%B3%A8%E5%86%8C%E6%8B%A6%E6%88%AA%E5%99%A8%0A%60%60%60java%0A%40Configuration%0Apublic%20class%20InterceptorConfig%20implements%20WebMvcConfigurer%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20MyInterceptor%20myInterceptor%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20addInterceptors(InterceptorRegistry%20registry)%20%7B%0A%20%20%20%20%20%20%20%20registry.addInterceptor(myInterceptor).addPathPatterns(%22%2Fhello%2F*%22).excludePathPatterns(%22%2Ferror%2F*%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%3E%20http%3A%2F%2Flocalhost%3A8081%2Fhello%2FsayHello%0A%3E%20http%3A%2F%2Flocalhost%3A8081%2Ferror%2FshowError%0A%0A!%5Bbb8515bbfa2db5fd3c0d6c25b337b530.png%5D(en-resource%3A%2F%2Fdatabase%2F1388%3A1)%0A%0A%0A%23%23%23%23%204.2%20%E5%A4%9A%E6%8B%A6%E6%88%AA%E5%99%A8%0A%0A%23%23%23%23%23%204.2.1%20%E6%B3%A8%E5%86%8C%E6%8B%A6%E6%88%AA%E5%99%A8%0A%60%60%60java%0A%40Configuration%0Apublic%20class%20InterceptorConfig%20implements%20WebMvcConfigurer%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20MyInterceptor1%20myInterceptor1%3B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20MyInterceptor2%20myInterceptor2%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20addInterceptors(InterceptorRegistry%20registry)%20%7B%0A%20%20%20%20%20%20%20%20registry.addInterceptor(myInterceptor1).addPathPatterns(%22%2Fhello%2F*%22).excludePathPatterns(%22%2Ferror%2F*%22)%3B%0A%20%20%20%20%20%20%20%20registry.addInterceptor(myInterceptor2).addPathPatterns(%22%2Fhello%2F*%22%2C%20%22%2Fuser%2F**%22).excludePathPatterns(%22%2Ferror%2F*%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%3E%20http%3A%2F%2Flocalhost%3A8081%2Fhello%2FsayHello%0A%0A!%5B4704b597810f13b124d82ba8fa70246d.png%5D(en-resource%3A%2F%2Fdatabase%2F1384%3A1)%0A%0A%0A%3E%20%E4%BF%AE%E6%94%B9MyInterceptor2%E7%9A%84preHandle%EF%BC%8C%E8%BF%94%E5%9B%9Efalse%0A%60%60%60java%0A%40Override%0Apublic%20boolean%20preHandle(HttpServletRequest%20request%2C%20HttpServletResponse%20response%2C%20Object%20handler)%20throws%20Exception%20%7B%0A%20%20%20%20log.info(%22MyInterceptor2%20preHandle%3A%20begin%20myInterceptor%22)%3B%0A%20%20%20%20return%20false%3B%0A%7D%0A%60%60%60%0A%3E%20http%3A%2F%2Flocalhost%3A8081%2Fhello%2FsayHello%0A%0A!%5B54d334dbcaa0471f27af468138f64142.png%5D(en-resource%3A%2F%2Fdatabase%2F1385%3A1)%0A%0A%0A%23%23%23%23%23%204.2.2%20%E6%8B%A6%E6%88%AA%E5%99%A8%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%0A!%5B84ecdf5218955aadcec10de148b05132.png%5D(en-resource%3A%2F%2Fdatabase%2F1386%3A1)%0A%0A%0A%23%23%23%23%204.3%20%E8%AE%BE%E7%BD%AE%E5%A4%9A%E6%8B%A6%E6%88%AA%E5%99%A8%E9%A1%BA%E5%BA%8F%0A%3E%20%E5%A4%9A%E4%B8%AA%E6%8B%A6%E6%88%AA%E5%99%A8%E7%9A%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E5%92%8C%E6%B3%A8%E5%86%8C%E9%A1%BA%E5%BA%8F%E6%9C%89%E5%85%B3%EF%BC%8C%E5%85%88%E6%B3%A8%E5%86%8C%E5%85%88%E6%89%A7%E8%A1%8C%0A%3E%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87Order%E6%96%B9%E6%B3%95%E6%9D%A5%E8%AE%BE%E7%BD%AE%E6%89%A7%E8%A1%8C%E7%9A%84%E9%A1%BA%E5%BA%8F%EF%BC%8C%E5%80%BC%E8%B6%8A%E5%B0%8F%E8%B6%8A%E5%85%88%E6%89%A7%E8%A1%8C%0A%0A%0A%60%60%60java%0A%40Override%0Apublic%20void%20addInterceptors(InterceptorRegistry%20registry)%20%7B%0A%20%20%20%20registry.addInterceptor(myInterceptor1).addPathPatterns(%22%2Fhello%2F*%22).excludePathPatterns(%22%2Ferror%2F*%22).order(2)%3B%0A%20%20%20%20registry.addInterceptor(myInterceptor2).addPathPatterns(%22%2Fhello%2F*%22%2C%20%22%2Fuser%2F**%22).excludePathPatterns(%22%2Ferror%22%20%2B%20%22%2F*%22).order(1)%3B%0A%7D%0A%60%60%60%0A%0A!%5B8df639b40d8289ef62214dfe0e99530c.png%5D(en-resource%3A%2F%2Fdatabase%2F1387%3A1)%0A

Java注解

创建时间:2020/9/2 15:07
更新时间:2024/6/2 12:50
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&mid=2247536666&idx=1&sn=35134386913c540322cd44873a29336e&chksm=fd57809cca20098ac23dad15e08228b788abea2b9ef2e2f662b94c8c47d7563288b85cd7d191&mpshare=1&scene=24&srcid=05292BiXRlQL73ssL0RZZB6u&sharer_shareinfo=b5ceb8c841dca533d02f27fb083edf7d&sharer_shareinfo_first=b5ceb8c841dca533d02f27fb083edf7d&key=2d8018214ec6abf5f6d3858b96c7322e5e09399c509affdd783beac95af42976f3bf52f21174475b59f142823ae4d2b4c3939a0f7141a1bfec916691fe2a9f771e729eb3a74848ab7f2df9b0210ca380118b92ec589315e3239869242210ea45587e2de2fda667c32b0eb2be5c1de32aa71c7c66627b2c1addfd5600249b8489&ascene=0&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+11+x64&version=63090a1b&lang=en&countrycode=CN&exportkey=n_ChQIAhIQK0Zt8rhAXbtgdQ8UyomYqxLjAQIE97dBBAEAAAAAAHjDIDbo%2F7AAAAAOpnltbLcz9gKNyK89dVj0W47Vswz96PeMzjE0YzUlj38tlG4Y2Wzd7f8YgxA8R7ku%2BKhAt64LR8c3xD1gfoOCNMA5rqvMKoxwkrjKL8l6zAVC5N2Y9xNe1WQ%2BgF1%2B3ilDRWYvNUfDlQ96%2BItHNcJbzrJDhxkjC1tmVGg0ie2PLBq%2BfPA6QnvE1PyMigBr4WXjnQg4i0moEHeA2Ufj8vAplnw0RvDfk1%2BShMtyoCnLiLidDC74s8XIf8mc73hpEGuJ0XENDSOIKydgC084&acctmode=0&pass_ticket=QdgIM7eVRBjPLmfo6VYGDD%2FhWVvnDyKSWKoKZ42GZB6q2vcpjMfW5Z6P1aYv11hQ&wx_header=1

1. 什么是注解

支持加入源代码的特殊语法元数据。
注解可以保存到class文件中,甚至运行期加载的Class对象中

2. 创建注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Configuration {
2.1 定义注解范围

@Target(ElementType.TYPE)

TYPE 表示可以修饰类,接口,注解和枚举类型
PACKAGE 可以用来修饰包
ANNOTATION_TYPE:可以用来修饰注解类型
METHOD:可以用来修饰方法
FIELD:可以用来修饰属性
CONSTRUCTOR:可以用来修饰构造子
LOCAL_VARIABLE:
2.2 定义生命周期

@Retention(RetentionPolicy.RUNTIME)

SOURCE -> CLASS -> RUNTIME
  1. SOURCE类型: 表示这个注解只在编译期有效,它甚至不会被编入class文件
@Documented
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest {
    String key() default "";
}
%5Btoc%5D%0A%23%23%23%23%201.%20%E4%BB%80%E4%B9%88%E6%98%AF%E6%B3%A8%E8%A7%A3%0A%0A%3E%20%E6%94%AF%E6%8C%81%E5%8A%A0%E5%85%A5%E6%BA%90%E4%BB%A3%E7%A0%81%E7%9A%84%E7%89%B9%E6%AE%8A%E8%AF%AD%E6%B3%95%E5%85%83%E6%95%B0%E6%8D%AE%E3%80%82%0A%3E%20%E6%B3%A8%E8%A7%A3%E5%8F%AF%E4%BB%A5%E4%BF%9D%E5%AD%98%E5%88%B0class%E6%96%87%E4%BB%B6%E4%B8%AD%EF%BC%8C%E7%94%9A%E8%87%B3%E8%BF%90%E8%A1%8C%E6%9C%9F%E5%8A%A0%E8%BD%BD%E7%9A%84Class%E5%AF%B9%E8%B1%A1%E4%B8%AD%0A%0A%23%23%23%23%202.%20%E5%88%9B%E5%BB%BA%E6%B3%A8%E8%A7%A3%0A%0A%60%60%60java%0A%40Target(ElementType.TYPE)%0A%40Retention(RetentionPolicy.RUNTIME)%0A%40Documented%0Apublic%20%40interface%20Configuration%20%7B%0A%60%60%60%0A%0A%23%23%23%23%23%202.1%20%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3%E8%8C%83%E5%9B%B4%20%0A%0A%40Target(ElementType.TYPE)%0A%0A%60%60%60java%0ATYPE%20%E8%A1%A8%E7%A4%BA%E5%8F%AF%E4%BB%A5%E4%BF%AE%E9%A5%B0%E7%B1%BB%EF%BC%8C%E6%8E%A5%E5%8F%A3%EF%BC%8C%E6%B3%A8%E8%A7%A3%E5%92%8C%E6%9E%9A%E4%B8%BE%E7%B1%BB%E5%9E%8B%0APACKAGE%20%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E4%BF%AE%E9%A5%B0%E5%8C%85%0AANNOTATION_TYPE%3A%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E4%BF%AE%E9%A5%B0%E6%B3%A8%E8%A7%A3%E7%B1%BB%E5%9E%8B%0AMETHOD%EF%BC%9A%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E4%BF%AE%E9%A5%B0%E6%96%B9%E6%B3%95%0AFIELD%3A%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E4%BF%AE%E9%A5%B0%E5%B1%9E%E6%80%A7%0ACONSTRUCTOR%3A%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E4%BF%AE%E9%A5%B0%E6%9E%84%E9%80%A0%E5%AD%90%0ALOCAL_VARIABLE%3A%0A%60%60%60%0A%0A%23%23%23%23%23%202.2%20%E5%AE%9A%E4%B9%89%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%0A%0A%40Retention(RetentionPolicy.RUNTIME)%0A%0A%60%60%60%0ASOURCE%20-%3E%20CLASS%20-%3E%20RUNTIME%0A%60%60%60%0A%3E%201.%20SOURCE%E7%B1%BB%E5%9E%8B%3A%20%E8%A1%A8%E7%A4%BA%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E5%8F%AA%E5%9C%A8%E7%BC%96%E8%AF%91%E6%9C%9F%E6%9C%89%E6%95%88%EF%BC%8C%E5%AE%83%E7%94%9A%E8%87%B3%E4%B8%8D%E4%BC%9A%E8%A2%AB%E7%BC%96%E5%85%A5class%E6%96%87%E4%BB%B6%0A%0A%0A%0A%0A%60%60%60java%0A%40Documented%0A%40Inherited%0A%40Target(ElementType.FIELD)%0A%40Retention(RetentionPolicy.RUNTIME)%0Apublic%20%40interface%20AnnotationTest%20%7B%0A%20%20%20%20String%20key()%20default%20%22%22%3B%0A%7D%0A%60%60%60

反射工具类

创建时间:2022/1/30 16:14
更新时间:2022/4/10 13:00
作者:Chris
来源:https://blog.csdn.net/qq_36666651/article/details/81215221

https://blog.csdn.net/xiexingshishu/article/details/121619404

1. ReflectionUtils

1.1 makeAccessible

org.springframework.util.ReflectionUtils#makeAccessible(java.lang.reflect.Method)

1.2 handleReflectionException

org.springframework.util.ReflectionUtils#handleReflectionException((Exception ex))

1.3 doWithFields

https://vimsky.com/examples/detail/java-method-org.springframework.util.ReflectionUtils.doWithFields.html

2. isAssignableFrom与instanceof的区别

父类或接口.class.isAssignableFrom(子类或接口.class) 
子类实例 instanceof 父类或接口类型

if (!Linkage.class.isAssignableFrom(linkClazz)) {
    throw new SdkException("[" + linkClazz.getName() + "]非link对象!");
}

isAssignableFrom() 方法是从类继承的角度去判断,instanceof关键字是从实例继承的角度去判断。
isAssignableFrom()方法是判断是否为某个类的父类,instanceof关键字是判断是否某个类的子类
isAssignableFrom() 方法的调用者和参数都是Class对象,调用者为父类或接口,参数为本身或者其子类。
instanceof关键字两个参数,前一个为类的实例,后一个为其本身或者父类或接口的类型。

3. Annotation

@Documented
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest {
    String key() default "";
}
 // 判断field是否被AnnotationTest注解,如果有,则获取AnnotationTest注解实例
 field.isAnnotationPresent(AnnotationTest.class))
 AnnotationTest annotation = field.getAnnotation(AnnotationTest.class);
%5Btoc%5D%0A%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2Fxiexingshishu%2Farticle%2Fdetails%2F121619404%0A%0A%23%23%201.%20ReflectionUtils%0A%0A%23%23%23%23%201.1%20makeAccessible%0A%0A%60%60%60java%0Aorg.springframework.util.ReflectionUtils%23makeAccessible(java.lang.reflect.Method)%0A%60%60%60%0A%23%23%23%23%201.2%20handleReflectionException%0A%60%60%60java%0Aorg.springframework.util.ReflectionUtils%23handleReflectionException((Exception%20ex))%0A%60%60%60%0A%0A%23%23%23%23%201.3%20doWithFields%0Ahttps%3A%2F%2Fvimsky.com%2Fexamples%2Fdetail%2Fjava-method-org.springframework.util.ReflectionUtils.doWithFields.html%0A%0A%23%23%202.%20isAssignableFrom%E4%B8%8Einstanceof%E7%9A%84%E5%8C%BA%E5%88%AB%0A%0A%60%60%60java%0A%E7%88%B6%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3.class.isAssignableFrom(%E5%AD%90%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3.class)%20%0A%E5%AD%90%E7%B1%BB%E5%AE%9E%E4%BE%8B%20instanceof%20%E7%88%B6%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3%E7%B1%BB%E5%9E%8B%0A%0Aif%20(!Linkage.class.isAssignableFrom(linkClazz))%20%7B%0A%20%20%20%20throw%20new%20SdkException(%22%5B%22%20%2B%20linkClazz.getName()%20%2B%20%22%5D%E9%9D%9Elink%E5%AF%B9%E8%B1%A1%EF%BC%81%22)%3B%0A%7D%0A%60%60%60%0A%3E%20isAssignableFrom()%20%E6%96%B9%E6%B3%95%E6%98%AF%E4%BB%8E%E7%B1%BB%E7%BB%A7%E6%89%BF%E7%9A%84%E8%A7%92%E5%BA%A6%E5%8E%BB%E5%88%A4%E6%96%AD%EF%BC%8Cinstanceof%E5%85%B3%E9%94%AE%E5%AD%97%E6%98%AF%E4%BB%8E%E5%AE%9E%E4%BE%8B%E7%BB%A7%E6%89%BF%E7%9A%84%E8%A7%92%E5%BA%A6%E5%8E%BB%E5%88%A4%E6%96%AD%E3%80%82%0A%3E%20isAssignableFrom()%E6%96%B9%E6%B3%95%E6%98%AF%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E4%B8%BA%E6%9F%90%E4%B8%AA%E7%B1%BB%E7%9A%84%E7%88%B6%E7%B1%BB%EF%BC%8Cinstanceof%E5%85%B3%E9%94%AE%E5%AD%97%E6%98%AF%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E6%9F%90%E4%B8%AA%E7%B1%BB%E7%9A%84%E5%AD%90%E7%B1%BB%0A%3E%20isAssignableFrom()%20%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%E8%80%85%E5%92%8C%E5%8F%82%E6%95%B0%E9%83%BD%E6%98%AFClass%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%B0%83%E7%94%A8%E8%80%85%E4%B8%BA%E7%88%B6%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%8F%82%E6%95%B0%E4%B8%BA%E6%9C%AC%E8%BA%AB%E6%88%96%E8%80%85%E5%85%B6%E5%AD%90%E7%B1%BB%E3%80%82%0A%3E%20instanceof%E5%85%B3%E9%94%AE%E5%AD%97%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%89%8D%E4%B8%80%E4%B8%AA%E4%B8%BA%E7%B1%BB%E7%9A%84%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%90%8E%E4%B8%80%E4%B8%AA%E4%B8%BA%E5%85%B6%E6%9C%AC%E8%BA%AB%E6%88%96%E8%80%85%E7%88%B6%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%E5%9E%8B%E3%80%82%0A%0A%0A%23%23%203.%20Annotation%0A%0A%60%60%60java%0A%40Documented%0A%40Inherited%0A%40Target(ElementType.FIELD)%0A%40Retention(RetentionPolicy.RUNTIME)%0Apublic%20%40interface%20AnnotationTest%20%7B%0A%20%20%20%20String%20key()%20default%20%22%22%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%20%2F%2F%20%E5%88%A4%E6%96%ADfield%E6%98%AF%E5%90%A6%E8%A2%ABAnnotationTest%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9C%89%EF%BC%8C%E5%88%99%E8%8E%B7%E5%8F%96AnnotationTest%E6%B3%A8%E8%A7%A3%E5%AE%9E%E4%BE%8B%0A%20field.isAnnotationPresent(AnnotationTest.class))%0A%20AnnotationTest%20annotation%20%3D%20field.getAnnotation(AnnotationTest.class)%3B%0A%60%60%60

PropertyDescriptor

创建时间:2022/4/10 12:50
更新时间:2022/4/10 12:52
作者:Chris

package com.chris.reflect;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.chris.reflect.Bean.HumanBeing;
import com.chris.reflect.Bean.Male;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.junit.Test;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Objects;

@Slf4j
public class PropertyDescTest {

    @Test
    public void buildPropertyDesc() {
        HumanBeing male = new Male("Chris", "SZ");
        PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
        PropertyDescriptor[] propertyDescriptors = propertyUtilsBean.getPropertyDescriptors(male);
        System.out.println(JSONUtil.toJsonPrettyStr(propertyDescriptors));

        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
            String name = propertyDescriptor.getName();
            Method readMethod = propertyDescriptor.getReadMethod();
            Method writeMethod = propertyDescriptor.getWriteMethod();
            Class<?> propertyType = propertyDescriptor.getPropertyType();

            JSONObject obj = JSONUtil.createObj();
            obj.set("name", name);
            obj.set("readMethod", readMethod);
            obj.set("writeMethod", writeMethod);
            obj.set("propertyType", propertyType);

            String s = JSONUtil.toJsonPrettyStr(obj);
            System.out.println(s);
        }

    }

    @Test
    public void testCopyValueForSameProperty() {
        HumanBeing male = new Male("Chris", "SZ");
        Male m = null;
        try {
            m = copyValueForSameProperty(male, Male.class);
            log.info("Male:{}", m);
        } catch (Exception e) {
            log.error("error happened when copy propeties", e);
        }
    }


    private <T> T copyValueForSameProperty(Object source, Class<T> targetClz) throws Exception {
        if (Objects.isNull(source)) {
            return null;
        }

        T target = targetClz.newInstance();

        // 获取source的所有属性及方法
        PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
        PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(source);

        for (PropertyDescriptor propItem : descriptors) {
            // 获取某一个属性的全部信息
            // 过滤setclass/getclass属性
            if ("class".equals(propItem.getName())) {
                continue;
            }
            try {
                // 通过get方法获取对应属性的值
                Method method = propItem.getReadMethod();
                Object val = method.invoke(source);
                // 如果是空,不做处理
                if (null == val) {
                    continue;
                }
                // 值复制,调用写方法,设置值
                // 获取target的当前属性propItem.getName()的信息
                PropertyDescriptor prop = propertyUtilsBean.getPropertyDescriptor(target, propItem.getName());
                if (null != prop && prop.getWriteMethod() != null) {
                    prop.getWriteMethod().invoke(target, val);
                }
            } catch (Exception e) {
                log.error("复制出错prop : " + propItem.getDisplayName() + ", source class: " + source.getClass()
                        + ";target type :" + targetClz, e);
            }
        }
        return target;
    }
}

%0A%0A%60%60%60java%0Apackage%20com.chris.reflect%3B%0A%0Aimport%20cn.hutool.json.JSONObject%3B%0Aimport%20cn.hutool.json.JSONUtil%3B%0Aimport%20com.chris.reflect.Bean.HumanBeing%3B%0Aimport%20com.chris.reflect.Bean.Male%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.apache.commons.beanutils.PropertyUtilsBean%3B%0Aimport%20org.junit.Test%3B%0A%0Aimport%20java.beans.PropertyDescriptor%3B%0Aimport%20java.lang.reflect.Method%3B%0Aimport%20java.util.Objects%3B%0A%0A%40Slf4j%0Apublic%20class%20PropertyDescTest%20%7B%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20buildPropertyDesc()%20%7B%0A%20%20%20%20%20%20%20%20HumanBeing%20male%20%3D%20new%20Male(%22Chris%22%2C%20%22SZ%22)%3B%0A%20%20%20%20%20%20%20%20PropertyUtilsBean%20propertyUtilsBean%20%3D%20new%20PropertyUtilsBean()%3B%0A%20%20%20%20%20%20%20%20PropertyDescriptor%5B%5D%20propertyDescriptors%20%3D%20propertyUtilsBean.getPropertyDescriptors(male)%3B%0A%20%20%20%20%20%20%20%20System.out.println(JSONUtil.toJsonPrettyStr(propertyDescriptors))%3B%0A%0A%20%20%20%20%20%20%20%20for%20(PropertyDescriptor%20propertyDescriptor%20%3A%20propertyDescriptors)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20String%20name%20%3D%20propertyDescriptor.getName()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Method%20readMethod%20%3D%20propertyDescriptor.getReadMethod()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Method%20writeMethod%20%3D%20propertyDescriptor.getWriteMethod()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Class%3C%3F%3E%20propertyType%20%3D%20propertyDescriptor.getPropertyType()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20JSONObject%20obj%20%3D%20JSONUtil.createObj()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20obj.set(%22name%22%2C%20name)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20obj.set(%22readMethod%22%2C%20readMethod)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20obj.set(%22writeMethod%22%2C%20writeMethod)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20obj.set(%22propertyType%22%2C%20propertyType)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20String%20s%20%3D%20JSONUtil.toJsonPrettyStr(obj)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(s)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20testCopyValueForSameProperty()%20%7B%0A%20%20%20%20%20%20%20%20HumanBeing%20male%20%3D%20new%20Male(%22Chris%22%2C%20%22SZ%22)%3B%0A%20%20%20%20%20%20%20%20Male%20m%20%3D%20null%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20m%20%3D%20copyValueForSameProperty(male%2C%20Male.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22Male%3A%7B%7D%22%2C%20m)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(Exception%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20log.error(%22error%20happened%20when%20copy%20propeties%22%2C%20e)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20private%20%3CT%3E%20T%20copyValueForSameProperty(Object%20source%2C%20Class%3CT%3E%20targetClz)%20throws%20Exception%20%7B%0A%20%20%20%20%20%20%20%20if%20(Objects.isNull(source))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20T%20target%20%3D%20targetClz.newInstance()%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96source%E7%9A%84%E6%89%80%E6%9C%89%E5%B1%9E%E6%80%A7%E5%8F%8A%E6%96%B9%E6%B3%95%0A%20%20%20%20%20%20%20%20PropertyUtilsBean%20propertyUtilsBean%20%3D%20new%20PropertyUtilsBean()%3B%0A%20%20%20%20%20%20%20%20PropertyDescriptor%5B%5D%20descriptors%20%3D%20propertyUtilsBean.getPropertyDescriptors(source)%3B%0A%0A%20%20%20%20%20%20%20%20for%20(PropertyDescriptor%20propItem%20%3A%20descriptors)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%E6%9F%90%E4%B8%80%E4%B8%AA%E5%B1%9E%E6%80%A7%E7%9A%84%E5%85%A8%E9%83%A8%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E8%BF%87%E6%BB%A4setclass%2Fgetclass%E5%B1%9E%E6%80%A7%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(%22class%22.equals(propItem.getName()))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E9%80%9A%E8%BF%87get%E6%96%B9%E6%B3%95%E8%8E%B7%E5%8F%96%E5%AF%B9%E5%BA%94%E5%B1%9E%E6%80%A7%E7%9A%84%E5%80%BC%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Method%20method%20%3D%20propItem.getReadMethod()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object%20val%20%3D%20method.invoke(source)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E5%A6%82%E6%9E%9C%E6%98%AF%E7%A9%BA%EF%BC%8C%E4%B8%8D%E5%81%9A%E5%A4%84%E7%90%86%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(null%20%3D%3D%20val)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E5%80%BC%E5%A4%8D%E5%88%B6%2C%E8%B0%83%E7%94%A8%E5%86%99%E6%96%B9%E6%B3%95%EF%BC%8C%E8%AE%BE%E7%BD%AE%E5%80%BC%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96target%E7%9A%84%E5%BD%93%E5%89%8D%E5%B1%9E%E6%80%A7propItem.getName()%E7%9A%84%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20PropertyDescriptor%20prop%20%3D%20propertyUtilsBean.getPropertyDescriptor(target%2C%20propItem.getName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(null%20!%3D%20prop%20%26%26%20prop.getWriteMethod()%20!%3D%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20prop.getWriteMethod().invoke(target%2C%20val)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(Exception%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.error(%22%E5%A4%8D%E5%88%B6%E5%87%BA%E9%94%99prop%20%3A%20%22%20%2B%20propItem.getDisplayName()%20%2B%20%22%2C%20source%20class%3A%20%22%20%2B%20source.getClass()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22%3Btarget%20type%20%3A%22%20%2B%20targetClz%2C%20e)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20target%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60

mysql issues

创建时间:2022/4/4 17:15
更新时间:2022/4/4 17:17
作者:Chris
来源:https://blog.csdn.net/iris_xuting/article/details/102689000

Host X is blocked

Host X is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'

mysql> flush hosts;
## 或者
mysql> truncate Performance_chema.host_cache;
%5Btoc%5D%0A%0A%23%23%23%23%20%20Host%20X%20is%20blocked%0A%3E%20Host%20X%20is%20blocked%20because%20of%20many%20connection%20errors%3B%20unblock%20with%20'mysqladmin%20flush-hosts'%0A%0A%60%60%60%0Amysql%3E%20flush%20hosts%3B%0A%23%23%20%E6%88%96%E8%80%85%0Amysql%3E%20truncate%C2%A0Performance_chema.host_cache%3B%0A%60%60%60

inner class

创建时间:2022/4/2 18:00
更新时间:2022/4/2 18:01
作者:Chris

使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

**1、**内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
**2、**在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
**3、**创建内部类对象的时刻并不依赖于外围类对象的创建。
**4、**内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
**5、**内部类提供了更好的封装,除了该外围类,其他类都不能访问。

内部类是个编译时的概念,一旦编译成功后,它就与外围类属于两个完全不同的类(当然他们之间还是有联系的)。

对于一个名为OuterClass的外围类和一个名为InnerClass的内部类,在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$InnerClass.class。

成员内部类

在成员内部类中要注意两点,
第一:成员内部类中不能存在任何static的变量和方法;
第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。

@Getter
public class Outer {
    private String name = "outer";
    private String outer = "I'm outer";
    private Inner innerInstance;

    // 推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时
    public Inner getInnerInstance() {
        if (null == innerInstance) {
            innerInstance = new Inner();
        }
        return innerInstance;
    }

    @Getter
    class Inner {

        private String name = "inner";

        public Inner() {
            System.out.println("construct inner cls");
            System.out.println("outer:" + outer + ", " + name);

            // if you wanna visit outer'name
            System.out.println("outer:" + outer + ", " + Outer.this.name);
        }
    }


%0A%0A%3E%20%E4%BD%BF%E7%94%A8%E5%86%85%E9%83%A8%E7%B1%BB%E6%9C%80%E5%90%B8%E5%BC%95%E4%BA%BA%E7%9A%84%E5%8E%9F%E5%9B%A0%E6%98%AF%EF%BC%9A%E6%AF%8F%E4%B8%AA%E5%86%85%E9%83%A8%E7%B1%BB%E9%83%BD%E8%83%BD%E7%8B%AC%E7%AB%8B%E5%9C%B0%E7%BB%A7%E6%89%BF%E4%B8%80%E4%B8%AA%EF%BC%88%E6%8E%A5%E5%8F%A3%E7%9A%84%EF%BC%89%E5%AE%9E%E7%8E%B0%EF%BC%8C%E6%89%80%E4%BB%A5%E6%97%A0%E8%AE%BA%E5%A4%96%E5%9B%B4%E7%B1%BB%E6%98%AF%E5%90%A6%E5%B7%B2%E7%BB%8F%E7%BB%A7%E6%89%BF%E4%BA%86%E6%9F%90%E4%B8%AA%EF%BC%88%E6%8E%A5%E5%8F%A3%E7%9A%84%EF%BC%89%E5%AE%9E%E7%8E%B0%EF%BC%8C%E5%AF%B9%E4%BA%8E%E5%86%85%E9%83%A8%E7%B1%BB%E9%83%BD%E6%B2%A1%E6%9C%89%E5%BD%B1%E5%93%8D%E3%80%82%0A%0A%20%20%20**1%E3%80%81**%E5%86%85%E9%83%A8%E7%B1%BB%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%A4%9A%E4%B8%AA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E6%AF%8F%E4%B8%AA%E5%AE%9E%E4%BE%8B%E9%83%BD%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E7%8A%B6%E6%80%81%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%B8%8E%E5%85%B6%E4%BB%96%E5%A4%96%E5%9B%B4%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%BF%A1%E6%81%AF%E7%9B%B8%E4%BA%92%E7%8B%AC%E7%AB%8B%E3%80%82%0A%20%20%20**2%E3%80%81**%E5%9C%A8%E5%8D%95%E4%B8%AA%E5%A4%96%E5%9B%B4%E7%B1%BB%E4%B8%AD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%AE%A9%E5%A4%9A%E4%B8%AA%E5%86%85%E9%83%A8%E7%B1%BB%E4%BB%A5%E4%B8%8D%E5%90%8C%E7%9A%84%E6%96%B9%E5%BC%8F%E5%AE%9E%E7%8E%B0%E5%90%8C%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%EF%BC%8C%E6%88%96%E8%80%85%E7%BB%A7%E6%89%BF%E5%90%8C%E4%B8%80%E4%B8%AA%E7%B1%BB%E3%80%82%0A%20%20%20**3%E3%80%81**%E5%88%9B%E5%BB%BA%E5%86%85%E9%83%A8%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%97%B6%E5%88%BB%E5%B9%B6%E4%B8%8D%E4%BE%9D%E8%B5%96%E4%BA%8E%E5%A4%96%E5%9B%B4%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%88%9B%E5%BB%BA%E3%80%82%0A%20%20%20**4%E3%80%81**%E5%86%85%E9%83%A8%E7%B1%BB%E5%B9%B6%E6%B2%A1%E6%9C%89%E4%BB%A4%E4%BA%BA%E8%BF%B7%E6%83%91%E7%9A%84%E2%80%9Cis-a%E2%80%9D%E5%85%B3%E7%B3%BB%EF%BC%8C%E4%BB%96%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E7%8B%AC%E7%AB%8B%E7%9A%84%E5%AE%9E%E4%BD%93%E3%80%82%0A%20%20%20**5%E3%80%81**%E5%86%85%E9%83%A8%E7%B1%BB%E6%8F%90%E4%BE%9B%E4%BA%86%E6%9B%B4%E5%A5%BD%E7%9A%84%E5%B0%81%E8%A3%85%EF%BC%8C%E9%99%A4%E4%BA%86%E8%AF%A5%E5%A4%96%E5%9B%B4%E7%B1%BB%EF%BC%8C%E5%85%B6%E4%BB%96%E7%B1%BB%E9%83%BD%E4%B8%8D%E8%83%BD%E8%AE%BF%E9%97%AE%E3%80%82%0A%0A%0A%0A%3E%20%E5%86%85%E9%83%A8%E7%B1%BB%E6%98%AF%E4%B8%AA%E7%BC%96%E8%AF%91%E6%97%B6%E7%9A%84%E6%A6%82%E5%BF%B5%EF%BC%8C%E4%B8%80%E6%97%A6%E7%BC%96%E8%AF%91%E6%88%90%E5%8A%9F%E5%90%8E%EF%BC%8C%E5%AE%83%E5%B0%B1%E4%B8%8E%E5%A4%96%E5%9B%B4%E7%B1%BB%E5%B1%9E%E4%BA%8E%E4%B8%A4%E4%B8%AA%E5%AE%8C%E5%85%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E7%B1%BB%EF%BC%88%E5%BD%93%E7%84%B6%E4%BB%96%E4%BB%AC%E4%B9%8B%E9%97%B4%E8%BF%98%E6%98%AF%E6%9C%89%E8%81%94%E7%B3%BB%E7%9A%84%EF%BC%89%E3%80%82%0A%3E%0A%3E%20%E5%AF%B9%E4%BA%8E%E4%B8%80%E4%B8%AA%E5%90%8D%E4%B8%BAOuterClass%E7%9A%84%E5%A4%96%E5%9B%B4%E7%B1%BB%E5%92%8C%E4%B8%80%E4%B8%AA%E5%90%8D%E4%B8%BAInnerClass%E7%9A%84%E5%86%85%E9%83%A8%E7%B1%BB%EF%BC%8C%E5%9C%A8%E7%BC%96%E8%AF%91%E6%88%90%E5%8A%9F%E5%90%8E%EF%BC%8C%E4%BC%9A%E5%87%BA%E7%8E%B0%E8%BF%99%E6%A0%B7%E4%B8%A4%E4%B8%AAclass%E6%96%87%E4%BB%B6%EF%BC%9AOuterClass.class%E5%92%8COuterClass%24InnerClass.class%E3%80%82%0A%0A%23%23%20%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%0A%0A%3E%20%20%E5%9C%A8%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%AD%E8%A6%81%E6%B3%A8%E6%84%8F%E4%B8%A4%E7%82%B9%EF%BC%8C%0A%3E%20%E7%AC%AC%E4%B8%80%EF%BC%9A%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%E4%B8%AD%E4%B8%8D%E8%83%BD%E5%AD%98%E5%9C%A8%E4%BB%BB%E4%BD%95static%E7%9A%84%E5%8F%98%E9%87%8F%E5%92%8C%E6%96%B9%E6%B3%95%EF%BC%9B%0A%3E%20%E7%AC%AC%E4%BA%8C%EF%BC%9A%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%E6%98%AF%E4%BE%9D%E9%99%84%E4%BA%8E%E5%A4%96%E5%9B%B4%E7%B1%BB%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E5%8F%AA%E6%9C%89%E5%85%88%E5%88%9B%E5%BB%BA%E4%BA%86%E5%A4%96%E5%9B%B4%E7%B1%BB%E6%89%8D%E8%83%BD%E5%A4%9F%E5%88%9B%E5%BB%BA%E5%86%85%E9%83%A8%E7%B1%BB%E3%80%82%0A%0A%60%60%60java%0A%40Getter%0Apublic%20class%20Outer%20%7B%0A%20%20%20%20private%20String%20name%20%3D%20%22outer%22%3B%0A%20%20%20%20private%20String%20outer%20%3D%20%22I'm%20outer%22%3B%0A%20%20%20%20private%20Inner%20innerInstance%3B%0A%0A%20%20%20%20%2F%2F%20%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8getxxx()%E6%9D%A5%E8%8E%B7%E5%8F%96%E6%88%90%E5%91%98%E5%86%85%E9%83%A8%E7%B1%BB%EF%BC%8C%E5%B0%A4%E5%85%B6%E6%98%AF%E8%AF%A5%E5%86%85%E9%83%A8%E7%B1%BB%E7%9A%84%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E6%97%A0%E5%8F%82%E6%95%B0%E6%97%B6%0A%20%20%20%20public%20Inner%20getInnerInstance()%20%7B%0A%20%20%20%20%20%20%20%20if%20(null%20%3D%3D%20innerInstance)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20innerInstance%20%3D%20new%20Inner()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20innerInstance%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Getter%0A%20%20%20%20class%20Inner%20%7B%0A%0A%20%20%20%20%20%20%20%20private%20String%20name%20%3D%20%22inner%22%3B%0A%0A%20%20%20%20%20%20%20%20public%20Inner()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22construct%20inner%20cls%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22outer%3A%22%20%2B%20outer%20%2B%20%22%2C%20%22%20%2B%20name)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20if%20you%20wanna%20visit%20outer'name%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22outer%3A%22%20%2B%20outer%20%2B%20%22%2C%20%22%20%2B%20Outer.this.name)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%0A!%5Bfa5b7a864efa1582f7835dc57819a8ef.png%5D(en-resource%3A%2F%2Fdatabase%2F1548%3A0)%0A!%5B6d7e4c8dc468f38267a17fe733241c55.png%5D(en-resource%3A%2F%2Fdatabase%2F1550%3A0)%0A

MySQL模糊查询再也用不着 like+% 了!

创建时间:2022/3/30 14:31
更新时间:2022/3/30 15:06
来源:https://mp.weixin.qq.com/s/eOsRHIV9UfCg2E5CBuFzLA

MySQL模糊查询再也用不着 like+% 了!

我们都知道 InnoDB 在模糊查询数据时使用 "%xx" 会导致索引失效,但有时需求就是如此,类似这样的需求还有很多,例如,搜索引擎需要根基用户数据的关键字进行全文查找,电子商务网站需要根据用户的查询条件,在可能需要在商品的详细介绍中进行查找,这些都不是B+树索引能很好完成的工作。
通过数值比较,范围过滤等就可以完成绝大多数我们需要的查询了。但是,如果希望通过关键字的匹配来进行查询过滤,那么就需要基于相似度的查询,而不是原来的精确数值比较,全文索引就是为这种场景设计的。
全文索引(Full-Text Search)是将存储于数据库中的整本书或整篇文章中的任意信息查找出来的技术。它可以根据需要获得全文中有关章、节、段、句、词等信息,也可以进行各种统计和分析。
在早期的 MySQL 中,InnoDB 并不支持全文检索技术,从 MySQL 5.6 开始,InnoDB 开始支持全文检索。
倒排索引
全文检索通常使用倒排索引(inverted index)来实现,倒排索引同 B+Tree 一样,也是一种索引结构。它在辅助表中存储了单词与单词自身在一个或多个文档中所在位置之间的映射,这通常利用关联数组实现,拥有两种表现形式:
  • inverted file index:{单词,单词所在文档的id}
  • full inverted index:{单词,(单词所在文档的id,再具体文档中的位置)}
对于 inverted file index 的关联数组
上图为 inverted file index 关联数组,可以看到其中单词"code"存在于文档1,4中,这样存储再进行全文查询就简单了,可以直接根据 Documents 得到包含查询关键字的文档;而 full inverted index 存储的是对,即(DocumentId,Position),因此其存储的倒排索引如下图,如关键字"code"存在于文档1的第6个单词和文档4的第8个单词。相比之下,full inverted index 占用了更多的空间,但是能更好的定位数据,并扩充一些其他搜索特性。

全文检索

创建全文索引

1、创建表时创建全文索引语法如下:
CREATE TABLE table_name ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, author VARCHAR(200), 
title VARCHAR(200), content TEXT(500), FULLTEXT full_index_name (col_name) ) ENGINE=InnoDB;
输入查询语句:
SELECT table_id, name, space from INFORMATION_SCHEMA.INNODB_TABLES
WHERE name LIKE 'test/%';
上述六个索引表构成倒排索引,称为辅助索引表。当传入的文档被标记化时,单个词与位置信息和关联的DOC_ID,根据单词的第一个字符的字符集排序权重,在六个索引表中对单词进行完全排序和分区。
2、在已创建的表上创建全文索引语法如下:
CREATE FULLTEXT INDEX full_index_name ON table_name(col_name);

使用全文索引

MySQL 数据库支持全文检索的查询,全文索引只能在 InnoDB 或 MyISAM 的表上使用,并且只能用于创建 char,varchar,text 类型的列。
其语法如下:
MATCH(col1,col2,...) AGAINST(expr[search_modifier])
search_modifier:
{
    IN NATURAL LANGUAGE MODE
    | IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
    | IN BOOLEAN MODE
    | WITH QUERY EXPANSION
}
全文搜索使用?`MATCH() AGAINST()`[1]语法进行,其中,MATCH() 采用逗号分隔的列表,命名要搜索的列。AGAINST()接收一个要搜索的字符串,以及一个要执行的搜索类型的可选修饰符。全文检索分为三种类型:自然语言搜索、布尔搜索、查询扩展搜索,下面将对各种查询模式进行介绍。

Natural Language

自然语言搜索将搜索字符串解释为自然人类语言中的短语,MATCH()默认采用 Natural Language 模式,其表示查询带有指定关键字的文档。
接下来结合demo来更好的理解Natural Language
SELECT
    count(*) AS count 
FROM
    `fts_articles` 
WHERE
    MATCH ( title, body ) AGAINST ( 'MySQL' );
上述语句,查询 title,body 列中包含 'MySQL' 关键字的行数量。上述语句还可以这样写:
SELECT
    count(IF(MATCH ( title, body ) 
    against ( 'MySQL' ), 1, NULL )) AS count 
FROM
    `fts_articles`;
上述两种语句虽然得到的结果是一样的,但从内部运行来看,第二句SQL的执行速度更快些,因为第一句SQL(基于where索引查询的方式)还需要进行相关性的排序统计,而第二种方式是不需要的。
还可以通过SQL语句查询相关性:
SELECT
    *,
    MATCH ( title, body ) against ( 'MySQL' ) AS Relevance 
FROM
    fts_articles;
相关性的计算依据以下四个条件:
  • word 是否在文档中出现
  • word 在文档中出现的次数
  • word 在索引列中的数量
  • 多少个文档包含该 word
对于 InnoDB 存储引擎的全文检索,还需要考虑以下的因素:
  • 查询的 word 在 stopword 列中,忽略该字符串的查询
  • 查询的 word 的字符长度是否在区间 [innodb_ft_min_token_size,innodb_ft_max_token_size] 内
如果词在 stopword 中,则不对该词进行查询,如对 'for' 这个词进行查询,结果如下所示:
SELECT
    *,
    MATCH ( title, body ) against ( 'for' ) AS Relevance 
FROM
    fts_articles;
可以看到,'for'虽然在文档 2,4中出现,但由于其是 stopword ,故其相关性为0
参数 innodb_ft_min_token_size 和 innodb_ft_max_token_size 控制 InnoDB 引擎查询字符的长度,当长度小于 innodb_ft_min_token_size 或者长度大于 innodb_ft_max_token_size 时,会忽略该词的搜索。在 InnoDB 引擎中,参数 innodb_ft_min_token_size 的默认值是3,innodb_ft_max_token_size的默认值是84

Boolean

布尔搜索使用特殊查询语言的规则来解释搜索字符串,该字符串包含要搜索的词,它还可以包含指定要求的运算符,例如匹配行中必须存在或不存在某个词,或者它的权重应高于或低于通常情况。例如,下面的语句要求查询有字符串"Pease"但没有"hot"的文档,其中+和-分别表示单词必须存在,或者一定不存在。
select * from fts_test where MATCH(content) AGAINST('+Pease -hot' IN BOOLEAN MODE);
Boolean 全文检索支持的类型包括:
  • +:表示该 word 必须存在
  • -:表示该 word 必须不存在
  • (no operator)表示该 word 是可选的,但是如果出现,其相关性会更高
  • @distance表示查询的多个单词之间的距离是否在 distance 之内,distance 的单位是字节,这种全文检索的查询也称为 Proximity Search,如 MATCH(context) AGAINST('"Pease hot"@30' IN BOOLEAN MODE)语句表示字符串 Pease 和 hot 之间的距离需在30字节内
  • :表示出现该单词时增加相关性
  • <:表示出现该单词时降低相关性
  • ~:表示允许出现该单词,但出现时相关性为负

    • :表示以该单词开头的单词,如 lik*,表示可以是 liklikelikes
  • " :表示短语
下面是一些demo,看看 Boolean Mode 是如何使用的。
demo1:+ -
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH ( title, body ) AGAINST ( '+MySQL -YourSQL' IN BOOLEAN MODE );
上述语句,查询的是包含 'MySQL' 但不包含 'YourSQL' 的信息
demo2:no operator
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH ( title, body ) AGAINST ( 'MySQL IBM' IN BOOLEAN MODE );
上述语句,查询的 'MySQL IBM' 没有 '+','-'的标识,代表 word 是可选的,如果出现,其相关性会更高
demo3:@
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH ( title, body ) AGAINST ( '"DB2 IBM"@3' IN BOOLEAN MODE );
上述语句,代表 "DB2" ,"IBM"两个词之间的距离在3字节之内
demo4:> <
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH ( title, body ) AGAINST ( '+MySQL +(>database <DBMS)' IN BOOLEAN MODE );
上述语句,查询同时包含 'MySQL','database','DBMS' 的行信息,但不包含'DBMS'的行的相关性高于包含'DBMS'的行。
demo5: ~
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH ( title, body ) AGAINST ( 'MySQL ~database' IN BOOLEAN MODE );
上述语句,查询包含 'MySQL' 的行,但如果该行同时包含 'database',则降低相关性。
demo6:*
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH ( title, body ) AGAINST ( 'My*' IN BOOLEAN MODE );
上述语句,查询关键字中包含'My'的行信息。
demo7:"
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH ( title, body ) AGAINST ( '"MySQL Security"' IN BOOLEAN MODE );
上述语句,查询包含确切短语 'MySQL Security' 的行信息。

Query Expansion

查询扩展搜索是对自然语言搜索的修改,这种查询通常在查询的关键词太短,用户需要 implied knowledge(隐含知识)时进行,例如,对于单词 database 的查询,用户可能希望查询的不仅仅是包含 database 的文档,可能还指那些包含 MySQL、Oracle、RDBMS 的单词,而这时可以使用 Query Expansion 模式来开启全文检索的 implied knowledge
通过在查询语句中添加 WITH QUERY EXPANSION / IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION 可以开启 blind query expansion(又称为 automatic relevance feedback),该查询分为两个阶段。
  • 第一阶段:根据搜索的单词进行全文索引查询
  • 第二阶段:根据第一阶段产生的分词再进行一次全文检索的查询
接着来看一个例子,看看 Query Expansion 是如何使用的。
-- 创建索引
create FULLTEXT INDEX title_body_index on fts_articles(title,body);
-- 使用 Natural Language 模式查询
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH(title,body) AGAINST('database');
使用 Query Expansion 前查询结果如下:
-- 当使用 Query Expansion 模式查询
SELECT
    * 
FROM
    `fts_articles` 
WHERE
    MATCH(title,body) AGAINST('database' WITH QUERY expansion);
使用 Query Expansion 后查询结果如下:
由于 Query Expansion 的全文检索可能带来许多非相关性的查询,因此在使用时,用户可能需要非常谨慎。

删除全文索引

1、直接删除全文索引语法如下:
DROP INDEX full_idx_name ON db_name.table_name;
2、使用 alter table 删除全文索引语法如下:
ALTER TABLE db_name.table_name DROP INDEX full_idx_name;

小结

本文从理论与实践结合的角度对 fulltext index 做了介绍


安装RocketMQ-4.9.0

创建时间:2020/9/2 14:32
更新时间:2022/3/25 14:51
作者:Chris
来源:https://rocketmq.apache.org/release_notes/release-notes-4.9.0/

安装RocketMQ

下载

https://rocketmq.apache.org/docs/quick-start/
https://rocketmq.apache.org/release_notes/release-notes-4.9.0/

下载
rocketmq-all-4.9.0-bin-release.zip

cd /opt
mv /tmp/rocketmq-all-4.9.0-bin-release.zip .
unzip rocketmq-all-4.9.0-bin-release.zip
mv rocketmq-all-4.9.0-bin-release rocketmq

配置broker

vi conf/broker.conf
追加如下内容

#name server服务器地址及端口,可以是多个,分号隔开
namesrvAddr=192.168.80.180:9876
#是否自动创建默认topic,生产需保持关闭
autoCreateTopicEnable=true
#brokerIP1:配置broker所在服务器的ip地址,以便Name Server连接
brokerIP1=192.168.80.180

启动

启动nameserver

[root@master]# nohup sh bin/mqnamesrv &
tail -f /logs/rocketmqlogs/nameserver.log

[root@master bin]# jps
3235 Jps
3207 NamesrvStartup

启动broker

-- 无参数启动
nohup sh bin/mqbroker -n master:9876 &

-- 加载参数启动
nohup sh bin/mqbroker -n master:9876 -c conf/broker.conf
autoCreateTopicEnable=true &

tail -f /logs/rocketmqlogs/broker.log

[root@master rocketmq]# jps
3429 Jps
3207 NamesrvStartup
3386 BrokerStartup

rockertmq启动默认设置内存较大会导致启动失败需要手动修改

vi bin/runserver.sh
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"

vi bin/runborker.sh
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m"

测试

[root@master rocketmq]# export NAMESRV_ADDR=localhost:9876
[root@master rocketmq]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

SendResult [sendStatus=SEND_OK, msgId=7F000001109B1B6D35866692827F03E6, offsetMsgId=C0A8657F00002A9F00000000000316F4, messageQueue=MessageQueue [topic=TopicTest, brokerName=master, queueId=1], queueOffset=249]
SendResult [sendStatus=SEND_OK, msgId=7F000001109B1B6D35866692828203E7, offsetMsgId=C0A8657F00002A9F00000000000317BF, messageQueue=MessageQueue [topic=TopicTest, brokerName=master, queueId=2], queueOffset=249]
[root@master rocketmq]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

ConsumeMessageThread_8 Receive New Messages: [MessageExt [brokerName=master, queueId=3, storeSize=203, queueOffset=229, sysFlag=0, bornTimestamp=1647784877377, bornHost=/192.168.101.127:40132, storeTimestamp=1647784877378, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F000000000002D5EE, commitLogOffset=185838, bodyCRC=2121214082, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=250, CONSUME_START_TIME=1647786877924, UNIQ_KEY=7F000001109B1B6D3586669281410394, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 57, 49, 54], transaction}]] 
ConsumeMessageThread_12 Receive New Messages: [MessageExt [brokerName=master, queueId=3, storeSize=203, queueOffset=228, sysFlag=0, bornTimestamp=1647784877348, bornHost=/192.168.101.127:40132, storeTimestamp=1647784877349, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F000000000002D2C2, commitLogOffset=185026, bodyCRC=2030234779, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=250, CONSUME_START_TIME=1647786877846, UNIQ_KEY=7F000001109B1B6D3586669281240390, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 57, 49, 50], transaction}]]

rocketmq服务关闭
先关broker,再关闭nameserver

关闭broker服务 :sh bin/mqshutdown broker
关闭namesrv服务:sh bin/mqshutdown namesrv  

安装可视化界面

https://github.com/apache/rocketmq-dashboard
下载zip包

unzip rocketmq-externals-master.zip
[root@master rocketmq-externals-master]# cd rocketmq-dashboard-master\src\main\resources
vi application.properties

server:
  port: 9877
namesrvAddrs:
      - master:9876

[root@master rocketmq-console]# mvn clean package -Dmaven.test.skip=true
[root@master rocketmq-console]# cd target/

nohup  java -jar rocketmq-dashboard-1.0.1-SNAPSHOT.jar > /data/mq/rocketmq/rocket-console.log 2>&1 &

issue

ava.lang.RuntimeException: org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <null> failed
at com.google.common.base.Throwables.propagate(Throwables.java:160)

solution

文件位于rocketmq-externals/rocketmq-console/src/main/resources下面
修改application.properties
rocketmq.config.namesrvAddr=master:9876
rocketmq.config.isVIPChannel=false

http://master:9877

%5Btoc%5D%0A%23%23%20%20%E5%AE%89%E8%A3%85RocketMQ%0A%0A%23%23%23%23%20%E4%B8%8B%E8%BD%BD%0A%3E%20https%3A%2F%2Frocketmq.apache.org%2Fdocs%2Fquick-start%2F%0A%3E%20https%3A%2F%2Frocketmq.apache.org%2Frelease_notes%2Frelease-notes-4.9.0%2F%0A%0A%3E%20%E4%B8%8B%E8%BD%BD%0A%3E%20rocketmq-all-4.9.0-bin-release.zip%0A%0A%60%60%60%0Acd%20%2Fopt%0Amv%20%2Ftmp%2Frocketmq-all-4.9.0-bin-release.zip%20.%0Aunzip%20rocketmq-all-4.9.0-bin-release.zip%0Amv%20rocketmq-all-4.9.0-bin-release%20rocketmq%0A%60%60%60%0A%0A%E9%85%8D%E7%BD%AEbroker%0A%3E%20vi%20conf%2Fbroker.conf%0A%E8%BF%BD%E5%8A%A0%E5%A6%82%E4%B8%8B%E5%86%85%E5%AE%B9%0A%0A%60%60%60%0A%23name%20server%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%9C%B0%E5%9D%80%E5%8F%8A%E7%AB%AF%E5%8F%A3%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%A4%9A%E4%B8%AA%EF%BC%8C%E5%88%86%E5%8F%B7%E9%9A%94%E5%BC%80%0AnamesrvAddr%3D192.168.80.180%3A9876%0A%23%E6%98%AF%E5%90%A6%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BA%E9%BB%98%E8%AE%A4topic%EF%BC%8C%E7%94%9F%E4%BA%A7%E9%9C%80%E4%BF%9D%E6%8C%81%E5%85%B3%E9%97%AD%0AautoCreateTopicEnable%3Dtrue%0A%23brokerIP1%EF%BC%9A%E9%85%8D%E7%BD%AEbroker%E6%89%80%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84ip%E5%9C%B0%E5%9D%80%EF%BC%8C%E4%BB%A5%E4%BE%BFName%20Server%E8%BF%9E%E6%8E%A5%0AbrokerIP1%3D192.168.80.180%0A%60%60%60%0A%0A%23%23%23%23%20%E5%90%AF%E5%8A%A8%0A%3E%20%E5%90%AF%E5%8A%A8nameserver%0A%0A%60%60%60%0A%5Broot%40master%5D%23%20nohup%20sh%20bin%2Fmqnamesrv%20%26%0Atail%20-f%20%2Flogs%2Frocketmqlogs%2Fnameserver.log%0A%0A%5Broot%40master%20bin%5D%23%20jps%0A3235%20Jps%0A3207%20NamesrvStartup%0A%60%60%60%0A%0A%3E%20%E5%90%AF%E5%8A%A8broker%0A%0A%60%60%60%0A--%20%E6%97%A0%E5%8F%82%E6%95%B0%E5%90%AF%E5%8A%A8%0Anohup%20sh%20bin%2Fmqbroker%20-n%20master%3A9876%20%26%0A%0A--%20%E5%8A%A0%E8%BD%BD%E5%8F%82%E6%95%B0%E5%90%AF%E5%8A%A8%0Anohup%20sh%20bin%2Fmqbroker%20-n%20master%3A9876%20-c%20conf%2Fbroker.conf%0AautoCreateTopicEnable%3Dtrue%20%26%0A%0Atail%20-f%20%2Flogs%2Frocketmqlogs%2Fbroker.log%0A%0A%5Broot%40master%20rocketmq%5D%23%20jps%0A3429%20Jps%0A3207%20NamesrvStartup%0A3386%20BrokerStartup%0A%0A%60%60%60%0A%0A%3E%20rockertmq%E5%90%AF%E5%8A%A8%E9%BB%98%E8%AE%A4%E8%AE%BE%E7%BD%AE%E5%86%85%E5%AD%98%E8%BE%83%E5%A4%A7%E4%BC%9A%E5%AF%BC%E8%87%B4%E5%90%AF%E5%8A%A8%E5%A4%B1%E8%B4%A5%E9%9C%80%E8%A6%81%E6%89%8B%E5%8A%A8%E4%BF%AE%E6%94%B9%0A%0A%60%60%60%0Avi%20bin%2Frunserver.sh%0AJAVA_OPT%3D%22%24%7BJAVA_OPT%7D%20-server%20-Xms512m%20-Xmx512m%20-Xmn256m%20-XX%3AMetaspaceSize%3D128m%20-XX%3AMaxMetaspaceSize%3D320m%22%0A%0Avi%20bin%2Frunborker.sh%0AJAVA_OPT%3D%22%24%7BJAVA_OPT%7D%20-server%20-Xms512m%20-Xmx512m%20-Xmn256m%22%0A%60%60%60%0A%0A%23%23%20%E6%B5%8B%E8%AF%95%0A%0A%60%60%60%0A%5Broot%40master%20rocketmq%5D%23%20export%20NAMESRV_ADDR%3Dlocalhost%3A9876%0A%5Broot%40master%20rocketmq%5D%23%20sh%20bin%2Ftools.sh%20org.apache.rocketmq.example.quickstart.Producer%0A%0ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001109B1B6D35866692827F03E6%2C%20offsetMsgId%3DC0A8657F00002A9F00000000000316F4%2C%20messageQueue%3DMessageQueue%20%5Btopic%3DTopicTest%2C%20brokerName%3Dmaster%2C%20queueId%3D1%5D%2C%20queueOffset%3D249%5D%0ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001109B1B6D35866692828203E7%2C%20offsetMsgId%3DC0A8657F00002A9F00000000000317BF%2C%20messageQueue%3DMessageQueue%20%5Btopic%3DTopicTest%2C%20brokerName%3Dmaster%2C%20queueId%3D2%5D%2C%20queueOffset%3D249%5D%0A%60%60%60%0A%0A%0A%60%60%60%0A%5Broot%40master%20rocketmq%5D%23%20sh%20bin%2Ftools.sh%20org.apache.rocketmq.example.quickstart.Consumer%0A%0AConsumeMessageThread_8%20Receive%20New%20Messages%3A%20%5BMessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D203%2C%20queueOffset%3D229%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1647784877377%2C%20bornHost%3D%2F192.168.101.127%3A40132%2C%20storeTimestamp%3D1647784877378%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F000000000002D5EE%2C%20commitLogOffset%3D185838%2C%20bodyCRC%3D2121214082%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'TopicTest'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D250%2C%20CONSUME_START_TIME%3D1647786877924%2C%20UNIQ_KEY%3D7F000001109B1B6D3586669281410394%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2082%2C%20111%2C%2099%2C%20107%2C%20101%2C%20116%2C%2077%2C%2081%2C%2032%2C%2057%2C%2049%2C%2054%5D%2C%20transactionId%3D'null'%7D%5D%5D%20%0AConsumeMessageThread_12%20Receive%20New%20Messages%3A%20%5BMessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D203%2C%20queueOffset%3D228%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1647784877348%2C%20bornHost%3D%2F192.168.101.127%3A40132%2C%20storeTimestamp%3D1647784877349%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F000000000002D2C2%2C%20commitLogOffset%3D185026%2C%20bodyCRC%3D2030234779%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'TopicTest'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D250%2C%20CONSUME_START_TIME%3D1647786877846%2C%20UNIQ_KEY%3D7F000001109B1B6D3586669281240390%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2082%2C%20111%2C%2099%2C%20107%2C%20101%2C%20116%2C%2077%2C%2081%2C%2032%2C%2057%2C%2049%2C%2050%5D%2C%20transactionId%3D'null'%7D%5D%5D%0A%0A%60%60%60%0A%0A%0A%0A%3E%20rocketmq%E6%9C%8D%E5%8A%A1%E5%85%B3%E9%97%AD%0A%3E%20%E5%85%88%E5%85%B3broker%EF%BC%8C%E5%86%8D%E5%85%B3%E9%97%ADnameserver%0A%60%60%60%0A%E5%85%B3%E9%97%ADbroker%E6%9C%8D%E5%8A%A1%20%EF%BC%9Ash%20bin%2Fmqshutdown%20broker%0A%E5%85%B3%E9%97%ADnamesrv%E6%9C%8D%E5%8A%A1%EF%BC%9Ash%20bin%2Fmqshutdown%20namesrv%20%20%0A%60%60%60%0A%0A%23%23%20%E5%AE%89%E8%A3%85%E5%8F%AF%E8%A7%86%E5%8C%96%E7%95%8C%E9%9D%A2%0A%0A%3E%20https%3A%2F%2Fgithub.com%2Fapache%2Frocketmq-dashboard%0A%3E%20%E4%B8%8B%E8%BD%BDzip%E5%8C%85%0A%60%60%60%0Aunzip%20rocketmq-externals-master.zip%0A%5Broot%40master%20rocketmq-externals-master%5D%23%20cd%20rocketmq-dashboard-master%5Csrc%5Cmain%5Cresources%0Avi%20application.properties%0A%0Aserver%3A%0A%20%20port%3A%209877%0AnamesrvAddrs%3A%0A%20%20%20%20%20%20-%20master%3A9876%0A%0A%5Broot%40master%20rocketmq-console%5D%23%20mvn%20clean%20package%20-Dmaven.test.skip%3Dtrue%0A%5Broot%40master%20rocketmq-console%5D%23%20cd%20target%2F%0A%0Anohup%20%C2%A0java%20-jar%20rocketmq-dashboard-1.0.1-SNAPSHOT.jar%20%3E%20%2Fdata%2Fmq%2Frocketmq%2Frocket-console.log%202%3E%261%20%26%0A%60%60%60%0A%0A%3E%20issue%0A%0A%60%60%60%0Aava.lang.RuntimeException%3A%20org.apache.rocketmq.remoting.exception.RemotingConnectException%3A%20connect%20to%20%3Cnull%3E%20failed%0Aat%20com.google.common.base.Throwables.propagate(Throwables.java%3A160)%0A%60%60%60%0A%0A%3E%20solution%0A%0A%60%60%60%0A%E6%96%87%E4%BB%B6%E4%BD%8D%E4%BA%8Erocketmq-externals%2Frocketmq-console%2Fsrc%2Fmain%2Fresources%E4%B8%8B%E9%9D%A2%0A%E4%BF%AE%E6%94%B9application.properties%0Arocketmq.config.namesrvAddr%3Dmaster%3A9876%0Arocketmq.config.isVIPChannel%3Dfalse%0A%60%60%60%0A%0Ahttp%3A%2F%2Fmaster%3A9877%0A

RocketMQ 概述

创建时间:2020/9/2 13:13
更新时间:2022/3/20 14:30
作者:Chris
来源:https://www.cnblogs.com/weifeng1463/p/12889300.html

1 RocketMQ 概述

https://www.jianshu.com/p/2838890f3284
https://www.cnblogs.com/weifeng1463/p/12889300.html

高并发系统的核心组件之一,能够帮助业务系统解构提升开发效率和系统稳定性

1.1 MQ主要具有以下优势:

  1. 削峰填谷(主要解决瞬时写压力大于应用服务能力导致消息丢失、系统奔溃等问题)
  2. 系统解耦(解决不同重要程度、不同能力级别系统之间依赖导致一死全死)
  3. 提升性能(当存在一对多调用时,可以发一条消息给消息系统,让消息系统通知相关系统)
  4. 蓄流压测(线上有些链路不好压测,可以通过堆积一定量消息再放开来压测)

1.2 Rocketmq具有主要优势特性有:

  1. 支持事务型消息(消息发送和DB操作保持两方的最终一致性,rabbitmq和 kafka不支持.
  2. 支持结合rocketmq的多个系统之间数据最终一致性(多方事务,二方事务是前提)
  3. 支持18个级别的延迟消息(rabbitmq和kafka不支持)
  4. 支持指定次数和时间间隔的失败消息重发(kafka不支持,rabbitmq需要手动确认)
  5. 支持consumer端tag过滤,减少不必要的网络传输(rabbitmq和kafka不支持)
  6. 支持重复消费(rabbitmq不支持,kafka支持)

1.3 详细对比:

2 RocketMQ 集群部署结构

2.1 Name Server

Name Server是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。

2.2 Broker

Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave的对应关系通过指定相同的Broker Name,不同的Broker Id来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。

每个Broker与Name Server集群中的所有节点建立长连接,定时(每隔30s)注册Topic信息到所有Name Server。Name Server定时(每隔10s)扫描所有存活broker的连接,如果Name Server超过2分钟没有收到心跳,则Name Server断开与Broker的连接。

3.3 Producer

Producer与Name Server集群中的其中一个节点(随机选择)建立长连接,定期从Name Server取Topic路由信息,并向提供Topic服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。

Producer每隔30s(由ClientConfig的pollNameServerInterval)从Name server获取所有topic队列的最新情况,这意味着如果Broker不可用,Producer最多30s能够感知,在此期间内发往Broker的所有消息都会失败。

Producer每隔30s(由ClientConfig中heartbeatBrokerInterval决定)向所有关联的broker发送心跳,Broker每隔10s中扫描所有存活的连接,如果Broker在2分钟内没有收到心跳数据,则关闭与Producer的连接。

3.4 Consumer

consumer与Name Server集群中的其中一个节点(随机选择)建立长连接,定期从Name Server取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。

Consumer每隔30s从Name server获取topic的最新队列情况,这意味着Broker不可用时,Consumer最多最需要30s才能感知。

Consumer每隔30s(由ClientConfig中heartbeatBrokerInterval决定)向所有关联的broker发送心跳,Broker每隔10s扫描所有存活的连接,若某个连接2分钟内没有发送心跳数据,则关闭连接;并向该Consumer Group的所有Consumer发出通知,Group内的Consumer重新分配队列,然后继续消费。

当Consumer得到master宕机通知后,转向slave消费,slave不能保证master的消息100%都同步过来了,因此会有少量的消息丢失。但是一旦master恢复,未同步过去的消息会被最终消费掉。

消费者队列是消费者连接之后(或者之前有连接过)才创建的。我们将原生的消费者标识由 {IP}@{消费者group}扩展为 {IP}@{消费者group}{topic}{tag},(例如xxx.xxx.xxx.xxx@mqtest_producer-group_2m2sTest_tag-zyk)。
任何一个元素不同,都认为是不同的消费端,每个消费端会拥有一份自己消费队列(默认是broker队列数量*broker数量)。新挂载的消费者对列中拥有commitlog中的所有数据。

3.5 Topic

一个应用尽可能用一个Topic,消息子类型用tags来标识,tags可以由应用自由设置。只有发送消息设置了tags,消费方在订阅消息时,才可以利用tags 在broker做消息过滤。

3.6 key

每个消息在业务层面的唯一标识码,要设置到 keys 字段,方便将来定位消息丢失问题。服务器会为每个消息创建索引(哈希索引),应用可以通过 topic,key来查询这条消息内容,以及消息被谁消费。由于是哈希索引,请务必保证key 尽可能唯一,这样可以避免潜在的哈希冲突。

3 发布订阅大体流程

Rocketmq如何支持分布式事务消息

原理:大事务 = 小事务 + 异步

MQ与DB一致性原理(两方事务)

MQ消息、DB操作一致性方案:

  1. 发送消息到MQ服务器,此时消息状态为SEND_OK。此消息为consumer不可见。
  2. 执行DB操作;DB执行成功Commit DB操作,DB执行失败Rollback DB操作。
  3. 如果DB执行成功,回复MQ服务器,将状态为COMMIT_MESSAGE;如果DB执行失败,回复MQ服务器,将状态改为ROLLBACK_MESSAGE。注意此过程有可能失败
  4. MQ内部提供一个名为“事务状态服务”的服务,此服务会检查事务消息的状态,如果发现消息未COMMIT,则通过Producer启动时注册的TransactionCheckListener来回调业务系统,业务系统在checkLocalTransactionState方法中检查DB事务状态,如果成功,则回复COMMIT_MESSAGE,否则回复ROLLBACK_MESSAGE。

说明:

  1. 上面以DB为例,其实此处可以是任何业务或者数据源。

  2. 以上SEND_OK、COMMIT_MESSAGE、ROLLBACK_MESSAGE均是client jar提供的状态,在MQ服务器内部是一个数字。

  3. TransactionCheckListener 是在消息的commit或者rollback消息丢失的情况下才会回调(上图中灰色部分)。这种消息丢失只存在于断网或者rocketmq集群挂了的情况下。

  4. 当rocketmq集群挂了,如果采用异步刷盘,存在1s内数据丢失风险,异步刷盘场景下保障事务没有意义。

  5. 所以如果要核心业务用Rocketmq解决分布式事务问题,建议选择同步刷盘模式。

多系统之间数据一致性(多方事务)

当需要保证多方(超过2方)的分布式一致性,上面的两方事务一致性(通过Rocketmq的事务性消息解决)已经无法支持。这个时候需要引入TCC模式思想(Try-Confirm-Cancel,不清楚的自行百度)。

以上图交易系统为例:

  1. 交易系统创建订单(往DB插入一条记录),同时发送订单创建消息。通过RocketMq事务性消息保证一致性
  2. 接着执行完成订单所需的同步核心RPC服务(非核心的系统通过监听MQ消息自行处理,处理结果不会影响交易状态)。执行成功更改订单状态,同时发送MQ消息。
  3. 交易系统接受自己发送的订单创建消息,通过定时调度系统创建延时回滚任务(或者使用RocketMq的重试功能,设置第二次发送时间为定时任务的延迟创建时间。在非消息堵塞的情况下,消息第一次到达延迟为1ms左右,这时可能RPC还未执行完,订单状态还未设置为完成,第二次消费时间可以指定)。延迟任务先通过查询订单状态判断订单是否完成,完成则不创建回滚任务,否则创建。
    PS:多个RPC可以创建一个回滚任务,通过一个消费组接受一次消息就可以;也可以通过创建多个消费组,一个消息消费多次,每次消费创建一个RPC的回滚任务。 回滚任务失败,通过MQ的重发来重试。

以上是交易系统和其他系统之间保持最终一致性的解决方案。

4 消息分类

4.1 按照发送的特点

4.1.1 同步消息

同步发送是指消息发送方发出数据后,会阻塞直到MQ服务方发回响应消息。
应用场景:此种方式应用场景非常广泛,例如重要通知邮件、报名短信通知、营销短信系统等。

关键代码


import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;

@Slf4j
public class MqUtil {

    private DefaultMQProducer mqProducer;

    public void init(DefaultMQProducer mqProducer) {
        this.mqProducer = mqProducer;
    }

    public SendResult send(String topic, String tags, String message) {
        try {
            Message msg = new Message(topic, tags, message.getBytes(RemotingHelper.DEFAULT_CHARSET));
            // 发送消息到一个Broker
            SendResult sendResult = mqProducer.send(msg);
            log.info("发送MQ", topic, tags, message.getBytes(RemotingHelper.DEFAULT_CHARSET));
            // 通过sendResult返回消息是否成功送达
            return sendResult;
        } catch (MQClientException e) {
            throw new IpdException(ErrorCode.SYSTEM_ERROR, "MQ主题:" + topic + "不存在,请联系测试人员配置!");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 延迟发送
     *
     * @param topic
     * @param tags
     * @param message
     * @param delayTimeLevel 等级:1:延时1s,2:延时5s,3:延时10s,4:延时30s,5:延时1m
     * @return
     */
    @SneakyThrows
    public SendResult send(String topic, String tags, String message, int delayTimeLevel) {
        try {
            Message msg = new Message(topic, tags, message.getBytes(RemotingHelper.DEFAULT_CHARSET));
            log.info("延迟发送MQ", topic, tags, message.getBytes(RemotingHelper.DEFAULT_CHARSET));
            msg.setDelayTimeLevel(delayTimeLevel);
            // 发送消息到一个Broker
            SendResult sendResult = mqProducer.send(msg);
            // 通过sendResult返回消息是否成功送达
            return sendResult;
        } catch (MQClientException e) {
            throw new IpdException(ErrorCode.SYSTEM_ERROR, "MQ主题:" + topic + "不存在,请联系测试人员配置!");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

4.1.2 异步消息

异步发送是指发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。MQ 的异步发送,需要用户实现异步发送回调接口(SendCallback),在执行消息的异步发送时,应用不需要等待服务器响应即可直接返回,通过回调接口接收服务器响应,  并对服务器的响应结果进行处理。
应用场景:异步发送一般用于链路耗时较长,对 RT 响应时间较为敏感的业务场景,例如用户视频上传后通知启动转码服务,转码完成后通知推送转码结果等。


关键代码:producer.sendAsync(msg, new SendCallback() {//...});

4.1.3 单向消息

单向(Oneway)发送特点为只负责发送消息,不等待服务器回应且没有回调函数触发,即只发送请求不等待应答。
此方式发送消息的过程耗时非常短,一般在微秒级别。
应用场景:适用于某些耗时非常短,但对可靠性要求并不高的场景,例如日志收集。

关键代码:producer.sendOneway(msg);

4.2 按照使用功能特点

4.2.1 定时消息

// 定时消息,单位毫秒(ms),在指定时间戳(当前时间之后)进行投递,例如 2016-03-07 16:21:00 投递。
// 如果被设置成当前时间戳之前的某个时刻,消息将立刻投递给消费者。    
long timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-03-07 16:21:00").getTime();    
msg.setStartDeliverTime(timeStamp);
// 发送消息,只要不抛异常就是成功    
SendResult sendResult = producer.send(msg);   

4.2.2 延时消息

Message sendMsg = new Message(topic, tags, message.getBytes());
sendMsg.setDelayTimeLevel(delayLevel);
// 默认3秒超时
SendResult sendResult = rocketMQProducer.send(sendMsg);
%5Btoc%5D%0A%0A%23%23%201%20RocketMQ%20%E6%A6%82%E8%BF%B0%0A%0Ahttps%3A%2F%2Fwww.jianshu.com%2Fp%2F2838890f3284%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fweifeng1463%2Fp%2F12889300.html%0A%0A%3E%20%E9%AB%98%E5%B9%B6%E5%8F%91%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%A0%B8%E5%BF%83%E7%BB%84%E4%BB%B6%E4%B9%8B%E4%B8%80%EF%BC%8C%E8%83%BD%E5%A4%9F%E5%B8%AE%E5%8A%A9%E4%B8%9A%E5%8A%A1%E7%B3%BB%E7%BB%9F%E8%A7%A3%E6%9E%84%E6%8F%90%E5%8D%87%E5%BC%80%E5%8F%91%E6%95%88%E7%8E%87%E5%92%8C%E7%B3%BB%E7%BB%9F%E7%A8%B3%E5%AE%9A%E6%80%A7%0A%0A%23%23%23%201.1%20MQ%E4%B8%BB%E8%A6%81%E5%85%B7%E6%9C%89%E4%BB%A5%E4%B8%8B%E4%BC%98%E5%8A%BF%EF%BC%9A%0A%0A%3E%201.%20%E5%89%8A%E5%B3%B0%E5%A1%AB%E8%B0%B7%EF%BC%88%E4%B8%BB%E8%A6%81%E8%A7%A3%E5%86%B3%E7%9E%AC%E6%97%B6%E5%86%99%E5%8E%8B%E5%8A%9B%E5%A4%A7%E4%BA%8E%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E8%83%BD%E5%8A%9B%E5%AF%BC%E8%87%B4%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E3%80%81%E7%B3%BB%E7%BB%9F%E5%A5%94%E6%BA%83%E7%AD%89%E9%97%AE%E9%A2%98%EF%BC%89%0A%3E%202.%20%E7%B3%BB%E7%BB%9F%E8%A7%A3%E8%80%A6%EF%BC%88%E8%A7%A3%E5%86%B3%E4%B8%8D%E5%90%8C%E9%87%8D%E8%A6%81%E7%A8%8B%E5%BA%A6%E3%80%81%E4%B8%8D%E5%90%8C%E8%83%BD%E5%8A%9B%E7%BA%A7%E5%88%AB%E7%B3%BB%E7%BB%9F%E4%B9%8B%E9%97%B4%E4%BE%9D%E8%B5%96%E5%AF%BC%E8%87%B4%E4%B8%80%E6%AD%BB%E5%85%A8%E6%AD%BB%EF%BC%89%0A%3E%203.%20%E6%8F%90%E5%8D%87%E6%80%A7%E8%83%BD%EF%BC%88%E5%BD%93%E5%AD%98%E5%9C%A8%E4%B8%80%E5%AF%B9%E5%A4%9A%E8%B0%83%E7%94%A8%E6%97%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%8F%91%E4%B8%80%E6%9D%A1%E6%B6%88%E6%81%AF%E7%BB%99%E6%B6%88%E6%81%AF%E7%B3%BB%E7%BB%9F%EF%BC%8C%E8%AE%A9%E6%B6%88%E6%81%AF%E7%B3%BB%E7%BB%9F%E9%80%9A%E7%9F%A5%E7%9B%B8%E5%85%B3%E7%B3%BB%E7%BB%9F%EF%BC%89%0A%3E%204.%20%E8%93%84%E6%B5%81%E5%8E%8B%E6%B5%8B%EF%BC%88%E7%BA%BF%E4%B8%8A%E6%9C%89%E4%BA%9B%E9%93%BE%E8%B7%AF%E4%B8%8D%E5%A5%BD%E5%8E%8B%E6%B5%8B%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%A0%86%E7%A7%AF%E4%B8%80%E5%AE%9A%E9%87%8F%E6%B6%88%E6%81%AF%E5%86%8D%E6%94%BE%E5%BC%80%E6%9D%A5%E5%8E%8B%E6%B5%8B%EF%BC%89%0A%0A%23%23%23%201.2%20Rocketmq%E5%85%B7%E6%9C%89%E4%B8%BB%E8%A6%81%E4%BC%98%E5%8A%BF%E7%89%B9%E6%80%A7%E6%9C%89%EF%BC%9A%0A%0A%3E%201.%20%20%E6%94%AF%E6%8C%81%E4%BA%8B%E5%8A%A1%E5%9E%8B%E6%B6%88%E6%81%AF%EF%BC%88%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E5%92%8CDB%E6%93%8D%E4%BD%9C%E4%BF%9D%E6%8C%81%E4%B8%A4%E6%96%B9%E7%9A%84%E6%9C%80%E7%BB%88%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%8Crabbitmq%E5%92%8C%20kafka%E4%B8%8D%E6%94%AF%E6%8C%81.%0A%3E%202.%20%20%E6%94%AF%E6%8C%81%E7%BB%93%E5%90%88rocketmq%E7%9A%84%E5%A4%9A%E4%B8%AA%E7%B3%BB%E7%BB%9F%E4%B9%8B%E9%97%B4%E6%95%B0%E6%8D%AE%E6%9C%80%E7%BB%88%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%88%E5%A4%9A%E6%96%B9%E4%BA%8B%E5%8A%A1%EF%BC%8C%E4%BA%8C%E6%96%B9%E4%BA%8B%E5%8A%A1%E6%98%AF%E5%89%8D%E6%8F%90%EF%BC%89%0A%3E%203.%20%20%E6%94%AF%E6%8C%8118%E4%B8%AA%E7%BA%A7%E5%88%AB%E7%9A%84%E5%BB%B6%E8%BF%9F%E6%B6%88%E6%81%AF%EF%BC%88rabbitmq%E5%92%8Ckafka%E4%B8%8D%E6%94%AF%E6%8C%81%EF%BC%89%0A%3E%204.%20%20%E6%94%AF%E6%8C%81%E6%8C%87%E5%AE%9A%E6%AC%A1%E6%95%B0%E5%92%8C%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%E7%9A%84%E5%A4%B1%E8%B4%A5%E6%B6%88%E6%81%AF%E9%87%8D%E5%8F%91%EF%BC%88kafka%E4%B8%8D%E6%94%AF%E6%8C%81%EF%BC%8Crabbitmq%E9%9C%80%E8%A6%81%E6%89%8B%E5%8A%A8%E7%A1%AE%E8%AE%A4%EF%BC%89%0A%3E%205.%20%20%E6%94%AF%E6%8C%81consumer%E7%AB%AFtag%E8%BF%87%E6%BB%A4%EF%BC%8C%E5%87%8F%E5%B0%91%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%EF%BC%88rabbitmq%E5%92%8Ckafka%E4%B8%8D%E6%94%AF%E6%8C%81%EF%BC%89%0A%3E%206.%20%20%E6%94%AF%E6%8C%81%E9%87%8D%E5%A4%8D%E6%B6%88%E8%B4%B9%EF%BC%88rabbitmq%E4%B8%8D%E6%94%AF%E6%8C%81%EF%BC%8Ckafka%E6%94%AF%E6%8C%81%EF%BC%89%0A%0A%0A%0A%23%23%23%201.3%20%E8%AF%A6%E7%BB%86%E5%AF%B9%E6%AF%94%EF%BC%9A%0A%0A!%5Baed5cdb1f0349dc200f61386e1686356.png%5D(en-resource%3A%2F%2Fdatabase%2F596%3A1)%0A%0A%0A%23%23%202%20RocketMQ%20%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2%E7%BB%93%E6%9E%84%0A%0A!%5Bcefb2fd3ac558f5dd3785014efd9bd13.png%5D(en-resource%3A%2F%2Fdatabase%2F595%3A1)%0A%0A%0A%23%23%23%202.1%20Name%20Server%0A%0A%3E%20%20Name%20Server%E6%98%AF%E4%B8%80%E4%B8%AA%E5%87%A0%E4%B9%8E%E6%97%A0%E7%8A%B6%E6%80%81%E8%8A%82%E7%82%B9%EF%BC%8C%E5%8F%AF%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2%EF%BC%8C%E8%8A%82%E7%82%B9%E4%B9%8B%E9%97%B4%E6%97%A0%E4%BB%BB%E4%BD%95%E4%BF%A1%E6%81%AF%E5%90%8C%E6%AD%A5%E3%80%82%0A%0A%23%23%23%202.2%20Broker%0A%0A%3E%20Broker%E9%83%A8%E7%BD%B2%E7%9B%B8%E5%AF%B9%E5%A4%8D%E6%9D%82%EF%BC%8CBroker%E5%88%86%E4%B8%BAMaster%E4%B8%8ESlave%EF%BC%8C%E4%B8%80%E4%B8%AAMaster%E5%8F%AF%E4%BB%A5%E5%AF%B9%E5%BA%94%E5%A4%9A%E4%B8%AASlave%EF%BC%8C%E4%BD%86%E6%98%AF%E4%B8%80%E4%B8%AASlave%E5%8F%AA%E8%83%BD%E5%AF%B9%E5%BA%94%E4%B8%80%E4%B8%AAMaster%EF%BC%8CMaster%E4%B8%8ESlave%E7%9A%84%E5%AF%B9%E5%BA%94%E5%85%B3%E7%B3%BB%E9%80%9A%E8%BF%87%E6%8C%87%E5%AE%9A%E7%9B%B8%E5%90%8C%E7%9A%84Broker%20Name%EF%BC%8C%E4%B8%8D%E5%90%8C%E7%9A%84Broker%20Id%E6%9D%A5%E5%AE%9A%E4%B9%89%EF%BC%8C**BrokerId%E4%B8%BA0%E8%A1%A8%E7%A4%BAMaster%EF%BC%8C%E9%9D%9E0%E8%A1%A8%E7%A4%BASlave**%E3%80%82Master%E4%B9%9F%E5%8F%AF%E4%BB%A5%E9%83%A8%E7%BD%B2%E5%A4%9A%E4%B8%AA%E3%80%82%0A%3E%0A%3E%20%E6%AF%8F%E4%B8%AABroker%E4%B8%8EName%20Server%E9%9B%86%E7%BE%A4%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E8%8A%82%E7%82%B9%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%AE%9A%E6%97%B6(%E6%AF%8F%E9%9A%9430s)%E6%B3%A8%E5%86%8CTopic%E4%BF%A1%E6%81%AF%E5%88%B0%E6%89%80%E6%9C%89Name%20Server%E3%80%82Name%20Server%E5%AE%9A%E6%97%B6(%E6%AF%8F%E9%9A%9410s)%E6%89%AB%E6%8F%8F%E6%89%80%E6%9C%89%E5%AD%98%E6%B4%BBbroker%E7%9A%84%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%A6%82%E6%9E%9CName%20Server%E8%B6%85%E8%BF%872%E5%88%86%E9%92%9F%E6%B2%A1%E6%9C%89%E6%94%B6%E5%88%B0%E5%BF%83%E8%B7%B3%EF%BC%8C%E5%88%99Name%20Server%E6%96%AD%E5%BC%80%E4%B8%8EBroker%E7%9A%84%E8%BF%9E%E6%8E%A5%E3%80%82%0A%0A%23%23%23%203.3%20Producer%0A%0A%3E%20Producer%E4%B8%8EName%20Server%E9%9B%86%E7%BE%A4%E4%B8%AD%E7%9A%84%E5%85%B6%E4%B8%AD%E4%B8%80%E4%B8%AA%E8%8A%82%E7%82%B9(%E9%9A%8F%E6%9C%BA%E9%80%89%E6%8B%A9)%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%AE%9A%E6%9C%9F%E4%BB%8EName%20Server%E5%8F%96Topic%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%B9%B6%E5%90%91%E6%8F%90%E4%BE%9BTopic%E6%9C%8D%E5%8A%A1%E7%9A%84Master%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E4%B8%94%E5%AE%9A%E6%97%B6%E5%90%91Master%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E3%80%82Producer%E5%AE%8C%E5%85%A8%E6%97%A0%E7%8A%B6%E6%80%81%EF%BC%8C%E5%8F%AF%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2%E3%80%82%0A%3E%0A%3E%20Producer%E6%AF%8F%E9%9A%9430s%EF%BC%88%E7%94%B1ClientConfig%E7%9A%84pollNameServerInterval%EF%BC%89%E4%BB%8EName%20server%E8%8E%B7%E5%8F%96%E6%89%80%E6%9C%89topic%E9%98%9F%E5%88%97%E7%9A%84%E6%9C%80%E6%96%B0%E6%83%85%E5%86%B5%EF%BC%8C%E8%BF%99%E6%84%8F%E5%91%B3%E7%9D%80%E5%A6%82%E6%9E%9CBroker%E4%B8%8D%E5%8F%AF%E7%94%A8%EF%BC%8CProducer%E6%9C%80%E5%A4%9A30s%E8%83%BD%E5%A4%9F%E6%84%9F%E7%9F%A5%EF%BC%8C%E5%9C%A8%E6%AD%A4%E6%9C%9F%E9%97%B4%E5%86%85%E5%8F%91%E5%BE%80Broker%E7%9A%84%E6%89%80%E6%9C%89%E6%B6%88%E6%81%AF%E9%83%BD%E4%BC%9A%E5%A4%B1%E8%B4%A5%E3%80%82%0A%3E%0A%3E%20Producer%E6%AF%8F%E9%9A%9430s%EF%BC%88%E7%94%B1ClientConfig%E4%B8%ADheartbeatBrokerInterval%E5%86%B3%E5%AE%9A%EF%BC%89%E5%90%91%E6%89%80%E6%9C%89%E5%85%B3%E8%81%94%E7%9A%84broker%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%EF%BC%8CBroker%E6%AF%8F%E9%9A%9410s%E4%B8%AD%E6%89%AB%E6%8F%8F%E6%89%80%E6%9C%89%E5%AD%98%E6%B4%BB%E7%9A%84%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%A6%82%E6%9E%9CBroker%E5%9C%A82%E5%88%86%E9%92%9F%E5%86%85%E6%B2%A1%E6%9C%89%E6%94%B6%E5%88%B0%E5%BF%83%E8%B7%B3%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%88%99%E5%85%B3%E9%97%AD%E4%B8%8EProducer%E7%9A%84%E8%BF%9E%E6%8E%A5%E3%80%82%0A%0A%23%23%23%203.4%20Consumer%0A%0A%3E%20%20consumer%E4%B8%8EName%20Server%E9%9B%86%E7%BE%A4%E4%B8%AD%E7%9A%84%E5%85%B6%E4%B8%AD%E4%B8%80%E4%B8%AA%E8%8A%82%E7%82%B9(%E9%9A%8F%E6%9C%BA%E9%80%89%E6%8B%A9)%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E5%AE%9A%E6%9C%9F%E4%BB%8EName%20Server%E5%8F%96Topic%E8%B7%AF%E7%94%B1%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%B9%B6%E5%90%91%E6%8F%90%E4%BE%9BTopic%E6%9C%8D%E5%8A%A1%E7%9A%84Master%E3%80%81Slave%E5%BB%BA%E7%AB%8B%E9%95%BF%E8%BF%9E%E6%8E%A5%EF%BC%8C%E4%B8%94%E5%AE%9A%E6%97%B6%E5%90%91Master%E3%80%81Slave%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E3%80%82Consumer%E6%97%A2%E5%8F%AF%E4%BB%A5%E4%BB%8EMaster%E8%AE%A2%E9%98%85%E6%B6%88%E6%81%AF%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E4%BB%8ESlave%E8%AE%A2%E9%98%85%E6%B6%88%E6%81%AF%EF%BC%8C%E8%AE%A2%E9%98%85%E8%A7%84%E5%88%99%E7%94%B1Broker%E9%85%8D%E7%BD%AE%E5%86%B3%E5%AE%9A%E3%80%82%0A%3E%0A%3E%20Consumer%E6%AF%8F%E9%9A%9430s%E4%BB%8EName%20server%E8%8E%B7%E5%8F%96topic%E7%9A%84%E6%9C%80%E6%96%B0%E9%98%9F%E5%88%97%E6%83%85%E5%86%B5%EF%BC%8C%E8%BF%99%E6%84%8F%E5%91%B3%E7%9D%80Broker%E4%B8%8D%E5%8F%AF%E7%94%A8%E6%97%B6%EF%BC%8CConsumer%E6%9C%80%E5%A4%9A%E6%9C%80%E9%9C%80%E8%A6%8130s%E6%89%8D%E8%83%BD%E6%84%9F%E7%9F%A5%E3%80%82%0A%3E%0A%3E%20Consumer%E6%AF%8F%E9%9A%9430s%EF%BC%88%E7%94%B1ClientConfig%E4%B8%ADheartbeatBrokerInterval%E5%86%B3%E5%AE%9A%EF%BC%89%E5%90%91%E6%89%80%E6%9C%89%E5%85%B3%E8%81%94%E7%9A%84broker%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%EF%BC%8CBroker%E6%AF%8F%E9%9A%9410s%E6%89%AB%E6%8F%8F%E6%89%80%E6%9C%89%E5%AD%98%E6%B4%BB%E7%9A%84%E8%BF%9E%E6%8E%A5%EF%BC%8C%E8%8B%A5%E6%9F%90%E4%B8%AA%E8%BF%9E%E6%8E%A52%E5%88%86%E9%92%9F%E5%86%85%E6%B2%A1%E6%9C%89%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%88%99%E5%85%B3%E9%97%AD%E8%BF%9E%E6%8E%A5%EF%BC%9B%E5%B9%B6%E5%90%91%E8%AF%A5Consumer%20Group%E7%9A%84%E6%89%80%E6%9C%89Consumer%E5%8F%91%E5%87%BA%E9%80%9A%E7%9F%A5%EF%BC%8CGroup%E5%86%85%E7%9A%84Consumer%E9%87%8D%E6%96%B0%E5%88%86%E9%85%8D%E9%98%9F%E5%88%97%EF%BC%8C%E7%84%B6%E5%90%8E%E7%BB%A7%E7%BB%AD%E6%B6%88%E8%B4%B9%E3%80%82%0A%3E%0A%3E%20%E5%BD%93Consumer%E5%BE%97%E5%88%B0master%E5%AE%95%E6%9C%BA%E9%80%9A%E7%9F%A5%E5%90%8E%EF%BC%8C%E8%BD%AC%E5%90%91slave%E6%B6%88%E8%B4%B9%EF%BC%8Cslave%E4%B8%8D%E8%83%BD%E4%BF%9D%E8%AF%81master%E7%9A%84%E6%B6%88%E6%81%AF100%25%E9%83%BD%E5%90%8C%E6%AD%A5%E8%BF%87%E6%9D%A5%E4%BA%86%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%BC%9A%E6%9C%89%E5%B0%91%E9%87%8F%E7%9A%84%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E3%80%82%E4%BD%86%E6%98%AF%E4%B8%80%E6%97%A6master%E6%81%A2%E5%A4%8D%EF%BC%8C%E6%9C%AA%E5%90%8C%E6%AD%A5%E8%BF%87%E5%8E%BB%E7%9A%84%E6%B6%88%E6%81%AF%E4%BC%9A%E8%A2%AB%E6%9C%80%E7%BB%88%E6%B6%88%E8%B4%B9%E6%8E%89%E3%80%82%0A%3E%0A%3E%20**%E6%B6%88%E8%B4%B9%E8%80%85%E9%98%9F%E5%88%97**%E6%98%AF%E6%B6%88%E8%B4%B9%E8%80%85%E8%BF%9E%E6%8E%A5%E4%B9%8B%E5%90%8E%EF%BC%88%E6%88%96%E8%80%85%E4%B9%8B%E5%89%8D%E6%9C%89%E8%BF%9E%E6%8E%A5%E8%BF%87%EF%BC%89%E6%89%8D%E5%88%9B%E5%BB%BA%E7%9A%84%E3%80%82%E6%88%91%E4%BB%AC%E5%B0%86%E5%8E%9F%E7%94%9F%E7%9A%84%E6%B6%88%E8%B4%B9%E8%80%85%E6%A0%87%E8%AF%86%E7%94%B1%20%7BIP%7D%40%7B%E6%B6%88%E8%B4%B9%E8%80%85group%7D%E6%89%A9%E5%B1%95%E4%B8%BA%20%7BIP%7D%40%7B%E6%B6%88%E8%B4%B9%E8%80%85group%7D%7Btopic%7D%7Btag%7D%EF%BC%8C%EF%BC%88%E4%BE%8B%E5%A6%82%5Bxxx.xxx.xxx.xxx%40mqtest_producer-group_2m2sTest_tag-zyk%5D(http%3A%2F%2Fxxx.xxx.xxx.xxx%40mqtest_producer-group_2m2sTest_tag-zyk)%EF%BC%89%E3%80%82%0A%3E%20%E4%BB%BB%E4%BD%95%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E4%B8%8D%E5%90%8C%EF%BC%8C%E9%83%BD%E8%AE%A4%E4%B8%BA%E6%98%AF%E4%B8%8D%E5%90%8C%E7%9A%84%E6%B6%88%E8%B4%B9%E7%AB%AF%EF%BC%8C%E6%AF%8F%E4%B8%AA%E6%B6%88%E8%B4%B9%E7%AB%AF%E4%BC%9A%E6%8B%A5%E6%9C%89%E4%B8%80%E4%BB%BD%E8%87%AA%E5%B7%B1%E6%B6%88%E8%B4%B9%E9%98%9F%E5%88%97%EF%BC%88%E9%BB%98%E8%AE%A4%E6%98%AFbroker%E9%98%9F%E5%88%97%E6%95%B0%E9%87%8F*broker%E6%95%B0%E9%87%8F%EF%BC%89%E3%80%82%E6%96%B0%E6%8C%82%E8%BD%BD%E7%9A%84%E6%B6%88%E8%B4%B9%E8%80%85%E5%AF%B9%E5%88%97%E4%B8%AD%E6%8B%A5%E6%9C%89commitlog%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A%23%23%23%203.5%20Topic%0A%0A%3E%20%E4%B8%80%E4%B8%AA%E5%BA%94%E7%94%A8%E5%B0%BD%E5%8F%AF%E8%83%BD%E7%94%A8%E4%B8%80%E4%B8%AATopic%EF%BC%8C%E6%B6%88%E6%81%AF%E5%AD%90%E7%B1%BB%E5%9E%8B%E7%94%A8tags%E6%9D%A5%E6%A0%87%E8%AF%86%EF%BC%8Ctags%E5%8F%AF%E4%BB%A5%E7%94%B1%E5%BA%94%E7%94%A8%E8%87%AA%E7%94%B1%E8%AE%BE%E7%BD%AE%E3%80%82%E5%8F%AA%E6%9C%89%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E8%AE%BE%E7%BD%AE%E4%BA%86tags%EF%BC%8C%E6%B6%88%E8%B4%B9%E6%96%B9%E5%9C%A8%E8%AE%A2%E9%98%85%E6%B6%88%E6%81%AF%E6%97%B6%EF%BC%8C%E6%89%8D%E5%8F%AF%E4%BB%A5%E5%88%A9%E7%94%A8tags%20%E5%9C%A8broker%E5%81%9A%E6%B6%88%E6%81%AF%E8%BF%87%E6%BB%A4%E3%80%82%0A%0A%23%23%23%203.6%20key%0A%0A%3E%20%E6%AF%8F%E4%B8%AA%E6%B6%88%E6%81%AF%E5%9C%A8%E4%B8%9A%E5%8A%A1%E5%B1%82%E9%9D%A2%E7%9A%84%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86%E7%A0%81%EF%BC%8C%E8%A6%81%E8%AE%BE%E7%BD%AE%E5%88%B0%20keys%20%E5%AD%97%E6%AE%B5%EF%BC%8C%E6%96%B9%E4%BE%BF%E5%B0%86%E6%9D%A5%E5%AE%9A%E4%BD%8D%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98%E3%80%82%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BC%9A%E4%B8%BA%E6%AF%8F%E4%B8%AA%E6%B6%88%E6%81%AF%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95(%E5%93%88%E5%B8%8C%E7%B4%A2%E5%BC%95)%EF%BC%8C%E5%BA%94%E7%94%A8%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%20topic%EF%BC%8Ckey%E6%9D%A5%E6%9F%A5%E8%AF%A2%E8%BF%99%E6%9D%A1%E6%B6%88%E6%81%AF%E5%86%85%E5%AE%B9%EF%BC%8C%E4%BB%A5%E5%8F%8A%E6%B6%88%E6%81%AF%E8%A2%AB%E8%B0%81%E6%B6%88%E8%B4%B9%E3%80%82**%E7%94%B1%E4%BA%8E%E6%98%AF%E5%93%88%E5%B8%8C%E7%B4%A2%E5%BC%95%EF%BC%8C%E8%AF%B7%E5%8A%A1%E5%BF%85%E4%BF%9D%E8%AF%81key%20%E5%B0%BD%E5%8F%AF%E8%83%BD%E5%94%AF%E4%B8%80%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%8F%AF%E4%BB%A5%E9%81%BF%E5%85%8D%E6%BD%9C%E5%9C%A8%E7%9A%84%E5%93%88%E5%B8%8C%E5%86%B2%E7%AA%81%E3%80%82**%0A%0A%23%23%203%20%E5%8F%91%E5%B8%83%E8%AE%A2%E9%98%85%E5%A4%A7%E4%BD%93%E6%B5%81%E7%A8%8B%0A%0A%0A-%20producer%E7%94%9F%E4%BA%A7%E8%80%85%E8%BF%9E%E6%8E%A5nameserver%EF%BC%8C%E4%BA%A7%E7%94%9F%E6%95%B0%E6%8D%AE%E6%94%BE%E5%85%A5%E4%B8%8D%E5%90%8C%E7%9A%84topic%EF%BC%9B%0A-%20%E5%AF%B9%E4%BA%8ERocketMQ%EF%BC%8C%E4%B8%80%E4%B8%AATopic%E5%8F%AF%E4%BB%A5%E5%88%86%E5%B8%83%E5%9C%A8%E5%90%84%E4%B8%AABroker%E4%B8%8A%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E6%8A%8A%E4%B8%80%E4%B8%AATopic%E5%88%86%E5%B8%83%E5%9C%A8%E4%B8%80%E4%B8%AABroker%E4%B8%8A%E7%9A%84%E5%AD%90%E9%9B%86%E5%AE%9A%E4%B9%89%E4%B8%BA%E4%B8%80%E4%B8%AATopic%E5%88%86%E7%89%87%EF%BC%9B%0A-%20%E5%B0%86Topic%E5%88%86%E7%89%87%E5%86%8D%E5%88%87%E5%88%86%E4%B8%BA%E8%8B%A5%E5%B9%B2%E7%AD%89%E5%88%86%EF%BC%8C%E5%85%B6%E4%B8%AD%E7%9A%84%E4%B8%80%E4%BB%BD%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AAQueue%E3%80%82%E6%AF%8F%E4%B8%AATopic%E5%88%86%E7%89%87%E7%AD%89%E5%88%86%E7%9A%84Queue%E7%9A%84%E6%95%B0%E9%87%8F%E5%8F%AF%E4%BB%A5%E4%B8%8D%E5%90%8C%EF%BC%8C%E7%94%B1%E7%94%A8%E6%88%B7%E5%9C%A8%E5%88%9B%E5%BB%BATopic%E6%97%B6%E6%8C%87%E5%AE%9A%E3%80%82%0A-%20consumer%E6%B6%88%E8%B4%B9%E8%80%85%E8%BF%9E%E6%8E%A5nameserver%EF%BC%8C%E6%A0%B9%E6%8D%AEbroker%E5%88%86%E9%85%8D%E7%9A%84Queue%E6%9D%A5%E6%B6%88%E8%B4%B9%E6%95%B0%E6%8D%AE%0A%0A%0A%23%23%23%23%23%20%20Rocketmq%E5%A6%82%E4%BD%95%E6%94%AF%E6%8C%81%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E6%B6%88%E6%81%AF%0A%0A%3E%20%E5%8E%9F%E7%90%86%EF%BC%9A%E5%A4%A7%E4%BA%8B%E5%8A%A1%20%3D%20%E5%B0%8F%E4%BA%8B%E5%8A%A1%20%2B%20%E5%BC%82%E6%AD%A5%09%0A%0A%23%23%23%23%23%20MQ%E4%B8%8EDB%E4%B8%80%E8%87%B4%E6%80%A7%E5%8E%9F%E7%90%86%EF%BC%88%E4%B8%A4%E6%96%B9%E4%BA%8B%E5%8A%A1%EF%BC%89%0A%0A!%5B23aaa622bb37e2b9744ce37769cbbf05.png%5D(en-resource%3A%2F%2Fdatabase%2F593%3A1)%0A%0A%0A%3E%20MQ%E6%B6%88%E6%81%AF%E3%80%81DB%E6%93%8D%E4%BD%9C%E4%B8%80%E8%87%B4%E6%80%A7%E6%96%B9%E6%A1%88%EF%BC%9A%0A%3E%0A%3E%201.%20%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E5%88%B0MQ%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E6%AD%A4%E6%97%B6%E6%B6%88%E6%81%AF%E7%8A%B6%E6%80%81%E4%B8%BASEND_OK%E3%80%82%E6%AD%A4%E6%B6%88%E6%81%AF%E4%B8%BAconsumer%E4%B8%8D%E5%8F%AF%E8%A7%81%E3%80%82%0A%3E%202.%20%E6%89%A7%E8%A1%8CDB%E6%93%8D%E4%BD%9C%EF%BC%9BDB%E6%89%A7%E8%A1%8C%E6%88%90%E5%8A%9FCommit%20DB%E6%93%8D%E4%BD%9C%EF%BC%8CDB%E6%89%A7%E8%A1%8C%E5%A4%B1%E8%B4%A5Rollback%20DB%E6%93%8D%E4%BD%9C%E3%80%82%0A%3E%203.%20%E5%A6%82%E6%9E%9CDB%E6%89%A7%E8%A1%8C%E6%88%90%E5%8A%9F%EF%BC%8C%E5%9B%9E%E5%A4%8DMQ%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%B0%86%E7%8A%B6%E6%80%81%E4%B8%BACOMMIT_MESSAGE%EF%BC%9B%E5%A6%82%E6%9E%9CDB%E6%89%A7%E8%A1%8C%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%9B%9E%E5%A4%8DMQ%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%B0%86%E7%8A%B6%E6%80%81%E6%94%B9%E4%B8%BAROLLBACK_MESSAGE%E3%80%82**%E6%B3%A8%E6%84%8F%E6%AD%A4%E8%BF%87%E7%A8%8B%E6%9C%89%E5%8F%AF%E8%83%BD%E5%A4%B1%E8%B4%A5**%E3%80%82%0A%3E%204.%20MQ%E5%86%85%E9%83%A8%E6%8F%90%E4%BE%9B%E4%B8%80%E4%B8%AA%E5%90%8D%E4%B8%BA%60%E2%80%9C%E4%BA%8B%E5%8A%A1%E7%8A%B6%E6%80%81%E6%9C%8D%E5%8A%A1%E2%80%9D%60%E7%9A%84%E6%9C%8D%E5%8A%A1%EF%BC%8C%E6%AD%A4%E6%9C%8D%E5%8A%A1%E4%BC%9A%E6%A3%80%E6%9F%A5%E4%BA%8B%E5%8A%A1%E6%B6%88%E6%81%AF%E7%9A%84%E7%8A%B6%E6%80%81%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%8F%91%E7%8E%B0%E6%B6%88%E6%81%AF%E6%9C%AACOMMIT%EF%BC%8C%E5%88%99%E9%80%9A%E8%BF%87Producer%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B3%A8%E5%86%8C%E7%9A%84%60TransactionCheckListener%60%E6%9D%A5%E5%9B%9E%E8%B0%83%E4%B8%9A%E5%8A%A1%E7%B3%BB%E7%BB%9F%EF%BC%8C%E4%B8%9A%E5%8A%A1%E7%B3%BB%E7%BB%9F%E5%9C%A8%60checkLocalTransactionState%60%E6%96%B9%E6%B3%95%E4%B8%AD%E6%A3%80%E6%9F%A5DB%E4%BA%8B%E5%8A%A1%E7%8A%B6%E6%80%81%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%88%90%E5%8A%9F%EF%BC%8C%E5%88%99%E5%9B%9E%E5%A4%8DCOMMIT_MESSAGE%EF%BC%8C%E5%90%A6%E5%88%99%E5%9B%9E%E5%A4%8DROLLBACK_MESSAGE%E3%80%82%0A%0A%E8%AF%B4%E6%98%8E%EF%BC%9A%0A%0A%3E%201.%20%E4%B8%8A%E9%9D%A2%E4%BB%A5DB%E4%B8%BA%E4%BE%8B%EF%BC%8C%E5%85%B6%E5%AE%9E%E6%AD%A4%E5%A4%84%E5%8F%AF%E4%BB%A5%E6%98%AF%E4%BB%BB%E4%BD%95%E4%B8%9A%E5%8A%A1%E6%88%96%E8%80%85%E6%95%B0%E6%8D%AE%E6%BA%90%E3%80%82%0A%3E%0A%3E%202.%20%E4%BB%A5%E4%B8%8ASEND_OK%E3%80%81COMMIT_MESSAGE%E3%80%81ROLLBACK_MESSAGE%E5%9D%87%E6%98%AFclient%20jar%E6%8F%90%E4%BE%9B%E7%9A%84%E7%8A%B6%E6%80%81%EF%BC%8C%E5%9C%A8MQ%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%86%85%E9%83%A8%E6%98%AF%E4%B8%80%E4%B8%AA%E6%95%B0%E5%AD%97%E3%80%82%0A%3E%0A%3E%203.%20%60TransactionCheckListener%60%20%E6%98%AF%E5%9C%A8%E6%B6%88%E6%81%AF%E7%9A%84commit%E6%88%96%E8%80%85rollback%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E6%89%8D%E4%BC%9A%E5%9B%9E%E8%B0%83%EF%BC%88%E4%B8%8A%E5%9B%BE%E4%B8%AD%E7%81%B0%E8%89%B2%E9%83%A8%E5%88%86%EF%BC%89%E3%80%82%E8%BF%99%E7%A7%8D%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E5%8F%AA%E5%AD%98%E5%9C%A8%E4%BA%8E%E6%96%AD%E7%BD%91%E6%88%96%E8%80%85rocketmq%E9%9B%86%E7%BE%A4%E6%8C%82%E4%BA%86%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E3%80%82%0A%3E%0A%3E%204.%20%E5%BD%93rocketmq%E9%9B%86%E7%BE%A4%E6%8C%82%E4%BA%86%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%87%87%E7%94%A8%E5%BC%82%E6%AD%A5%E5%88%B7%E7%9B%98%EF%BC%8C%E5%AD%98%E5%9C%A81s%E5%86%85%E6%95%B0%E6%8D%AE%E4%B8%A2%E5%A4%B1%E9%A3%8E%E9%99%A9%EF%BC%8C%E5%BC%82%E6%AD%A5%E5%88%B7%E7%9B%98%E5%9C%BA%E6%99%AF%E4%B8%8B%E4%BF%9D%E9%9A%9C%E4%BA%8B%E5%8A%A1%E6%B2%A1%E6%9C%89%E6%84%8F%E4%B9%89%E3%80%82%0A%3E%0A%3E%205.%20%E6%89%80%E4%BB%A5%E5%A6%82%E6%9E%9C%E8%A6%81%E6%A0%B8%E5%BF%83%E4%B8%9A%E5%8A%A1%E7%94%A8Rocketmq%E8%A7%A3%E5%86%B3%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E9%97%AE%E9%A2%98%EF%BC%8C%E5%BB%BA%E8%AE%AE%E9%80%89%E6%8B%A9%E5%90%8C%E6%AD%A5%E5%88%B7%E7%9B%98%E6%A8%A1%E5%BC%8F%E3%80%82%0A%0A%23%23%23%23%23%20%E5%A4%9A%E7%B3%BB%E7%BB%9F%E4%B9%8B%E9%97%B4%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%88%E5%A4%9A%E6%96%B9%E4%BA%8B%E5%8A%A1%EF%BC%89%0A%0A!%5Ba54750c861289bfecdc43041beaf4c80.png%5D(en-resource%3A%2F%2Fdatabase%2F594%3A1)%0A%0A%0A%3E%20%E5%BD%93%E9%9C%80%E8%A6%81%E4%BF%9D%E8%AF%81%E5%A4%9A%E6%96%B9%EF%BC%88%E8%B6%85%E8%BF%872%E6%96%B9%EF%BC%89%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%8C%E4%B8%8A%E9%9D%A2%E7%9A%84%E4%B8%A4%E6%96%B9%E4%BA%8B%E5%8A%A1%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%88%E9%80%9A%E8%BF%87Rocketmq%E7%9A%84%E4%BA%8B%E5%8A%A1%E6%80%A7%E6%B6%88%E6%81%AF%E8%A7%A3%E5%86%B3%EF%BC%89%E5%B7%B2%E7%BB%8F%E6%97%A0%E6%B3%95%E6%94%AF%E6%8C%81%E3%80%82%E8%BF%99%E4%B8%AA%E6%97%B6%E5%80%99%E9%9C%80%E8%A6%81%E5%BC%95%E5%85%A5TCC%E6%A8%A1%E5%BC%8F%E6%80%9D%E6%83%B3%EF%BC%88%60Try-Confirm-Cancel%60%EF%BC%8C%E4%B8%8D%E6%B8%85%E6%A5%9A%E7%9A%84%E8%87%AA%E8%A1%8C%E7%99%BE%E5%BA%A6%EF%BC%89%E3%80%82%0A%0A%E4%BB%A5%E4%B8%8A%E5%9B%BE%E4%BA%A4%E6%98%93%E7%B3%BB%E7%BB%9F%E4%B8%BA%E4%BE%8B%EF%BC%9A%0A%3E%201.%20%E4%BA%A4%E6%98%93%E7%B3%BB%E7%BB%9F%E5%88%9B%E5%BB%BA%E8%AE%A2%E5%8D%95%EF%BC%88%E5%BE%80DB%E6%8F%92%E5%85%A5%E4%B8%80%E6%9D%A1%E8%AE%B0%E5%BD%95%EF%BC%89%EF%BC%8C%E5%90%8C%E6%97%B6%E5%8F%91%E9%80%81%E8%AE%A2%E5%8D%95%E5%88%9B%E5%BB%BA%E6%B6%88%E6%81%AF%E3%80%82%E9%80%9A%E8%BF%87RocketMq%E4%BA%8B%E5%8A%A1%E6%80%A7%E6%B6%88%E6%81%AF%E4%BF%9D%E8%AF%81%E4%B8%80%E8%87%B4%E6%80%A7%0A%3E%202.%20%E6%8E%A5%E7%9D%80%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%88%90%E8%AE%A2%E5%8D%95%E6%89%80%E9%9C%80%E7%9A%84%E5%90%8C%E6%AD%A5%E6%A0%B8%E5%BF%83RPC%E6%9C%8D%E5%8A%A1%EF%BC%88%E9%9D%9E%E6%A0%B8%E5%BF%83%E7%9A%84%E7%B3%BB%E7%BB%9F%E9%80%9A%E8%BF%87%E7%9B%91%E5%90%ACMQ%E6%B6%88%E6%81%AF%E8%87%AA%E8%A1%8C%E5%A4%84%E7%90%86%EF%BC%8C%E5%A4%84%E7%90%86%E7%BB%93%E6%9E%9C%E4%B8%8D%E4%BC%9A%E5%BD%B1%E5%93%8D%E4%BA%A4%E6%98%93%E7%8A%B6%E6%80%81%EF%BC%89%E3%80%82%E6%89%A7%E8%A1%8C%E6%88%90%E5%8A%9F%E6%9B%B4%E6%94%B9%E8%AE%A2%E5%8D%95%E7%8A%B6%E6%80%81%EF%BC%8C%E5%90%8C%E6%97%B6%E5%8F%91%E9%80%81MQ%E6%B6%88%E6%81%AF%E3%80%82%0A%3E%203.%20%E4%BA%A4%E6%98%93%E7%B3%BB%E7%BB%9F%E6%8E%A5%E5%8F%97%E8%87%AA%E5%B7%B1%E5%8F%91%E9%80%81%E7%9A%84%E8%AE%A2%E5%8D%95%E5%88%9B%E5%BB%BA%E6%B6%88%E6%81%AF%EF%BC%8C%E9%80%9A%E8%BF%87%E5%AE%9A%E6%97%B6%E8%B0%83%E5%BA%A6%E7%B3%BB%E7%BB%9F%E5%88%9B%E5%BB%BA%E5%BB%B6%E6%97%B6%E5%9B%9E%E6%BB%9A%E4%BB%BB%E5%8A%A1%EF%BC%88%E6%88%96%E8%80%85%E4%BD%BF%E7%94%A8%60RocketMq%E7%9A%84%E9%87%8D%E8%AF%95%E5%8A%9F%E8%83%BD%60%EF%BC%8C%E8%AE%BE%E7%BD%AE%E7%AC%AC%E4%BA%8C%E6%AC%A1%E5%8F%91%E9%80%81%E6%97%B6%E9%97%B4%E4%B8%BA%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E7%9A%84%E5%BB%B6%E8%BF%9F%E5%88%9B%E5%BB%BA%E6%97%B6%E9%97%B4%E3%80%82%E5%9C%A8%E9%9D%9E%E6%B6%88%E6%81%AF%E5%A0%B5%E5%A1%9E%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E6%B6%88%E6%81%AF%E7%AC%AC%E4%B8%80%E6%AC%A1%E5%88%B0%E8%BE%BE%E5%BB%B6%E8%BF%9F%E4%B8%BA1ms%E5%B7%A6%E5%8F%B3%EF%BC%8C%E8%BF%99%E6%97%B6%E5%8F%AF%E8%83%BDRPC%E8%BF%98%E6%9C%AA%E6%89%A7%E8%A1%8C%E5%AE%8C%EF%BC%8C%E8%AE%A2%E5%8D%95%E7%8A%B6%E6%80%81%E8%BF%98%E6%9C%AA%E8%AE%BE%E7%BD%AE%E4%B8%BA%E5%AE%8C%E6%88%90%EF%BC%8C%E7%AC%AC%E4%BA%8C%E6%AC%A1%E6%B6%88%E8%B4%B9%E6%97%B6%E9%97%B4%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%EF%BC%89%E3%80%82%E5%BB%B6%E8%BF%9F%E4%BB%BB%E5%8A%A1%E5%85%88%E9%80%9A%E8%BF%87%E6%9F%A5%E8%AF%A2%E8%AE%A2%E5%8D%95%E7%8A%B6%E6%80%81%E5%88%A4%E6%96%AD%E8%AE%A2%E5%8D%95%E6%98%AF%E5%90%A6%E5%AE%8C%E6%88%90%EF%BC%8C%E5%AE%8C%E6%88%90%E5%88%99%E4%B8%8D%E5%88%9B%E5%BB%BA%E5%9B%9E%E6%BB%9A%E4%BB%BB%E5%8A%A1%EF%BC%8C%E5%90%A6%E5%88%99%E5%88%9B%E5%BB%BA%E3%80%82%20%0APS%EF%BC%9A%E5%A4%9A%E4%B8%AARPC%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%9B%9E%E6%BB%9A%E4%BB%BB%E5%8A%A1%EF%BC%8C%E9%80%9A%E8%BF%87%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E7%BB%84%E6%8E%A5%E5%8F%97%E4%B8%80%E6%AC%A1%E6%B6%88%E6%81%AF%E5%B0%B1%E5%8F%AF%E4%BB%A5%EF%BC%9B%E4%B9%9F%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%88%9B%E5%BB%BA%E5%A4%9A%E4%B8%AA%E6%B6%88%E8%B4%B9%E7%BB%84%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E5%A4%9A%E6%AC%A1%EF%BC%8C%E6%AF%8F%E6%AC%A1%E6%B6%88%E8%B4%B9%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AARPC%E7%9A%84%E5%9B%9E%E6%BB%9A%E4%BB%BB%E5%8A%A1%E3%80%82%20%20%E5%9B%9E%E6%BB%9A%E4%BB%BB%E5%8A%A1%E5%A4%B1%E8%B4%A5%EF%BC%8C%E9%80%9A%E8%BF%87MQ%E7%9A%84%E9%87%8D%E5%8F%91%E6%9D%A5%E9%87%8D%E8%AF%95%E3%80%82%0A%0A%E4%BB%A5%E4%B8%8A%E6%98%AF%E4%BA%A4%E6%98%93%E7%B3%BB%E7%BB%9F%E5%92%8C%E5%85%B6%E4%BB%96%E7%B3%BB%E7%BB%9F%E4%B9%8B%E9%97%B4%E4%BF%9D%E6%8C%81%E6%9C%80%E7%BB%88%E4%B8%80%E8%87%B4%E6%80%A7%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%E3%80%82%0A%0A%0A%23%23%204%20%E6%B6%88%E6%81%AF%E5%88%86%E7%B1%BB%0A%23%23%23%204.1%20%E6%8C%89%E7%85%A7%E5%8F%91%E9%80%81%E7%9A%84%E7%89%B9%E7%82%B9%0A%23%23%23%23%204.1.1%20%E5%90%8C%E6%AD%A5%E6%B6%88%E6%81%AF%0A%3E%20%E5%90%8C%E6%AD%A5%E5%8F%91%E9%80%81%E6%98%AF%E6%8C%87%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E6%96%B9%E5%8F%91%E5%87%BA%E6%95%B0%E6%8D%AE%E5%90%8E%EF%BC%8C%E4%BC%9A%E9%98%BB%E5%A1%9E%E7%9B%B4%E5%88%B0MQ%E6%9C%8D%E5%8A%A1%E6%96%B9%E5%8F%91%E5%9B%9E%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF%E3%80%82%0A%3E%20%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%EF%BC%9A%E6%AD%A4%E7%A7%8D%E6%96%B9%E5%BC%8F%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E9%9D%9E%E5%B8%B8%E5%B9%BF%E6%B3%9B%EF%BC%8C%E4%BE%8B%E5%A6%82%E9%87%8D%E8%A6%81%E9%80%9A%E7%9F%A5%E9%82%AE%E4%BB%B6%E3%80%81%E6%8A%A5%E5%90%8D%E7%9F%AD%E4%BF%A1%E9%80%9A%E7%9F%A5%E3%80%81%E8%90%A5%E9%94%80%E7%9F%AD%E4%BF%A1%E7%B3%BB%E7%BB%9F%E7%AD%89%E3%80%82%0A%0A!%5B88aef886994944aa8f0bb27dbe1500d1.png%5D(en-resource%3A%2F%2Fdatabase%2F1157%3A1)%0A%0A%3E%20%E5%85%B3%E9%94%AE%E4%BB%A3%E7%A0%81%0A%60%60%60java%0A%0Aimport%20lombok.SneakyThrows%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.apache.rocketmq.client.exception.MQClientException%3B%0Aimport%20org.apache.rocketmq.client.producer.DefaultMQProducer%3B%0Aimport%20org.apache.rocketmq.client.producer.SendResult%3B%0Aimport%20org.apache.rocketmq.common.message.Message%3B%0Aimport%20org.apache.rocketmq.remoting.common.RemotingHelper%3B%0A%0A%40Slf4j%0Apublic%20class%20MqUtil%20%7B%0A%0A%20%20%20%20private%20DefaultMQProducer%20mqProducer%3B%0A%0A%20%20%20%20public%20void%20init(DefaultMQProducer%20mqProducer)%20%7B%0A%20%20%20%20%20%20%20%20this.mqProducer%20%3D%20mqProducer%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20SendResult%20send(String%20topic%2C%20String%20tags%2C%20String%20message)%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%20msg%20%3D%20new%20Message(topic%2C%20tags%2C%20message.getBytes(RemotingHelper.DEFAULT_CHARSET))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E5%88%B0%E4%B8%80%E4%B8%AABroker%0A%20%20%20%20%20%20%20%20%20%20%20%20SendResult%20sendResult%20%3D%20mqProducer.send(msg)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22%E5%8F%91%E9%80%81MQ%22%2C%20topic%2C%20tags%2C%20message.getBytes(RemotingHelper.DEFAULT_CHARSET))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E9%80%9A%E8%BF%87sendResult%E8%BF%94%E5%9B%9E%E6%B6%88%E6%81%AF%E6%98%AF%E5%90%A6%E6%88%90%E5%8A%9F%E9%80%81%E8%BE%BE%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20sendResult%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(MQClientException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20IpdException(ErrorCode.SYSTEM_ERROR%2C%20%22MQ%E4%B8%BB%E9%A2%98%EF%BC%9A%22%20%2B%20topic%20%2B%20%22%E4%B8%8D%E5%AD%98%E5%9C%A8%2C%E8%AF%B7%E8%81%94%E7%B3%BB%E6%B5%8B%E8%AF%95%E4%BA%BA%E5%91%98%E9%85%8D%E7%BD%AE!%22)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(Exception%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20RuntimeException(e)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%BB%B6%E8%BF%9F%E5%8F%91%E9%80%81%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%40param%20topic%0A%20%20%20%20%20*%20%40param%20tags%0A%20%20%20%20%20*%20%40param%20message%0A%20%20%20%20%20*%20%40param%20delayTimeLevel%20%E7%AD%89%E7%BA%A7%EF%BC%9A1%3A%E5%BB%B6%E6%97%B61s%EF%BC%8C2%3A%E5%BB%B6%E6%97%B65s%EF%BC%8C3%3A%E5%BB%B6%E6%97%B610s%EF%BC%8C4%3A%E5%BB%B6%E6%97%B630s%EF%BC%8C5%3A%E5%BB%B6%E6%97%B61m%0A%20%20%20%20%20*%20%40return%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40SneakyThrows%0A%20%20%20%20public%20SendResult%20send(String%20topic%2C%20String%20tags%2C%20String%20message%2C%20int%20delayTimeLevel)%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%20msg%20%3D%20new%20Message(topic%2C%20tags%2C%20message.getBytes(RemotingHelper.DEFAULT_CHARSET))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22%E5%BB%B6%E8%BF%9F%E5%8F%91%E9%80%81MQ%22%2C%20topic%2C%20tags%2C%20message.getBytes(RemotingHelper.DEFAULT_CHARSET))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20msg.setDelayTimeLevel(delayTimeLevel)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E5%88%B0%E4%B8%80%E4%B8%AABroker%0A%20%20%20%20%20%20%20%20%20%20%20%20SendResult%20sendResult%20%3D%20mqProducer.send(msg)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E9%80%9A%E8%BF%87sendResult%E8%BF%94%E5%9B%9E%E6%B6%88%E6%81%AF%E6%98%AF%E5%90%A6%E6%88%90%E5%8A%9F%E9%80%81%E8%BE%BE%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20sendResult%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(MQClientException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20IpdException(ErrorCode.SYSTEM_ERROR%2C%20%22MQ%E4%B8%BB%E9%A2%98%EF%BC%9A%22%20%2B%20topic%20%2B%20%22%E4%B8%8D%E5%AD%98%E5%9C%A8%2C%E8%AF%B7%E8%81%94%E7%B3%BB%E6%B5%8B%E8%AF%95%E4%BA%BA%E5%91%98%E9%85%8D%E7%BD%AE!%22)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(Exception%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20RuntimeException(e)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%204.1.2%20%E5%BC%82%E6%AD%A5%E6%B6%88%E6%81%AF%0A%3E%20%E5%BC%82%E6%AD%A5%E5%8F%91%E9%80%81%E6%98%AF%E6%8C%87%E5%8F%91%E9%80%81%E6%96%B9%E5%8F%91%E5%87%BA%E6%95%B0%E6%8D%AE%E5%90%8E%EF%BC%8C%E4%B8%8D%E7%AD%89%E6%8E%A5%E6%94%B6%E6%96%B9%E5%8F%91%E5%9B%9E%E5%93%8D%E5%BA%94%EF%BC%8C%E6%8E%A5%E7%9D%80%E5%8F%91%E9%80%81%E4%B8%8B%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%8C%85%E7%9A%84%E9%80%9A%E8%AE%AF%E6%96%B9%E5%BC%8F%E3%80%82MQ%20%E7%9A%84%E5%BC%82%E6%AD%A5%E5%8F%91%E9%80%81%EF%BC%8C%E9%9C%80%E8%A6%81%E7%94%A8%E6%88%B7%E5%AE%9E%E7%8E%B0%E5%BC%82%E6%AD%A5%E5%8F%91%E9%80%81%E5%9B%9E%E8%B0%83%E6%8E%A5%E5%8F%A3%EF%BC%88SendCallback%EF%BC%89%EF%BC%8C%E5%9C%A8%E6%89%A7%E8%A1%8C%E6%B6%88%E6%81%AF%E7%9A%84%E5%BC%82%E6%AD%A5%E5%8F%91%E9%80%81%E6%97%B6%EF%BC%8C%E5%BA%94%E7%94%A8%E4%B8%8D%E9%9C%80%E8%A6%81%E7%AD%89%E5%BE%85%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%93%8D%E5%BA%94%E5%8D%B3%E5%8F%AF%E7%9B%B4%E6%8E%A5%E8%BF%94%E5%9B%9E%EF%BC%8C%E9%80%9A%E8%BF%87%E5%9B%9E%E8%B0%83%E6%8E%A5%E5%8F%A3%E6%8E%A5%E6%94%B6%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%93%8D%E5%BA%94%EF%BC%8C%E3%80%80%E3%80%80%E5%B9%B6%E5%AF%B9%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E5%93%8D%E5%BA%94%E7%BB%93%E6%9E%9C%E8%BF%9B%E8%A1%8C%E5%A4%84%E7%90%86%E3%80%82%0A%3E%20%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%EF%BC%9A%E5%BC%82%E6%AD%A5%E5%8F%91%E9%80%81%E4%B8%80%E8%88%AC%E7%94%A8%E4%BA%8E%E9%93%BE%E8%B7%AF%E8%80%97%E6%97%B6%E8%BE%83%E9%95%BF%EF%BC%8C%E5%AF%B9%20RT%20%E5%93%8D%E5%BA%94%E6%97%B6%E9%97%B4%E8%BE%83%E4%B8%BA%E6%95%8F%E6%84%9F%E7%9A%84%E4%B8%9A%E5%8A%A1%E5%9C%BA%E6%99%AF%EF%BC%8C%E4%BE%8B%E5%A6%82%E7%94%A8%E6%88%B7%E8%A7%86%E9%A2%91%E4%B8%8A%E4%BC%A0%E5%90%8E%E9%80%9A%E7%9F%A5%E5%90%AF%E5%8A%A8%E8%BD%AC%E7%A0%81%E6%9C%8D%E5%8A%A1%EF%BC%8C%E8%BD%AC%E7%A0%81%E5%AE%8C%E6%88%90%E5%90%8E%E9%80%9A%E7%9F%A5%E6%8E%A8%E9%80%81%E8%BD%AC%E7%A0%81%E7%BB%93%E6%9E%9C%E7%AD%89%E3%80%82%0A%0A!%5B23f68b57fd3edb0c2c0488603954f670.png%5D(en-resource%3A%2F%2Fdatabase%2F1159%3A1)%0A%60%0A%E5%85%B3%E9%94%AE%E4%BB%A3%E7%A0%81%EF%BC%9Aproducer.sendAsync(msg%2C%C2%A0new%20SendCallback()%20%7B%2F%2F...%7D)%3B%60%0A%0A%23%23%23%23%204.1.3%20%E5%8D%95%E5%90%91%E6%B6%88%E6%81%AF%0A%3E%20%20%E5%8D%95%E5%90%91%EF%BC%88Oneway%EF%BC%89%E5%8F%91%E9%80%81%E7%89%B9%E7%82%B9%E4%B8%BA%E5%8F%AA%E8%B4%9F%E8%B4%A3%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%EF%BC%8C%E4%B8%8D%E7%AD%89%E5%BE%85%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%9B%9E%E5%BA%94%E4%B8%94%E6%B2%A1%E6%9C%89%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E8%A7%A6%E5%8F%91%EF%BC%8C%E5%8D%B3%E5%8F%AA%E5%8F%91%E9%80%81%E8%AF%B7%E6%B1%82%E4%B8%8D%E7%AD%89%E5%BE%85%E5%BA%94%E7%AD%94%E3%80%82%0A%3E%20%20%E6%AD%A4%E6%96%B9%E5%BC%8F%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E7%9A%84%E8%BF%87%E7%A8%8B%E8%80%97%E6%97%B6%E9%9D%9E%E5%B8%B8%E7%9F%AD%EF%BC%8C%E4%B8%80%E8%88%AC%E5%9C%A8%E5%BE%AE%E7%A7%92%E7%BA%A7%E5%88%AB%E3%80%82%0A%3E%20%20%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%EF%BC%9A%E9%80%82%E7%94%A8%E4%BA%8E%E6%9F%90%E4%BA%9B%E8%80%97%E6%97%B6%E9%9D%9E%E5%B8%B8%E7%9F%AD%EF%BC%8C%E4%BD%86%E5%AF%B9%E5%8F%AF%E9%9D%A0%E6%80%A7%E8%A6%81%E6%B1%82%E5%B9%B6%E4%B8%8D%E9%AB%98%E7%9A%84%E5%9C%BA%E6%99%AF%EF%BC%8C%E4%BE%8B%E5%A6%82%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86%E3%80%82%0A%0A!%5B053c919dd06e63f78d833e930e5430dc.png%5D(en-resource%3A%2F%2Fdatabase%2F1161%3A1)%0A%0A%60%E5%85%B3%E9%94%AE%E4%BB%A3%E7%A0%81%EF%BC%9Aproducer.sendOneway(msg)%3B%60%0A%0A%23%23%23%204.2%20%E6%8C%89%E7%85%A7%E4%BD%BF%E7%94%A8%E5%8A%9F%E8%83%BD%E7%89%B9%E7%82%B9%0A%0A%23%23%23%23%204.2.1%20%E5%AE%9A%E6%97%B6%E6%B6%88%E6%81%AF%0A%60%60%60java%0A%2F%2F%20%E5%AE%9A%E6%97%B6%E6%B6%88%E6%81%AF%EF%BC%8C%E5%8D%95%E4%BD%8D%E6%AF%AB%E7%A7%92%EF%BC%88ms%EF%BC%89%EF%BC%8C%E5%9C%A8%E6%8C%87%E5%AE%9A%E6%97%B6%E9%97%B4%E6%88%B3%EF%BC%88%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4%E4%B9%8B%E5%90%8E%EF%BC%89%E8%BF%9B%E8%A1%8C%E6%8A%95%E9%80%92%EF%BC%8C%E4%BE%8B%E5%A6%82%202016-03-07%2016%3A21%3A00%20%E6%8A%95%E9%80%92%E3%80%82%0A%2F%2F%20%E5%A6%82%E6%9E%9C%E8%A2%AB%E8%AE%BE%E7%BD%AE%E6%88%90%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4%E6%88%B3%E4%B9%8B%E5%89%8D%E7%9A%84%E6%9F%90%E4%B8%AA%E6%97%B6%E5%88%BB%EF%BC%8C%E6%B6%88%E6%81%AF%E5%B0%86%E7%AB%8B%E5%88%BB%E6%8A%95%E9%80%92%E7%BB%99%E6%B6%88%E8%B4%B9%E8%80%85%E3%80%82%20%20%20%20%0Along%20timeStamp%20%3D%20new%20SimpleDateFormat(%22yyyy-MM-dd%20HH%3Amm%3Ass%22).parse(%222016-03-07%2016%3A21%3A00%22).getTime()%3B%20%20%20%20%0Amsg.setStartDeliverTime(timeStamp)%3B%0A%2F%2F%20%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%EF%BC%8C%E5%8F%AA%E8%A6%81%E4%B8%8D%E6%8A%9B%E5%BC%82%E5%B8%B8%E5%B0%B1%E6%98%AF%E6%88%90%E5%8A%9F%20%20%20%20%0ASendResult%20sendResult%20%3D%20producer.send(msg)%3B%20%20%20%0A%60%60%60%0A%0A%23%23%23%23%204.2.2%20%E5%BB%B6%E6%97%B6%E6%B6%88%E6%81%AF%0A%60%60%60java%0AMessage%20sendMsg%20%3D%20new%20Message(topic%2C%20tags%2C%20message.getBytes())%3B%0AsendMsg.setDelayTimeLevel(delayLevel)%3B%0A%2F%2F%20%E9%BB%98%E8%AE%A43%E7%A7%92%E8%B6%85%E6%97%B6%0ASendResult%20sendResult%20%3D%20rocketMQProducer.send(sendMsg)%3B%0A%60%60%60

CAS

创建时间:2022/3/7 22:42
更新时间:2022/3/19 17:16
作者:Chris

1 CAS的定义

CAS 全称"CompareAndSwap" 即比较并替换

CAS 操作包含三个操作数

  • 内存位置 V
  • 期望值 A
  • 新值 B

如果内存位置与期望值相匹配,那处理器会将该位置的值更新为新值,否则处理顺不做任何处理。

无论哪种情况,它都会在CAS指令之前返回该位置的值。(CAS一些特殊情况下返回CAS是否成功,而不提取当前值)

2 JDK中的CAS支持

怎么使用JDK中的CAS支持?

java中提供了对CAS的支持,具体在sun.misc.unsafe类中

/**
 *var1:表示操作的对象
 *var2:表示要操作对象中属性地址的偏移量
 *var4:表示要修改数据的期望值
 *var5:表示需要修改为的新值
*/
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

3 CAS的实现原理

CAS通过JNI的代码实现的,JNI [Java Native Interface], 允许java调用其它语言,而compareAndSwapxxx系统的方法就是借助‘C语言’来实现的。

以常用的Intel x86平台来说,最终映射到的cpu指令为 cmpxchg , 这是一条原子指令即不能再拆分,要么都执行要么都不执行,cpu执行此命令时,实现比较并替换的操作!

4 CAS存在的问题

4.1 CAS存在的问题

  • 1 高并发问题

  • 在高并发情况下,多个请求已经拿到了期望值和需要设置的新值,前面的线程进入compareAndSwap方法的线程后会改变原有的期望值为新值,则后面的线程获取锁和cpu资源后进入compareAndSwap会发现内存位置的值 与期望值不匹配,则会退出并进入自悬再次compareAndSwap,直到内存位置的值与期望值匹配修改成功为

  • 2 什么是ABA问题

  • CAS需要在操作值之前会先比较内存位置的值有没有发生变化,如果没有发生变化则更新。

  • 但是如果一个值原来是A,在CAS方法操作之前被别的线程改成了B,然后又改回成A,那么CAS比较内存位置的值时会发现它的值没有发生变化,但是实际上这个值是有变化的,这就是CAS的ABA问题

4.2 模拟ABA问题

public class CAS_ABA {

    private static AtomicInteger count = new AtomicInteger(1);

    public static void main(String[] args) {
        Thread mainThread = new Thread(() -> {
            System.out.println("thread name:" + Thread.currentThread().getName() + ", initValue:" + count.get());
            int expectValue = count.get();
            int newValue = expectValue + 1;
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean isSucceed = count.compareAndSet(expectValue, newValue);
            System.out.println("thread name:" + Thread.currentThread().getName() + ", CAS result:" + isSucceed);
        }, "main-thread");


        Thread otherThread = new Thread(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(20);
                int incrementValue = count.incrementAndGet();
                System.out.println("thread name:" + Thread.currentThread().getName() + "increment value:" + incrementValue);
                int decrementValue = count.decrementAndGet();
                System.out.println("thread name:" + Thread.currentThread().getName() + "decrement value:" + decrementValue);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "other-thread");

        mainThread.start();
        otherThread.start();
    }
}
thread name:main-thread, initValue:1
thread name:other-thread, increment value:2
thread name:other-thread, decrement value:1
thread name:main-thread, CAS result:true

可以看出other-thread线程将count加1后再减1,但mainThread对于count的值变化没有感知,成功修改并返回结果true

4.3 如果解决ABA问题

  • 如果你的系统对ABA问题不敏感,可以忽略ABA问题

  • 如果你的系统对ABA问题比较敏感,如银行系统,一种方式是不要使用CAS相关的原子类,直接使用 synchronized来保证数据安全性.

  • 如果你的系统对ABA问题比较敏感并且对并发也有要求,则可以使用

    java.util.concurrent.atomic.AtomicStampedReference

public boolean compareAndSet(V expectedReference,   //期望引用
                                 V newReference,    //新值的引用
                                 int expectedStamp, //期望引用的版本号
                                 int newStamp){      //新值版本号
        Pair<V> current = pair;
        return
            expectedReference == current.reference &&
            expectedStamp == current.stamp &&
            ((newReference == current.reference &&
              newStamp == current.stamp) ||
             casPair(current, Pair.of(newReference, newStamp)));
    }

如果要修改成功,需要expectedReference,expectedStamp与current里面的当前引用及当前引用的版本号相同

public class CAS_ABA2 {

    private static final AtomicStampedReference<Integer> count = new AtomicStampedReference<>(1, 1);

    public static void main(String[] args) {
        Thread mainThread = new Thread(() -> {
            System.out.println("thread name:" + Thread.currentThread().getName() + ", init reference:" + count.getReference() + ", init stamp:" + count.getStamp());
            Integer expectReference = count.getReference();
            int expectStamp = count.getStamp();

            Integer newReference = expectReference + 1;
            int newStamp = expectStamp + 1;
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean isSucceed = count.compareAndSet(expectReference, newReference, expectStamp, newStamp);
            System.out.println("thread name:" + Thread.currentThread().getName() + ", CAS result:" + isSucceed + ", " + "reference:" + count.getReference() + ", stamp:" + count.getStamp());
        }, "main-thread");


        Thread otherThread = new Thread(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(20);
                count.compareAndSet(count.getReference(), count.getReference() + 1, count.getStamp(),
                        count.getStamp() + 1);
                System.out.println("thread name:" + Thread.currentThread().getName() + ", increment reference:" + count.getReference() + ", stamp:" + count.getStamp());

                count.compareAndSet(count.getReference(), count.getReference() - 1, count.getStamp(),
                        count.getStamp() + 1);
                System.out.println("thread name:" + Thread.currentThread().getName() + ", decrement reference:" + count.getReference() + ", stamp:" + count.getStamp());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "other-thread");

        mainThread.start();
        otherThread.start();
    }
}
thread name:main-thread, init reference:1, init stamp:1
thread name:other-thread, increment reference:2, stamp:2
thread name:other-thread, decrement reference:1, stamp:3
thread name:main-thread, CAS result:false, reference:1, stamp:3
%5Btoc%5D%0A%23%23%201%20CAS%E7%9A%84%E5%AE%9A%E4%B9%89%0A%0A%3E%20CAS%20%E5%85%A8%E7%A7%B0%22CompareAndSwap%22%20%E5%8D%B3%E6%AF%94%E8%BE%83%E5%B9%B6%E6%9B%BF%E6%8D%A2%0A%3E%0A%3E%20CAS%20%E6%93%8D%E4%BD%9C%E5%8C%85%E5%90%AB%E4%B8%89%E4%B8%AA%E6%93%8D%E4%BD%9C%E6%95%B0%0A%3E-%20%E5%86%85%E5%AD%98%E4%BD%8D%E7%BD%AE%20V%0A%3E%20-%20%E6%9C%9F%E6%9C%9B%E5%80%BC%20A%0A%3E%20-%20%E6%96%B0%E5%80%BC%20B%0A%3E%20%0A%3E%20%E5%A6%82%E6%9E%9C%E5%86%85%E5%AD%98%E4%BD%8D%E7%BD%AE%E4%B8%8E%E6%9C%9F%E6%9C%9B%E5%80%BC%E7%9B%B8%E5%8C%B9%E9%85%8D%EF%BC%8C%E9%82%A3%E5%A4%84%E7%90%86%E5%99%A8%E4%BC%9A%E5%B0%86%E8%AF%A5%E4%BD%8D%E7%BD%AE%E7%9A%84%E5%80%BC%E6%9B%B4%E6%96%B0%E4%B8%BA%E6%96%B0%E5%80%BC%EF%BC%8C%E5%90%A6%E5%88%99%E5%A4%84%E7%90%86%E9%A1%BA%E4%B8%8D%E5%81%9A%E4%BB%BB%E4%BD%95%E5%A4%84%E7%90%86%E3%80%82%0A%3E%20%0A%3E%20%E6%97%A0%E8%AE%BA%E5%93%AA%E7%A7%8D%E6%83%85%E5%86%B5%EF%BC%8C%E5%AE%83%E9%83%BD%E4%BC%9A%E5%9C%A8CAS%E6%8C%87%E4%BB%A4%E4%B9%8B%E5%89%8D%E8%BF%94%E5%9B%9E%E8%AF%A5%E4%BD%8D%E7%BD%AE%E7%9A%84%E5%80%BC%E3%80%82%EF%BC%88CAS%E4%B8%80%E4%BA%9B%E7%89%B9%E6%AE%8A%E6%83%85%E5%86%B5%E4%B8%8B%E8%BF%94%E5%9B%9ECAS%E6%98%AF%E5%90%A6%E6%88%90%E5%8A%9F%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%8F%90%E5%8F%96%E5%BD%93%E5%89%8D%E5%80%BC%EF%BC%89%0A%0A%23%23%202%20JDK%E4%B8%AD%E7%9A%84CAS%E6%94%AF%E6%8C%81%0A%3E%20%E6%80%8E%E4%B9%88%E4%BD%BF%E7%94%A8JDK%E4%B8%AD%E7%9A%84CAS%E6%94%AF%E6%8C%81%EF%BC%9F%0A%3E%0A%3E%20java%E4%B8%AD%E6%8F%90%E4%BE%9B%E4%BA%86%E5%AF%B9CAS%E7%9A%84%E6%94%AF%E6%8C%81%EF%BC%8C%E5%85%B7%E4%BD%93%E5%9C%A8sun.misc.unsafe%E7%B1%BB%E4%B8%AD%0A%0A%60%60%60java%0A%2F**%0A%20*var1%3A%E8%A1%A8%E7%A4%BA%E6%93%8D%E4%BD%9C%E7%9A%84%E5%AF%B9%E8%B1%A1%0A%20*var2%3A%E8%A1%A8%E7%A4%BA%E8%A6%81%E6%93%8D%E4%BD%9C%E5%AF%B9%E8%B1%A1%E4%B8%AD%E5%B1%9E%E6%80%A7%E5%9C%B0%E5%9D%80%E7%9A%84%E5%81%8F%E7%A7%BB%E9%87%8F%0A%20*var4%3A%E8%A1%A8%E7%A4%BA%E8%A6%81%E4%BF%AE%E6%94%B9%E6%95%B0%E6%8D%AE%E7%9A%84%E6%9C%9F%E6%9C%9B%E5%80%BC%0A%20*var5%3A%E8%A1%A8%E7%A4%BA%E9%9C%80%E8%A6%81%E4%BF%AE%E6%94%B9%E4%B8%BA%E7%9A%84%E6%96%B0%E5%80%BC%0A*%2F%0Apublic%20final%20native%20boolean%20compareAndSwapObject(Object%20var1%2C%20long%20var2%2C%20Object%20var4%2C%20Object%20var5)%3B%0Apublic%20final%20native%20boolean%20compareAndSwapInt(Object%20var1%2C%20long%20var2%2C%20int%20var4%2C%20int%20var5)%3B%0Apublic%20final%20native%20boolean%20compareAndSwapLong(Object%20var1%2C%20long%20var2%2C%20long%20var4%2C%20long%20var6)%3B%0A%60%60%60%0A%0A%23%23%203%20CAS%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%0A%0A%3E%20CAS%E9%80%9A%E8%BF%87JNI%E7%9A%84%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8CJNI%20%5BJava%20Native%20Interface%5D%EF%BC%8C%20%E5%85%81%E8%AE%B8java%E8%B0%83%E7%94%A8%E5%85%B6%E5%AE%83%E8%AF%AD%E8%A8%80%EF%BC%8C%E8%80%8CcompareAndSwapxxx%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%96%B9%E6%B3%95%E5%B0%B1%E6%98%AF%E5%80%9F%E5%8A%A9%E2%80%98C%E8%AF%AD%E8%A8%80%E2%80%99%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%E4%BB%A5%E5%B8%B8%E7%94%A8%E7%9A%84Intel%20x86%E5%B9%B3%E5%8F%B0%E6%9D%A5%E8%AF%B4%EF%BC%8C%E6%9C%80%E7%BB%88%E6%98%A0%E5%B0%84%E5%88%B0%E7%9A%84cpu%E6%8C%87%E4%BB%A4%E4%B8%BA%20%60cmpxchg%60%20%2C%20%E8%BF%99%E6%98%AF%E4%B8%80%E6%9D%A1%E5%8E%9F%E5%AD%90%E6%8C%87%E4%BB%A4%E5%8D%B3%E4%B8%8D%E8%83%BD%E5%86%8D%E6%8B%86%E5%88%86%EF%BC%8C%E8%A6%81%E4%B9%88%E9%83%BD%E6%89%A7%E8%A1%8C%E8%A6%81%E4%B9%88%E9%83%BD%E4%B8%8D%E6%89%A7%E8%A1%8C%EF%BC%8Ccpu%E6%89%A7%E8%A1%8C%E6%AD%A4%E5%91%BD%E4%BB%A4%E6%97%B6%EF%BC%8C%E5%AE%9E%E7%8E%B0%E6%AF%94%E8%BE%83%E5%B9%B6%E6%9B%BF%E6%8D%A2%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%81%0A%0A%23%23%204%20CAS%E5%AD%98%E5%9C%A8%E7%9A%84%E9%97%AE%E9%A2%98%0A%23%23%23%23%20%204.1%20CAS%E5%AD%98%E5%9C%A8%E7%9A%84%E9%97%AE%E9%A2%98%0A%0A%3E%20-%201%20%E9%AB%98%E5%B9%B6%E5%8F%91%E9%97%AE%E9%A2%98%0A%3E-%20%E5%9C%A8%E9%AB%98%E5%B9%B6%E5%8F%91%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E5%A4%9A%E4%B8%AA%E8%AF%B7%E6%B1%82%E5%B7%B2%E7%BB%8F%E6%8B%BF%E5%88%B0%E4%BA%86%E6%9C%9F%E6%9C%9B%E5%80%BC%E5%92%8C%E9%9C%80%E8%A6%81%E8%AE%BE%E7%BD%AE%E7%9A%84%E6%96%B0%E5%80%BC%EF%BC%8C%E5%89%8D%E9%9D%A2%E7%9A%84%E7%BA%BF%E7%A8%8B%E8%BF%9B%E5%85%A5compareAndSwap%E6%96%B9%E6%B3%95%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%90%8E%E4%BC%9A%E6%94%B9%E5%8F%98%E5%8E%9F%E6%9C%89%E7%9A%84%E6%9C%9F%E6%9C%9B%E5%80%BC%E4%B8%BA%E6%96%B0%E5%80%BC%EF%BC%8C%E5%88%99%E5%90%8E%E9%9D%A2%E7%9A%84%E7%BA%BF%E7%A8%8B%E8%8E%B7%E5%8F%96%E9%94%81%E5%92%8Ccpu%E8%B5%84%E6%BA%90%E5%90%8E%E8%BF%9B%E5%85%A5compareAndSwap%E4%BC%9A%E5%8F%91%E7%8E%B0%E5%86%85%E5%AD%98%E4%BD%8D%E7%BD%AE%E7%9A%84%E5%80%BC%20%E4%B8%8E%E6%9C%9F%E6%9C%9B%E5%80%BC%E4%B8%8D%E5%8C%B9%E9%85%8D%EF%BC%8C%E5%88%99%E4%BC%9A%E9%80%80%E5%87%BA%E5%B9%B6%E8%BF%9B%E5%85%A5%E8%87%AA%E6%82%AC%E5%86%8D%E6%AC%A1compareAndSwap%EF%BC%8C%E7%9B%B4%E5%88%B0%E5%86%85%E5%AD%98%E4%BD%8D%E7%BD%AE%E7%9A%84%E5%80%BC%E4%B8%8E%E6%9C%9F%E6%9C%9B%E5%80%BC%E5%8C%B9%E9%85%8D%E4%BF%AE%E6%94%B9%E6%88%90%E5%8A%9F%E4%B8%BA%0A%3E%20%0A%3E%20-%202%20%E4%BB%80%E4%B9%88%E6%98%AFABA%E9%97%AE%E9%A2%98%0A%3E-%20CAS%E9%9C%80%E8%A6%81%E5%9C%A8%E6%93%8D%E4%BD%9C%E5%80%BC%E4%B9%8B%E5%89%8D%E4%BC%9A%E5%85%88%E6%AF%94%E8%BE%83%E5%86%85%E5%AD%98%E4%BD%8D%E7%BD%AE%E7%9A%84%E5%80%BC%E6%9C%89%E6%B2%A1%E6%9C%89%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%E5%88%99%E6%9B%B4%E6%96%B0%E3%80%82%0A%3E%20-%20%E4%BD%86%E6%98%AF%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E5%80%BC%E5%8E%9F%E6%9D%A5%E6%98%AFA%EF%BC%8C%E5%9C%A8CAS%E6%96%B9%E6%B3%95%E6%93%8D%E4%BD%9C%E4%B9%8B%E5%89%8D%E8%A2%AB%E5%88%AB%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%94%B9%E6%88%90%E4%BA%86B%EF%BC%8C%E7%84%B6%E5%90%8E%E5%8F%88%E6%94%B9%E5%9B%9E%E6%88%90A%EF%BC%8C%E9%82%A3%E4%B9%88CAS%E6%AF%94%E8%BE%83%E5%86%85%E5%AD%98%E4%BD%8D%E7%BD%AE%E7%9A%84%E5%80%BC%E6%97%B6%E4%BC%9A%E5%8F%91%E7%8E%B0%E5%AE%83%E7%9A%84%E5%80%BC%E6%B2%A1%E6%9C%89%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%EF%BC%8C%E4%BD%86%E6%98%AF%E5%AE%9E%E9%99%85%E4%B8%8A%E8%BF%99%E4%B8%AA%E5%80%BC%E6%98%AF%E6%9C%89%E5%8F%98%E5%8C%96%E7%9A%84%EF%BC%8C%E8%BF%99%E5%B0%B1%E6%98%AFCAS%E7%9A%84ABA%E9%97%AE%E9%A2%98%0A%0A%23%23%23%23%204.2%20%E6%A8%A1%E6%8B%9FABA%E9%97%AE%E9%A2%98%0A%0A%60%60%60java%0Apublic%20class%20CAS_ABA%20%7B%0A%0A%20%20%20%20private%20static%20AtomicInteger%20count%20%3D%20new%20AtomicInteger(1)%3B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20Thread%20mainThread%20%3D%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread%20name%3A%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%2C%20initValue%3A%22%20%2B%20count.get())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20expectValue%20%3D%20count.get()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20newValue%20%3D%20expectValue%20%2B%201%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20boolean%20isSucceed%20%3D%20count.compareAndSet(expectValue%2C%20newValue)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread%20name%3A%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%2C%20CAS%20result%3A%22%20%2B%20isSucceed)%3B%0A%20%20%20%20%20%20%20%20%7D%2C%20%22main-thread%22)%3B%0A%0A%0A%20%20%20%20%20%20%20%20Thread%20otherThread%20%3D%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.MILLISECONDS.sleep(20)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20int%20incrementValue%20%3D%20count.incrementAndGet()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread%20name%3A%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22increment%20value%3A%22%20%2B%20incrementValue)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20int%20decrementValue%20%3D%20count.decrementAndGet()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread%20name%3A%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22decrement%20value%3A%22%20%2B%20decrementValue)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%2C%20%22other-thread%22)%3B%0A%0A%20%20%20%20%20%20%20%20mainThread.start()%3B%0A%20%20%20%20%20%20%20%20otherThread.start()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0Athread%20name%3Amain-thread%2C%20initValue%3A1%0Athread%20name%3Aother-thread%2C%20increment%20value%3A2%0Athread%20name%3Aother-thread%2C%20decrement%20value%3A1%0Athread%20name%3Amain-thread%2C%20CAS%20result%3Atrue%0A%60%60%60%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BAother-thread%E7%BA%BF%E7%A8%8B%E5%B0%86count%E5%8A%A01%E5%90%8E%E5%86%8D%E5%87%8F1%EF%BC%8C%E4%BD%86mainThread%E5%AF%B9%E4%BA%8Ecount%E7%9A%84%E5%80%BC%E5%8F%98%E5%8C%96%E6%B2%A1%E6%9C%89%E6%84%9F%E7%9F%A5%EF%BC%8C%E6%88%90%E5%8A%9F%E4%BF%AE%E6%94%B9%E5%B9%B6%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9Ctrue%0A%0A%0A%0A%23%23%23%23%204.3%20%E5%A6%82%E6%9E%9C%E8%A7%A3%E5%86%B3ABA%E9%97%AE%E9%A2%98%20%0A%0A%3E%20-%20%E5%A6%82%E6%9E%9C%E4%BD%A0%E7%9A%84%E7%B3%BB%E7%BB%9F%E5%AF%B9ABA%E9%97%AE%E9%A2%98%E4%B8%8D%E6%95%8F%E6%84%9F%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%BF%BD%E7%95%A5ABA%E9%97%AE%E9%A2%98%0A%3E%0A%3E%20-%20%E5%A6%82%E6%9E%9C%E4%BD%A0%E7%9A%84%E7%B3%BB%E7%BB%9F%E5%AF%B9ABA%E9%97%AE%E9%A2%98%E6%AF%94%E8%BE%83%E6%95%8F%E6%84%9F%EF%BC%8C%E5%A6%82%E9%93%B6%E8%A1%8C%E7%B3%BB%E7%BB%9F%EF%BC%8C%E4%B8%80%E7%A7%8D%E6%96%B9%E5%BC%8F%E6%98%AF%E4%B8%8D%E8%A6%81%E4%BD%BF%E7%94%A8CAS%E7%9B%B8%E5%85%B3%E7%9A%84%E5%8E%9F%E5%AD%90%E7%B1%BB%EF%BC%8C%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%20%60synchronized%60%E6%9D%A5%E4%BF%9D%E8%AF%81%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%E6%80%A7.%0A%3E%0A%3E%20-%20%E5%A6%82%E6%9E%9C%E4%BD%A0%E7%9A%84%E7%B3%BB%E7%BB%9F%E5%AF%B9ABA%E9%97%AE%E9%A2%98%E6%AF%94%E8%BE%83%E6%95%8F%E6%84%9F%E5%B9%B6%E4%B8%94%E5%AF%B9%E5%B9%B6%E5%8F%91%E4%B9%9F%E6%9C%89%E8%A6%81%E6%B1%82%EF%BC%8C%E5%88%99%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%0A%3E%0A%3E%20%20%20%60java.util.concurrent.atomic.AtomicStampedReference%60%0A%0A%60%60%60java%0Apublic%20boolean%20compareAndSet(V%20expectedReference%2C%20%20%20%2F%2F%E6%9C%9F%E6%9C%9B%E5%BC%95%E7%94%A8%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20V%20newReference%2C%20%20%20%20%2F%2F%E6%96%B0%E5%80%BC%E7%9A%84%E5%BC%95%E7%94%A8%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20int%20expectedStamp%2C%20%2F%2F%E6%9C%9F%E6%9C%9B%E5%BC%95%E7%94%A8%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20int%20newStamp)%7B%20%20%20%20%20%20%2F%2F%E6%96%B0%E5%80%BC%E7%89%88%E6%9C%AC%E5%8F%B7%0A%20%20%20%20%20%20%20%20Pair%3CV%3E%20current%20%3D%20pair%3B%0A%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20expectedReference%20%3D%3D%20current.reference%20%26%26%0A%20%20%20%20%20%20%20%20%20%20%20%20expectedStamp%20%3D%3D%20current.stamp%20%26%26%0A%20%20%20%20%20%20%20%20%20%20%20%20((newReference%20%3D%3D%20current.reference%20%26%26%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20newStamp%20%3D%3D%20current.stamp)%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20casPair(current%2C%20Pair.of(newReference%2C%20newStamp)))%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BF%AE%E6%94%B9%E6%88%90%E5%8A%9F%EF%BC%8C%E9%9C%80%E8%A6%81expectedReference%EF%BC%8CexpectedStamp%E4%B8%8Ecurrent%E9%87%8C%E9%9D%A2%E7%9A%84%E5%BD%93%E5%89%8D%E5%BC%95%E7%94%A8%E5%8F%8A%E5%BD%93%E5%89%8D%E5%BC%95%E7%94%A8%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%E7%9B%B8%E5%90%8C%0A%0A%60%60%60java%0Apublic%20class%20CAS_ABA2%20%7B%0A%0A%20%20%20%20private%20static%20final%20AtomicStampedReference%3CInteger%3E%20count%20%3D%20new%20AtomicStampedReference%3C%3E(1%2C%201)%3B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20Thread%20mainThread%20%3D%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread%20name%3A%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%2C%20init%20reference%3A%22%20%2B%20count.getReference()%20%2B%20%22%2C%20init%20stamp%3A%22%20%2B%20count.getStamp())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Integer%20expectReference%20%3D%20count.getReference()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20expectStamp%20%3D%20count.getStamp()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Integer%20newReference%20%3D%20expectReference%20%2B%201%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20newStamp%20%3D%20expectStamp%20%2B%201%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20boolean%20isSucceed%20%3D%20count.compareAndSet(expectReference%2C%20newReference%2C%20expectStamp%2C%20newStamp)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread%20name%3A%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%2C%20CAS%20result%3A%22%20%2B%20isSucceed%20%2B%20%22%2C%20%22%20%2B%20%22reference%3A%22%20%2B%20count.getReference()%20%2B%20%22%2C%20stamp%3A%22%20%2B%20count.getStamp())%3B%0A%20%20%20%20%20%20%20%20%7D%2C%20%22main-thread%22)%3B%0A%0A%0A%20%20%20%20%20%20%20%20Thread%20otherThread%20%3D%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.MILLISECONDS.sleep(20)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count.compareAndSet(count.getReference()%2C%20count.getReference()%20%2B%201%2C%20count.getStamp()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count.getStamp()%20%2B%201)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread%20name%3A%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%2C%20increment%20reference%3A%22%20%2B%20count.getReference()%20%2B%20%22%2C%20stamp%3A%22%20%2B%20count.getStamp())%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count.compareAndSet(count.getReference()%2C%20count.getReference()%20-%201%2C%20count.getStamp()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count.getStamp()%20%2B%201)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22thread%20name%3A%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%2C%20decrement%20reference%3A%22%20%2B%20count.getReference()%20%2B%20%22%2C%20stamp%3A%22%20%2B%20count.getStamp())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%2C%20%22other-thread%22)%3B%0A%0A%20%20%20%20%20%20%20%20mainThread.start()%3B%0A%20%20%20%20%20%20%20%20otherThread.start()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0Athread%20name%3Amain-thread%2C%20init%20reference%3A1%2C%20init%20stamp%3A1%0Athread%20name%3Aother-thread%2C%20increment%20reference%3A2%2C%20stamp%3A2%0Athread%20name%3Aother-thread%2C%20decrement%20reference%3A1%2C%20stamp%3A3%0Athread%20name%3Amain-thread%2C%20CAS%20result%3Afalse%2C%20reference%3A1%2C%20stamp%3A3%0A%60%60%60%0A%0A

synchronized-volatile详解

创建时间:2022/3/14 15:27
更新时间:2022/3/15 16:25
作者:Chris

1 synchronized概述

synchronized关键字可以作用于函数,也可作为函数内的语句,也就是平时说的同步方法和同步块。
如果再细的分类,synchronized可作用于

  • instance变量
  • object reference(对象引用)
  • static函数
  • class literals(类名称字面常量)。
  • 无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或方法当作锁――而且同步方法很可能还会被其他线程的对象访问。
  • 每个对象只有一个锁(lock)与之相关联。
  • 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
1. 每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,
2. 方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。
3. 这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized的成员方法中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突.
4. 不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员方法声明为 synchronized ,以控制其对类的静态成员变量的访问。

2 synchronized关键字的作用域有二种:

1. 对象实例范围

synchronized Method(){}

  • 可以防止多个线程同时访问这个对象的synchronized方法(如果这个对象实例有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象实例中任何一个synchronized方法)。
  • 但不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
2. 类的范围

synchronized static Method(){}

  • 防止多个线程同时访问这个类中的 synchronized static 方法。
  • 它可以对类的所有对象实例起作用。

3 volatile概述

  1. 使用volatile修饰的变量会强制将修改的值立即写入主存,主存中值的更新会使缓存中的值失效
  2. 非volatile变量不具备这样的特性,非volatile变量的值会被缓存,线程A更新了这个值,线程B读取这个变量的值时可能读到的并不是是线程A更新后的值
  3. volatile会禁止指令重排。

可见性:是指当一条线程修改了共享变量的值,新值对于其他线程来说是可以立即得知的。
有序性:即程序执行时按照代码书写的先后顺序执行。

  • 在Java内存模型中,允许编译器和处理器对指令进行重排序.
  • 重排序过程不会影响到单线程程序的执行,但是却会影响到多线程并发执行的正确性
-可见性有序性原子性线程阻塞
volatile1100
synchronized1111

4 JMM

java虚拟机有自己的内存模型(Java Memory Model,JMM)
JMM可以屏蔽掉各种硬件和操作系统的内存访问差异,以实现让java程序在各种平台下都能达到一致的内存访问效果。

JMM决定一个线程对共享变量的写入何时对另一个线程可见
JMM定义了线程和主内存之间的抽象关系:共享变量存储在主内存(MainMemory)中,
每个线程都有一个私有的本地内存(LocalMemory),本地内存保存了被该线程使用到的主内存的副本拷贝,
线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。
这三者之间的交互关系如下

https://www.cnblogs.com/chengxiao/p/6528109.html

%5BTOC%5D%0A%23%23%23%23%201%20synchronized%E6%A6%82%E8%BF%B0%0A%3E%20synchronized%E5%85%B3%E9%94%AE%E5%AD%97%E5%8F%AF%E4%BB%A5%E4%BD%9C%E7%94%A8%E4%BA%8E%E5%87%BD%E6%95%B0%2C%E4%B9%9F%E5%8F%AF%E4%BD%9C%E4%B8%BA%E5%87%BD%E6%95%B0%E5%86%85%E7%9A%84%E8%AF%AD%E5%8F%A5%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%B9%B3%E6%97%B6%E8%AF%B4%E7%9A%84%E5%90%8C%E6%AD%A5%E6%96%B9%E6%B3%95%E5%92%8C%E5%90%8C%E6%AD%A5%E5%9D%97%E3%80%82%0A%E5%A6%82%E6%9E%9C%E5%86%8D%E7%BB%86%E7%9A%84%E5%88%86%E7%B1%BB%EF%BC%8Csynchronized%E5%8F%AF%E4%BD%9C%E7%94%A8%E4%BA%8E%0A%3E%20-%20instance%E5%8F%98%E9%87%8F%0A%3E%20-%20object%20reference%EF%BC%88%E5%AF%B9%E8%B1%A1%E5%BC%95%E7%94%A8%EF%BC%89%0A%3E%20-%20static%E5%87%BD%E6%95%B0%0A%3E%20-%20class%20literals(%E7%B1%BB%E5%90%8D%E7%A7%B0%E5%AD%97%E9%9D%A2%E5%B8%B8%E9%87%8F)%E3%80%82%20%20%20%20%0A%0A%3E%20-%20%E6%97%A0%E8%AE%BAsynchronized%E5%85%B3%E9%94%AE%E5%AD%97%E5%8A%A0%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%8A%E8%BF%98%E6%98%AF%E5%AF%B9%E8%B1%A1%E4%B8%8A%EF%BC%8C%E5%AE%83%E5%8F%96%E5%BE%97%E7%9A%84%E9%94%81%E9%83%BD%E6%98%AF%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%98%AF%E6%8A%8A%E4%B8%80%E6%AE%B5%E4%BB%A3%E7%A0%81%E6%88%96%E6%96%B9%E6%B3%95%E5%BD%93%E4%BD%9C%E9%94%81%E2%80%95%E2%80%95%E8%80%8C%E4%B8%94%E5%90%8C%E6%AD%A5%E6%96%B9%E6%B3%95%E5%BE%88%E5%8F%AF%E8%83%BD%E8%BF%98%E4%BC%9A%E8%A2%AB%E5%85%B6%E4%BB%96%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%AF%B9%E8%B1%A1%E8%AE%BF%E9%97%AE%E3%80%82%20%20%0A%3E%20-%20%E6%AF%8F%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E9%94%81%EF%BC%88lock%EF%BC%89%E4%B8%8E%E4%B9%8B%E7%9B%B8%E5%85%B3%E8%81%94%E3%80%82%20%20%20%20%0A%3E%20-%20%E5%AE%9E%E7%8E%B0%E5%90%8C%E6%AD%A5%E6%98%AF%E8%A6%81%E5%BE%88%E5%A4%A7%E7%9A%84%E7%B3%BB%E7%BB%9F%E5%BC%80%E9%94%80%E4%BD%9C%E4%B8%BA%E4%BB%A3%E4%BB%B7%E7%9A%84%EF%BC%8C%E7%94%9A%E8%87%B3%E5%8F%AF%E8%83%BD%E9%80%A0%E6%88%90%E6%AD%BB%E9%94%81%EF%BC%8C%E6%89%80%E4%BB%A5%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E6%97%A0%E8%B0%93%E7%9A%84%E5%90%8C%E6%AD%A5%E6%8E%A7%E5%88%B6%E3%80%82%20%20%0A%0A%60%60%60%0A1.%20%E6%AF%8F%E4%B8%AA%E7%B1%BB%E5%AE%9E%E4%BE%8B%E5%AF%B9%E5%BA%94%E4%B8%80%E6%8A%8A%E9%94%81%EF%BC%8C%E6%AF%8F%E4%B8%AAsynchronized%E6%96%B9%E6%B3%95%E9%83%BD%E5%BF%85%E9%A1%BB%E8%8E%B7%E5%BE%97%E8%B0%83%E7%94%A8%E8%AF%A5%E6%96%B9%E6%B3%95%E7%9A%84%E7%B1%BB%E5%AE%9E%E4%BE%8B%E7%9A%84%E9%94%81%E6%96%B9%E8%83%BD%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%90%A6%E5%88%99%E6%89%80%E5%B1%9E%E7%BA%BF%E7%A8%8B%E9%98%BB%E5%A1%9E%EF%BC%8C%0A2.%20%E6%96%B9%E6%B3%95%E4%B8%80%E6%97%A6%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%B0%B1%E7%8B%AC%E5%8D%A0%E8%AF%A5%E9%94%81%EF%BC%8C%E7%9B%B4%E5%88%B0%E4%BB%8E%E8%AF%A5%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E6%97%B6%E6%89%8D%E5%B0%86%E9%94%81%E9%87%8A%E6%94%BE%EF%BC%8C%E6%AD%A4%E5%90%8E%E8%A2%AB%E9%98%BB%E5%A1%9E%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%96%B9%E8%83%BD%E8%8E%B7%E5%BE%97%E8%AF%A5%E9%94%81%EF%BC%8C%E9%87%8D%E6%96%B0%E8%BF%9B%E5%85%A5%E5%8F%AF%E6%89%A7%E8%A1%8C%E7%8A%B6%E6%80%81%E3%80%82%0A3.%20%E8%BF%99%E7%A7%8D%E6%9C%BA%E5%88%B6%E7%A1%AE%E4%BF%9D%E4%BA%86%E5%90%8C%E4%B8%80%E6%97%B6%E5%88%BB%E5%AF%B9%E4%BA%8E%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%85%B6%E6%89%80%E6%9C%89%E5%A3%B0%E6%98%8E%E4%B8%BA%20synchronized%E7%9A%84%E6%88%90%E5%91%98%E6%96%B9%E6%B3%95%E4%B8%AD%E8%87%B3%E5%A4%9A%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%A4%84%E4%BA%8E%E5%8F%AF%E6%89%A7%E8%A1%8C%E7%8A%B6%E6%80%81%EF%BC%88%E5%9B%A0%E4%B8%BA%E8%87%B3%E5%A4%9A%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E8%83%BD%E5%A4%9F%E8%8E%B7%E5%BE%97%E8%AF%A5%E7%B1%BB%E5%AE%9E%E4%BE%8B%E5%AF%B9%E5%BA%94%E7%9A%84%E9%94%81%EF%BC%89%EF%BC%8C%E4%BB%8E%E8%80%8C%E6%9C%89%E6%95%88%E9%81%BF%E5%85%8D%E4%BA%86%E7%B1%BB%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%E7%9A%84%E8%AE%BF%E9%97%AE%E5%86%B2%E7%AA%81.%0A4.%20%E4%B8%8D%E5%85%89%E6%98%AF%E7%B1%BB%E5%AE%9E%E4%BE%8B%EF%BC%8C%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B9%9F%E5%AF%B9%E5%BA%94%E4%B8%80%E6%8A%8A%E9%94%81%EF%BC%8C%E8%BF%99%E6%A0%B7%E6%88%91%E4%BB%AC%E4%B9%9F%E5%8F%AF%E5%B0%86%E7%B1%BB%E7%9A%84%E9%9D%99%E6%80%81%E6%88%90%E5%91%98%E6%96%B9%E6%B3%95%E5%A3%B0%E6%98%8E%E4%B8%BA%20synchronized%20%EF%BC%8C%E4%BB%A5%E6%8E%A7%E5%88%B6%E5%85%B6%E5%AF%B9%E7%B1%BB%E7%9A%84%E9%9D%99%E6%80%81%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%E7%9A%84%E8%AE%BF%E9%97%AE%E3%80%82%0A%60%60%60%0A%0A%23%23%23%23%202%20synchronized%E5%85%B3%E9%94%AE%E5%AD%97%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%9C%89%E4%BA%8C%E7%A7%8D%EF%BC%9A%0A%23%23%23%23%23%201.%20%E5%AF%B9%E8%B1%A1%E5%AE%9E%E4%BE%8B%E8%8C%83%E5%9B%B4%20%20%0A%3E%20%60synchronized%20Method()%7B%7D%20%20%60%0A%3E%20-%20%E5%8F%AF%E4%BB%A5%E9%98%B2%E6%AD%A2%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%97%B6%E8%AE%BF%E9%97%AE%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E7%9A%84synchronized%E6%96%B9%E6%B3%95%EF%BC%88%E5%A6%82%E6%9E%9C%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%AE%9E%E4%BE%8B%E6%9C%89%E5%A4%9A%E4%B8%AAsynchronized%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8F%AA%E8%A6%81%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E8%AE%BF%E9%97%AE%E4%BA%86%E5%85%B6%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AAsynchronized%E6%96%B9%E6%B3%95%EF%BC%8C%E5%85%B6%E5%AE%83%E7%BA%BF%E7%A8%8B%E4%B8%8D%E8%83%BD%E5%90%8C%E6%97%B6%E8%AE%BF%E9%97%AE%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%AE%9E%E4%BE%8B%E4%B8%AD%E4%BB%BB%E4%BD%95%E4%B8%80%E4%B8%AAsynchronized%E6%96%B9%E6%B3%95%EF%BC%89%E3%80%82%0A%3E%20-%20%E4%BD%86%E4%B8%8D%E5%90%8C%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%AE%9E%E4%BE%8B%E7%9A%84synchronized%E6%96%B9%E6%B3%95%E6%98%AF%E4%B8%8D%E7%9B%B8%E5%B9%B2%E6%89%B0%E7%9A%84%E3%80%82%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E5%85%B6%E5%AE%83%E7%BA%BF%E7%A8%8B%E7%85%A7%E6%A0%B7%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E8%AE%BF%E9%97%AE%E7%9B%B8%E5%90%8C%E7%B1%BB%E7%9A%84%E5%8F%A6%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%AE%9E%E4%BE%8B%E4%B8%AD%E7%9A%84synchronized%E6%96%B9%E6%B3%95%EF%BC%9B%20%20%0A%0A%23%23%23%23%23%202.%20%E7%B1%BB%E7%9A%84%E8%8C%83%E5%9B%B4%20%20%0A%3E%20%60synchronized%20static%20Method()%7B%7D%60%0A%3E%20-%20%E9%98%B2%E6%AD%A2%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%97%B6%E8%AE%BF%E9%97%AE%E8%BF%99%E4%B8%AA%E7%B1%BB%E4%B8%AD%E7%9A%84%20%60synchronized%20static%60%20%E6%96%B9%E6%B3%95%E3%80%82%0A%3E%20-%20%E5%AE%83%E5%8F%AF%E4%BB%A5%E5%AF%B9%E7%B1%BB%E7%9A%84%E6%89%80%E6%9C%89%E5%AF%B9%E8%B1%A1%E5%AE%9E%E4%BE%8B%E8%B5%B7%E4%BD%9C%E7%94%A8%E3%80%82%0A%0A%0A%23%23%23%23%203%20volatile%E6%A6%82%E8%BF%B0%0A%0A%3E%201.%20%E4%BD%BF%E7%94%A8volatile%E4%BF%AE%E9%A5%B0%E7%9A%84%E5%8F%98%E9%87%8F%E4%BC%9A%E5%BC%BA%E5%88%B6%E5%B0%86%E4%BF%AE%E6%94%B9%E7%9A%84%E5%80%BC%E7%AB%8B%E5%8D%B3%E5%86%99%E5%85%A5%E4%B8%BB%E5%AD%98%EF%BC%8C%E4%B8%BB%E5%AD%98%E4%B8%AD%E5%80%BC%E7%9A%84%E6%9B%B4%E6%96%B0%E4%BC%9A%E4%BD%BF%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84%E5%80%BC%E5%A4%B1%E6%95%88%0A%3E%202.%20%E9%9D%9Evolatile%E5%8F%98%E9%87%8F%E4%B8%8D%E5%85%B7%E5%A4%87%E8%BF%99%E6%A0%B7%E7%9A%84%E7%89%B9%E6%80%A7%EF%BC%8C%E9%9D%9Evolatile%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%E4%BC%9A%E8%A2%AB%E7%BC%93%E5%AD%98%EF%BC%8C%E7%BA%BF%E7%A8%8BA%E6%9B%B4%E6%96%B0%E4%BA%86%E8%BF%99%E4%B8%AA%E5%80%BC%EF%BC%8C%E7%BA%BF%E7%A8%8BB%E8%AF%BB%E5%8F%96%E8%BF%99%E4%B8%AA%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%E6%97%B6%E5%8F%AF%E8%83%BD%E8%AF%BB%E5%88%B0%E7%9A%84%E5%B9%B6%E4%B8%8D%E6%98%AF%E6%98%AF%E7%BA%BF%E7%A8%8BA%E6%9B%B4%E6%96%B0%E5%90%8E%E7%9A%84%E5%80%BC%0A%3E%203.%20volatile%E4%BC%9A%E7%A6%81%E6%AD%A2%E6%8C%87%E4%BB%A4%E9%87%8D%E6%8E%92%E3%80%82%0A%0A%3E%20%60%E5%8F%AF%E8%A7%81%E6%80%A7%60%EF%BC%9A%E6%98%AF%E6%8C%87%E5%BD%93%E4%B8%80%E6%9D%A1%E7%BA%BF%E7%A8%8B%E4%BF%AE%E6%94%B9%E4%BA%86%E5%85%B1%E4%BA%AB%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%EF%BC%8C%E6%96%B0%E5%80%BC%E5%AF%B9%E4%BA%8E%E5%85%B6%E4%BB%96%E7%BA%BF%E7%A8%8B%E6%9D%A5%E8%AF%B4%E6%98%AF%E5%8F%AF%E4%BB%A5%E7%AB%8B%E5%8D%B3%E5%BE%97%E7%9F%A5%E7%9A%84%E3%80%82%0A%3E%20%60%E6%9C%89%E5%BA%8F%E6%80%A7%60%EF%BC%9A%E5%8D%B3%E7%A8%8B%E5%BA%8F%E6%89%A7%E8%A1%8C%E6%97%B6%E6%8C%89%E7%85%A7%E4%BB%A3%E7%A0%81%E4%B9%A6%E5%86%99%E7%9A%84%E5%85%88%E5%90%8E%E9%A1%BA%E5%BA%8F%E6%89%A7%E8%A1%8C%E3%80%82%0A%3E%20-%20%E5%9C%A8Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B%E4%B8%AD%EF%BC%8C%E5%85%81%E8%AE%B8%E7%BC%96%E8%AF%91%E5%99%A8%E5%92%8C%E5%A4%84%E7%90%86%E5%99%A8%E5%AF%B9%E6%8C%87%E4%BB%A4%E8%BF%9B%E8%A1%8C%E9%87%8D%E6%8E%92%E5%BA%8F.%0A%3E%20-%20%E9%87%8D%E6%8E%92%E5%BA%8F%E8%BF%87%E7%A8%8B%E4%B8%8D%E4%BC%9A%E5%BD%B1%E5%93%8D%E5%88%B0%E5%8D%95%E7%BA%BF%E7%A8%8B%E7%A8%8B%E5%BA%8F%E7%9A%84%E6%89%A7%E8%A1%8C%EF%BC%8C%E4%BD%86%E6%98%AF%E5%8D%B4%E4%BC%9A%E5%BD%B1%E5%93%8D%E5%88%B0%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%B9%B6%E5%8F%91%E6%89%A7%E8%A1%8C%E7%9A%84%E6%AD%A3%E7%A1%AE%E6%80%A7%0A%0A%20%20-%20%20%7C%20%E5%8F%AF%E8%A7%81%E6%80%A7%7C%E6%9C%89%E5%BA%8F%E6%80%A7%7C%E5%8E%9F%E5%AD%90%E6%80%A7%7C%E7%BA%BF%E7%A8%8B%E9%98%BB%E5%A1%9E%7C%0A---%7C---%7C---%7C---%7C---%7C%0Avolatile%20%20%20%20%20%7C%201%20%7C%201%20%7C%200%20%7C%200%20%7C%0Asynchronized%20%7C%201%20%7C%201%20%7C%201%20%7C%201%20%7C%0A%0A%23%23%23%23%204%20JMM%0A%3E%20java%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B%EF%BC%88Java%20Memory%20Model%EF%BC%8CJMM%EF%BC%89%20%20%0A%3E%20JMM%E5%8F%AF%E4%BB%A5%E5%B1%8F%E8%94%BD%E6%8E%89%E5%90%84%E7%A7%8D%E7%A1%AC%E4%BB%B6%E5%92%8C%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%86%85%E5%AD%98%E8%AE%BF%E9%97%AE%E5%B7%AE%E5%BC%82%EF%BC%8C%E4%BB%A5%E5%AE%9E%E7%8E%B0%E8%AE%A9java%E7%A8%8B%E5%BA%8F%E5%9C%A8%E5%90%84%E7%A7%8D%E5%B9%B3%E5%8F%B0%E4%B8%8B%E9%83%BD%E8%83%BD%E8%BE%BE%E5%88%B0%E4%B8%80%E8%87%B4%E7%9A%84%E5%86%85%E5%AD%98%E8%AE%BF%E9%97%AE%E6%95%88%E6%9E%9C%E3%80%82%0A%0A%0A%60%60%60%0AJMM%E5%86%B3%E5%AE%9A%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%AF%B9%E5%85%B1%E4%BA%AB%E5%8F%98%E9%87%8F%E7%9A%84%E5%86%99%E5%85%A5%E4%BD%95%E6%97%B6%E5%AF%B9%E5%8F%A6%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%8F%AF%E8%A7%81%0AJMM%E5%AE%9A%E4%B9%89%E4%BA%86%E7%BA%BF%E7%A8%8B%E5%92%8C%E4%B8%BB%E5%86%85%E5%AD%98%E4%B9%8B%E9%97%B4%E7%9A%84%E6%8A%BD%E8%B1%A1%E5%85%B3%E7%B3%BB%EF%BC%9A%E5%85%B1%E4%BA%AB%E5%8F%98%E9%87%8F%E5%AD%98%E5%82%A8%E5%9C%A8%E4%B8%BB%E5%86%85%E5%AD%98(MainMemory)%E4%B8%AD%EF%BC%8C%0A%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AA%E7%A7%81%E6%9C%89%E7%9A%84%E6%9C%AC%E5%9C%B0%E5%86%85%E5%AD%98%EF%BC%88LocalMemory%EF%BC%89%EF%BC%8C%E6%9C%AC%E5%9C%B0%E5%86%85%E5%AD%98%E4%BF%9D%E5%AD%98%E4%BA%86%E8%A2%AB%E8%AF%A5%E7%BA%BF%E7%A8%8B%E4%BD%BF%E7%94%A8%E5%88%B0%E7%9A%84%E4%B8%BB%E5%86%85%E5%AD%98%E7%9A%84%E5%89%AF%E6%9C%AC%E6%8B%B7%E8%B4%9D%EF%BC%8C%0A%E7%BA%BF%E7%A8%8B%E5%AF%B9%E5%8F%98%E9%87%8F%E7%9A%84%E6%89%80%E6%9C%89%E6%93%8D%E4%BD%9C%E9%83%BD%E5%BF%85%E9%A1%BB%E5%9C%A8%E5%B7%A5%E4%BD%9C%E5%86%85%E5%AD%98%E4%B8%AD%E8%BF%9B%E8%A1%8C%EF%BC%8C%E8%80%8C%E4%B8%8D%E8%83%BD%E7%9B%B4%E6%8E%A5%E8%AF%BB%E5%86%99%E4%B8%BB%E5%86%85%E5%AD%98%E4%B8%AD%E7%9A%84%E5%8F%98%E9%87%8F%E3%80%82%0A%E8%BF%99%E4%B8%89%E8%80%85%E4%B9%8B%E9%97%B4%E7%9A%84%E4%BA%A4%E4%BA%92%E5%85%B3%E7%B3%BB%E5%A6%82%E4%B8%8B%0A%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fchengxiao%2Fp%2F6528109.html%0A%60%60%60%0A!%5B8dfa7b1f00113c948aba119afb0e220a.png%5D(en-resource%3A%2F%2Fdatabase%2F1383%3A1)%0A

Thread

创建时间:2020/9/2 14:48
更新时间:2023/3/25 13:45
作者:Chris

https://www.cnblogs.com/renhui/p/6066852.html

Java Thread 的使用

Java Thread 的使用
Java Thread 的 run() 与 start() 的区别
Java Thread 的 sleep() 和 wait() 的区别

1. 线程的状态

线程从创建到最终的消亡,要经历这几个状态:

   1. 创建(new)
   2. 就绪(runnable)
   3. 运行(running)
   4. 阻塞(blocked)
   5. time waiting
   6. waiting
   7. 消亡(dead)

2. 状态之间的流转

2.1 运行 -> 就绪

当需要新起一个线程来执行某个子任务时,就创建了一个线程。但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如 内存资源,程序计数器、Java栈、本地方法栈 都是线程私有的,所以需要为线程分配一定的内存空间),只有线程运行需要的所有条件满足了,才进入就绪状态。

2.2 就绪 -> 运行

当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。当得到CPU执行时间之后,线程便真正进入运行状态。

2.3 运行 -> 阻塞

线程在运行状态过程中,可能有多个原因导致当前线程不继续运行下去,

  1. 比如用户主动让线程睡眠(睡眠一定的时间之后再重新执行)、

  2. 用户主动让线程等待,

  3. 或者被同步块给阻塞,

此时就对应着多个状态:

time waiting(睡眠或等待一定的时间)
waiting(等待被唤醒)
blocked(阻塞)
2.4 运行 -> 消亡

当由于突然中断或者子任务执行完毕,线程就会被消亡。

下面这副图描述了线程从创建到消亡之间的状态:

在有些教程上将blocked、waiting、time waiting统称为阻塞状态,这个也是可以的,只不过这里我想将线程的状态和Java中的方法调用联系起来,所以将waiting和time waiting两个状态分离出来。

3. 上下文切换

对于单核CPU来说(对于多核CPU,此处就理解为一个核),CPU在一个时刻只能运行一个线程,当在运行一个线程的过程中转去运行另外一个线程,这个叫做线程上下文切换(对于进程也是类似)。

由于可能当前线程的任务并没有执行完毕,所以在切换时需要保存线程的运行状态,以便下次重新切换回来时能够继续切换之前的状态运行。举个简单的例子:比如一个线程A正在读取一个文件的内容,正读到文件的一半,此时需要暂停线程A,转去执行线程B,当再次切换回来执行线程A的时候,我们不希望线程A又从文件的开头来读取。

因此需要记录线程A的运行状态,那么会记录哪些数据呢?因为下次恢复时需要知道在这之前当前线程已经执行到哪条指令了,所以需要记录程序计数器的值,另外比如说线程正在进行某个计算的时候被挂起了,那么下次继续执行的时候需要知道之前挂起时变量的值时多少,因此需要记录CPU寄存器的状态。

所以一般来说,线程上下文切换过程中会记录程序计数器、CPU寄存器状态等数据。

说简单点的:对于线程的上下文切换实际上就是 存储和恢复CPU状态的过程,它使得线程执行能够从中断点恢复执行。

虽然多线程可以使得任务执行的效率得到提升,但是由于在线程切换时同样会带来一定的开销代价,并且多个线程会导致系统资源占用的增加,所以在进行多线程编程时要注意这些因素。

4 . Thread类中的方法

通过查看java.lang.Thread类的源码可知:

5. 常用方法

Thread类实现了Runnable接口,在Thread类中,有一些比较关键的属性,比如

  1. name 表示Thread的名字,可以通过Thread类的构造器中的参数来指定线程名字,
  2. priority 表示线程的优先级(最大值为10,最小值为1,默认值为5),
  3. daemon 表示线程是否是守护线程,
  4. target 表示要执行的任务。

下面是Thread类中常用的方法:

以下是关系到线程运行状态的几个方法:

5.1 start方法

start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。

5.2 run方法

run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。

5.3 sleep方法

sleep方法有两个重载版本:
sleep(long millis) //参数为毫秒 sleep(long millis,int nanoseconds) //第一参数为毫秒,第二个参数为纳秒
sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。
sleep方法不会释放锁

但是有一点要非常注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。看下面这个例子就清楚了:

public class Test {
    private int i = 10;
    private Object object = new Object();

    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread1 = test.new MyThread();
        MyThread thread2 = test.new MyThread();
        thread1.start();
        thread2.start();
    } 
    class MyThread extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                i++;
                System.out.println("i:"+i);
                try {
                    System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
                    Thread.currentThread().sleep(10000);
                } catch (InterruptedException e) {
                    // TODO: handle exception
                }
                System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
                i++;
                System.out.println("i:"+i);
            }
        }
    }
}

输出结果:

从上面输出结果可以看出,当Thread-0进入睡眠状态之后,Thread-1并没有去执行具体的任务。只有当Thread-0执行完之后,此时Thread-0释放了对象锁,Thread-1才开始执行。

注意,如果调用了sleep方法,必须捕获InterruptedException异常或者将该异常向上层抛出。当线程睡眠时间满后,不一定会立即得到执行,因为此时可能CPU正在执行其他的任务。所以说调用sleep方法相当于让线程进入阻塞状态。

5.4 yield方法

调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。

它跟sleep方法类似,同样不会释放锁

但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会

注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

5.5 join方法

join方法有三个重载版本:

join() 
join(long millis)     //参数为毫秒
join(long millis,int nanoseconds)    //第一参数为毫秒,第二个参数为纳秒

假如在main线程中,调用thread.join方法,则main方法会等待thread线程执行完毕或者等待一定的时间。

如果调用的是无参join方法,则等待thread执行完毕,如果调用的是指定了时间参数的join方法,则等待一定的时间。

join方法会让线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。

看下面一个例子:

public class Test {
    public static void main(String[] args) throws IOException  {
        System.out.println("进入线程"+Thread.currentThread().getName());
        Test test = new Test();
        MyThread thread1 = test.new MyThread();
        thread1.start();
        try {
            System.out.println("线程"+Thread.currentThread().getName()+"等待");
            thread1.join();
            System.out.println("线程"+Thread.currentThread().getName()+"继续执行");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } 
 
    class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println("进入线程"+Thread.currentThread().getName());
            try {
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
                // TODO: handle exception
            }
            System.out.println("线程"+Thread.currentThread().getName()+"执行完毕");
        }
    }
}

输出结果:

可以看出,当调用thread1.join()方法后,main线程会进入等待,然后等待thread1执行完之后再继续执行。

实际上调用join方法是调用了Object的wait方法,这个可以通过查看源码得知:

5.6 wait方法
wait方法会让线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。

由于wait方法会让线程释放对象锁,所以join方法同样会让线程释放对一个对象持有的锁。

5.6 interrupt方法

用来中断一个正处于阻塞状态的线程

调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常,

通过interrupt方法和isInterrupted()方法来停止正在运行的线程。

下面看一个例子:

public class Test {
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
        }
        thread.interrupt();
    }
    class MyThread extends Thread{
        @Override
        public void run() {
            try {
                System.out.println("进入睡眠状态");
                Thread.currentThread().sleep(10000);
                System.out.println("睡眠完毕");
            } catch (InterruptedException e) {
                System.out.println("得到中断异常");
            }
            System.out.println("run方法执行完毕");
        }
    }
}

输出结果:

从这里可以看出,通过interrupt方法可以中断处于阻塞状态的线程 那么能不能中断处于非阻塞状态的线程呢?看下面这个例子:

public class Test {
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {

        }
        thread.interrupt();
    } 
 
    class MyThread extends Thread{
        @Override
        public void run() {
            int i = 0;
            while(i<Integer.MAX_VALUE){
                System.out.println(i+" while循环");
                i++;
            }
        }
    }
 }

运行该程序会发现,while循环会一直运行直到变量i的值超出Integer.MAX_VALUE。所以说:

直接调用interrupt方法不能中断正在运行中的线程。

但是如果配合isInterrupted()能够中断正在运行的线程,因为调用interrupt方法相当于将中断标志位置为true,那么可以通过调用isInterrupted()判断中断标志是否被置位来中断线程的执行

比如下面这段代码:

public class Test {
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {

        }
        thread.interrupt();
    } 

    class MyThread extends Thread{
        @Override
        public void run() {
            int i = 0;
            while(!isInterrupted() && i<Integer.MAX_VALUE){
                System.out.println(i+" while循环");
                i++;
            }
        }
    }
 }

运行会发现,打印若干个值之后,while循环就停止打印了。

但是一般情况下不建议通过这种方式来中断线程,

一般会在MyThread类中增加一个属性 isStop来标志是否结束while循环,然后再在while循环中判断isStop的值
 class MyThread extends Thread{
   private volatile boolean isStop = false;
   
   @Override
   public void run() {
       int i = 0;
       while(!isStop){
         i++;
        }
    }
    
	public void setStop(boolean stop){
        	this.isStop = stop;
    	}
}

那么就可以在外面通过调用setStop方法来终止while循环。

7)stop方法

stop方法已经是一个废弃的方法,它是一个不安全的方法。因为调用stop方法会直接终止run方法的调用,并且会抛出一个ThreadDeath错误,如果线程持有某个对象锁的话,会完全释放锁,导致对象状态不一致。所以stop方法基本是不会被用到的。

8)destroy方法

destroy方法也是废弃的方法。基本不会被使用到。

以下是关系到线程属性的几个方法:

1)getId 用来得到线程ID
2)getName和setName 用来得到或者设置线程名称。
3)getPriority和setPriority 用来获取和设置线程优先级。
4)setDaemon和isDaemon 用来设置线程是否成为守护线程和判断线程是否是守护线程

6. 守护线程和用户线程的区别

守护线程依赖于创建它的线程,而用户线程则不依赖。举个简单的例子:

如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。
而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。

Thread类有一个比较常用的静态方法currentThread()用来获取当前线程。

在上面已经说到了Thread类中的大部分方法,那么Thread类中的方法调用到底会引起线程状态发生怎样的变化呢?下面一幅图就是在上面的图上进行改进而来的:

%5Btoc%5D%0A%0A%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Frenhui%2Fp%2F6066852.html%0A%0A%5B**Java%20Thread%20%E7%9A%84%E4%BD%BF%E7%94%A8**%5D(https%3A%2F%2Fwww.cnblogs.com%2Frenhui%2Fp%2F6066852.html)%0A%0A%7C%20%5BJava%20Thread%20%E7%9A%84%E4%BD%BF%E7%94%A8%5D(http%3A%2F%2Fwww.cnblogs.com%2Frenhui%2Fp%2F6066852.html)%20%7C%0A%7C%20------------------------------------------------------------%20%7C%0A%7C%20%5BJava%20Thread%20%E7%9A%84%20run()%20%E4%B8%8E%20start()%20%E7%9A%84%E5%8C%BA%E5%88%AB%5D(http%3A%2F%2Fwww.cnblogs.com%2Frenhui%2Fp%2F6066750.html)%20%7C%0A%7C%20%5BJava%20Thread%20%E7%9A%84%20sleep()%20%E5%92%8C%20wait()%20%E7%9A%84%E5%8C%BA%E5%88%AB%5D(http%3A%2F%2Fwww.cnblogs.com%2Frenhui%2Fp%2F6069353.html)%20%7C%0A%0A%20%0A%0A%23%23%23%23%201.%20%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%8A%B6%E6%80%81%0A%0A%E7%BA%BF%E7%A8%8B%E4%BB%8E%E5%88%9B%E5%BB%BA%E5%88%B0%E6%9C%80%E7%BB%88%E7%9A%84%E6%B6%88%E4%BA%A1%EF%BC%8C%E8%A6%81%E7%BB%8F%E5%8E%86%E8%BF%99%E5%87%A0%E4%B8%AA%E7%8A%B6%E6%80%81%EF%BC%9A%0A%60%60%60%0A%20%20%201.%20%E5%88%9B%E5%BB%BA(new)%0A%20%20%202.%20%E5%B0%B1%E7%BB%AA(runnable)%0A%20%20%203.%20%E8%BF%90%E8%A1%8C(running)%0A%20%20%204.%20%E9%98%BB%E5%A1%9E(blocked)%0A%20%20%205.%20time%20waiting%0A%20%20%206.%20waiting%0A%20%20%207.%20%E6%B6%88%E4%BA%A1%EF%BC%88dead%EF%BC%89%0A%60%60%60%0A%0A%23%23%23%23%202.%20%E7%8A%B6%E6%80%81%E4%B9%8B%E9%97%B4%E7%9A%84%E6%B5%81%E8%BD%AC%0A%0A%23%23%23%23%23%202.1%20%E8%BF%90%E8%A1%8C%20-%3E%20%E5%B0%B1%E7%BB%AA%0A%0A%3E%20%E5%BD%93%E9%9C%80%E8%A6%81%E6%96%B0%E8%B5%B7%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%9D%A5%E6%89%A7%E8%A1%8C%E6%9F%90%E4%B8%AA%E5%AD%90%E4%BB%BB%E5%8A%A1%E6%97%B6%EF%BC%8C%E5%B0%B1%E5%88%9B%E5%BB%BA%E4%BA%86%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E3%80%82%E4%BD%86%E6%98%AF%E7%BA%BF%E7%A8%8B%E5%88%9B%E5%BB%BA%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%B8%8D%E4%BC%9A%E7%AB%8B%E5%8D%B3%E8%BF%9B%E5%85%A5%E5%B0%B1%E7%BB%AA%E7%8A%B6%E6%80%81%EF%BC%8C%E5%9B%A0%E4%B8%BA%E7%BA%BF%E7%A8%8B%E7%9A%84%E8%BF%90%E8%A1%8C%E9%9C%80%E8%A6%81%E4%B8%80%E4%BA%9B%E6%9D%A1%E4%BB%B6%EF%BC%88%E6%AF%94%E5%A6%82%20**%E5%86%85%E5%AD%98%E8%B5%84%E6%BA%90%EF%BC%8C%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%E3%80%81Java%E6%A0%88%E3%80%81%E6%9C%AC%E5%9C%B0%E6%96%B9%E6%B3%95%E6%A0%88**%20%E9%83%BD%E6%98%AF%E7%BA%BF%E7%A8%8B%E7%A7%81%E6%9C%89%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E4%B8%BA%E7%BA%BF%E7%A8%8B%E5%88%86%E9%85%8D%E4%B8%80%E5%AE%9A%E7%9A%84%E5%86%85%E5%AD%98%E7%A9%BA%E9%97%B4%EF%BC%89%EF%BC%8C%E5%8F%AA%E6%9C%89%E7%BA%BF%E7%A8%8B%E8%BF%90%E8%A1%8C%E9%9C%80%E8%A6%81%E7%9A%84%E6%89%80%E6%9C%89%E6%9D%A1%E4%BB%B6%E6%BB%A1%E8%B6%B3%E4%BA%86%EF%BC%8C%E6%89%8D%E8%BF%9B%E5%85%A5%E5%B0%B1%E7%BB%AA%E7%8A%B6%E6%80%81%E3%80%82%0A%0A%23%23%23%23%23%202.2%20%E5%B0%B1%E7%BB%AA%20-%3E%20%E8%BF%90%E8%A1%8C%0A%0A%3E%20%E5%BD%93%E7%BA%BF%E7%A8%8B%E8%BF%9B%E5%85%A5%E5%B0%B1%E7%BB%AA%E7%8A%B6%E6%80%81%E5%90%8E%EF%BC%8C%E4%B8%8D%E4%BB%A3%E8%A1%A8%E7%AB%8B%E5%88%BB%E5%B0%B1%E8%83%BD%E8%8E%B7%E5%8F%96CPU%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%8C%E4%B9%9F%E8%AE%B8%E6%AD%A4%E6%97%B6CPU%E6%AD%A3%E5%9C%A8%E6%89%A7%E8%A1%8C%E5%85%B6%E4%BB%96%E7%9A%84%E4%BA%8B%E6%83%85%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%AE%83%E8%A6%81%E7%AD%89%E5%BE%85%E3%80%82%E5%BD%93%E5%BE%97%E5%88%B0CPU%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E4%B9%8B%E5%90%8E%EF%BC%8C%E7%BA%BF%E7%A8%8B%E4%BE%BF%E7%9C%9F%E6%AD%A3%E8%BF%9B%E5%85%A5%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81%E3%80%82%0A%0A%23%23%23%23%23%202.3%20%E8%BF%90%E8%A1%8C%20-%3E%20%E9%98%BB%E5%A1%9E%0A%3E%20%E7%BA%BF%E7%A8%8B%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81%E8%BF%87%E7%A8%8B%E4%B8%AD%EF%BC%8C%E5%8F%AF%E8%83%BD%E6%9C%89%E5%A4%9A%E4%B8%AA%E5%8E%9F%E5%9B%A0%E5%AF%BC%E8%87%B4%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E4%B8%8D%E7%BB%A7%E7%BB%AD%E8%BF%90%E8%A1%8C%E4%B8%8B%E5%8E%BB%EF%BC%8C%0A%3E%0A%3E%201.%20%E6%AF%94%E5%A6%82%E7%94%A8%E6%88%B7%E4%B8%BB%E5%8A%A8%E8%AE%A9%E7%BA%BF%E7%A8%8B%E7%9D%A1%E7%9C%A0%EF%BC%88%E7%9D%A1%E7%9C%A0%E4%B8%80%E5%AE%9A%E7%9A%84%E6%97%B6%E9%97%B4%E4%B9%8B%E5%90%8E%E5%86%8D%E9%87%8D%E6%96%B0%E6%89%A7%E8%A1%8C%EF%BC%89%E3%80%81%0A%3E%0A%3E%202.%20%E7%94%A8%E6%88%B7%E4%B8%BB%E5%8A%A8%E8%AE%A9%E7%BA%BF%E7%A8%8B%E7%AD%89%E5%BE%85%EF%BC%8C%0A%3E%0A%3E%203.%20%E6%88%96%E8%80%85%E8%A2%AB%E5%90%8C%E6%AD%A5%E5%9D%97%E7%BB%99%E9%98%BB%E5%A1%9E%EF%BC%8C%0A%3E%0A%3E%20%E6%AD%A4%E6%97%B6%E5%B0%B1%E5%AF%B9%E5%BA%94%E7%9D%80%E5%A4%9A%E4%B8%AA%E7%8A%B6%E6%80%81%EF%BC%9A%0A%0A%60%60%60%0Atime%20waiting%EF%BC%88%E7%9D%A1%E7%9C%A0%E6%88%96%E7%AD%89%E5%BE%85%E4%B8%80%E5%AE%9A%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%89%0Awaiting%EF%BC%88%E7%AD%89%E5%BE%85%E8%A2%AB%E5%94%A4%E9%86%92%EF%BC%89%0Ablocked%EF%BC%88%E9%98%BB%E5%A1%9E%EF%BC%89%0A%60%60%60%0A%0A%23%23%23%23%23%202.4%20%E8%BF%90%E8%A1%8C%20-%3E%20%E6%B6%88%E4%BA%A1%0A%0A%3E%20%E5%BD%93%E7%94%B1%E4%BA%8E%E7%AA%81%E7%84%B6%E4%B8%AD%E6%96%AD%E6%88%96%E8%80%85%E5%AD%90%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%EF%BC%8C%E7%BA%BF%E7%A8%8B%E5%B0%B1%E4%BC%9A%E8%A2%AB%E6%B6%88%E4%BA%A1%E3%80%82%0A%0A%E4%B8%8B%E9%9D%A2%E8%BF%99%E5%89%AF%E5%9B%BE%E6%8F%8F%E8%BF%B0%E4%BA%86%E7%BA%BF%E7%A8%8B%E4%BB%8E%E5%88%9B%E5%BB%BA%E5%88%B0%E6%B6%88%E4%BA%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E7%8A%B6%E6%80%81%EF%BC%9A%0A%0A!%5Bd1a47339f1fc2278ed9f8282e444ecd0.png%5D(en-resource%3A%2F%2Fdatabase%2F1061%3A1)%0A%0A%0A%3E%20%E5%9C%A8%E6%9C%89%E4%BA%9B%E6%95%99%E7%A8%8B%E4%B8%8A%E5%B0%86blocked%E3%80%81waiting%E3%80%81time%20waiting%E7%BB%9F%E7%A7%B0%E4%B8%BA%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%EF%BC%8C%E8%BF%99%E4%B8%AA%E4%B9%9F%E6%98%AF%E5%8F%AF%E4%BB%A5%E7%9A%84%EF%BC%8C%E5%8F%AA%E4%B8%8D%E8%BF%87%E8%BF%99%E9%87%8C%E6%88%91%E6%83%B3%E5%B0%86%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%8A%B6%E6%80%81%E5%92%8CJava%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%E8%81%94%E7%B3%BB%E8%B5%B7%E6%9D%A5%EF%BC%8C%E6%89%80%E4%BB%A5%E5%B0%86waiting%E5%92%8Ctime%20waiting%E4%B8%A4%E4%B8%AA%E7%8A%B6%E6%80%81%E5%88%86%E7%A6%BB%E5%87%BA%E6%9D%A5%E3%80%82%0A%0A%0A%0A%23%23%23%23%203.%20%E4%B8%8A%E4%B8%8B%E6%96%87%E5%88%87%E6%8D%A2%0A%0A%3E%20%E5%AF%B9%E4%BA%8E%E5%8D%95%E6%A0%B8CPU%E6%9D%A5%E8%AF%B4%EF%BC%88%E5%AF%B9%E4%BA%8E%E5%A4%9A%E6%A0%B8CPU%EF%BC%8C%E6%AD%A4%E5%A4%84%E5%B0%B1%E7%90%86%E8%A7%A3%E4%B8%BA%E4%B8%80%E4%B8%AA%E6%A0%B8%EF%BC%89%EF%BC%8CCPU%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%97%B6%E5%88%BB%E5%8F%AA%E8%83%BD%E8%BF%90%E8%A1%8C%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%BD%93%E5%9C%A8%E8%BF%90%E8%A1%8C%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%E8%BD%AC%E5%8E%BB%E8%BF%90%E8%A1%8C%E5%8F%A6%E5%A4%96%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%8F%AB%E5%81%9A%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%88%87%E6%8D%A2%EF%BC%88%E5%AF%B9%E4%BA%8E%E8%BF%9B%E7%A8%8B%E4%B9%9F%E6%98%AF%E7%B1%BB%E4%BC%BC%EF%BC%89%E3%80%82%0A%0A%3E%20%E7%94%B1%E4%BA%8E%E5%8F%AF%E8%83%BD%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BB%BB%E5%8A%A1%E5%B9%B6%E6%B2%A1%E6%9C%89%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%EF%BC%8C%E6%89%80%E4%BB%A5%E5%9C%A8%E5%88%87%E6%8D%A2%E6%97%B6%E9%9C%80%E8%A6%81%E4%BF%9D%E5%AD%98%E7%BA%BF%E7%A8%8B%E7%9A%84%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81%EF%BC%8C%E4%BB%A5%E4%BE%BF%E4%B8%8B%E6%AC%A1%E9%87%8D%E6%96%B0%E5%88%87%E6%8D%A2%E5%9B%9E%E6%9D%A5%E6%97%B6%E8%83%BD%E5%A4%9F%E7%BB%A7%E7%BB%AD%E5%88%87%E6%8D%A2%E4%B9%8B%E5%89%8D%E7%9A%84%E7%8A%B6%E6%80%81%E8%BF%90%E8%A1%8C%E3%80%82%E4%B8%BE%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E4%BE%8B%E5%AD%90%EF%BC%9A%E6%AF%94%E5%A6%82%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8BA%E6%AD%A3%E5%9C%A8%E8%AF%BB%E5%8F%96%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8C%E6%AD%A3%E8%AF%BB%E5%88%B0%E6%96%87%E4%BB%B6%E7%9A%84%E4%B8%80%E5%8D%8A%EF%BC%8C%E6%AD%A4%E6%97%B6%E9%9C%80%E8%A6%81%E6%9A%82%E5%81%9C%E7%BA%BF%E7%A8%8BA%EF%BC%8C%E8%BD%AC%E5%8E%BB%E6%89%A7%E8%A1%8C%E7%BA%BF%E7%A8%8BB%EF%BC%8C%E5%BD%93%E5%86%8D%E6%AC%A1%E5%88%87%E6%8D%A2%E5%9B%9E%E6%9D%A5%E6%89%A7%E8%A1%8C%E7%BA%BF%E7%A8%8BA%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E6%88%91%E4%BB%AC%E4%B8%8D%E5%B8%8C%E6%9C%9B%E7%BA%BF%E7%A8%8BA%E5%8F%88%E4%BB%8E%E6%96%87%E4%BB%B6%E7%9A%84%E5%BC%80%E5%A4%B4%E6%9D%A5%E8%AF%BB%E5%8F%96%E3%80%82%0A%0A%3E%20%E5%9B%A0%E6%AD%A4%E9%9C%80%E8%A6%81%E8%AE%B0%E5%BD%95%E7%BA%BF%E7%A8%8BA%E7%9A%84%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81%EF%BC%8C%E9%82%A3%E4%B9%88%E4%BC%9A%E8%AE%B0%E5%BD%95%E5%93%AA%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%91%A2%EF%BC%9F%E5%9B%A0%E4%B8%BA%E4%B8%8B%E6%AC%A1%E6%81%A2%E5%A4%8D%E6%97%B6%E9%9C%80%E8%A6%81%E7%9F%A5%E9%81%93%E5%9C%A8%E8%BF%99%E4%B9%8B%E5%89%8D%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E5%B7%B2%E7%BB%8F%E6%89%A7%E8%A1%8C%E5%88%B0%E5%93%AA%E6%9D%A1%E6%8C%87%E4%BB%A4%E4%BA%86%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E8%AE%B0%E5%BD%95**%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8**%E7%9A%84%E5%80%BC%EF%BC%8C%E5%8F%A6%E5%A4%96%E6%AF%94%E5%A6%82%E8%AF%B4%E7%BA%BF%E7%A8%8B%E6%AD%A3%E5%9C%A8%E8%BF%9B%E8%A1%8C%E6%9F%90%E4%B8%AA%E8%AE%A1%E7%AE%97%E7%9A%84%E6%97%B6%E5%80%99%E8%A2%AB%E6%8C%82%E8%B5%B7%E4%BA%86%EF%BC%8C%E9%82%A3%E4%B9%88%E4%B8%8B%E6%AC%A1%E7%BB%A7%E7%BB%AD%E6%89%A7%E8%A1%8C%E7%9A%84%E6%97%B6%E5%80%99%E9%9C%80%E8%A6%81%E7%9F%A5%E9%81%93%E4%B9%8B%E5%89%8D%E6%8C%82%E8%B5%B7%E6%97%B6%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%E6%97%B6%E5%A4%9A%E5%B0%91%EF%BC%8C%E5%9B%A0%E6%AD%A4%E9%9C%80%E8%A6%81%E8%AE%B0%E5%BD%95**CPU%E5%AF%84%E5%AD%98%E5%99%A8**%E7%9A%84%E7%8A%B6%E6%80%81%E3%80%82%0A%3E%0A%3E%20%E6%89%80%E4%BB%A5%E4%B8%80%E8%88%AC%E6%9D%A5%E8%AF%B4%EF%BC%8C%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E5%88%87%E6%8D%A2%E8%BF%87%E7%A8%8B%E4%B8%AD%E4%BC%9A%E8%AE%B0%E5%BD%95%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%E3%80%81CPU%E5%AF%84%E5%AD%98%E5%99%A8%E7%8A%B6%E6%80%81%E7%AD%89%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A%0A%0A%60%60%60%0A%E8%AF%B4%E7%AE%80%E5%8D%95%E7%82%B9%E7%9A%84%EF%BC%9A%E5%AF%B9%E4%BA%8E%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%B8%8A%E4%B8%8B%E6%96%87%E5%88%87%E6%8D%A2%E5%AE%9E%E9%99%85%E4%B8%8A%E5%B0%B1%E6%98%AF%20%E5%AD%98%E5%82%A8%E5%92%8C%E6%81%A2%E5%A4%8DCPU%E7%8A%B6%E6%80%81%E7%9A%84%E8%BF%87%E7%A8%8B%EF%BC%8C%E5%AE%83%E4%BD%BF%E5%BE%97%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E8%83%BD%E5%A4%9F%E4%BB%8E%E4%B8%AD%E6%96%AD%E7%82%B9%E6%81%A2%E5%A4%8D%E6%89%A7%E8%A1%8C%E3%80%82%0A%60%60%60%0A%0A%E8%99%BD%E7%84%B6%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%8F%AF%E4%BB%A5%E4%BD%BF%E5%BE%97%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C%E7%9A%84%E6%95%88%E7%8E%87%E5%BE%97%E5%88%B0%E6%8F%90%E5%8D%87%EF%BC%8C%E4%BD%86%E6%98%AF%E7%94%B1%E4%BA%8E%E5%9C%A8%E7%BA%BF%E7%A8%8B%E5%88%87%E6%8D%A2%E6%97%B6%E5%90%8C%E6%A0%B7%E4%BC%9A%E5%B8%A6%E6%9D%A5%E4%B8%80%E5%AE%9A%E7%9A%84%E5%BC%80%E9%94%80%E4%BB%A3%E4%BB%B7%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E4%BC%9A%E5%AF%BC%E8%87%B4%E7%B3%BB%E7%BB%9F%E8%B5%84%E6%BA%90%E5%8D%A0%E7%94%A8%E7%9A%84%E5%A2%9E%E5%8A%A0%EF%BC%8C%E6%89%80%E4%BB%A5%E5%9C%A8%E8%BF%9B%E8%A1%8C%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B%E6%97%B6%E8%A6%81%E6%B3%A8%E6%84%8F%E8%BF%99%E4%BA%9B%E5%9B%A0%E7%B4%A0%E3%80%82%0A%0A%0A%0A%23%23%23%23%204%20.%20Thread%E7%B1%BB%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95%0A%0A%E9%80%9A%E8%BF%87%E6%9F%A5%E7%9C%8Bjava.lang.Thread%E7%B1%BB%E7%9A%84%E6%BA%90%E7%A0%81%E5%8F%AF%E7%9F%A5%EF%BC%9A%0A%0A!%5Ba469f9442f2c076b014c4635196fe0ef.png%5D(en-resource%3A%2F%2Fdatabase%2F1060%3A1)%0A%0A%0A%23%23%23%23%205.%20%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95%0A%0AThread%E7%B1%BB%E5%AE%9E%E7%8E%B0%E4%BA%86Runnable%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%9C%A8Thread%E7%B1%BB%E4%B8%AD%EF%BC%8C%E6%9C%89%E4%B8%80%E4%BA%9B%E6%AF%94%E8%BE%83%E5%85%B3%E9%94%AE%E7%9A%84%E5%B1%9E%E6%80%A7%EF%BC%8C%E6%AF%94%E5%A6%82%0A%0A%3E%201.%20name%20%E8%A1%A8%E7%A4%BAThread%E7%9A%84%E5%90%8D%E5%AD%97%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87Thread%E7%B1%BB%E7%9A%84%E6%9E%84%E9%80%A0%E5%99%A8%E4%B8%AD%E7%9A%84%E5%8F%82%E6%95%B0%E6%9D%A5%E6%8C%87%E5%AE%9A%E7%BA%BF%E7%A8%8B%E5%90%8D%E5%AD%97%EF%BC%8C%0A%3E%202.%20priority%20%E8%A1%A8%E7%A4%BA%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%88%E6%9C%80%E5%A4%A7%E5%80%BC%E4%B8%BA10%EF%BC%8C%E6%9C%80%E5%B0%8F%E5%80%BC%E4%B8%BA1%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%80%BC%E4%B8%BA5%EF%BC%89%EF%BC%8C%0A%3E%203.%20daemon%20%E8%A1%A8%E7%A4%BA%E7%BA%BF%E7%A8%8B%E6%98%AF%E5%90%A6%E6%98%AF%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%EF%BC%8C%0A%3E%204.%20target%20%E8%A1%A8%E7%A4%BA%E8%A6%81%E6%89%A7%E8%A1%8C%E7%9A%84%E4%BB%BB%E5%8A%A1%E3%80%82%0A%0A%E4%B8%8B%E9%9D%A2%E6%98%AFThread%E7%B1%BB%E4%B8%AD%E5%B8%B8%E7%94%A8%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%9A%0A%0A%E4%BB%A5%E4%B8%8B%E6%98%AF%E5%85%B3%E7%B3%BB%E5%88%B0%E7%BA%BF%E7%A8%8B%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81%E7%9A%84%E5%87%A0%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%9A%0A%0A%23%23%23%23%23%205.1%20start%E6%96%B9%E6%B3%95%0A%0A%3E%20%20start()%E7%94%A8%E6%9D%A5%E5%90%AF%E5%8A%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%BD%93%E8%B0%83%E7%94%A8start%E6%96%B9%E6%B3%95%E5%90%8E%EF%BC%8C%E7%B3%BB%E7%BB%9F%E6%89%8D%E4%BC%9A%E5%BC%80%E5%90%AF%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%9D%A5%E6%89%A7%E8%A1%8C%E7%94%A8%E6%88%B7%E5%AE%9A%E4%B9%89%E7%9A%84%E5%AD%90%E4%BB%BB%E5%8A%A1%EF%BC%8C%E5%9C%A8%E8%BF%99%E4%B8%AA%E8%BF%87%E7%A8%8B%E4%B8%AD%EF%BC%8C%E4%BC%9A%E4%B8%BA%E7%9B%B8%E5%BA%94%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%88%86%E9%85%8D%E9%9C%80%E8%A6%81%E7%9A%84%E8%B5%84%E6%BA%90%E3%80%82%0A%0A%23%23%23%23%23%205.2%20run%E6%96%B9%E6%B3%95%0A%0A%3E%20run()%E6%96%B9%E6%B3%95%E6%98%AF%E4%B8%8D%E9%9C%80%E8%A6%81%E7%94%A8%E6%88%B7%E6%9D%A5%E8%B0%83%E7%94%A8%E7%9A%84%EF%BC%8C%E5%BD%93%E9%80%9A%E8%BF%87start%E6%96%B9%E6%B3%95%E5%90%AF%E5%8A%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E4%B9%8B%E5%90%8E%EF%BC%8C%E5%BD%93%E7%BA%BF%E7%A8%8B%E8%8E%B7%E5%BE%97%E4%BA%86CPU%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%8C%E4%BE%BF%E8%BF%9B%E5%85%A5run%E6%96%B9%E6%B3%95%E4%BD%93%E5%8E%BB%E6%89%A7%E8%A1%8C%E5%85%B7%E4%BD%93%E7%9A%84%E4%BB%BB%E5%8A%A1%E3%80%82%E6%B3%A8%E6%84%8F%EF%BC%8C%E7%BB%A7%E6%89%BFThread%E7%B1%BB%E5%BF%85%E9%A1%BB%E9%87%8D%E5%86%99run%E6%96%B9%E6%B3%95%EF%BC%8C%E5%9C%A8run%E6%96%B9%E6%B3%95%E4%B8%AD%E5%AE%9A%E4%B9%89%E5%85%B7%E4%BD%93%E8%A6%81%E6%89%A7%E8%A1%8C%E7%9A%84%E4%BB%BB%E5%8A%A1%E3%80%82%0A%0A%23%23%23%23%23%205.3%20sleep%E6%96%B9%E6%B3%95%0A%0A%3E%20sleep%E6%96%B9%E6%B3%95%E6%9C%89%E4%B8%A4%E4%B8%AA%E9%87%8D%E8%BD%BD%E7%89%88%E6%9C%AC%EF%BC%9A%0A%3E%20sleep(long%20millis)%20%20%20%20%20%2F%2F%E5%8F%82%E6%95%B0%E4%B8%BA%E6%AF%AB%E7%A7%92%20sleep(long%20millis%2Cint%20nanoseconds)%20%20%20%20%2F%2F%E7%AC%AC%E4%B8%80%E5%8F%82%E6%95%B0%E4%B8%BA%E6%AF%AB%E7%A7%92%EF%BC%8C%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%8F%82%E6%95%B0%E4%B8%BA%E7%BA%B3%E7%A7%92%0A%3E%20sleep%E7%9B%B8%E5%BD%93%E4%BA%8E%E8%AE%A9%E7%BA%BF%E7%A8%8B%E7%9D%A1%E7%9C%A0%EF%BC%8C%E4%BA%A4%E5%87%BACPU%EF%BC%8C%E8%AE%A9CPU%E5%8E%BB%E6%89%A7%E8%A1%8C%E5%85%B6%E4%BB%96%E7%9A%84%E4%BB%BB%E5%8A%A1%E3%80%82%0A%3E%20sleep%E6%96%B9%E6%B3%95%E4%B8%8D%E4%BC%9A%E9%87%8A%E6%94%BE%E9%94%81%0A%0A%E4%BD%86%E6%98%AF%E6%9C%89%E4%B8%80%E7%82%B9%E8%A6%81%E9%9D%9E%E5%B8%B8%E6%B3%A8%E6%84%8F%EF%BC%8C%60sleep%E6%96%B9%E6%B3%95%E4%B8%8D%E4%BC%9A%E9%87%8A%E6%94%BE%E9%94%81%60%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E6%8C%81%E6%9C%89%E5%AF%B9%E6%9F%90%E4%B8%AA%E5%AF%B9%E8%B1%A1%E7%9A%84%E9%94%81%EF%BC%8C%E5%88%99%E5%8D%B3%E4%BD%BF%E8%B0%83%E7%94%A8sleep%E6%96%B9%E6%B3%95%EF%BC%8C%E5%85%B6%E4%BB%96%E7%BA%BF%E7%A8%8B%E4%B9%9F%E6%97%A0%E6%B3%95%E8%AE%BF%E9%97%AE%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E3%80%82%E7%9C%8B%E4%B8%8B%E9%9D%A2%E8%BF%99%E4%B8%AA%E4%BE%8B%E5%AD%90%E5%B0%B1%E6%B8%85%E6%A5%9A%E4%BA%86%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20class%20Test%20%7B%0A%20%20%20%20private%20int%20i%20%3D%2010%3B%0A%20%20%20%20private%20Object%20object%20%3D%20new%20Object()%3B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20IOException%20%20%7B%0A%20%20%20%20%20%20%20%20Test%20test%20%3D%20new%20Test()%3B%0A%20%20%20%20%20%20%20%20MyThread%20thread1%20%3D%20test.new%20MyThread()%3B%0A%20%20%20%20%20%20%20%20MyThread%20thread2%20%3D%20test.new%20MyThread()%3B%0A%20%20%20%20%20%20%20%20thread1.start()%3B%0A%20%20%20%20%20%20%20%20thread2.start()%3B%0A%20%20%20%20%7D%20%0A%20%20%20%20class%20MyThread%20extends%20Thread%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20synchronized%20(object)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20i%2B%2B%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22i%3A%22%2Bi)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%BA%BF%E7%A8%8B%22%2BThread.currentThread().getName()%2B%22%E8%BF%9B%E5%85%A5%E7%9D%A1%E7%9C%A0%E7%8A%B6%E6%80%81%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Thread.currentThread().sleep(10000)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20TODO%3A%20handle%20exception%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%BA%BF%E7%A8%8B%22%2BThread.currentThread().getName()%2B%22%E7%9D%A1%E7%9C%A0%E7%BB%93%E6%9D%9F%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20i%2B%2B%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22i%3A%22%2Bi)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%20%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%0A!%5Bimage.png%5D(data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAnQAAADaCAYAAAAv4N94AAAgAElEQVR4Aey9Z7hkdbX1%2B1t5VdipA00TFQxEE6CCooAgkpNkMaEelWAiqqioCEpQBCUnyTk0QXIQEAxgAAQVJUPTYaeqWnmt%2B4xZ9Dnn3vt%2Bf7%2B4eXaze4faVf8w55hjjDnbefrpp5s8z9F7WZb%2F%2FV7XNXpvmob%2FvP1nBf6zAv9Zgf%2BswH9W4D8r8J8V%2BM8K%2FN9ZAcdxcF3X3n3fZ8V7GIasePcF5FZZeXXi2KfM%2BixespjH%2FvAkH9tpB2qvABd8P6Dfy4i9NlHYYpBME0UR%2BmJWFpQueJ6D5wQ0eYlTusSBQ%2BA05PWAvEnxgxZNGVGVNWFc0TiQJrU9XlPXlHWBF7agLmjyBD8KyZwOtVPg1X0CCgKnTT8rcVpdA55RCZHvMChzojimKmoGaUJrfJQ0z%2FRQTC1dxqO%2FeYgdd9ye2m3IvRYZMbUPVQ40Ja3QpylrnBIC38UrctzQYzpPCKMOYemQDyBqNfhuQdkfEEZtSi9kkEMQQlEPcEIHL%2FZZPpvQCiNG%2FYik38MLfIqioht0KGsoGyj9hqJICSMXypKm9vGcCMFn34NBUtLp%2BBQZ1CWMjsLMbI4X%2BQRAWTc0NVROjeuVeiE0OPppam0aDm7j4jQQelrrlCgICUKXftK3w%2BB6AVmW4XmendDb7rhzeFKrko03ejdrrL4KXlPia92yPnEU0DQVuA5VVVGUNe24RaVj0njUTQhOTuNPgVPR1G2wz9W4LjhuaYWDQ0zgt6hKd1gwNNo%2Fj6zIqfVi0aHFDmmWNjj1CI4DfjRFUfZoqjZh0IHagarGLQrqqKbfqsjLhIm6BYVP4Y1SNSWuN43fZIRliFd71IQUHiRBTeHVuHWFW0OrAbfyIHdpPJ8mqqnckqZIiOKAsqhJk4pWaz51WRF4GXWdU%2BHgeBFZUeP5Li2%2FpKxymiag0Mup4Pbbb2eHHbdBlzJwWrbublgTuA5Orp%2F3KT2PNMtoeQFOq2RJ%2FjJh3IKZEbqtEfrODA4lYeHhVj4OIVWje1fSBCV5mNuehM4YbTcmnZqh0%2FLISWmqGj%2F3CNsdllcpYRxQzxa0w4CM2u5jQ2DnRWcGR5ua2F5QtPDckLzJCUKdu8KCSpp7eJ6PqzOhy6PHwaVBsUFnoqJx7ZLR6JzWOmf6um9f1%2BdqICld7rj9NnbfbitCanwnJM0KnCCmCTzKpqTWKpfDYOY0CjgFlZdRUYITU%2FQLxtujuCWUSUEchyR1QuXWFp8cPNzMpxO2caqaQTJL1IbUqUmdmE6rBdOLafsueeVR4lJ5gf3%2BzK3snLVLz85K42Z4WrfMoS5cIrdtr91ru%2FSSSfu43WnRGwyIopimicmynCDwcUKfXKtUNbTTyuKa66f0ywS3PYdBBZnj0fVaRJMV3ThiSb6ckYkO%2BcwsvuPSKHa5eko1ruMQNoovWi%2Bdh5LAcam9htT1qF1dfgedlshzqLQmFPheQ9z41BUMyuFdi%2FKaxnOZdVxu%2BvVN7LrDh%2FAah6Zp4TiB3U0%2FgDTv4Tk%2BThMQ%2BZHd6SgK6CfDWKJ4NyQCXIsTji6zjpT2zT7Qrv%2FPm87gZK9P3YoI%2FJCgnxHonEQ%2B%2FaRH1HKpm4LI9%2BinGY7foak9Yt191yVxRDxUxB6UaUq3NYyzM0ll510x7vY7bmXn7bfFdXRvXZIsxw1iHMW%2BuiTJM9qjY7aOVZ7ReDVe5FGVDUEW47sBWZPjejWhVw%2FX2%2FPxiXFyF1e5jh5OoHwZkpcReRITeRCylMbpU4U6yz5F32GkO4dM90ZRu1CsLGlHbQZZDz92SdOU2Bmx51fEGb3ZARPxfJqyoq5m8b0aX%2FunpfQjBnlGEPm4kTMkZ%2BqS0I8pcp1duOOOu9hh2%2B1pdL98l7JK8UMLyiSDhtHRUdLZKVufltcmE5kTd%2BhXJbWrM1ARliWhA0HTUNKQUtD4LhGR5Qm3KS2%2FF8S27r102n5XUDr4rkeSz%2BAHEa14nCxLccue5S49fpJBFC%2BknyinKIMV9lobp6QgJ%2FR8ojyiaQqcLlx82cXss9cnhjncVd4DzxmetyAK6SeDIbbwXZrapWyEMUocpyH2PXv9TlURxMqmMJukhJ0x6rRkLA8IHcdiTuoV9NwUvx1bbMl6CaNxa5jvkhBHydpNKOsM1w0tl1alY%2FcvVzxsKlqeR5WVtP0uRdWQ1aXtlWJQtxvTFDlXX3MV%2B%2B69F0mSEAWenet%2BUtDudMmrFXF1GDftCVuGX3GPal544QXLLd6BBx74vTettgZZlvDiKy%2FyyKO%2FY6edd6OuSqLApcj7VKUOW0wQRExOLaPd8RkMZnEI8KMIPwxIsgyncYj8AEcnqNahr4zl09cFN8osJ27FFGVBrsdsdakFpJwGX6CnqhBKCQLPDqKCZpqlOBSECoRJgadkpyTiuLTCkGTQp9WKmJmdpt1q4fseaZrguB7Llk7xmwceZpcddwJXic2jlylgBhRaCw871EmiVOTghcODVTce%2FaIiHG8xPbArZ2tYOjVFXRG1BeRSBpVD2PbIssJeV5am5HlFZ6RrnyvSijCIKRsHx%2FVxiob%2B7ACvFZKkOZ1uTDLIaPmxXQQFwrTEnn%2BnG9FPh4GjFXlMTc3SinWgG4qytINU4eL5Hk3d6EnS6AU1Ho0C5xtgTrlZa6xkop8rCh1qjyCMbI21f1Ho0ev1ectab%2BHt667DmquvziOP%2FpZnnvob7XaLOeNj1HX1BsBKbS%2B1IK12x86G%2FW5nGKyVpAXmrBIw6Kkk7Nmei%2FFttzo0jWPrEynwOymOO0vjDajq2SFoDirKqo%2FjCRTpfIQGlLJsyl5HHHXIspK6agg8n6Iu8CMfvIY6LwldXdKQIq8JIg%2Bn0RnSSghM6N0zACOAr897rk9T1PhVQ%2BR5eFFIQU1WC7AVBoTztMCtHaJohKpq7DUWSsK%2BXndDWdd4XkytM1xnhL7D7GDA2Pi4gaG13rwWixbdyHrrrUtRVoRxaIG3bnRbFGwaGte1NVZwz6uMWGCg8pnoTDA7O0sU%2BWRJThS0hI4pK%2BzeOEL2XkNW5XbeBv3ctqAbtyiLnLwp8TzdlzaDNKURmNMZcASwFOItOljC1R3WChnYsi11iAjI84K402KQDvCsBqkMmLVaLeqyACXVIRLEaQQfVFII6L0RdITI3%2Fjs8Gzob%2Fo9rhVja621FrfedB3rrbsOZVkZEErKkrrR%2FgzPi4qHYfGnvVEyqUnqHDf28ULf7lYYxvhByOygR9SNqZuhyhD5IW7l0NM6tiJL1kmVU3sujuOT9mbptiLSNLO44IUhrhuQqkD1PXuuAv1h4FrhoecYeBGtVhenrsmrlMIdJohQwLyfMNrp2n4JdI92Rw0U9vt93MC3%2FSBPiEOPrMwI4w5JUQ7jS9zBbzy8CvqDHt3RjsW5MHRxfNcKV8U3razrhVRFSavdpp%2BnuDq%2FKviqmlxJPQisaPCU0PLM%2Fl5WlYFB3%2FHt%2B9qdEXK9TkG9sqL0XN62ztu49qoreMeGG1qiEsAQI6AE5fkBYRBB7ZGkKa1YgDVlZHTMCm0BTd31QJWunTD7n8V5qxjsr3r2Djq7%2FZlZRgWmgKLIicPICnIBjyD0KfLcStQsz%2FC9kKCtAsOhHGT2nGpPBZEge4Onc1Y39NOc8Yl5pHlO1IpZ681v5uZFN7DeeutQlQVhFJOp2qpVEA0BbZLklld0vgWUVUU2lUPLjfEcj1w%2FFwTDClvxtsYAsQ6MFaxeSVGmw2LE8e3e%2B55DXSd0um0GSU7gxXTb4%2BRFySBJ8D3fitU4DMmzlCgMqKgs15aq%2FC22lIx0Rkn6CWEYoMdUnssGiZEtyl2dkREGyYA8S2wtdNX0XBVr47DNWmutzc03LWL99TcwYK4CNc0SA9ztdpfp6Rm6rVCltJEOM0mBG7cpHZesUuxXLGqIgpiqUkFf47YifIGVPLd9VG4SYPOD2ICJiqphfNUaVHQ6HSuKZ3t9ew0uKoCV92ta7VHSpKEVGV1BXuYEis%2FuMLeNdscpEymINVmTsdHGG3H5ZVew4TveYWsgddHVXcaxOy8sEEQBk5NTdicUN0baHYo0N%2BAXusI2OSiWK%2FfbPqgiaAiVP3V%2FqgLXdwg7LZYvX2ZnfiRu4dUO%2Fdk%2Bne4IZZkb6aT9KGuXvFCRqucNjq998qmLgqZSDA4tD7Y6HQZJn3YnssKycR022GBDbrj%2BRt62ztuJ45adD%2F0%2FSVK7f%2FaAFj%2BHd2mIWPTxML4uWbLEfpfzyCOPNBus9WZefPU1Hnvqr2yz7XZ0jE0bcOUl51E3OU0QUDYuUattixOG0O2M4XgTfOSjH%2BPXd91tm%2FWed75jyA9VKYEqmtyn1eqQF9M46KIGFrRyLbsb4pe6hI5V4GJ9tHjaGB0aBRBVXwpiqrKzZEAriK0iqRrPvk9VYiR2rcqoypx22LZKi9DnhVcW88BDj7Hbrh83pJ9VNb3SIxqPSGsMOCnH273V%2FuluVzDSGjJ3XgiLZ4fMWKDEOTxXlFmPbqyKpaFyI7K0pBNEBGJKSoekyCjCyir4VhOQDmqawDVOotM0hKHDsrSwixIJbCjnFZVV1oXf2GWMA58sT%2BwxVPkVg5QRrX0BvUGO247IawGdwIK5qhelS4GVFVssBlT5VZ9RwG%2FHw2rODr4j8KNKu7IAHbiFgWixCYNBYgmnKQvqpuS%2Be%2B%2Fi%2FRu%2FmwUrzUVJQcBaLJqYJu2Zql%2BBqhVJesVx03OxuknA0hkyerqcYgObWtdcVWlO5Uxx610Xsu2Om9vX7HGbYSBS0LjtlgfYbpsDcGkh7KSvazVVBVH5uH5A5erCZPjaRLETYdtAWz0oLGFWTmY0WaMArZ3Qc9I1VrLXwziuncNQCEkVYeCS6vlpv%2FTa0oKWLzrHw1XB0GSUXknUDuxcKtHXuh%2BdeQwGKS23Ry1W2i5khdOMWpJphQ5XX3Mpu%2B21O3lW0oq6lAKlnRZK9JEnkJZbkNUdmDM635KUMWyOMJtLELRJi4xXJ5cyNtJhMDNN6A7PS%2BFVTMyZS6bAl1REYlGUHnztr085m%2BCGLaYFkvwAP1fl61LpoDQuip16t9rUrSncIcPbKZScI6bFpDsVbpkzOjLCTC%2B1hBFY4ThcS50DtxZrp1xZGjA0sKfQoyOj3yN6XOfV0ZmFwligmnZYc91VV7DnHnuTCZjHXUpdSgHesiT2ImO3b7v7TrbecRvKKOPHp%2F2E1yZfZZX5q%2FDVz3wDL3cJvZYVj0M2sYS8NGZOv7t2XJKqoAmGzP5It42TVjRFhe%2B66E72UjEgSrAenh9R6%2BB5DXlvkjAYstmW2EqHUpV3KyJrCnpObme4lbs4aWHsWl6LKfPJVSAayxyQBQ1FnRLmmR6WuDXBkmVLGRlrI7Q8yBvqyqEdRMSuT9XvEUQus9XA7lyXNp4bMZUN8KKIuixtf8XcKXH4ZY3vOuROaayEAHrg%2B1SJEo3YaZ8wCkhml9Nut0mUvFWeew3tkS6T0317HlHgcN21V7PjDjsj4K54vHz5ctpdMeaOAUsxc1kiBca1ZB0EAVVT2%2FdLLRGwW6EAGN63e6c%2F6uGZA%2FE7dham6xKvFdFPlD8cRvyAfNA3NUgMj96kBi1LpojF9JQeQdBiKk8QK%2BMWCaGATpINFSFXcVJ3XuesoB04XHP15ez18T1I84IwHrW7hpQBxfi4TZKltFtSOSpjvaKoQ5B5FFnJ6LwuU9MzuE1uDHBaOIRxzCBVbnMoimlj8isxQkXzBjAtjEUPXQ%2B3LI1hrRyfynEMINr6i5UPPeqsZ0VeE8YEUWvIBoudcYfM5NjYCIPZHoLsFov92tamn1TonKGCInJ1lQ1UqOhw7C76xlLFQcw111zFHnvuRpbPErcCe%2F1i5gWClWv0wzUtgk7AMpEZwlfiB2rwFeeyYY5MBgI7ko8yWoFvioXAowgX%2FXbjlJwhc1zVmRXFdT1k2JVD7Huk8hQFUor0S8SC9voDom4L128ok2mLwR4qTB1a3oiBpKyZpmxSe%2B3XXnMdO%2BywyxtKX2nfT1PZWRVgHh%2BfYzFWBcu%2B%2B%2B7LNVddgyeGMS%2FotMQup5R%2BRW5MZEAralP0E8biNkWWWl5O3Bo38uyeRZ5PPt1nfGwOs0lueZQ6t0IcT%2Bdjlnlzx8mKlF7SI4x8i%2BsUlYFRkWCOF1ugLapp%2FFBlSGwFlec03H7brWz70a0JXM8es6gbYUtbnxX5XfFZb1bIvxFHn376abvLvgKljntnpM3MIKH2fZJKso9Drz%2FFpw7Yh7H5C6kGAzw9jnTMsKFqAtzRN3HPb%2F%2FER7b5iAWFPz3%2BGO9cf10CyS%2BeEn9tlLU2WiWMXXAHOm1VhELngaHkOJZcJVloiGglv2rT247L9OysAZggiinz0l6onq8YJj1sWuT4foTf0qIMA2qlhOUFhGGX6dncqqfKD%2BmOB3zr2HOYSrOhBFSpGhcrFiJWbqTTpje9nMhT4mrwuuOMjY9w6Of2QgSQmF0%2FaptsUZYFlT%2BkRvV7VbV4lU%2FciowxyjPHWB%2FR%2B24IM8t7RHGXtDdkBVRJJwMJpHqXxFMS%2BA5FlZNlDZmCetq3dfDdml7SJ5nNGR%2BbT6Y9c30GScZIp0WVKWTZNlrS1LrozRHodHTpfQZZasmnO9Y1%2BVwsRdTyaCoPVz7JpmRqatLkAlUtCngTE2NsseXW3HXnr%2BlGERus%2F3bWedva9PslfuDYfljVbr9NdeKQGqaJLDAY1y%2FmRsdRbKgkk36fOGwhxb4vynm8ZvtdN%2BOmX1%2BA71UU1ZDp9fyYuvDZadcDaPkps9OSB%2BfZwU%2FSHp3OKFUuYC15c0ArCvFTSRouaTGUeMWmSzLW768kE0uu0hEWgGsgqkuTWjOntDMkeUosZumWuIGoeq2PbAEBZZ7jeyPGinVGWiybfZ18Nqfdji1AKAEXWU2V5VSxZMnagqXugPa4024x6E8b25MJSEW61I5J4QoYVVMg9VCgQhVcNx4lomOBz5ek7jY0hdgZW00Wzp3L0qmlxnoowIsJjsKaqcnleG7bKupqIAnMNTAkKTcKdGdcWq3YrBKqDPV33vDJKpQPj85wHwXAtE4Ctgp8YhBb3TZl7huYi8LQ7rhkEJ25%2F5bUFNCNsRuCPAEpvQ3%2FFJAbBqThZ%2FRZh26nRdJbauujoiiMWrY%2BSs66Qx0xKokY%2Fg4PPfwwy4sZnn7l73QXjrL5JmvzykuvcuIZp3D0wd%2ByOOKG7tDSELjEAi29PqNiAdIBUTtmUJZ4YcT0TI8J3zewNZuW5LVHKLtHmtLpzLN7mCYlQezR6rbMRiKmoDH2xLPiZ5D28WMF6gDX98l7KaNhiCP5UwxL05iUGVnickh7PYJArEqbdFCwfKZidM6qlNUUTlkgiSqO2%2FSLARJLpYxpjyIxrjhMz%2BQWjySHhvg0YcCM7tKIGNQ%2BI%2F7QulFZshSZLGajYKw7h8lZWUNCiqah0x0nGfSMERDDpD1etnw5rZFxS7QWFmrHivV%2BP7EkOTF3nhUjko4C2W%2FyjE67Y%2BsqUGX73PjM9nviPYaKTCHubcWbGPw3PjZQp8JS988nULHQlIy0W3Z3%2BtnwXpd5ZbJfP8vpjrfpGFNb0gpC%2BoNZWiMjFq8b1XMCBmIPpYi4kpRLdM677RHS2UnLC3kmhi40UCp1RYWPlIhcBaKKDB1PFY5iJKvQglerHbN8WYEXtGi3RVJkZqeo0sYAiVlfwgjdbaEg2Vv6M8ssyRZ%2Bh0wAX%2BpSUxsjK9aw7UmWFRiN6PVnGW97RJEKtiETr%2BIyjmOL22PtLnmS2nPujIySDXoUVUI%2BO0OrM45AqR%2B2KJpiKO%2BHoak%2BuuuyIin%2B9GZmLReKLJAsLFBeFBmup1VTLK1xxErXHkun4K6Hfs9Nt9xq9ouRbpf%2BZJ8oaLPz9juw3dbvwJOQL0ZKipGkf9mQypJ%2Bb5YJ2Z7ESPoeraBlcUI2mLqq7awoLqq4Vp5WoVBkufRyxtotUmBmZobR0cCcHJ72IB%2By8oExn7LbeDhORd1UQzDXiAyqabdDev3E5OuO1zLJXmcharUMK6ggTwaJscq7fvzjXHH5pdQqtoLQCreZmSnmjI6xdNkko%2B2OnWFZlmSxCZ0WdZ7TjmOSbAYnCJDCouBXFA1pOs3E%2FDksXrrU9j2KpF7k6ByPjnSpBxlVkRHLRiKLmSlypZ1FgXYFyEFS2LrUKtIrubGqN0Dy%2F7o%2F9qHu0f%2FEUa273l0DdJHPr%2B%2B5i30%2FdQCZxKbIoQghFSQXmnY8ev96gccvu5LLDj%2BaJy%2B6mMHfnrFFltekn5S2Ke95z3v565NPU7oejTf00NVFf1iheT6Z49MSdTy9jLDJhwfKaUjLgXnwLCFKC%2FW0UQnJdJ%2BJeAzXFS2rJKtDUOI3gcmvYvTEVs3WIYOmxWzmULkxr7y2nHsf%2BC2bb7kthRNR2M%2B7LJ2Efk80a07QZLRV4RSzTEQJMUsoB88Re0vpxgPa%2FgAn77Hk5RcJhEeLmrKXEhYOfuYQZi5xDmHZ4Be1%2BTsyMvrG1kiDl2nRJctT8750YoeewJo7lIwlR%2BtxBU5zBWxJp2mPpj%2BglNfLGWG8NYeqL8nBJashmJjPwHUpc49sJmNsRJSsqnBV9EocAgaSO8T4FVTIk5aTZrMUdUJrRFJvj3YnpNebpT%2FITN4d6ONZ%2Ba3axkALzEnKWbpshiRv%2BPBW27LJph%2Fgscf%2FyhNPPYPjiUoPaMWdofyImA%2Bda4ENvSRBGNFpOnTiY4fvVZnQaqliTsnLGcI4Ybr3Ijffei34GWn9Al73ZfzRf5O4f8FpvcSi289jqv8iYSRQkVuwjVuSiuTvEgApGY0cqjyhX%2FmUftfYCl%2FBUAq0mEZjgsRAaaHfkFzfyCryasRkVM2AngOZ36FNm07ZwisCqlyybEbppvT8jJ6fkyYJHb%2BFKt48q0lUIEhWzxJGW6GxE3F3xAqk0dFx82XOTE3ZPdhr73254ebbUJVuPhmZbIoBY52YwBsWCAMZM3G56%2F57ue2uu7jx1ru48eY7ueOe%2B7ntzl9z7313GwCPzA3oqiA1gKG1kByDK7%2BT2DwlFiWJyNjexolxwjbTvRnSrM%2Fo2JgxR%2FpdOorDim8YaPU5sQACeaXrm98odBsGM5M0XkDQ6hg4XyHPatu9Wr4qyeglpVdQegJ2GCPn1z5%2BPWT89HWx7saUNp4xvFO2Pi577b03N928yIC35Dw99ygI%2BN63juGUH5%2FIUUcdRbc7whNP%2F40n%2F%2FkMhVPxl7%2F9iUE2w1P%2FfJrp%2FqzR7XHjMhIqIRTGUollS8XiSjKdnjK%2FZMeJGI27BshV0IyPiEmVZKf18CwZpJJDu22K2iHV3ZRSILkzyyhkYIpi%2FKhLMqhoNTHVoCIe7VJ4JWkxQ1NNE%2FspkZ8xnSy35zCvO0Ek0DPZZ5BB0GqTFJh3T4lxLPKpZicZa3mURQ%2FixnzCKgDzIiKaN5fc1%2Fe1CdKcsigI4og8TRhpSWYuKMRSBIHdY9%2BNiV0BcRW%2FCtt98jJlavkMkd8hzZOhxN4IgMlHNmROJK%2FustuuXHzx5Xang7BtSVrSriPGVzS%2F16YnG0DcNqnR84f%2Bx6jVwQ1CY6%2BMMlJYWAHkLEgYOzAE%2FvLPOiVOVRDlBSyfIi4qU4MKkaNRbP5Av9Olb14ZpYgKz22IPYcs6VtsUJ5S4aozI8BgoKERSRCyfGoove29994sWrTI7pdAu1QJL2rRSxsuu%2BpGtvzozjz1zL%2FJSo%2BHf%2FckH9jiY1x%2BzU0MCrhm0Z1svtVO%2FPmpfzHIXR776z%2F40FY7cvmVNxjrMpvlxn7K41eVPnPbcwkqlzId%2BjXroKDwCiLFryLBKXq0AteKQMmR%2FbxHVg7MA9nyQhRDEvm53ZqmTGl5EU7jMTmYJXcrAw2Sp%2FNsmrrJTNXxPREfHnUV0WrPMduJANPk1Ot4fsle%2B%2B7KTTddZ7lX%2FuQoHDEJ0hQTgU2TUl1OP%2F8K%2FvXqFPt%2B%2BoucfOoP2f%2BTB3LgwUey7kYf5qHHnuWEn11tSou2dMjKuSRpn7LIDCw5dTOEDlVp7KasRcoHUn2Uz1udrjGPYqTzSoWLvI8xTlkbcG11O%2BaXl0wtQCofd9ytyZ2MyekBZRUjDLjXnntz%2FfXXmwqlfVdMFZssa0gtplI2KnJuuvs28tDlqtsXkcUek%2BTMuDV54BNHXWM95T9tAtnESuZMTJCXjXkEq1p7AsV0TasZo%2FEy%2FTRRKzD7UhiNIdYmbjvMzC6m2%2B3iqp9AT8D1TamZGQxszUdHIopkCVUh%2B5DkdVmrZLVwqN2AnXf%2FOLfdeY95oQUWA0ndhhJ0aVYAOMXqoZpiV0nMtewp8tTaH05gdKc0ZVXDekHLZyaJRkZMlpNT9x8PP075t%2BfY8U3r0n55Kf%2B49yGrhupKicM36lBVjZCqGifExDihSyiprxxQ5ClXXX0tRxz1bTrtMc4%2F%2F0K6IzGrr76QOXPnMjExwRoLVmaN%2BSvxwKMPMKhSNtvkA0xMjDNnZJSV5qzEKT89ldXXXIt5cyZYuPJ8ut0Oc0a6bL7VR5lJG1ojowYs9bs7nRGroOStSuVFKQSdFKtDkxmP%2B8HhHHP0kZzwg%2B9wzJFf4Wc%2FPoaTjzuak350DD%2F67uEc951vmYxqmFarVuXETkiT1iRTA6La47mnn%2BWb3zgCuVn6gxniVsjf%2FvY39tpjP5Yt7TPoJSYTysCcCZB6JVXV57577uSXP%2F%2BZgb3ZQZ%2B8yCmyhGymz%2BFfPYI%2F%2FfUfTCUwM9mY8dWrIl54fgm77fVJXn1tyhgfHbDZni5gY5SyvH2Sp%2BSP0f%2FVtFBVBVU9fD%2FlpBP5zneP4vgTjiVJp%2FDDCkdSZZPxi9N%2Fxsknn8yxxx5rP6dDmFcOadEQtsaoxFR5Me%2F7wId58pl%2F8eprS8nLitl%2BatLAimNmIdqC9orP6CSq8WEYVAXI1I1jz6mRN8nhjrtuNxC6%2Fcd2wItD8ycpiOn7tttmOwOpd955p1XbaiiRf01%2BDj2WDNqSP5reFK5MweNdppuhAVaVvmR60%2F7%2Bm6J2cflttQEAACAASURBVMyYP8zbQ8BZiqSlLnIczzXmrK48qrQidj1GO21jmWNV8NZ84JAq4QdtOx%2FtwDWDuJ6viiyB6cFgYEzH%2BNhcpmZ6xj6LGZU3dGamZ5dfDIcCrVhNSezyvmi%2FzNwudjj0LSjJS6JqXj7UXI0WVpUNmTTJa3VVWKAQw6EmFQsSWYZrwL62BKd7qepV%2FiQl%2FXa3YwzYkqVLTEIcUvhi01bIpisChu2oNYiIvVdTzKsvvchaa7%2BVu%2B9%2FkJHumMUTMXP%2Fm50rvWoI2JQ232Dn9I1i%2BHWf7E3nwiRwTB6VKVvPXZW59kFnWOujN%2B3197%2F%2FfY466pv84NjvW9B%2B17vew6qrrsriV141%2BXfZ4iW8adU1mTs2134mKwb00hmcyDGJVaBMZmTJf2IDi2TAJuu%2Fk6XPv0qdpqy%2F7jrmaZk%2Fb4KxkQkWLlyNufPmsmDluVxw6ZVEnZArr7iCleasyoK5c1hpwUrMnTuP8bExRsdGkQdwfneEtVd5E%2F988RX6Llx61a%2BYv9JadEdXZnRsPiuvsirz5o1bA8b8iXmsueoqrLLSfC67%2FGarxhvZUFwfsr5ZP0477afccMuNxqZJUhMLGwchk7MzQ2Zwepb3bbQRS5a%2BQujL%2F6lY23D%2BhRdxw6JFJsMpQRe1WKsWTz75NLvuuqvJirJPJrOz7Lrjjnbu1BQgyW2ougW4ajKjss%2B14q55BSuZ912PzuiIeaAvvuwq9t3vAMSmy76BL29xSdhus8%2B%2Bn%2BD8Cy40Fk%2BM%2BLA00J4PWXLbpDdAnoCeivN2HJrFoOtBy2345hFHc%2FxPTiYrVRhIvdDvkB3CI4hbzLzyIp%2Fbfy9WXbgyC%2BfNY%2B5K85k3fyFxp8u8%2BQtYbc03sXx6ymKKFVayDcz0DFAoPq44X2Ll3TBkg3dtQpKrkaJNE4Qc%2BrUjOO2sC%2FjpaadRB%2FDeD3yYtHJoxID6EYcd%2FR1%2BcfaF%2FOKXF5Jac1zbGL7ASa0JqzebUtZDGS8dDPjq1w%2FhB8cfS5INjCmTd7kqBpau5av0JZc2Nc8%2B%2FXc2WHdDXnj5JauN5VFUs2EyIzY1xvGlKlVsv%2F32TMyZx9x5q7Daaitz7bXXcuaZ57Daqmsxb2wB46Pz2PQDH2a216Mz2iFs%2BfT601bUiHUX%2ByuXin0sNl7WHXnPZ%2BCZf71E47VpvMga8wI%2FZqafW0OhO7KAh%2F%2FwhDWISQrP02EzTON4Fqc6nRbTU5N4dTm0YBm5EXPVVVdw443XkiR9i1lB3DG7haxYKkazpIfnurz0%2FAu8a8N30eunuGFkPjpPdiwxksWAOQvGcK1BzzPFRrhF8U9gTgWRWFKx8jvvsTt77rM3e3%2FyE5x0%2BqmMLpjDNbfdyL1%2FeJAtd%2F4onzj4QHpuwXQyQMKHUkOrE1t%2B6g1mzV6jphipJrItbbvFR1n22lJ6vR4bb7wRrdYYE%2BPjjI2OGwCcN38uCxYs5JKrr%2BH%2Bh%2F%2FAcd8%2F3u6kGjelbIrUn%2BklLJtexi6778S223yUW2%2B8hcCPiDtDO5nWMEtzawrVa1Hs%2B%2F%2B%2FrQii%2F%2FOVFQWMAboq9wiIqaZnGXEc2p5LHEUsE6qgDe4I%2F37kadqvDFj226fo%2FfXfvPjoEzCQ9Vwm%2FNpM7vJG%2B45nUqOM5oU77BRtdRzcasCn99uPdd6%2BITvvdSAHHHiwVQ0vv%2FRPXptawrLJ5cy%2B%2BDx7bL8NTuwhzL7B%2Bu9m8TMvUg6WcuqpP2Cl1d7Cv55bzOIXX2DjDdbhz3%2F5I6%2F3e9z3wD2E6u7J%2BuZxmzPepj8t6cln%2BZTYFQ8n8sx%2FkeTOsOLzYWIc5s%2BHBRMBC8dh5TkBc1oRc0ciVl3JxSk862CTTybvJ1YpiLEZ74yh4KZqoq5yClQxDEgn%2B6y%2F1lt51zvX5rLLzoS6Z6h6qnCp4zaXXXIWPz%2Fxm3TClNDLLXmPjXUp0mkO%2Ba8v4GUuU8szZkoPqW3yTrUCj5efW8r%2Bu3%2Ben%2F3kdMa7I5BP4TYDk3Fy9cmpa1bsnHXQDg32Bn7EFsr3pAaUTswZp5%2FCWaefyPE%2F%2Bg55osfoc%2FKJP%2BSUk37I2WeeNLwMWUYimSuMLUBP9xPkFclKubECNtxwIx79%2FWMsXTY99OPkw8M19F%2Bps1ayh%2Fo%2ByzdM9qHJFk4TS3gkz8X4%2BmaczbOArIipnZhFt95Hna%2BCU74Vp1iHOn0Li279M9TzyfMuRe6byVoNHUUmICTJoMGr1bNc8PkD9ue0C68ii%2BVnLXDqjM74hFHirhKTzNy19waLpIsgObox%2BXUIj1xCkx9hUDQYM%2BD0SaYXm1l39dXWZY1VV2PluXPY6wuHMJk1%2BOr27E%2FREmDKC9SLqT8FGuaMzTGpRNKZSlUxJgPJzZLdGs%2BYE4E3AUGZ7tWVLcN94EvKaqiKPmOtDm2Zaps%2BSTlJFIv19RgUsgwIFwZ48nTVQ6vBoBSY9ZkYDamSSfOMzF1pAd3uGCsvWMB6b12DJa%2B9SF5Kag0ZiSJCpzQmTolchYcIKmHyofyq9THhnLjTpkjlbRr6VzvdUTsvSlTWBGHAraZ2xb6pM04FeYhTqwFDZ6Q0kOnJR1NLmpNPSb%2BvNnCiBKtCTKBOb1pDddAHYWiS1EzStwYJNZ%2B8b5P3s%2F0223LsN48x1u%2FpPzzBmDfG979%2BDHU%2FN99L3XUpxx16YY7TDiyxy6uTlgV9sThBwO%2Fve5j9d%2F44Lz%2F%2FApu%2Bb2Nefu5vLF%2F6GrvuujdPPvEM01Mv8%2Fkvfhqv1eL1SRW7Id887CBeeu6f9GeW8%2Bjjj%2FPxT32S6bzHP595ksGLr7HDhz6C053LQI07TcUhX%2FskS5a%2FxlRvhpmZZSxbvoTFry8n7aW8%2BI%2BnOef0UwgjePT3T3D8cacY46tO%2Brro8eAjD%2FOBLT5K7bTodsZxnIw8XcpYHJmv9ubbb2PnPXZh5ZVHyfpLjbXqhF3qOiLJXapwCMzMRlPI0tHBddqoFVOeup8c9x023%2Bw9pg7oLFFof2vzGCfyObqOSU0623WhYr2iLCpr6Lr86mu44aab2X6HXUjl2Ys74MYUlZoHXLb8yHbcc9%2FDnHPeRcMmJINqKn1XgDoBuyFjW%2BUpV1xyCa2RuXTG5zF%2FwUIEwH519nmc9IMTmbdgVWuaWHXluSwYG2HXT3%2Ba5WXDaLfDPN%2Fj7089yYuLFzO5fJrZ2WmT1F599VU%2BuPnm5qn1vaFX7P91vtzA4q%2BaDHQG1ZgUddrWvSmW1wtdZPPpdLvkTmXF7Ww6wIkDKhmqI4fpJBk2DgQjzPRhJB4lyAYE6Yv87qHrmbPmKnTmrUq3u4DV5q%2FOJRddyok%2FOY2VVlnI2Jx5tEfmMGfeAq696QYOP%2FIwxkdXZ%2F68Ndhssw%2Fy0uJX2WD9dVh5zlw6rQ7zF6zEmmuvbrL6Zpt%2FyKwA8%2BbN49l%2FPMnypc9zwvHH2X2U9%2FMb3ziCpZPT%2FPu5l1hrrbeIe7eiVIWmJEcBOHliVeSJvZTCE4rpy8uhpNwx2zB%2F%2F%2Fuz%2FOmPj%2FHkn5%2Fl5eef5zcP%2Fpan%2Fv48v%2F%2FzM7TGV6Yz4lEX6qYdqgGyrMxmpdkb5o50aPIhA1lWDm7QNilUDN1oJyQd9JkdqGNZPvSUHxz7HVZauJDueJdNN96Il559gbeuuRbz585lfM4Y43NGmDc6l4XzFrDhe7dkMpHnL8ATqxyqOUOdtEPiQL59NX9ddvmVXHbV1Xz5kIPpzp3gtHN%2Byde%2B%2BQ3OvfwC1lhvTa674zqyIGernT7Gx3baedhIJBAj%2B0GV2xlQHKoKeYI97rznFnbadVuWvT7NOzZ4D6%2B%2F8jdmJl9i71125bln%2F8lLrzzJZw7al14TstlWm5m%2F%2FvjvHIOTLGci1kSANlUwxiuzGQvftDaLrr2Wm668nCf%2B%2FCeWL58yosmUV6kslbBFZeqOCu5h0f0%2FAE7xX7F5xZvyvPbV1x91I%2BrQZWJ0hF4ya1pyFHaM4XLUUVe7NNLnS4%2F26DhFM2OSohh3V80MrmuS6YMPPMKmm2xM80YLrzpblZzSZJpXXn2JE076ISf%2F7AwO2O9TNE1iP1OZuSqizgo8tySdXUau0SatLn%2F4w2Os8fY16JORunDGeRfz7WN%2ByIWnn2Cv432bbExaOpxw1lXst%2BceQ79ZCYPeNKPqKtLYAPnWSjV2gHWzNo51xQ4G2AV7%2FdVXTBdfsmQxRZlx%2BeVnma9K5E63Nc7rk8sskEWx6O6hL3DZ1HK%2B%2FtUvc%2B%2F995kRddHtV7H11h%2FljuvvVSoCjWpwGn550oloEb9%2F1plstukmnHXGL1n84r84%2B5yzzdD%2F85%2F8HMION9%2B%2ByLqGtIFjo12SVAARxqKKp556jE988iBuWHQ7o%2FPHzWsg%2BfTLBx9EP1zAT88422RSmfKHfqghqzGUz6Q1yvAPvamBjS9RkXv2Gadx5JFHMzk5yblnn6nza80mOhRxu4O8nlOzfavqtdC1RpA4OuQlo2MTvGeTzbjngfv58OYfZOGCeUMSzMZWKHRIZh2OHjGpRV2T8oqJQRMTVc3gxz1qv6CoM3b9%2BHYU7stA33yEGgSg52OeQhti0cWv1iBPpwmCYaNMnmrsSZssreiowSNLqdOEaGSMXgFzggC%2FcplcvgRR9%2FIrqHtLBmEBQqOu%2F9t%2FIGynTlihYVVRDmUUGIuTL3%2Bdp%2F78OB%2Fcdj%2FO%2B9VlbLfdR8zM%2FPsn%2F8XxJ%2F2Ek474opm3BUyyQhJjiHwTZX8Zdd6w%2F6c%2Bww677snu%2B%2B5nNjWBCGNRNIajKQ3MyWciYKlkkKvVPgqsMcVzPTvHbuCQq2tWndVZguuEw7k2vk9vdiixNRorU8njp4RakpXTOGra8H3OPuNcdtt%2Fdxoyfnf%2FPbz7Hety%2FBmXsPfe%2B%2BDKD1vlOG5sic9MtwJYNiYESo2qsIYRjXWprGhYuNrqvPDci9YhqIaYbrtjDLG%2BT4b1ygChGkEqPI27kAfPTOClsRf6u6Rc%2BbMqJfk3uqN19gTmBFjlW9TfBXatc1NsZijPZ5t8tsdHttjSuuOmBgOO%2BeqRJul7dcgdi%2B5mq623xevAib84iaX9l5kzMY%2BvHPh1RibGKPuF9V2ro9DXfInY58EHH6Qsl9veX3bZhRz%2BzR9TOS2uveFa9tj1AyxY403WcTY6HlLlYrQrWiNtevmwEUDsxGDQY3S0S9CX169NlldktYN8uz%2F%2B6a847qe%2FMuajlAzqOTa%2BSa7ZEa%2B0MSUnnXs1m7x3A%2B5cdDk%2FPfEkvv2VT%2FLoH3%2FHzbfcxY03rCvdyCR2Sf%2FyeJ179s%2FZY%2Fd9%2BO4Pj%2BOue%2B80H9QX%2F%2Btz3HLdXUPA5EdUdYk%2Bp7e1112fVSbm8dsHHrAuzjevugpnn3MGN914AzOzfb536qmgprLhhAt%2BeN6V7Ln%2FXtSlT%2BitYCgyG1GU1iWp4%2FDSS69bzNjvE%2Fuw3z77sdPOO7DXXntx06JbuOKKK%2Bz99rvu4dXXllkhOGxNEJzT7dNtfMMDpLFKYch%2B%2B%2BzN%2FnvtQ0uNc71lHPKVQznqeycysdJq7HfAgVx88cX4QY3XDnkt6yH8KZprenqat751HUo1rli3%2F9DYLy9Y0Bk39l%2BxS82MXhCa5Kxid8X5EqujFCQvWV2mxkiOjgxzhxjzVI0nToWREq5GTYkxGXoSNWpJryYvZhmfgESdomLaNP0gcPjGYYdw2BHft4LP9x1Ov%2BAMRueMstvOu9hYFq%2BuueyKq2WdNQb6hGMOxqkc3r3R9px78eW89d1vRo0pcaZBSxE9SYCRTx04JL1pev0%2Bb37r%2BlaA6THOOvdsY7NO%2BsnxnPSTHxsgf%2FuG61tThho1PL9t8Vk2ERVQcazudXXOxqjztB3GxrAWslR4Ie%2FcYEPWeduavG%2FdOTzzz1fZcos38cenXmZkXp%2FX%2FvW45SiJhiqUlGs1XaEbB3hVSV5mfGK%2FT%2FLrux%2FUkBzrYB4Gg4ovf%2FFL6hGA1ly23HJLbrryHI751nc46Uc%2FYXaqz%2Fs3357TzjuPt2%2ByIXEEsTpTlddlI%2BlMMKUGRsmLGhlSerbHuTy%2B5p33jJF0%2FICJ8TGWzk7x%2Fvd%2FkKuuu94wyNHfPJIzz%2F4ladZjemY5B3%2F1SxxmapzLHnvsYRMfLr%2F0CkbnTpBMJTa1Q93CkpA1HeC%2Bhx%2BirmbwyoZLLjyfI4860exH1918DR%2Fefj3WWv%2Bd1qCzZBK%2B870fcfKPjuDwww%2Fn3POutXWQ0mXjoKqKay%2B5yYraQePb85OipBwhtUg%2BGjGDEimEBf5PbyuaJPQ1vXYDdPpLpa5Kx7FZLC2ZH%2BUPKTWKwSEV7RM5fOzLn%2BXZ%2Bx7mN3%2F9M2uuvwFbbfMRo4MLJ7UuVaVhdcRKKkqt80sdmNP4TkIYaB6dQ7%2Fpmtx09UWncdAhhxpIs2fseBx9xOH86EufpNPxaLkhWVKz0aabcvapJ9GaN8v5l1yCm8szEXPrHXew0SYbKA9z9sXX0PgyNGKmaYFbUbgaXaLgmYhaj3x6iezEagMrcJuC0Q58%2BYv7W4CXFmvdrvJcVZCLftW7ybOByZpqn%2B%2F3EjrStD2H084%2Bk78%2F%2B0%2FOu%2Bhcjv%2FRtznu2B9w8s9O5CPbbG%2FzxCSBqmHhogvPoZUt494bruCrXz%2BGHXbZmXsfupM%2F%2FeH3HPXloykLjyl1uRKS1jNU1RImWgVNf4orrj6HG6%2B%2BnFvuvBavGzDVT%2FjKQV%2Fiid%2FcMtSvyhYfetc7ueWOuxifO8%2Fm1YmmFWjr2FAmeWUz6sbnyMO%2ByyFf%2BjZn%2FPKHhmd%2BesLxZihdAfL%2F67%2B%2BymFHH2NjVOSzMl%2BWkrSNlXHJBzkjrS5LJpeZ12HTD27Jnffcw7Zbb8nCuSM2ZygvZIRWoPCHJvpKCVsZXh2LnkkNRMu4%2Fq5TafyEnbb7BNfdciV1%2BDL4sxYcNURD4EqvQ3JdU47h5Guw2477cuMtF0PZZqetD6HIfFrhXGopFjIbixqsavNtFPLZaCxH7FkAVsERBpoLluPL6Bp41LWaL%2BRjHFaZ7SAmk0wZeiSNqrKc%2BV7DZw74BL8470I%2BuvMedJzCXt%2F711%2BbLTY%2BzOh%2FMV2hec08CskTZc2oH%2BKrwqsK6xxMcY3Z6qjDSWZyAWQN0fFia7xoE1D2ciKnRVv%2BG7uUDWHXJ5HXxg1sDIOkoKp2yPs5OvCdYMIqZM1kE6oO1B0MBG2X2d4MVZligwjUUxG4fHiL9%2FPbR%2B7nozt%2Bjo9tvhVzVpIJvCYXwJLUVzfECih5j1xr312ZbJDR0T2W57UzSla4NFlFJG%2BIV1CUg2F3td8mrXxCNSjJO1ZIou2Y3Kd0lNWajab9qSlmJumOjIl%2FZjZXZ1plVXuixw19O0syIfsyH5c5pdvQNZ%2BTxsQI8juUSWbJU3PnbOZg4%2FHo40%2BSd7s88sQDrLTGCB98y4f5xzP%2F4IenncwPvn6srYUvebjO2HPfPbnhjvs4%2F9xz2GeHbcyH9unPfopPfunL7P%2BZr3P6z05hzfGMw759rM2tk11Oa3j8yWdywilnmnG78UUHV9x0%2BQUmzweluvrncVBVWHd06oYcevSXOfaoY22ckQZWyiejmZOx1xDkk1x4yeXmV1an8PHfOZKDP%2F8JnluyhJ9feDFXX7OILbfeQViLWrMQmeLrX%2Fo02226Htf%2B6pcceez38cdW4jOf3oXDD%2Fsa5597KW4Qcf6FlzA2NsGOO%2Bxmc%2BgqzeGoKp58%2BDd8%2B9vf4IobrmKrLbbkyquu5b2bbsFShG0z5vZf5MJLr2ZZMDSmt4xhlS9TvsrUgK0XShry%2Bd0fn%2BC9G29scXLHXXbluuuvZ2x8Ja66%2BkZ232NfA7Bve%2FuGPP6nv9rHe358Tyvg5XuTMfz6a6%2BhKHO7601dEQcuTPf40ucP5ejvfZ%2BZ2iWJctregNhxeOiuhzj7sku54FdnMj9KaZfKUTne%2FAU8%2BY%2B%2FM7ryAkJ1amoUhhMy20v48lcPN65ZNg3NaBMFrcS%2FonjQuAz9bkeeateG80CR4NY5slJ86XOf5aD%2FOpCvHPxFY5fdJiNyNRc1p%2BXDoV%2F%2BLz534N4cedhnqfNJRkMx9QLy89j4g9uzzjrvZcuN3syzzy0hEaMSjVvHxZeqL%2BKWFXFnLr%2F%2F0xN054yj0VRRAY88%2BgjrvfvdfPtHP%2BLBuxdZvoplN1XRGCw0r%2BRjj13HmqvM45prriNT3IjUzJXxq8su59VXX%2BPFxc%2Fyvk0%2FyHnnX8gmm2xKlctvaH4Q87ipKNTc2MSKZE0UUGPUcAqCfLxWdEm9yBKCKrf5ax2vZjqXY76xotELZAHRjFOP2pGK0BA7NXGTkxQaaeYTj6zGU0%2F9mwUrt61r%2BPyLriIeGWW3fT9unrGXXljKCccdR557zOlOwOSr%2FP2xP7Pa29%2FMD37%2BU%2B675RrDMW3V2nqPVqV2I%2F7ylwdYYxU1yA3nYXqBdl3jdDRCTM1f8pE67Pvx%2FRgUOeddfCH77rE3J3%2F%2FR5xz6ql0ApeOPP2TCV%2F8wqf45ZnXscdOu3PD9ddZQ2fSuCzv9xnxOrhVRV322P9Tn%2BXGWx%2FhnLPPZY9tN6Ll1nz205%2Fls589iE9%2F%2FjBOPPF4Vlm55GtHf0tDnuiqYb1xOOp7J%2BB6yznh1NNx847gB%2F1shoMOOZhTf3mW9RSoSmsK%2BWwdagFsheIqI9AIuFqDWLT%2FQ6LGwNv%2F%2Bvj%2Fy9zJvW4MinxzYhckoWhAcOhJhG347YN388faI8hh%2FptXY5VVF%2BBPtPnN888TyujoevzzmX%2FanCzNVmmqgk5H89VmbI6d5sWJXpVHxtXwVYFPSi6%2B4FQ%2Bstt%2BlGGHRx59nHtvvhYiF8320kI4ZcMjj%2F%2BehW9bzQanCmSdfeZFNpsmw%2BWYH%2F6IDd7%2BZhTec8%2B3%2BXJKyr7nWoemzXIpKzNNi6GpS4d2pEBa0Y0860S76LwLqTUsNlOHSs7yqWXMzqhVuuKs839pr2Px8iE8lpYu1GeeJvMzpSDkrm6UJOe73z2W2cncWvx%2F%2BJOf8PTf%2F8YJ3%2FsO9z10H512yEEHHcLvfvMHjj7saHB7ljwv%2BNn5Ni9tv88fbDJhWQl8FaSDhL%2F%2B6a8c9%2F3vQTVgs403hEBgeJQLLruUdU79vl2soLsSTz%2F7Il%2F9xmH8%2FBe%2FtDk709MJc%2Ba06PewYYbjoxF10jA7PctBXzqIL37%2B65xzzimmq9lIlCrnkEOP4huHH2H%2BNLFweT8zb4NTDKl0ebVallBT6xwWG6X27vd%2FYAvu%2F80jvPdd6%2FH2t60xHNrb1BZc9AtE%2F2uWYNkMrHtVPogmzMndF3C8HiVLyJtJXHcaz%2B%2Fb5ZUnTN42xR8dVhUJVSMpZAmV%2BzK128YLZKCWETQn0iwIdQY1w5mHOvbGxun%2F8i3UDW%2FbYCMWv7aMQCMbcPjDM8%2Bw8krjZj7uz07zzo03Y%2FHiJcZkHv2D7%2FKLm3%2FDLYsW8cwjf2LBwjXZbrvtiCKHbHqARo%2BMtiSR9k0O%2FPvTz7L15lswOUhxugs45WensOeOH2LzTd7DCy8u4abb72WtX17IXbffaTPGqjo3ds6Gm%2FYS2qGGDCeMdUeZmp0264GGXTodl9fcxfhjEW4SMm90jjUkRI7LqvEosWYKZjmtbkxaDf%2BVF3msdPuTPGFkXMNXxYpp9IoGqWa4UcPaa6%2FNphttzCP33c%2BbdtmMtM7Y%2BMNb8o9%2F%2FJtu6PK1Q7%2FEYYd9lQM%2B%2FyUWrrc5Pzr2m7Rrh19deB4nX3wFPzvjIg7Y6wvcf%2BfdzJ%2BnIq7iPZu8z%2BQd3IivHfVVjj%2FiQBu7seGG7%2BCfz71O4AUc%2BvVDOeRb36DluCy6%2FkYOOuhQMiLC1ih%2FevLPjHTmmZm9SMUaNjbfykbiqOkg9JiZnSV0hoBYAVtz0JJ8wNcO%2FhqrLlgDN%2Bqa5eDue%2B9hun6d1sqr8%2Bhjv2OsO8Hzzz%2F%2FBgXtEHqhzWO77OorOf2Ci8gprftZ5uv999%2Bf2x94HI1FestN17JSDNvuuDVv644ySJRUSr75rYP4yje%2BiRd1%2BNvfn%2BPUU0%2Fj3LNPZ2rxFPM6K7P3Jz%2BFmkf03k8Lm5kpAOBWOe2583l9qmegQYMdOkHI3p%2F4NNN%2B1wJ4O3K5%2BJKLuPuRB5jqF%2Bz00a157PG%2FcPDh3%2BH6G67miksuZ7XVVrOxCCf%2B5DieelXTtzvcceuV%2FOWJv7D5FjvYHTLNyIrXLxBHbX56zmnsvttO3HH7LWY4lyn9mWf%2Fzcyrk1x06SXccP9vuOisn%2BFEPv%2F%2B1z9oz93IWCN5X1UMqTO4023ZY09pVlsQDLtF5V1yYJ999rKJBb%2B65FK2%2BsjWfHyv3e0pKJ%2B4fiTim%2Buuv9oM%2Brq4SpKDNLPCO9Skg2KWIh3wmQP2NZvAgtVWESyz8Sg21sKFD31wM4KxMbbaaivuv%2FsKDjvqMK48W6wHnHPjLcbWiTJUES8foespqfvceM11rLfxxlxz1eUsnDNqs0%2BDcNhtL8ZO1qLKxhU5rLbqqjz%2Bh0fIshnzGXzuc%2FvziU%2FsT9RoSH3J2m9anTvvuoNuVBlw2HvPXdl1l51xmuWMdjQWSDM6ZfPzDbSOdyJ%2B%2F8hv8NoT3Hjvo%2Bzx8U%2Bz6fY7ct1ZpzDe7tKvYmsXU10wmJ1E427OOv0sPvPVY9jsIx%2FF6fcY8SuafDmPPvYEW25zIKecdQZrrrqQSy84i0MO%2Bh6urCc2EiyipzE4kcvxPz7e8vJ2H9nCBru%2FbYN3cdstv2Z8pGud1SqyhyZ6jVTRHW7odLrUhbowNWfVJev3aPk%2BXq1xLxDaYPBhPFGzn3KlyHVJ8PpHALQ%2BnsaHaX5myycrA3ql5iZ2rIAVI%2FbgA%2Ffz%2Ba98naRU2a5GPs0M1agTx%2FJv3EScfeZ5fP3II3nbxu%2Bl5ZxDWOW0mpKHHv4T2%2BzwaU674HzWWLgqufbIccz%2FnMoqEGkIv8b3DKVjNfWdf%2B6Fpmbsue%2FeLF6%2BmLXXeZMB%2FmR2igcfupuNNlp%2F2FhxwD5ccv5l7LbF%2B03m1EQE1w%2FRf6RSEj0uvfwSzrj0ZprIsSaKbFCx60678pvfP2N35de338BoULLN9luSDzL22f%2Bz%2FHbRzZxx3mnshmQyLwAAIABJREFUvseHTGsKhWs0kaA9xwYi9%2BRLluKZJXQ7bVtzYSON7NE8VLHx6k7XHNcV8ur%2FBna6kPr7%2FwZ1Bujy%2FhRjGguSFHTiERufUPR7%2FOCbR4CTDumrJqLOO8POJtkrPBV9NQ8%2B9Fve%2FtaNWLToZnbdflsipyHpqYNDxnENO8yZPzrBs%2F98Esf%2B5QWMOpb%2FTFRmnqZmUPbMvyRmRfPcNOumzR%2Bf%2BD1dgYBixijxVjSHb%2F%2FwBArNX%2FNavG2ttXn86WdJywYnEjUZ2MBRja2Qni9yUcNjRXmYBDvVMJh8jXjVVehGAV%2F%2BwueMptT09v5ArcUdo%2BSnl8%2BiAeJlOQmNQGpFoZ74JrCLIAJZR7LIG2695U5uvvYqtt9%2BJ2677X5uWnQrq625Khus9xZ22eqD7LzH3nzq0O9xwpnXMydIqPrLefihh3jmmX%2FzuS8cap1yGiJ7xDe%2BbIbn%2FkBdr%2BOsu8EGPPDwX5k%2F4jOl7k43tuCoqdICFJNTA5Nt5y1ck3POv8DAghiokTF1vg7jukywqcz9knnq4dBaXy3TeilIAh3OiJMkocPVuLWZ%2FRXwO3HbmL5BWqCgOz2b%2FneDh4ZsLlk%2By7z5c1jvHe%2Fmz0%2F%2BGc%2BvedOa8823KAOpumCV4CUL%2BpGOnOQJmV%2Fl%2B0pxwqEZWOMpahvyqFbNCN%2BPzX%2Bngdauo0GibRsObJW35vTZpZB5WK6XGZtHpH8FQiBI%2F5KDtjtQB1CeMZia5v0f2op9P%2FVFDjvqSKJq9v%2Bh7q3D7KrO%2Fu%2Fv3vu4jMQIVrxIcSjSYkWLBQga3LXFCy1QKBVo0eJOcRIkOEnQ0uLu0uKBJJBMZubM8bPlvT73OkN5nuv3XM9f7%2B%2B93tOSZM6cs%2Ffaa93rXrd%2Bv3rr7fe0zno%2F1UvPPatSf6INNlhfv7%2FwGm3%2F8y00VnO0%2Bx57K0gWlZeCCWS8Gu1sF7V8RLli4jqIW9SNEEVu6%2BZb79D7n3%2BuUqFXD01%2FXEccfaS22fJpPf%2Fem9p%2F9%2F00Za%2F9tc3kvawQ2wOSRdQvZW2vGUgpUb9CpIHWt0oX6ejMGWtAmA6125TJLJQE8UZVGieJNgQq0JYWe8TXYEzKJGXddERHO52GmknTMMxsjsKWQVMU%2B4pm1MHUAogujAy04G%2B82aa69No7tOH6GyozslD77L2rps94WIcff4KOOulPOu34EzQ%2BiDTr0Ud16GEHqLe%2FJCB5Ws3Y2A5%2BtMaPtMeBx%2Bk3Z53p4GOiirzKt9pkg5%2Fpyhse1hprry%2B%2FPk8HHbW%2Fps%2B4R2uvu6F%2B%2B8eL9eG7X2rRxcYp9GONRImGq1UVUokKWQee7YOhZwotVKU6bE1TCfWaXkTw1ZweDL2LLrpIXqpsab0%2FnHueNt9gQz377tOqDwxpzMR%2BLfj6G6242A%2BUVFoq%2Bj2GuJ8rp5VYrSLAzIkdhL0TFtdfzvuDymP6FGeLSsK6er2qjj%2Fld6rUQLiXRSaWX2FFtTqySKYzdqrW6FIs99lBBVtDu1FR1MwY%2FEGhXNDtN16pE076k4bxNoKCGXLtet2lpws5vfbuh1p8sQkaGRrQeX%2F%2Bk7bYaVfdfdd0tRbMVrhwtqUV61GgvQ44QtmkoiAb66W33tV9M%2F6pdTfcVEv8YFGtte4aOuTAg9QEpzLTawYNTVmws%2FiZmsL6PE2%2F41bNXTCkA48%2BVbffeYc16fz1kvM19ZHHrP4oHq6Znlhu2RWc%2FiPNDjNJLmvNKpYSJ2tBsCcC5B2oC%2BnOO6dZ5%2BhBBx6s66%2B%2FXmP7x2innXYwowfkezprd955L2u4I1rvx7EZqHTX41Cno0gXX3CxTjrjVK2%2B5mqKUpGuvuJKBekea7C79fabTaH9ZL0V9Zdz%2FqA%2FXHiN%2FnLpzTrv1LP0i6OP0fm3TVOq3K%2BXnn1Gjz86U2ef9XsNjTR08JG%2F1Mmn%2FkarAj7rJ9ZZWgNuCqDcbMoOQ9KWsAPRIvDci6%2Fq1F%2BfrpNPOFr77L%2Brrrv5IV122WWaesu1mjhxot587x2d%2FtszdMTBe2vybrtr6rRHdMN11%2Bv6K%2F%2BivMabI1oqpZRtjVizw377H6L7ZrykRpDV1jvuqq%2B%2F%2BlwfffiuFl1scSuFueLG2zR5j90MBgvCoLtuf1j%2FeOpV%2FebaZdXqDGlsLmtID%2Ffe%2FZAuu%2FZazV74iZvzdlP77nmoDtnvOIO1wLFbbbXVdPwRJ%2BibgYX6%2BMsvddf0BwwbszJcN1BicnsEagcHXWMFxfZ0Y%2BLw1uqwcGScQw%2F0Vx5cOqKXoYFm42ABgQPEOBBaRFmBIwEdhtKFhZURTejrUYqmBlGDGWu40lK%2BNMY6VZvNjt5%2B4w09cN99mnb%2FQ7r01pts%2FgD%2Fo1ea853miqm3P6qHZjynk6%2BaqJ5SrOZCOsD7dcPfrtCNN9ykOfM%2FVjbXo1oTh6%2BkXK6tVrMiyoipwyPI4HuBIjAjOx2VevqsgejWO27XVtttZY1WCxYuNKaqtdZdS%2Fc9dJfWXHdjteKSwb3gjPQX8rrj%2FvvNwBqYM19ji0Upydt5k%2FiDqrcbCpWXlxqr6fferEJ%2FQcTOO82a%2Br26Tj39j8pk%2B3T71Bs19Ybb7F633HKlzvr1HxXXOEvyOvTgw9VJAo2fME5xTFeuA2IOgH4BjJuGlRh5dc0REenC771GjTve4rz7%2FssMulIxrVptxKFB82lwZcKmlLQ1%2BMk7%2Bsfzz2n9jbfWmCXXltJFO2Molu%2FNk3bxVMrJWvqjVlPDzZr6espWc1UDy4kCxcps9ZTKViMD%2Fhjo0A7Sg5Zs6o6y1kEHEjbGBM0Mp59%2Bmq6%2F%2FBI7nLFsMQdWW2N1rbL2OvZ5zGJqHACSBJCvSPZjKDS4Dq7HpuU%2FV98EJQkuduBqXTis48BqwqgjMAUFRlo7lFqJQTIQTi71FpXMS6yjyxgBMBSsHiPRiSedrOeffEYbbrO1LrngT3rhH8%2Fr0fuf1qQdJytpDdGbRy5IXn6MNtpkK9Vbvn515DF67R8z3Px7aV1%2B6XUK8mXdfu%2FtVksEqK8BMUeO3mfhQF3bbLKNGi0AlrrJUQ6FsCVlSlKY0WmXXqFNNtnIIAJgsGg2aV9OlE%2BD8RcqE1DQSxOGdN4F5%2Bmaq883rwY4TyKXpPMuvfwiHXv8WTr40KNcN1ocW%2Bq10QxV7i0qJDzqpaxjeWjhQvX39iid9%2FXNgorG9IzTiquurWdf%2BIe8zDpacvHxlpL2E4zkpsrlHnWiijKpvHXGgnhEygN0ccJJYEyB8o5nhUHH73ifn30vNG8bL50X6RI%2FKVhpnkujpuW1QS1KzNAGKJJSuIw15oT66ovPzRA47uTTLDLXW%2FC00irLaJ11N9Srr72tak%2FNlNqmW29r2FAKmjr9pGO19W%2BmWoifxXZgyHSwAsdAjQPFrRkND42ov5TXWWecrmtuuVm%2FPvkMjYmLSmVSqtKEks6YsU4hOQZYGLasmBokft4DeJsoHbUm5q0CvxA6gOQQD4SUztW%2FsQ7hy6acoydmPqwDfr6DpmyxucKRSHe9%2FIyDfKAjFIgHSieIsudyKmfHqLJwoTDeU%2FD8FfLW6QczAPWMdNwu%2BoPF9N577%2BnjT%2Bdq2623tuLk%2FjZRU2np9dbTLyfvq6hR14fvvKlmSXrrvQ907k3X6Kv5w6Y4M%2BmCXnr5KVGYfeSxx6kBbR4pZsV6%2B9VX9fVXC7XVNjsoyJVUaM42A2rieqtos59vb%2BnXH6%2B3oe6d9jet%2B5P1DFOwQ5q9DbaWA%2BCkHoRDhvfpJKtVK0orY6nrSnVE5b5CFxBZgvGBqMPqa6yinbbbVjvstIl%2Bf96Z%2BuS19%2FWDxZbWaSf%2FRrlOQVEjUm9vrxrhsM0PDSExNE%2BprIaakd5951%2BatMuuArOaw%2B%2B0k%2FZTttjj0Pnp5Qky2v%2FAY5XO%2FloNrDo8z8DT%2FdPvMXgbAFBpQPndJWdZLUzYBK%2FR1wH7H6yDjvyl5rcDtcEo68RGDVijzhAw705LXhzp83kL9MU3C%2FTTn26odmVQfZmc%2FvXeuyrnfH3w%2FjvacL01VG8BgtzUAQcfoVmP%2FN1qw2DXmzFrlvbYebKGMcqUNccBNLp8MaVX3n1Bjz7ygDbeeGN9O1DRlAP317RpdyqpVnXyqb%2FWM089rtVWWFo%2FW29VMzgpRYDqEFD3AAgiHLwCGIxE53xV6hWtt%2B4aeumFl82ge%2FiB%2B7XTpEnaaovNNDy4UNPvmaZdJu2gD997V5ttvJE5vvfdO9VSRzBfjO0raWhwyDAcMxjo7ZZOPuUknXH2mdp4y8mGfUg0n4xEw%2FREqFQupVN%2FdZKOPfEkrbPZTzXSqGtcrqQ3Xn9Li4xfzBrEMEI4Dy6%2B6K9KZYpWQ3dktWrPAfixkVUaeHTWjM2%2B%2Fh7LsCBrNGad9bs%2F6IYbb9Ghh%2B6nrbffSWus9WPDKqSJiKayo485Tnfedaf23nNn7brnnlp3vZ%2FqrxdfoUyqrDRRVhFpbFg97%2F57763Hnnrb1Y7Fvh574AH98JG71USXwYaQBDrm0IN0zCEHapW1VtSNl1ym0379B8kv6Jprr9Qlf72YsmJzgTGl%2FFxGS07oMQfvx2utqfXXXEvXXf8304uFjPThvz6yGmIFOT3%2FyusaU%2BjDe5BXLGuF5ZbTYzNnWNMVLE8RKeY06UkHxAsiBLlzzuQstHukUsEq7AB9RXzHsy5jIlUo2A40kBlfrVZsNJ29xR7LwhXBVkW3ZTIqFWmGo9Er0LR77tGvTj5OH338kTK9%2Fdr74AM07fbbdcVFV1r9W76Q1ux%2Ff6Ffn%2F57e%2F47pk7T7876EzFaRa1IXhbYlo4Wm9BrQZUfrraBZsyYYcYlXd8EGDgPKNOhJpLwcE9PWUOVIRXKZavDLRSL2nPvKfrjOefq6GMPUzoTm2P%2FyGNPavW1t7aShN%2F89gxtv%2BVW2mvPfXTtVddq0UUWseYjR1kYKZ%2BiOaGtKhSP%2BX79%2FR%2FPacp%2BBxvsGOfr6b84WJnsWMUR%2BIVSMRurPrJAhxx5mPbf71CduP%2Fv9NdzLlHf%2BJwOOHI%2FfTVnthZZckmrlePcAl%2BwWatYXWsWPL5m02wYxxLhzIb%2F7U%2FOAcVBpITmBQ82BXjsOiouUlZj9tt697VZ2mKjVfT2S7OU6SxUqjGorFoaW6SSxRUy46UBpEg6o1TssfAdwpCm461ZdbgwrVAj7UgVwHTbbR110C81duwETZgwUTtstZUhYOf7xyjlZzVSa%2BnPF5yvofp8ffrlR9puq0n67JNv9MSzz6nYX1ZjeFCPP%2Fyg4VdhtKXjlmoDiQpeqHIGvsaUMC4BUGRxUxk8EUBAMxqut9VJ9eiKmx%2FSFbc9pAuvv1fnXHqrbpn%2BhK6%2B7UFddv1duupvd%2BvSa%2B5UnM5pqNZUkOUQSBmuGDC1dK%2Bd%2Bfs%2F6LZHZxio5XCtqY02%2FplefPktPfboY9p53yk6%2FYK%2F6IUPP9aTz72gcrqtTLsuPxivWc9%2FootvvkNTjjhEb7z%2BpjZe%2F6eS16O2R8FqoBCGiFRMnb8atZa23WayXnjzUz352sea9donmvn8B3r1zdl68fnXtO2UndRuLZAfQKsGrtSARRLgax2uDiqdA8SyptBr66LLLtRV1%2F%2FF1T1KOuSo43TEL35lBzgycMHFZ%2Buqq69Vq01dFNAbTfX1FTU81DADBEMbHtNUhqJvOmp961yauwCAxT6tts6mevGl9%2FXxZ%2FOUBBlT%2FPDwjraaUzPGvyOQ7JOygqSX4LMwMmD8AL8oBLOQiIIVH7cMAsf3so76hEQqeGjGytJxyN5xTu2miwTSlTtSGTDDFQBquEcBN4WJgcM3m81Y8XqpmFM%2Bm9NiExe3vQFSO9RMbCY0GZ5Tua%2FPClE3WmdZtatz9MprHxkrCDWVVL81SVH09mj%2B7M%2B1ynJLm1e8YOGg3n7%2BBfVnM4Z2PwRQdpAzrssUaPmJg%2FKge5aOKWA%2BrDAcCWXto7zyflElFdUTlCwqd%2Bke5%2Bqy3c6xCPOWP99BFUlXPfmUrn35Wc2j1CAFHY9nNV5EUcN0SiPttuEeZiG9AOqBhglTyljEod545VW999mnWnrVVcx4XnPlpTR7zlzNmzdP3347R0OD83TqmX8wQ3%2BP7TfXM489omdefVuT9jlE4%2FtK6g0SDQ0ttFQitTZEB1GmUKFmvIw6TZyqUKusuaw%2Bmf2F5sz9QgPfDGnul5%2Frd6edqb5SUR9%2B8qE%2B%2BOwjXXr55Zo4YVHNevxJB0kNqDkdqODmdTsTcWNomILbE%2FpBUkXPvfSCKu2GhuOmzr3qIp196e91xc2XaOtJmyoMa8o0I515%2BMm65qxLdcbhv1KnChxMZF3BQ8MLlY49LTp%2BgnJJqE6zqjP%2BeK7KYxeVHxS083ZbqrXwU112wSmKvazxMntJyxqlPvzwS1159Q36%2BqtvVavW9PJrr2n3PXbVvG%2B%2BVnXoW9XmzdZWm25o96m1I3383gcanDeo%2FvHLqVScqMUnLqIlFunTIotOUKm%2FV4suNkHjejLacavNNDQ4qJvunKH9Dz9R7dp85fyGPv7sG01%2F8Ek9fM9Nuu%2F2K62bvRWUVYlLuvbmaRqe%2F7k6lS9Vmfu5FpswQVvvPEXfjISav3ChqvPnqjHnC03aYitVw6yqfq%2BOPvEkg03aZuMfabP1V9Grb7ytHSbvpSmTd9GVl%2FxVsz%2Bdr0ZYVCGgIQuopSZIlqqhM%2BGYbbUsNdyTZ%2F5KBt46beo9um%2F6ndp11x1VLPraZeftdPddt%2Bruu%2B9Qp1NTX19B%2BRwR3aZR8RQygZW19JbBxWuo1a4pyCOjbZ1x1jkaHBjQpC231BMPPaK533yqhSMDeu%2Bjz1QqjdM%2B%2Bx2kYjErrz2kElipka9V19pQX339tQaGBvXUk0%2FohBNOUGW4ojlz5miDDTYwhw0nFwMFg8RFVZv2%2FuDggMH68GwEf9Hj%2BXIvVcDKlaCTwykjF5Ox36dyWSvEh9qKF2wmQTqrSg0c1bSCMFCOqGJxUf1t2iOa%2Fuj92nHH7VT59hs1BuZo9mfvaPIeW%2BuFf72h9we%2B1qRdd9fnH3%2Bq5598SvfddY%2FumDpd4xZZwqKOX877QkMLXOfuhVdcoYsuv1wDAxWj%2B5r52KM6%2B5zfadJ2WxuEFXGIHyy9oh555CE9%2B%2Bzz2u7nO0ugCsRZLb308nr88VmGApHJ8SwNwdzAPqLx0YcHudVQveGyYOgMMjiUaATZgrxMUQ36TNIlmwMiYKQDwya1XtQm48ZEClt11eD86J1oDArEP1VfoN%2BecpIuu%2B5OvfHvOeqbsLhKhYzuu%2B1arbbsopo2bZpqAPK2Q1193dW6487btOzyK2jHXfbX7MGKFsz9RpWhBTr%2FovN1xQ1Xa%2BHggCojQ3rhuVkaNyZn5wF88LBWFK2pzMGXGIRTG5YHYLxaRu9pjTExjX3StdffrG8HaxppSmuv9VM99uAMBZ1Ym23xM43UKrr1%2BpvUm3MYnXTXK8N5XFEujJX10jr7z39WO5tRsX%2BcJu34M1UH%2FqXz%2FvRrxZl%2BLQArkgwOMZDaXI0perrsxlu0oB2oGflWC5tqfa3Vlu7Rl3PmqpUqqNpJrFt6YHhEiZ9WubffNVbBZgIA%2FfdfpL5d2MWdH99v7jNrh%2F5CaIfw4iHThhUqjZ9eVXvoK23845W12vJ7a4NVl9ac95%2BX3%2F5Wiod01cXnWjcatWcYdEODCxzHmyEmgwcDByOeriN25%2BDE2wW1gbTZDddcpPkLv9XX8%2BdquDakc8%2F5o%2BrDDQHw2FssqDL4jfaYsrsd3K%2B%2F85EWX245rb3uujr66CN13HG%2F1M%2B33VoXXHCR4Gzbe6%2FJGjfGkx8nqg5XDNfKwP183ya3UQ%2FVBooijgyr6LW3PtSLr3%2Bo51%2F%2FQP94%2FX298%2Bk3mvXMa3rq2Tf18puf6tlX3tdb732q5156VT9YdnmN1Ojao5Ynb9dgM8CdCFMDxk0qmxMLD%2FJzubdkja6Rn2jB0KDl8BEwCnMNRLAtzR0YUDqP4Vp1nSnZnM75y4VWl9MKE%2BPBoxaBiBSTODgyYjhVMAjwqjZb5jGx%2BfgvCT1lMijOskB0J3KJB0ZXJKli0MMh3cbzwuM69OjTdOBhx%2Bngw0%2FUYUefZu%2BBR2Qk80S3aH9OpVSpNA33CFockM6BM6F2iTTsSB1qMDCpxmn%2BYFNeql8rrbahXnr1A3325Wy1KBwujVLplGxcpNUzfklBuITyWlFxOE5xq6y4lTYvl6gPTRhwGGbSvcoE4xS2SopaPYrifmX9H8iPJyrl9whDr1ZtKV8oSynSzA315zxhyFDsnOodo5XWXkPDzRFdffFflUCFFRT03PMvae68L%2FWjlZfX%2Bhv%2BVHPmzNWMB%2B%2B3JgjlenT%2BJVdp%2FiAgwOyORL866WTts%2BduevHZN6xOBIiGJ194Xb%2F%2F8%2Fn67N8faJnFxumEXx5t6%2FD40383rCGMB7AYy7mC0SIB9kzeiXkF9iNDDip0dDPMM1FLC7d7KMqWUcEV%2FYJm3PG40u28Hrz3fotKPjrraVWV1fRZz6jupVWjKJyCdsN9dEDLlBaQXqeln%2Bsa7y%2BYY62m3n3vQ22%2F02Sde%2F5f1De2T6utvaYGFgxq5sMPm7xAUXXaH%2F%2BsgcGqYewdts9ueumfT%2BqOBx%2FVptvubGPLeZH6ynDWtrT22msbQ8MTM2dqeH5L9WqiO%2B96QGv8ZD19Pu9z%2Ff2pWQqbkUHUXHjRlRqcM19zP%2FtcD943VYViWtfeeL023WprDY9UValSZxkbQC1YTDiEVIdAYu%2FxvheoUR0x1oJ%2FvvyC7p35oC649jJlJ%2FZojY1XU6o%2F0SXXXEjfgRnmE3snKhfmlA6zymeLto%2Fg4gR%2BhVRPXG%2FovTde12%2Fo9h6qa7GlVjDA5IcefUJj%2BpfVaaecJzr8C6VepUDfbzQ1Z15Fm2%2BzizER4D0XckVWTlmgntKBgb%2FS9AFwOtXPn3z1lQ487AgNzvtW1QUDOuLww3X51Vfrm%2FlzdOON1%2BrdN97S4EBVT854XP967yO1O02t8%2BN1zRmhfGTSlAN0%2FKmnq5RP6SdrraTz%2FnCGcmlPYIL1jpmgTz7%2F2mAuxo9dWtOnTjU9DiUgupaC8VYdBP%2B0UeEdeORRhi2HAR7Vq3rhn3%2FXnbf8TRPHj9UyE8fq4Qce1u77HaFKx1NjeIEK6O8gUCfxlSLyDd82RhH182FDhxywn7bZaks9cP%2F9xucMu07SaWlMb8Houh598H7ttdtkHXHIQSbrKS8WjR8GEAtUiHEVp42aj%2BgkFHvG6NHqWLPGRX%2B9RLfdfrtuu%2FVmTd5lJ737zjtacsklVRmm0S5Ru1nXuj%2FZRPc%2F9riWWOIHGtvXry0231IXnX%2BB%2Bnt7NX7cWD01Y6a22Worvfv22y5bA%2Beu1SS5yDgAtIDZ0lnOOZXJ%2BsaxCYYjqZ12p2Zk8NZtRkVI0lS9NqRCPmNUYVZIYh2wRPzgUAWwvSMYR7xsUZEHsSX9ax3lUl43xRlZ9qRAUX4DViCw2jyddcZvtdaaaxuVIU2FwIn0FHNG0ZUwcdaMgvFSNcpEnHi4ST96700NDnyiyy8%2F26CTKOf4xS%2BO10B1oeYML9DSSy1jsGKUSBFrw9kiVQ6uJSl59hiNhHkgkdIgVQXcypAmjDQAAgfO8UKvcYuDD0lmATYIo2Ik5UdTSyZlXcRDtaoZvSSxAao%2F77wL9MRTTyvfO8bq9cCMSzp1XXDenwTIs9VZehmddebZhu2GgAHUTZMWEDowsLeijsHi4Hj74MzVh622vEmNYbnXzj3wb8H2hMEFg8fAgXtJl3a09x6767577tYWm26um6%2B%2FRf96%2FxPdfsNduv6K23TXLfeqPVjTrdddZzq4VOoRjC4w%2FuDAwKNMenpsb6%2FefOUF%2FeLwY7VgqKIfrPQjBbmy7n%2FwaY3r%2B6FOP%2FXPSoFTm6RVHjtGgIMQpvv7E4%2Fp2aeeMno0cHdpWIP6ZcLiE%2FWPZx7XJ%2F%2F%2BUJN321MLBqsq9QFaDM%2B8J1hRwFNsdkJDGvhvmdXvTDyc6u%2B%2FLOVazEB5VVGhlFe7WVHUqmjhe2%2Fqizee11orL6m%2Fnb%2B5gto3Gvz6E%2FXlExWWXUlFr27RtCBxm%2FyXvzhUN111l%2Fbfew%2BFXk0d2g8hPvbhCAS8va4mgIKSDjr4eIXhAnXS9MZ25DXB1UqrlR2juDhGqU5d%2F379BT32yN91QPNorbjmj%2FXiNW%2Fp44%2F%2FqXVXX0U3THtY226zlVLVb60z81tNsFTJEpm81UN0FixQpdZSP9192YyxOND52G5WddghB1m0hUZBUhUU8n7%2B2Wxls30Wcl5kwngduM9eJtyDLWhtsspEUrVC5CB29Dr1YbVbLcv7oxQshQigbATLQ1v1zoiUUPAO8Gtdg22aA0rys3RZVYy26ZmZj2izKzfXSiuvauFfuAZHYJ4oL2IUKmCpZXt9TZ85VdNnPWqpYCPSw%2FwCVRibWzmtvNom6jTTqlZaFlGDjBpoAVI90AChfKyuQGn98vhzzAg%2F7LATLaXY6fg68JATdfChp4n0A8%2FBQeWlHG8j%2FJMJwL2xK44mCkYxsxdQY5fVELRsfqRyuV8DlbpK%2BR6tvvZGevHlRxWGK2nVH65pqP6wJEycuLgqwyOqD7W085anWKoxaI%2FRnjser3seO9uAM2mGSFmC0lPSSilKsvLD8Zo86WTFnbK22ugkgyupDZWUTRc1dkJBA3O%2FUBEaFS%2BlEw%2Baol8ccLAoqFzhR8vqsb9P0z9fe1YbrbyFbrzwYlWTIQWlnF5%2B50ONG59VdW5Nj896Quv%2FbAcdf9g%2BKkk67qxT9fJzn4tG2XZmvHafcqjGL7mStt9ybQgY1FZG608%2BUPffdo16572vFX8wXstMdEX5O28xWfVs1iLHpcTTlj9dX8ccc7jOv%2BF6zXj8MRXJIsEj2q4pl%2FVUhYIoRa0nhPeJqvVhozWCgL3VrmvHnbY1Y3vyzjvbQbr5Nj8zI23zbTay4u%2BsyRepVjp%2Bi4ZTVh8cNIovOD5Zy18ceagOPfZQSwGsvMqqeutfn2nsIhPlQfmTyejhmTO1%2Fmbb6rDDDjcDllqBToY8AAAgAElEQVSd8X3jlE3a6lt0rEVYBjI9WnWDjVVOvtacyucGmprEDeULJT39xNNaf5NtdeTQkQpyvXrzrWcUlmu6b9b92nij%2FXVM4yiFYUM3%2F%2B0GTSxN0JIZ6cHXr1XPfvvBa6Gf77S7ttl%2Be6vnjKK61dVWm3VLERNNhUINUomzzz7L6LCqnZYaXqjXP3hXX9XnaLlxy%2BibT9%2FQmEJB7%2Fz7DbUTB20ziIEY%2BsrkCwohxjZ4lNjq4KAarAzO07xv51rq8dDjztcRh5%2BsdvVrbb%2FDFrr9xouULhS0sJbWGb8%2FT%2Bmwofdff0XvfzJXYbZfDbVUzKc1srCikpc19hhwKol2kKXoTbX14F03aZl11tJILlBvY1AH7L6PNt33EO241z6WuVhu%2BaW0%2Bw6765orr9ca66ytG666Rr8%2F73TlUzX9%2FZkPtMtOu%2BnBWTO1%2BrqrS60hHTJlik45%2FTc6dOfNdOPtD2jc4itplZVX1vtfDqgvG%2BvfH3%2Bgi67YXj9YdIzieqJ8qqwcTpof69ALwZIccU5eI1Shd3HtuecBmjLlIGW8RDnqTRuJot4ltf9hR2rNlZdXUh9WirmDWs%2BDm5qymqaVNPSWy5q3YEQHHrSvDjpoX4XNinrLWQ0OD6vpBVY2Mm3qLWaUE3Wnc5L6XANXhW%2BVyFebqBYd5i11oEbq79Fgc1iFMWXNePJZTZ%2F1lO6d9ZSRu%2Ff29KpVXagomyhrJTo5A41%2B8%2F33zZHrANvZU9Q%2FnnhCLzz7nE466VRRnZXvKWsQqJp02hhySgVAcinc75iuI4UcpKGuqhm0zq9OOELHHL6vTvjlUYZ%2BkE9T7zdijXQ0Bpxw9EE69qj9ddhBh8gL2ypnwbesq9McVCa%2FiGUU8CiCNGUDDUMaeOShRzVx4ji14Q%2Blijif0rln1zS%2Bl4aBrJJ8j9EV9qTBSBxRxgjdS2q1QGgYtOAGh3tfsd%2FKXgJ1VOzJafDbBdaIuOKP1rQyIKpirr7uUgO3v%2FySi3T5pZdbynXZ1Vex0o%2Bc8apGZrxhoPDKw0FsNGAYSjjCOJl1jaiobLGkV958R8P1hgYW9qk2UtXHXwxo%2FnDD8OrG9fVaypUOXKCFCqWSrUUhA4ZtRiODDQ3VyWZl1AOauMfZ0rEADO28tUZD1JGmrCaaxg6gyrIaGR4wSKAysB2ptqU8iSRSN5cv9KsxOKSeQslov7I5zyKL7TBUs9U27EKcA6K%2BGOEt6kmTWA%2FcNdWya719Y1Sp1lTqFHT47oeZwQbQdrVSsa7XNkZc2FZfqleZgq960jZjrgACxciIBuZ%2Bppkz7tA%2BR16s%2FQ45XgsrH2vS5K019dbrFTfbimqBzjz%2FGs2vD%2BubBmhDfXr37Q%2F16KzpijoL9fWc9zVxxaXkpRPNfPxBnX3gXtps0w21xKITVejtEzYJmLc4ArCyeLBCWa2qWeO2Zs6Aoyzp%2By9LtNobZtBhTBEdobsy40Nj1dEr77yqTdZaUwoHNfDN15rz2Qf60Zob6sUX%2F6kNfriWxo9bUp1GbLUKGGlc8tDD99ClF1%2Bno47cT2EEh2nO6rjyXlGd5nz15h1Kab3VVrlQNjqqJAz1%2FLMvaJdddlMjDLTKj1bWCiusqMsuv0gzZ95vqc5dtt5bE5d6SGmqwyXtsetuSjod0fvIJvnpt5H2nbKr6iNN23y5AmnfrBkmVbrmCJDQFp8EFrG79ba7NHvePOuApYgZL5v%2F6vWWvvjia%2F353AssVLvUCsto9933NA5N0Lq9oKl53y7QmFJRf%2F3rpXr4tru02xGH66VX3tRpRx3lytXx7oKmHrtruv6cPkdqB1p127111lnn6vTfnqZsEOrTT9pafoWV9bsz%2F2KblMjoscf9Sh89909NWGlVHTZxMYvmVMNYm22zvY4%2F9Q8GzlmGJiZuG1csIL9XXonSTFu0KhUEqjccJhAcd1CtEL2qVmvWln%2F4UcfbpkynMxppxHb4QDwO9tkRx5yiKl1WhR6jO%2FGStNWuEX3M52lr79gmjvHsUuDkhGpV4CAsWAdOtUbLeF6sK2mqZVdaS%2B%2F%2B698Ko179cKnlVCz1asH8QYv25dJ98jplFYn01ToGm7HTdvvo%2FpnXmrG%2F8893sjV%2BYMZDSpK8Jm1%2FkJJmn%2BJGUUUAnduRCimKX1OaP3%2FAUqX5JKupdz2gppdTG769oKC215HSFSu4%2FveH7ymsx6qnIvk9eWMhadSHtMiY8erNFPXJB%2B9Zl5TnNfTEy2%2FoqkffhudaXooUX1ub%2F2wjDVOg7mXVzpT0LcCtjVATe8bo%2Bptu19WF8RqoJeopjzNU%2F1oyrFQU6fBDD9MRhx%2BjBRxLEKKHwB4Ay0HQom3UaWxYL6Y7K61UqWSpKdIV7KlHHn5Y2%2B%2B4ne699z5N2nEXPT7zMW3%2F8200a8bD2mrbHYxDMaEMGQYN9kNAsX7OujYBgp561zSLGje82NJ1CcZHJmMRFCBV6GRfYunlrNYQqJZOIWdMI2ngHzod4%2Bi8Y%2BqdWpieYE1J4Ektt%2FzKevftV9TxgS0Y0RJLLKlP%2F%2FWRfFIydIHHDTMifrDcivrys4%2FkJ73yc1nD1itmUFgjOuO003Xm736vpgd7A%2B4%2F428psCh2bITn8Jx2mm0rDqZG5rTTzjDKpEqnqT9eeIl%2B%2FOO19eQbT2tkYEiLLtanuV9%2BqeWWXMo%2Bb%2FWXSUb5ILBIVTpIKSI9liJ976nWhgavrOtvukU333qfpuy%2Bl1ZfdSUV0ktpk5%2FcpCCoa%2Bedd9WDT7ytYrlfrx17nC678gb94ugjRZCcw49oWt6YDQLN%2FmK2tt5ia80brmiVlVbU2FKP5nz%2BhfY75FijrJqy6976x9Ov6ranX1Fy%2BNHyLJolpZK8Nt9mS11z5XW67pqrlSk2dMKJx%2BuLz2r6Zv6AsRNQ%2BxsAqdMa1jlnn6Hbp96jQ%2Fff1zp3SRUSSY4iHEhfO%2B6wrS669Eql1acYesLI1wFHHqJiNmWgwxYtSgHp0Va5v0dJp2o1Xxuu%2FWN9OmdANfVoyx0naVxfn6Xl6MlrEyHohK4pLZ%2B3SHa91tDYvl4NN5oGCp3LBKpWHPYnshjSbRkEykLaTnE9NF1kEyySkzW%2BajDE0uBskd7MFXXiiSfor9ffZLXX20%2FaSfMWLFA6IZpN1GxY6wL8PPtrUcu8xZZbWsbj7089Y8b6KDcwhx3n0J%2FOvdBFNSgm93z9aI01NGvWDIWAo0eJOQbIBIDsgNHSFAfMxc47bKMdt6OjPW%2F7foWll9CLzzwlargJdOy7125WP0e0GDSFcFxZ%2F%2FzHLAEETWovigLlM7BmDBr8Do12kyb9XDddd7OCDFAwjg5x38mTNPOpv%2BuHa%2F3M6lwB5jeKuSK4i7AqtTU2W9KZJ5%2Biy6%2B4Re3eMZp69%2F0uW9JsqFqpqbfcZ8%2Fxrw%2Fe15gJZd1y262GUQnTyklWj%2Fg7jYw0dfChhyjteda9WcjQcdyybA61y1C3oHfCuG2MEQgTGYOypI3WXUlPPP%2BWomWWsCgemSBo5DN0%2FIYj2mCDVc0J5dwMCinbD1lYpsKOGu2O0lkyVSlbrwTO1ahhZz7drqef%2BRtdd%2F0tCltp%2FfqUM0ynM29DC4eULuVVLORMR5524q901VU3qVks6f5HHreGpp4yOnJEfuDg4DF6kDWo04aGh60WHxngPcaMhOFs9RWKqg7iMBdU8jLabtMtLU3eGALAvaBWvSa4qVH8yCwRPlLT6EsQLsh43Dltuq656XbtsdsuWm%2BdFZXzl9KWm62raq2qQ%2Fc%2FUI%2FPfFZBcYweOfkUwSM%2B%2B6u5OuePF%2Bru26bp5JPP1Vbbb6evvpkjH4M0aOvk40%2FQjltN0mXX326ZFjibU9ms7TXGDs8wJQL%2F04v9zOv7QTrv8ccfT9b7yZaaeudtmrL7rgqihYLX9NmZU7XJOj9UWJmjhx6Zqu23316Z8qJ6%2BIGXtcPxV%2BiIw36roDRODZCiA1%2Bt1ohy%2BUA%2FXHYpHbz%2F%2FiZ8TdIlUBtFROA4UAFC8ZTrhkU7cNQBXApGFYdOYOWXysBlaqMEdV5q%2Bxnr5shFFDxKLT9vGz%2BVNKydl64T0n%2FZLrL5V199pWdf%2FUCLr%2Foztf0yrod9jz8Ix1LTBNhOSEeM59sBRI59lMLIQu5Ekrv5aTel3Q47%2Bny7XSfw6vE9E1hml%2B4KhCnhHhy1DhKhiScqOhExHCPJB3ONG5QdirqZ3Q4NmoAxFjrLFIiuSErmKUb9T3sy9%2BRn8H8o2GTcvGfjxZsmqma2M2DInJc0FUDbA1gC%2BxiEdgw1UincF6gQmB3A6fONg9PaowGctu87gnvgYXhlyc8SwO8KGyCLJlwBnc2EiCtq1oc0smBYzcpCbbbuD7XY%2BLJRHrE52DC0uocdem3nKSp%2FpAdn3KxUnNMuO0wymJoHHrpf7cDX9j8%2FSOnmCgpCjPSa8W56cU5JkuneP7bxcP9W4DrXmDOseKITYNkV4qwpST8bqBm31YLii%2BeoVnT8UcfqrPMuUnFMWZ7f1hrrbaRtdzlSZ%2F%2FhFKXhEEyQuZY9L%2Fek%2BL4T4JnHFgGxJmoD1HUOg62NbTG%2B6zypmMMjjgzbKmq3dM9d92rybgBhc1C3LGWRydG4kFj9WNRpGOVdLoC2DqfFahcMZw9JAqeIupmFI0MGsRGEqC0OL9YlNplmwOwhZIKtZAC%2BXRou5gqsP%2BTUvZA5Xy23vMrD%2BBIjF6HNcT1FOXmiQtQ02cewBUjYH63ABMPKSYASHzkD4489gNxmDKCYMZC6xFOnCsTNkwMiTugyDCMVgrx1dt05%2FXbtuusuKgQYdR2rS6p1RpTpoR6yqQfvfVqT99hT9WBI51z4Jw0ODWix8YvoxCOPURYolFRZnaZrRqGpxYre2fmkwAAfNbAIB5Yd04iTlGyfBV5Vnlez8VM3FcfghqXduA2BMGudqb7XtLlhfs2IsHlmBdy%2Bhb8YgGX2C%2BCxxZDUFnorbfNp2513EhqB2Nc0PUFA7%2FaVMWkkcDs6Ve1qMEmfokd9c1pw6KyWhjR%2BzJ5Df7L6vjIR%2BFVujtkDbRyZ78kr68zKp0i%2FYQSZ%2Fk19t06mo0hbdUGf75t%2Bj3bbbbI9K%2FIC5hmQRJCrU8McEH0zfUCQ1zd6N2QshObLFIMFf7%2BTtw4ccFbREBsdHFoZPRThRRkOJU0DDp2fz8VeYvzAwkmz39uR7VIs3AAMI3si1gCAa9aB%2FddRwDP60EbFBm1DKv%2Feu6Zp913Zfxnbf6QgeSExETieNu%2Be0pGrEwfQ2cZHvS91o8AnyFcDFgFqYsFAM1q7LvOFH9rnGRqXgs%2FVPoVOtsPEfd%2FQ7hm317LrGgk9pa5pkCU67pxKUup4JdufARiqatv9TC%2FjDCGXiJJJWLe66jsWAX5BdoUO1pZy2cTSsvfc9YCB6OYyQBzRlJVSupAzcPJOs2X8xiMNafoTL%2BnOex4SvZlE14yz1Iu0%2BWZrad%2B9t9NY2IwaUPUFBjWWAaakC3CPHFrTG93Ftt6hsmD%2BgXlpVHCU9qBXkEPk050%2F7UCqpdEtsXpb4BTyc87OavYBcz16LhP4Q97uvu9%2B7bbbbqZbuB4OhQVwWNOIQqLA0sCs%2Fb77HWCg15T2cA5BpRYB9GjyY8P5Ts5HZdftc27WMpkPBa4epiztKmhnnouxgDOQUSNIm9xnyRyB32l5FtaIlrGU21d0e4OcwcsvWLkJgOcAV99z9zQHcgw%2BMLWMVv%2FjPvo%2F%2Ffnyq6%2BoXC5bTaVhz6BQvdhNIGKzwurr655HHlWWIvUxK%2Bux5%2F%2BtoPOxdtj9SIXVWOdecpnxk0KdwjlC%2Fh30f7jpStke1SpVAxPGiyW3bR2fRujlTBX68gA0BOsILBxYJQhK80nMOmYEWg9%2B4oBAQYZeYsqHuP93n6Mxw6OOz0FzpNJpg%2F%2FAsqV1eSSEfiRlCg5DCYw7P3YHHw29KAuQE00v2Djo2LZdZ3OHEdT5rvCQuwa2cG4B3fSCW8O1nEJHoTrYKw5MlBS9tgAfKnIsCG4jewbQad9BIaFTMKjsXm6hqbljAziFxfxw4jI2pxC5O%2B3NJuQIb3fYrnLD1Iz8GIx2rp9YPQzfcUp89Cq%2BEt%2BxKGDoMQ%2BmHhlHkri2aAr6OaC6nbZEUjCaOhRPcj2%2BQ%2B0aa0l61svbJi%2BN71V%2FvwPPXGfV5bT88suqGWGUgZEHT2xRgcpKkkWUSpZSKskpiBaXF9YVt%2FpF7YivXiUxtQl4%2BBgIrpWeFDVpFeYjdPDQxvKAQZGi3R6glJDfe2pyWAJTEbhIQW8%2Bb5g%2FRA5POe3XWne9H%2BubyqB5rMced4J%2B%2F7tT1KizHKFa6tZyGSAt68PdMPKg%2BSp2u49plUBxUGjzH9kxOeYAisHrojbQs9b5Yl%2BPRTZIOxRyeKPgG6KofOvqS3m%2BKkQ8enpNzm2Su0vO2nRCaWBgnnv2Vls%2BESg%2BZBqI9YbaiwOZN7snqq2VUzxcdHT%2FuNEaCI%2FtETOGbR8gs4FC0uBg5zH%2BBDykriwz%2F989qztQUcLuNlYSbXh7GMPOVSHew41dxxz%2FNHo4ZJnGDvZPp2OGXU%2B5zyKL9caIitmS2gaODSVbQ7lCTjvvsKOCNl1nKZ32i18Zz2hlaFDjSuNVG64ooiaLDl9KCGrA5pDSScyhcRLLn139Q%2FzBFCu6p%2BPo4Ax8wUxkcyB4JjOAWXcMREjebH90Z89LuakffVJ0DAc%2FBiwHNOweo7vW9iPzz7pgyLnZ4fcJ8s3PScOpA1sH1tY5eYHFSGhI5NtOhxHdoSvXmd%2FOoACdAFEYZe5Iue1vtVSslOlb5pu1gDaQOlwUWveAGT0wDQWVNCFg00TeQpoLqLWiG53mJc9wxACB5oBDRE1LdfUz12TszIWZ8V0Hwt0%2FtuYUvoOcmczSGkhUBQJ3Jh22DaJLgNyawDjD1FaGJQQdHwk3obM3TOaptULfmQOBs4qOhK0kbBvUFpiodHTWGi3lchnFdqAzTpwRVsVtNqdbE8U4KSbbGCHc12bR9jvad%2FT2xrzihmXPZPNhUUMcS%2BdAcOaFRAWTRJkYRiFOhkQdWy9mwQjWbd86vRYYdAiOnBn99gmXomSPM%2BMR54adC0gR90GGTOTsfcDM0dEYMRg47vlTqjVHXOClFand7ChJ09yUVSpuqScTaNftN9VO220moD6bDSlXIjLNndoqZDpqjMBfnlUbQ617gqOjYYaxaQqo9baTz56TTI%2FJgsk1a%2B7mGXgl06B%2BZE6AhyHO8cN%2B4AmM19npLs4hVp3nw2nhJ%2FZ6pLaidmyZFuoDnXwiq6AqOCYQ6hJpvEAOfGr1KAWIsR2c%2FnLGKDd2DoZziuLufgFKJNed27ZllvicORsJ%2B58dyPc6ykRuDfg9e8uzQABrwj4jI%2BOun1hACPgndz7EHSKZbfWWSwb1Q114Np8xylG3pt1xjY7ve3%2BPrjaSoFRY1dhy2lDfM6WsWuEYlZbo0w77b2Cb2IdyJW4qCyVQ7KmTQbgIK0cWZUmrLIr5wVMD02fB0LcqAVdABAxE%2FjQeFt%2FB8nYYdqx4FLhDx4wjtkDXIyRAFQcsmrPmCQQhCAZVZz90NxzXwvDDogSLpgXsg3uOOGkpSIFA7hkKPIoCr5ulc0YThprpDBeZs0u6xXSbwY4fW1yE0sZvygPFhfeInuCZWHCiAO4A4LuE8s1osc0dCC47O2vtO8yA46s0RWAjQoW4aBJ%2FO09UCiKH%2FB8FrubBj51HQ%2FcoL7ol2V4oZTPrbDMF9rN9wG7gNjfk1jy7eUddz8bNr4uYYf5ZgYwpeJ4HQXT3jYAZ8fmcXdU8G2bHzUuiBvAnYAMS8Qs989Ah21Y2gN5RYxdfQS%2B%2F85FeePN1bbzhOlpm8UXENecOD6l3XJ9xS2692dHyOonCZmApjB22OUaddGLdsPKKdn0OfTM4zPH0DY%2BM48DmloODAwQGoMBFIUeJ4CFlRyu1wC9r1NQTJ%2FJaLQ2ppqVXWVH%2F%2FuxT%2B14YONwfatyKhbQqdGjnMvKowTLlQcrEgTDaPaF46yrS7hniJui%2F%2FRmGkRUiQ8uFEqO2EYUHZEnOz6oRdoxQmpQ3HjOwEWA8onDhJIT2igYcUhF0M5PusVQWeFCAEHcjxtzWxtH9%2B78Nw350sm3nnf08qvc5yMw8MYVpZ6AdjmbDE2ng093f2TXMARm9A4KBcnM%2FMwYX5UYwcRi4H192UWYOJ350n4eNBDaCQO24ahFQ6jRxbgCcTXJEKENTbG0%2FK3C1%2Bov9atarJn8lYAlqNeWLeVUgHocDttMwOsN0LmuUSRwW9pw2PjdWkyPmicPBdBM6iklgsBifwCDYqWGT6q4w%2Blm3j%2FgshsxoZM5566FF55FLgzjqRiPQGaMOl%2BkyIv1dA2o0uuJ0DKwdbqIZA3M%2BumZmPNhYAZIkesQLgwKd4VLBvDM6%2F6SjbP1MbznfgznnMe273fXkO%2FbzqDB8N09urlqdphmRjI%2BieuYFgHVod0MinnaK8Lz2j%2B79u%2FfhWkwj9xjVt3Z%2F%2FjBATLencRR4bh6WvUYWgR8xNgPWhguw8V1NJW8wOiLmo2tp08HKmYOMJQVOnm9cszAldCJHs1cHJ86P1YpaygbgHiKXLlLJP3C%2B0Ot%2BCgOEcbLGHNpOfvksL0QFNWfftQ3yn%2FftTVsd99zMgS0r68QlR%2Bea9YOlxfSX09WUQLmXe5%2Fn4x4uskUWBZcdiXSRJZMT%2BwIz4m7KfEF1yIvOb49C%2FxAjKlC9OazEb5r%2ByXtZFXN0DNN8gGGUNi5ekjBkLLIp0sjkpttqdwq2DqmAiEWifJBXKk4p9Ntuh7HOzB0%2F2RJigPC8bpdQCMyRZPvMZI7n7a4n%2BgN57SYjmE4i98wT36cZh1%2Fa%2BzbnXNP9Hvk0k5CsGxFZSgVCcFYRF3RpolKpYHiROHcEcKFLhGawUhkyFA7mydaEa7M2%2Fxf%2FDmkAS3mGLoH5a%2BcDDD5WopN259z%2FNh5baUO7IiTctM6ldNozkMBCD63bLAbgqs4qTKc7ynhw21UNMiBdzFv3EijwPtEPU2y%2BFXm3yWsbNiG0GW0bkKmGrkdl8SePJcDJYvYovv%2BPkOMpm%2FJiF4zqVPuUE2MMKDacS6Ukrk4vn7f2ZHjlWH0UT6NZtehMCrodFGo3RTTqGWBGYbgYMwVYRKaeiaiwEbiXs8DtXiaoKBSEyKkQ28OGW%2ByMOScU%2BJLOazZlwO%2FN02ADdjccECq2ofH0mYTu%2B84pNYMEobJb8tyjGsTtFUXOcTEDy65jURP2GBEU5xGbErDrdr1LrmOpFX6PsYbRiRHnCqcZNYYB4%2BFz7lBwCteM1ZgrOj88BHLDIi0czAzaLMSu0R4oisBGI%2FLKUUyHYq%2FGLbmGFFf0zIvv6fnoNYua%2FHCN9ZTrHSdFBWVTBaPJMp6jpKMsQY04VL3SUT6FuZlYCo%2F1YurMmOyuJ4clRpDtQ2p2zHdGCTrZ8lIkvwHDTFmaE6R6MwTadY20m9ZokcvmNFBvyAOZvVVXIwxVHjPONleOy5gmYp2RSf60Ubj3%2BbV9BHkhiuCiFfzJfPpEGgPXWIKMjFSr8gJf%2BaJTkCHjMZDPjnE3RpGnbDZnReZ0UxN2x5jDYzMwV46wBKq7hqVo3R5yO5px2H7iL7Tqf3uNyiCfc4rLYh%2Fu8czzhdsZOfjPc7pndanL0X9bVMT27ugNiMbgnTsl7aLobp5sfAm%2Fx0AfjS4xZ8ynbx194FnaQZz4qo3UrR6Ibk02ATAmHepaBNtLXnAekhnoeJ59FsUMLA21Mqx1jrQG0TkoDIFPSrsuTfPETW9wb9t43SiLs2wYLXvI7UesD6ICbq5N87AhR6NPzLLJoosgccW07See30XY3XbFkepGmswq4ZOURTC%2F7nOWisEIscVjDM5I%2BE7OuhEEvs64R3Um%2BtPpEfQYc8kz8W8X8XB7BZ3F%2FzkqGD8i6xSIu45bI1tvSxl3Zd3SmCbV9pwwvoCdSLNWwrg5Yf2UOuZwOP3nZIPrj%2Bp2mzWTQ35n79r9nULj%2Fqb5unv3u%2FHwfneP8Z79N3oi2Hr85%2Ftu9IyTK3E%2FZtutE%2FKGAePT5BUElpom6TVSg%2BvYs65ap9G6ER9k0wyvrrPKWrPGFoFx68xYLI9EGtgWxD01d%2B%2FGogzQ12kjl%2B1gVKYLkHd7HqcwzHnnvdGMkEXx3FpGFuXq6mkTjNE1Zq5Ho1ujhp0JjtPFtv5M8qicoH%2FAzvS7DWcyaA6en%2F3FIzQbdYNfYUljeJO9tLKFrGug6NTUbI7Y%2FuIMtWwbZ7oHE1DOOKwTuh7tdHBZCgIOzKvLk5ARI1jh5ovoLPvYtI5HbNbNgjmErJeJnNsLmGZQExIR5S9n1iLCZI5G5QJ5S1wNcsa30hZzcANgrnyDpSlkC%2FY3egQmJGet4Ui2rfaOqKW7qgmn0%2B1c322W%2F9f%2FBh0Dve7EIDD0C8bO%2BcDL5up%2FG09XDZsJb1yrrZpNSl%2BhoPkDQ0bCbpRZWIZQpdQdiXEqV7J2YtI%2B6aTXFjiKm1bXk6UfIEoUE85u1%2B2cp74OsbM0HxyZhH67oRMI1E2tslpmgXYVjQ0OK7%2BL12WROrcOfC5li843XQ1b5PvwHhhvJLqPQutMoWwLmrIoIVNCbZGpj%2B8OYTLBZhgwbjto3O89C0WxDd3vnUFnutAWvjtcu445k93L8gk76DyXwjV7GW%2BKD1mUz0XWrOmAi3vUZiGwzhPj9KfOZ1TEva7l5mrqcGiZH6ca%2BDr1c%2B7gdeqEKFwcUweCgYOZw%2FVdAsEOTzNEOWCcp0mE0baWhQ5Iu7oHiRKwZZxSdBLVpR4xxetb8a%2B7ozP2KVonzdXxRkwRy89YlC7fTikQFDCesnnoTvJadKmJardqwst7553ZeuO1D5X1Olp1lRW00rJL2jkBYT30PKlMTkVYuEnBULNgnrQzGojGjZoreFuEy51cOJkw2eh%2BwKJZhMEjuv9yRi9XbTWNF9TIpRWq0QBYu2BUcvl8yqJGjWZHWZ80cNPqIbkP808ayPECcwP%2Bc6rGojqjYtqVZ3R0H0EAACAASURBVKQUaiGidGxSxgL2Il4jBwJR5Wy3lg7FQlFy2IZaLSdj0WCiKbukFjALrIuLCmLEcF%2FScC4lz0q5%2FcS%2F3JE3OkO2ivYHI3cv%2BHKRWONYs38zv%2FZNQgi2IbmeJ%2FhP%2Bdl51hwy7n337O5qLnrBmEh1UTfCbCDLo7Ni%2FrQ7CEyOmEt%2B71vRsaXzcEziWBPHLUqFhm04auiYP6KU2BFggcVWwxYr6iRW5MycRPW2YfJhxBVydLtjfEhZyMw53OzwYKwsjJsXiyJ2jTKLjhnMhEuXulky88k9t605lpaTNZ7KHInuXuLKzIoV%2F5thxJOReqLOijnGCXL3RRcSC0Ev2otr8m2mRK7%2BZtTYRgu5deKzLnIzWptp9iGPw%2F%2FsObrlINTn2LU5%2BF1Ug88E5vixnl3HDw1nygxDm%2Bu78dkNbZ5YA0%2BlfEmNatMaMHC2wbkEZgRWE%2Be0UkvEcqUtMktTljM0R%2B9vd7dnxsH57%2Fd3UTbedw6zzYlPetOdB3zehIHTnolhQtxs20w72HneoxAeiSPlxeFMbSd7GRlzUR6oFSdMGGedrtRwtQz8OW3fMwBZw%2FlyMuvBnEOk0Oad1WIjOmOEP20XWOaHf7nIKs%2FtIUcmY8wn42F9uxBTVqjvSmt4b%2FQ5%2BB6ZJtYxNMghJ6d2H1L4dnd0G9%2Fhd64ExZl2zgFH%2F%2FN%2BGpwpkvJAUHHeRqHhf2ZiUpGxxi0y0Wq24AltNSOlC33W%2FQ2nLRLLfqk2OupQy5ZFf3UsouXFGZVzefntUDRQRhnfymKYa8qLLFDQnT%2FGYjoBw4%2BUqZUhcL4hj6PRZWSbeWEv8YT8jvly7xEJYubYKzw1cEY8j7uPm09kBcO0UW04DmhSsCmoSzMmn%2FwefdVutNVT6rWGl3rV0Uy2OvDgUiGIfLm1%2BP%2Fib6srt%2FPBOaKLjJ9oTYnYA6TCSRX%2F7%2BOyXSNrithw9ZX04MzHVQkp88uoWO5VnaS51TAAuhiqr9SjpAZycUtRjokmf5U3XLJQkPGG8luE3RMFRSi4QqvNy0Mp0rGybptYDLoWRR30hIZpVyhrhhYbsGs4sDlsBd2D2EayaMeoInYpHcLmCE1igK%2Bc%2B5GLwMjTcD1U%2F5KryM%2BWzeHmc4STebnroSJYyG5Y14TG%2BRQ%2BETpTIkRc2KijOXFX%2FA0LgukVfDUr2GXbcSU0Msapa4ZAmZAWxXDlFQVEHkkHghHG57ocXeCnoIxMoUNo4eYn1TXo%2FuvPhKadkeYOYK7TcdGxBEInmh24Pk%2FXkOdR%2F%2BQ2DGNhTHYbDrhujc%2FovalbQOGONju4ItSk26TBhnIpATaIPa2tm3vu2APegBokzq6cUpGnYicx77OVyZu3lvcTa5YAvb7VHBYE5V7cUBC3VB9ZqGZ1yOYFsmXSOlHovEyjJCPqH2HcjSqvSElAbSWGJwcJxdjOIOUZsaGRD9aP58IYihotUyCsT5NuryBtYfdOB%2BqwvEZaeKee0mHH6jIqNMoarVbdDDqUjvnaloIhkuNSGpY6shX%2BP%2F9BRx86FoMOo40UYf%2BYXmuJHz0UiMJhzNGtxb%2BJxgGJg8IjlVVr1K3epdGsmcIyI1WOaxcaptHyBBtB13Bwo3Gy95%2BRuTniILczD6OOvcaKmovInDm5t8MaBd1930xo%2Bx7XdBJv3yPKy%2F6yZh6K0WFbdsLsjjMK6N1N8KxpSmD3UbzONQGBTmKAyF2quVKNrfay0xk2I4QIBoDWHBJtY1VwhcKAcDIPxv%2Fs%2Bdbx3KjVjSkEAxH6ZVIsGM%2FIAbvAXhZlx4nryos9L4rB%2FWx7m0gNn7eIQrdGzqPmCT3FpLGP0t2IOHrDRYasdMHdxTQNd%2B34FEJjKLp5Y28Sv%2BCgYx5xSLmmNSXZzIx%2Bjr3tdAG%2FhwGCl9Nfzml0BxyxBAyg0X3vHEVqcO1QtQXGgHQOJcC5rI5HPY8ZP6wGEUmuj%2FNJ84prYOH5G7VE48cvYhkPuJUd8HfHaluZjlQ3JerujzZxzWt2fzueGfX%2F%2Bf48P2PkRSSHl%2Bl0Zp%2FDn5pcGyzzQD01z%2Brmn6Y0e5ljzBcztjy%2B52q3nHMMk0DBNRRR0xU3DR6ob8xYNVuYDuh01yBE8wJrjk6hbs5qHKnTjXPWgEbTnp0a5mA6UbDxdg1hdDrz4faPGxp%2Fon%2FsOLNnczp29H3mGweRZ0x3a8w6AK2TLkaXYqBErhqXCBl1kQ6cnMYlV9rDtZBvaPSYyVE9GHrIHR2frjA6k6RN%2FwwDMzO2rBh6FwII4A0CYxR3lAd2xc%2BbwQc8D9G2Qt6zbvFGI6N8KqtcKrSzNg7ytufZg2R7RmuXkW70gWtOcQ6ei0h3zx9TBUyKi1BznvAdnpfx2vtkgeycdPqCwAVnG9c1IxcTELxNmiaaNY2bMN50JmNBzxKZB26LPU0DTy6fEYGCWn1EfX19FtVDF%2FP5717sTztP%2Fu%2F%2BHaDHkCnqPOOOatWGOx9aoTEVjT6HZVz%2Bh%2FEtt0TpP00RcbFPNb9PY5ZeU7U2fJoppZo1lQo5q2sIchktXDCo3lJBFCym8r4dOnm%2FZIduGISWA7ZieU%2Bqq6lMTNFrWjkon7qGAwKIAZRFIKx2L2%2BRO1czxsSyiU08bYGtC8wUAl1G1EcRvvVd1xD1HLQYW%2BdmYF4%2BxeR8nZZ0OhSTVFFR6ABd3WHsFABKDMF3Rw7lGpAtcfS4DWEFx92J4zNEsuyzdgCQgnGC6BQ%2Bv%2BeuCCjdSdSZZLspazYiBb7OcOxYjRuhc9epRHrOtro1H%2FxHsOJujjXsHjg0GtjLfiaK4X50f6EQXTTNat4sNOsOBIvOMR4%2BjsKw62Dg8bM75Nx1UU7U3mHIotBQ%2FChNFGSsKHBdnn7kCLpN0bEZY6cwLKJoHmZeRETRhUSfahRSQxUTcRBSuxGrXOgzfCWqPodboYq5sWoSwi%2F3q9TjO0iPJLLvZBLAKkmSMBYMNg4%2BjAAOUiykhiled1hSOkAonlVE8flqIWco50bLgH5BZ7Z6rVJGOeYMhwWKuE5V2XxJPpQt1nwBtEFGQRuybzxP19XIJHKYUIvJGL5v0DFP373Q6jblbt2c0nDRuazvaxweJUDUdJJ6Muy1TKtlXL02nnRdiywBREtHzU6bnIl6x0PrVte4RfOm5NvttsHGmCEYcDB1DQ27szsg3Xi%2B%2F2%2FeGR2n%2BxvRtYOD9WN%2BORi6nd8oWmTcFKcddE6uRt93u8XdxSlk93tXjG7HpPtl98DjQGL2zJEwuXQed4zDg6EIlIofqA8ZIb0cNy3tAzxOpVK1tFkpS6NMYgobcnXSLZm0U%2BDQ2OUKHWW7XYu4kcg6ERNn0LnCao4IVoZDiKWywnuG3jWEMbycsWc7R5FH1Iz9zb7g0HYOHwcM16FLHEOOaxFB4dDlWhw2zG13O9sB7AyY0TnvaiA72IiQO5lyUZjIDC7XSYwDh2yW7LoYYoyFMfGfM7hJ52GQUYvsHEU6eFkXc8CI2mH4JIyUfYzMtMxgtGezZ%2BL7TJh738mKr3JSUKcTKpXngAEoOlGeVYgy1ikadtz9nMHJ7DZsPd39nfPLIQ3mKK%2F%2Fen9LbNn7RC7t90R3bO3cHDKPFk1lL3Ows2nMKEeeMPK4vy8vKpnRTDcw84OBQ7YiDnGYfflhaKw6Y4pp1Vs1FdBTvm%2BQQsg%2B3auuka2rG63Gj3nHcKEBxNWCs858zsmIa7ZhL%2FhRF9WflKP%2FH4PYj%2FMugorOgm7OR5%2FyedYB2acZkSYJ5AZ2F2OptPMNYxCwdGQSPRha16g7f1JRtlvb6wy6hHsi1zi%2BzLMFIkijukxXAuB6IC1VpHyjpqQH%2FeN0YF86p6DLqQ2%2FayYIVcggg7HhuYHpNybdY%2FAsfjxskCVxnFdIo59lC5AcxsU%2BcWvKvuGFoceWsIipqUQeFNkd1ZOj5zLvOaNuVG5t7U1uWHsX0XdOCs1aTgOVgPjoAD7sIn7YL8ws80UTD6xHbO0gF2mZ5fs1ODhotbbAudBBig5xL6e%2FbE1MT%2F7f%2Bdmd5%2B5ch9N33DJg%2BnE%2BoLsSY8QY3Yv%2F89%2Fv2SNYiKEZ%2B6qCWxQWlaRKanUqKucLSqKOOo22geiSqsI4ox6sNjKkYimrVr2qXJY8PBa%2Bi8gBnAinZC5XUNBIq9HoKGaUTC%2FryIa0OifXfWJ1CBYqZjwYJsi0WX6uRoGv2Bexpl0DAIc6Ah5ZrR1RQQ55kMhTarco4IUrE0wcQC0JY7JBTaTsoVEOdgCaUGGAOSFEvmzb2PoyWBdniJEG85DdNUwOUaSjcoAytHA5ioQDseUMOg5DaNGsho6okwW0laGwmIqSxHnZQRe%2BYNRuc9ajEzH%2BTDOU779Mwbk3MGhdxUpsCoHDBkRz2xi0WdPIwnZKfGViV5NBxJFDxpSmUymm3gGJZu6JsPDyE7ctoItxP3fcSeQ7%2FlFLATE35s1CbenYOtwsYu%2BBa%2BQLzLOANmgvrbA5pGy6qcDvKJdJGwl6Jg3bBaUSFOe6AQEpwDxT8E0jDnNilRlWd8N6oyAwjkOrWeEN9znqlahvchuEeSgUy2pU64Z9l0Euou6a%2B9RhRcoVeywlindEXQiI%2BJUafIV4tK4ehPQ5hytziVHH%2Fbtmvq1x13SzeXKFIEyVexeDwrzGMFYun9dItW7PhdcIfhzeMfzGsUWsApXKaXOYAIeirb4ZUV8RGEgube1p2%2BRE%2B1xZAg0mbkSjAumGYVrM1JpNX%2FdNNtT3BIo5dse4pdyZag5CZ5%2FGVs%2BF4uQbti9tC%2F%2FXn919%2BD1yTTesu6IZU5aedfsAo4oXozUBtf1HRBfOXIqxMfDzqlYrpmRzeUf1RXSSmkdSJAS1EDmDeWl2rIsNzmKOE4xhOtwsRcQYUnSxYUA4h%2Be7WbD9jypinK7qis%2FZocxb3elhTs2RxGj4bpIQd%2Fchvsm%2FqNB0ssCuppPZOTppy2gS7WF4OEA8vXNM%2BacZYqNrYZ91v3eVZRiOzKZbHO7j1oRxdw9N4EK6e8Tm0z7gDkVuZtdhsuwqbi25jruQhX%2Fc9%2FmITYDdxWw6Z6lyfboB6V5nHxUVhlAqtayw35p8sD7svqN%2FdxsYTK5G552bIjOMafRzo%2FfvTrbNDH90y07Q16MPPfo3V%2BkadMiW0%2BPoAHd95oX6QwwtZNX%2Bx%2Fz6pO3SxppTyuathg6ZgEqubaUYzmnHUUcmjE7PhuIcAqsZtPOju8pmXGEos0aUTvAMlLswDv7JP%2FgPuUxZXRpraWJva%2BY%2B%2BF10CD5b9o2dE9Qeo5%2FoXiWSTXARB8I5BgQXQiLc7Ks4bRkQu7SlPJ1%2BoinPvedqoAFpooawGTXd%2Fhqpm2ygW3Bwc9SYE%2BmmloygSQpHBZ0c2vvFTI%2FakcsuOH3IPsegj5SBbzlyMucirTybkyMX%2BHDnvDuD7HG%2Bmx%2FbF8yllSNw7rjUKoYb43fyiwyxObisc4D5vJ1dNuGxBaCYS1KvyCSy%2Bl2UjvMTLLkoUq6QUa1BpzrlPGkrbWFEXIb7uTX7v%2F83%2Bs%2FnLGrRdV38jkFqdH3MPrGpc3LzP4%2Bz2xSBcQQXK7shrbp%2BtuFEC8ozwbxHaoMlguONhpw4mKB21FQmm7KwJpEnnGLscRRgw2sKr7vkZ9WsG9%2BzWu1EBcLIXCdL%2B3SsTJSy%2BiAyn%2BwXDH0I6ikSzBbTGlgolfJu%2FVMpYDJiO%2FhGhmUAnzyjpTj8wIBvAbIM247PjQgGdUjG4WghZaIukPdGyhcCawXuABtRKqoWUWeQCI7Ceo3ieRaZcDT0ZRkTEAZuzx4jIIwzVDGfEuxcMDnFFtRCm7Dx4ASNjTvWPKwWqR9pBActkFJNCZzjVhpTDD8%2FbRuL%2BazV2irknWfTBuIAkvLAQQbQ8EHreSELLhAULq66AJ0KWG2q2TKzw%2Bd6iCddaOiRQOq0EuHJQDLR7DTlpVPqUK%2BVSHnC%2BG02U2AhXtI83JdaP2wS0qm8ktBxqTIPAI4GcKtiPCEmUaSxpUCNkbbCTkrZsq8KRNQp5x2yITkH00HZDmVAFDHYbDP5oXGnUpeDjNFRC5%2BtAfB2MNjTNk7w1ww%2FiOiHD5wCXaE1pTMlUQ8CjBcHPvoP0eech8aGe3daUolGnSbNFVKQ9TS%2FEytTxHN3upc%2BH2jewKuL436T5zgkKoGR7NaM8cIigQKAOYKXnRldNWbzZAoeR8R16jE%2FyBTPNvpC3oEXooaONTEqHuSjax9TJ0XkCRogUnbID85Bs9ZWL3Vh8jTSTpTOEkVzOo9np4%2BgA22mwUxEyuUMnMwdJt355jDM5aRao1vbzvshXV%2BArFqvk0W2mGOCq%2BzLiP1bYP8w727Nsb15VOQh6nKOQ9vGdcAthYYQUPq4GSmbdUY4c8d1zYfjAkSZKGAO3Gf5HbqkBawNeAnIJqlvowzkfSkDfFtXx3OAs5eop6PQ214YcVGiVI5uN9eYzP06zdiI2pFZuhMbNTh%2B02qiV8BQRGjAW%2BUwAVeMuQgdXBLP1OpEyucDNUc6yuXS9sxgkbbb4Ae6A53DtB5DpSQBYch9SECy1imeIyU1kaEEEGg3j2hF1ituU6juDm57fjr06T9Ixwo7sQOrrUpWK23I%2FhgzrluPeSfiwOdzBRnIdxoqIsc6Z%2BtA5J3oBfVyzJ85dQkd2DgcMt2Xz2NcM%2BdE4lx9I7ocQOUapUfoEy8y1gnkDdnGV4OoPZ8e7WJ0axG13FojA9ms%2BXNG64dS4n4WcE%2BAneKazIKnZidRLu%2Bp6Ro4BVZasxarVMSgcPcxyIms298mR0S0wticeGI9RKLoGqRbGpgb008IhtdreibwqK9GtKhvpkbMrQvRjQRyeXBD2eN8h8oK05mQzrt6U66HgrGIIiKK%2FPGWlVV0f8bJ4vwk3R4ByO5klvmjaQQaxb7egu1BLwXVVwq0GbtWgz2SAyMOoP%2BUMh3fuk2toD%2FlqSkcQGp7fZNBrsnQiJs0Ox3VIiLVONixYiJXqazJm0WOmYZGpCJy7MRdsD20W7HS%2BciyTRiQjJcMMyW7mbzcerBmXo8yuQlGr5kSwPJuLjhH2mw%2F9jbTxppyZvpSYyRUT09KjYbbx8Z1mkupSU1sV3cgA1lkEbgxaou7ups5BXYFp4K9xH6mEgmdUOruTxR1m8%2BkcOrcerF%2B6Axk77%2FAuJkj4NSEBQy6KsO98%2F%2FfP995%2BQMbvEXoqPGy8J4pyY61bWeTwe%2BaD4Igb%2FydfUQykkitNhG8QI3mgO1SyMXhUEsT4cgykaTpUkoagXrzFCU3Vc4m6tTbRtHyTe1b5bMFFYOyGWIR5PLwUoaxxuUAf22qWYm0aP84tZstpf22PCAezBPOK9Xbq3q9rZ5My8husegzadDgO8arSI1bX09OlYVz1FcqGf5aNuMppGAaEORqWz3lvFqtitJxS3kP4EIAvlIqpcCwwo5tu7QOBaoB4KN0boLoH6gyOCjob%2BzkJPfd9q2uCUgLo8pRQ73FnAYXDtpzeu1QuSCvNuH2TqyxACWGRJZQpomKfluNdl2ZuKhcAe7bQUs10u5qHX7NigrUYcUZFTIpA3Psz%2BXNyGm2Y2WDnBmyPVmQvH2FzbZhwrXMUPBsU1vypQGQYla5dEM1WqWDMW7d23Xlrd4MzQTUizPYYgASY0%2FYl2aA50oGnwEfaRy3jYyddcfDg6ZlZP4cjenrV5wuGuNEMQWSvK%2FYnCIEI6dqvWkEzY2RqvJBWml2qTrWvtGuUzMWqL8s1RuDSqVdxC%2FwMurL5zV%2F6FuLtqX9opqtmjIBeEAtxc2q0S1msz3W5ZTNFFSrNwwBfHikonQuoyRqGkcf485BSN3xzMDjAPTbkcqZtGpDC9VbKKnlZWzcjaEFGtc%2FRpWRukWEkjaQDZ5B4aTSyD81pYa0ZZG0Wr1iqVovSIx2K58r2t%2B5AO5TLEwQ1F33GNyP2RyYia7utFptqVgaI9Id1lQQNc2gTAFKDAtHrWM8mOMKpGqqtnnT%2BaKaHQ4OUkkYYh2pRso70v%2FD3Xe4S1GfUZ%2FdnZ2Z7bu3F3pHEKmCWLD3YDRqbChRY1SsERuxV9SYHlMssSEoCAhYEFRAEJDe5NLr7W37zM7s7H7PeVfzfN%2BfkM%2FnMfdi4LK78yvve95TAjrpEiWSNZVrQuaW%2B4Voug2X5YWfg2MXy%2F8iXKpLIndEJW6XkGNeMkTVOCkK%2BzRJGgl4VRTsIhSxwWHh7RXrogAzQs00GK9ksNmg1YubsXkOIrEQUsk4mDMpIhSlNPLxush5VWDmHMmSZgVEJSWLSyruPcy7tAyEVF4GJD0HEGFh6C6hmnzl%2FP1E5aMBn7w%2BCUknalDMQwXFOSYc3jQuF6KhADLZBJycKTmJbncOHiginGBhrct6L00QNL2kKpaLkj6GBRZgGqxsHuUBDVYuLq8lnU7DH4zCyFoiiKBbvj%2FoRyqRQJjRTqw42aCwmXIXZeIRZApGgT56KrJGWoRAJD6rvOAzSdi5OKKhCDJZBbFQUBwPs7k09EIQvgAk35PPRnFYSPpg5MhHZUPuAp9DJpsGvRZZqRD1hFlENKALkm9ZGShiKs6Lz4GiKcLlpN1QVdAvKsACvQ2pLqaIjeiW2wszbSPEyt7DO5sOAnQ9UOBS6G9AZMCCWtRLP0uMjEl9Z6OpIhpSRS3u5EregfwJFChJe8%2BJhmWUEgtyRZQFwkimeUb4ZY8jV0S5T0PeoFeXCz6NlQY91DiSpy8eTecVeJhWkYhD8zPRh2MqFmmO7AXbpiVOEYqPmdGMgyoR6I2kiVA4KgXbT3YseY7PKT7LFxEKRxBPJWRUF9Tcko3LQkpxKfJ6uQmZjJDP5ySflcwBIkU0MiY1gAWdkWPGN88bikk8sHNcJ0VUVoTRnYgjwAqf9xrpHeRIEnnzFJHNpFEZDtOwU4gKecuEIrZgupwLVBcrLl08KAWNtJifXoCf64zWHG4FmWQ7ymIx4Y5xbehBn2TBhnUKAfKwbMaveeX9KCrV4KbYJHldURQsHvoKwj4FqWwWquLAL42kjUQ6jUA4hGyyXaLYaJbO50XmbKlJKCJvGCgLBdDdnUBFuFyEcGH6xRWYDmTB5wlKfBrXHVF50h%2FyqQ6oqsZBqajYSdehtY%2BmMNPZkc%2BQQpyiOyg1RsHOgFFjjLvUXCzwwqW0CN1fGrdbDsKaJnftT6VayQOb7fCPaJdU7aVJ3E%2B%2F53%2F5q%2BfGG298ql9VX%2BxuOAQlVI2ip4B%2BPXXwsCN2RKUMK3uyzBxXXrLTGDHkpeRXFJwuKGwHnAJ85NcVbBh2FhqhwyQfhgYYXdBdpRBimv0qQRU2D1WbqkNeWCUJsuawW2Onmxf0L5HohE7Jdd4R5Y7imMiZBhw9Cs3ngd3diahPkxEax66Eib1s392K5IZqhHjATufHNpJQq0ZOX8mKIBTwy6WctgsIhMMwcllQBcV%2FeeGy1WA3aFMhRddmRtooHgTD%2FHNpKe6YZUpZNVWMjIpiZh%2BtLzhGU9we%2BHUVXl647PCp%2FmLrkqW7NmDQEJaXVjohGXe8VDhS4zibprOKjL%2BJxNGlmz5vJHaaghA6Rar%2FeKGqMC0WhhxRWDAzKWiMmfLpSDM3lPJ0rYBi3hLBCF9XoZCBonklIisrB6UtcDQ3I19n0aKi2QMtFEXWtiRrUfV6kbWKcDMX0TIQCAZKn4uLfAUPik4GWsCBCQMm3eM1L3h5uMnH4KVt8QDxiBRbLnBVlwstl8lK95kzbQRDYfCZGRkDAY5c%2BbxcXim4qKoKRcolTcExOXZ0wTYzCPg0BKhotPNiZqzRsy3RKR2iYzuIhMMws0lUhPywEp0IaKXinORaIhB5MwOfy0FA5fopyKFRmpY4CAV8IMk%2BGAjCIjTF6CJNgZlNSYyR1%2BOCqijwco%2FkcvAxQihvyv%2FHi4eHLn2cWDQRNfDTkNWxxdhaV10oOpZc8gXLEtsSurGTPKwyeFtXhdLAOBrm1PLQLI8Gke7ugEYejc1xOuTv50XHupjFB30geQi6CBlLxi0LRF4yLMIgSQz0ZLJyOUEnuP9cXFNEyEjKVlzSFLl4ARE544jQIeqaQ9irQmf2bN6W91EyZSU%2FhuIWW0jdtpWTZyyRSlZWQslTGVMu3kLOkGgeW5S9HskZpq%2BezjWVTQs3izycAjMfNR2mkRaUklwvH8fzRAvFzIsXDD0LiW66oOrcFxlxmeQzIFog7D%2FbgOYpwi%2FjFUNad16y5E%2FqrAuIBvBCti0xyKU9TdFmqkNe9r%2BqB4RQ7uRTCHg9opYUc1%2F6meVSUJ2svIesQwTZg5jfD8fKwGGDpBSh0qvNXRqxsjh1TBYgGnIU4XjcMOOdCHoVKSRTyaTwRsMRHW4nIQWC7o0hnbAlgzro80rBXLDT8Ic0GNmM%2BIDlcyz0XVA1j3AyTZNuBdyPHDsw3o24O0foedh5hk%2FxvTNfuyCXKwsFIuO6V0G8o03WN58xi608hXFsOgUtdiFv0k7GQdGypQiNBv0wskmxkCDa4ZMRty37vciCnkp7KWJJfSF6kgf%2FO58HERmqLymo8PlU2NksyhgHmaGZqg95TkiI0ruK8JomghQU0TWfyUFM%2BvAUEWYgvFOAlSsphiMB4nOMnqLrghdeGh4bzFRVS0bCtlGyqTDTcFkWKsIRWPQzdOdlHJlzu0E7LsZ4sQEyrDyKShGmKwOvXoqY0jjSL%2BbEL5JabprOuz00HyZvrijeqhQOWrYJk5ZIuhemk0OOSnnVAzffOBwkUnHZsBQssCS2GNWo%2B0WMSKNcCt4coyCT%2BlwmCb%2FuQUAjoliEx%2FELT45IIs9YphEEaNvDly1IVhpFK42gLyKTCU6u5AdZppxRRHOzRhaBgFfO25zJBAQbhhkXeyTCeQqRQU1FVzoNPaTL58dxm00%2BcjCKDPew3w2PYiPk9YplT85My7lLjmPIH0C2uwOVkbDQR%2BxciRPL6RK7T5NFILOCLRuWy0HOMRAQlDsnvpyKT0PSycGju1GQeoKJTi5YxQIMonY8rz1stEwJDiBUybvPp2lwOFUpsKnVkE0ll2NyiwAAIABJREFUJcmK4%2FmfRvQlhTkbcRbRJbrKT9%2F%2Fr3493tT8o2KXFY8QNRmzxX9ZuJFMyoavNN9mMQdvUaK59JAmEHtnZydGjhiFiooqBPx%2B1NZVo6yyEtGKWlSX90VID6NXj1549oVn4eeDB5WMaUyYMBHNR5vh9%2BowzSRGjhqCpqbj8FLR5%2FWB%2BaEmPVGK5NPwwnQkDF54c46F%2B%2B%2B5E6vWfot4xoQvEJJunh0RDx4rZ8iFzPFpKBqRkGDiviWlmyNmtiSR%2FzRfz%2FBhqyqCgSiSKUNy57zsrBQXAsEQmHvKUSTLWctOIxAoZXsm4ikE%2FQEYJl3pLTlMiURl7Jy4ZptGSQgR9BElbIPHbcG0UrAdkjR1UQ2hmIHjJhSuIxApk86WOZ%2B8vInS6P6AoG5UHfHKzNKim6RWNz2FyFMsjSkoBNFVTR4msWU30SjGAFEN6GHkjYk841kIk%2FEyVtxyaa9f%2F53EpQQDARm3U8qdZ2daVORyf%2BfNf8OnBFETq0V9XQ%2BUlZejqqwG5eEa9OjdC%2BGAHzV1vSRPNU%2B0zO3GocZ29Ox7Al588SVcecUvUFnRCxXVdQgGy1FZUYEB%2FQfjyP5j8LmJkhlIU7kZDAvZf%2Be2zTh5wuloao%2FLBhRRRdYSToSqFqB5gSStKTw%2BaD42HJDnb5kWsikmCrDgzgvCoGtehPyqkHW7EnEE%2FSFkuxMIMTGkaCPrcpBFAZZhIubX4Xc7SMVbxcNM1TW5mFwOuWAqwIzjXJZWlYIa8e%2FVfeRC2igSybJots2RXYlcK%2BMrydckv6RUEHHNEdW0frw8eYizMeFlxjVLzorJcOeciSAvt5yFZCoDFhTkptLmhaOnttZGhCMhyQclb5VFmJ3LCM%2BPIzI2HuS4CHqj0KaiKAUmnbOEcUqUW1fBvMf2tk4MGTIUK79ZJerfMSeNQDyTksuHo11eusIVY9cfDsmaogI4l0nL6JejSnLaiGww%2BolFKPcZR8fkqVBNxuzWok00LIx4JodwOIiCZUgwO0eFtBgpsWY4AibPhSNQTYp0y8yKypfjKX7m2WwaYb8feSMnP5ufIQsPft6MA6OJrqa6cfDQPvTp2x8bNm6CT1NFtsBLm0ULs4ZVry4WS2wGOK4jv4b2ODwTinkW1A6CUT%2B8ugLDtmXfaTL6zoD5l%2BS6eDVd%2FAK9LhNXTr4QCxZ%2BArfXJ%2B%2BbaBZtPXhvH923B0MH8rWslwJA8dLhn%2FuPXo0OymJR4WDRuT4Wi8HnD5YI264C9jXsRN8%2BA7Bl6w4JHSeFhGIPL89mx5aimf9NpzBE7CfYiFqypoi6EFEkmswCSPd5SypGlyLiIBbK2WxKFN5E%2BJiPzAOlsrJc0DJ%2B3nQMYHYy7R8I0VpMFfCVUni4N32qhq7uTgT9PyqxueYLOVAg8ZMlD58RWYU0HiaX1ucLCKLIBAr%2BXq6BfIGq75SgVywUqWolmkVaAM8xPn%2F2wEKPIafS5pqhsTGLJkOaIhYP%2BZwl6nG%2BNq9OdDMv9lqhkBdOrhN5OwGvHkR7PAufFkWAKH6yCwrPIo8la8LFCYLNRJ0SBSIcpGO%2FIukJbODZVLHZJcdY8xahqD646Z%2BpegSpsyzyuVj8KNKIhILMTmWzpELTAv9tzNiZxKIBARvyNseaDiLBiBgg637%2Fj8%2FNDa9Hh6eoIBSJwuBeEV%2FONMaPnICOprhwzLlvuLdJoidiz%2FQcio4aD%2B%2FHhRdejLRpCveYfDaCmyzyyYCLVZfLOWBkU9C8BWlMVD0CK0cjYQ1Ev3K5ToRCVJab4vWqFlWZNGWNIvzhqDwDJ89sVxOZdBxhnwcBesHlizBsB9FoDImubmk4Qj6eyS6YRhJGnrwGHR3tXfD7iGLnpaHg1IpGwDEi4EYKHk2XRsnHn2lmhFtIRws2pGzgZcrl9iDHZ6Io8Pt9ss6IApJ%2Fls2WzhD5oH%2F6n%2F%2FyG0tedqXBOtG6HxG7%2F9mvpTcoEJal5GArOeS8%2FFqyuWABRXWUQJNMXdAAM2%2FCQgGZgo1IdTW%2B3bQFncksurq7cbylGa3xbrTGO9Gd6kJXPIOZr%2F5RiodUrhsuHZi7ZDEuu%2BJa1JT1klyamS8%2Fj4bDhzHshCGIBiMIxKrRY%2BhJiGcojSdvgJs9AdpHmB6fwNHJeJf8TDWog2HhWW5ADtQLtuRfUgnIC5aHXpaFDAnNTk5GUlwY7DA5ogr7vfB7iyiYWeFQMD6FSJKdz8qYjBckVZ6qoglvxrZIIGEXxcOcyE1pbMtONydES5fwHgIRHzyeEDQlglwmg0jQi0ceuRuVVXW48cbfIJt2kLfbsGnz1zj1jHOQtVzgH%2FepPoHWA5qOts40xeoIqzryWQOKGhR0TncrKAsEYFsuuD26HLZ5k6HmDsx0VnJ1vRwZOnm59DjS07wu%2BBRmDVpixGqShKooOPHEE7FndwPWrf5OolXoNVUo6jCyjCIxEAqoeOixl9DUYaKr8zDWf%2FclbrjxLjS1J9B8rBltnW342aVXyGc3Z9ZbCJeV46SRF%2BP7dU148rfPokIvx%2B4DLTjSkkBn51F0tBxFXV0P%2BBQgaB3Fc49MRXlVJfRwFLGaWlx42QXY0bAaA4ZUI1IZQCDqR02fXjjl7NMx7d4bUVFbhTPOvwhtCRMGLXFcdsls1s2ROMcUinAhB544EtXV1fAHwrj6pilQQ1HhoVG8wwDm0ePG4OvNm%2BGEQvDw4OKHn8%2Fg5ltuRDBSgVCkAmWhCL5YtASZgoqMmwo3Xvy0zqBSNwOLYwMa2GrkkFCFS0MIyvTdMAsF5PIO7EJRxjxUxykcj3MnicUOZ1aKoI8k9vKSMUj68%2FoRi4QF8fD6NLh4OKtBGD%2BSkQM%2BFWVlZUhmTGRp3MwxO5XkRI7IBVJ1ePge80Wkc0RJbeFJulUvbpg6BYFIJSpra%2BALhXHWuRcgbVqwigqC0Qrxa2KjkSRBzc9MWXr2ka9CLijQkoijoKkwc7Y4zisMafd45PeTKzp%2B%2FDh8s2KFIN9Zx4OCoskoy7HS2LJ5A0affhZMbwhxIyejxmhZTIpng4plVZeiySJnSwsK78kmukh%2BoUM3f%2FKCmBThl66e46RItELGtCeNHI01a9cjTzKjTxerJBkxqhpMKEimMyKIYnSV6g%2Bg4NE4fZSin81Owsgix%2BB1uJEyiGCTL2vjsy8WI1xWgaq63qjrOwDHWpsxauwYbN%2FeALvgRcq0QATBzHZD97mRFpKYC5bLywkhih6vvHaVr5nNKSMHVYo%2BbLh5xhRdSJom6BpBBPzEk07E%2Bg3r0JU2xRNMZyQeEy%2FyeXj8fmQ4qtc1ueipxm7tSsN2kSflE8NUt%2B4rudp5FdAUnj%2B3qOhS%2BGetHJLZrKxBPu8sObiRELwkiMtl7xHEpSuZkWhFL5vQbA7w%2BJDK2kJXIceRv9%2BwTaSI0qm%2B%2F%2F53aWJFJEBRD9d6iVpR8NAP0w3DtsA1GE9nkDJt2PAgbRqibFdIsvRosg%2BJEuxs2IehI0Ziw5ZtyNLGhwRYoo0eNw4dO4L6%2Bh6oqKlFRWU1Ppw3F6rfh4LqQleqGyPHjkGsshbRil5YsbYBbn%2B5GMlb2UZs3roMVXU1mDV%2FMQreIExLQyZLDixVnwYO7dmGIb174ZWZf4Zj6%2FCpIXp1IdGWgF5QYKVNRPUQuo%2B0YFBtT9REa9GjvALvvTlLVKYeUn2KbgQ8MXgMH3Q2gvyc7BS2rl%2BDslA1PpmzFC5LAXI2ImoRDds2YEivQagoq0VlRS3WbtgIg%2F5vDjlyJdEax69FFxW5DjyMK%2BQZ7uTh04PwuCnoKMh5w0adZ0ycxEOVv9%2FC%2Bu834tRJZ0INhGHkCzIaZwFksenzKuhI52St%2BHSinEl8v2oFykP9MGfuKiSSefh9CgJqGo7ZiDHDh6G2rB7VFfXYsW0%2FvH4%2FOro5ffEI7YYekS6vG2tWLUMoGMPchZ%2FChA%2BJjINQNCoFIUGjnTs3YtCwwXjxL6%2FB8fsRjVXATBnwudRSSlAmjwmjxqE8UI7hvQeg8VgHcmYBimnj2K4fMKDvCagsq0dYC2Hh7HkIakF4mLVMkp%2BiIGXkcN%2F0h%2FGXv7%2BG7mQKUEt53zyX%2Be9PABWVz5w82u6S4TfX6U%2B%2F53%2F160%2F1amkm%2BdOvfqxO6f%2FiKahCnhVPG8dCwWK4L2XLXuFUsBt8fubTeOf91yXaixUuD2Aj56BY8EJhBUjY2s4gEFTQ3nkMf%2F7rXzB16m244bpb8Oc%2F%2FBWfLJqHX992FdriXWhJZvDKm%2B9g0OjxKK%2BohhQqOQMvPfskFn6xDDl36UCj8TEp4eyGmHXHg8uj%2BURpm0obiJZVCJs5ky2Nsdh1s3rnWIhIB3PTOA7JGxm4cmncdO0v8dHseYiEvYLE8H2FQhEYWbpTc%2F5eQgeCHBPblnB53EVNxBKWaQhyN2XK9fhw7kciREhkmKNItW0eZiYrZE5Nd%2BGvf30e774%2FSxAIxfMjb0QPIpEmAZuKXEegZXYiFVW1yLNFtbMIqCQIUzmmyq%2B72hoFZSA5lIIVv5cdqIUAVcleH1JWHlogKKpAFrpUUSp5E%2FM%2F%2BkC6wJqqOgSjdaipG4Bjh49i8sWXCDoQDIZQW1uPV155RUZ3HIUl%2BeLYedsm%2FLomhwEJ00RRWDSTiMyx1Y3X%2FQJdzYdR17s%2FLOjiH8S5l0V4nkbUXk3c5vMFErpVuNUc3FYn3nj7dRyPx5FMd%2BN482E0drWgKd4iKkdGPB0%2B1omvV67GX%2F72EubN%2Fyd1adKFMksyx9aW%2FmXwgMjmV199hT71PfDUc8%2Bjta0NnR2tuPeu%2B%2FDM08%2FJeiVawYL9rrvuwlcrV0mhkrMYFVeAm2sEBXy9dh3aU1k0bFyH6Xfdjg1bd6Ggl7YI47%2ByaaIPLjECprJNxk0coDhFMQHmawn4Q%2FAFgrKjiMgQ4eVnxb%2Ffy%2FG4acr4lmuSKA07bxc5coYlfFByHTl%2BLrhUdCQMqP4wfF4P0vFOcL3RqsPti6Cg6DJWI4eHPzfHxoYRY14NgWBQOGMcjWdzpnSq%2F3rjb2jraBc%2FuzVr16Gmth4Ne%2Fdh%2BLAREPNey4ES8MklQeUebRxKBr2aIHS8cFkYkT%2FE192dSIn3E5fpHb%2B5DStXrpT9qPhCIhohQkwuajrRDtPxwFZKhS8NkfleHI6M3Ypgh1xPLGBsuyhiKhq60gSXQpeAPyJnCRu8gkNUx4GRNcW%2B5tFHH8WyZcug%2Bnzo6OyWfd6%2Ff3%2FsOXAYY8edjIqKanAEzL2VTqbgYmKEm6ajJf8%2BFtSqPwinUESEvNx0Gju3b8OTT%2F0OR1oOY9%2FxZjS2tCNSFsODDz6IL5etkAuGBTnHer4Ac0CZ3uGBIZGhtNPRYNIwXVFRW9cTx481Yty4MTKi1hTympLSrFZUVSNt2kLTeGD6%2Ffj8y8%2Fh1clRVpFKZNCvd3%2Fs3bsXJ540BHm3LZ%2B5YxNVzqO8qhfyRUXC1Ck2IVJHhSEv7Lb2dvHs4%2FlATSYRZ%2F5D1N%2BtlPZhxiAHs1BSTecLEqfGM9cwsjL25fshLKp6%2FXB7eO6Vwun5nCgQ8iq6TFKIDrGhIO2DMBxHqmx0jFxezq9So1WyuAqGQ8Ils%2FJFEaLRb5EFCZ%2B5TSeEnI2rp0zB0lUrMXbceJSFYzJ%2BZfpH0sjgiReex6Yd29DZ1ont32%2FCK8%2B%2BgENHDiJhZHDN9Tdi6q9uRSadwbz583HVdTfhSGObcKpvuWkKHrjvDowZO1AufMVHkQng8%2FllXRAtnPnsk%2BhRV4u0Qasr3hSKILdMbyFCTvVkV2c3Lrv4Z3j1xRfR3bobWzavxTPPvYS163YJD5w8MDZBpEHkDAu66sPkS3%2BGh6c%2FjLPPPFvETxx0EU3sau%2FAVb%2B4En%2F7y9%2BR6OjG0s8X457770E2x7FtiQ9oWowH5HSo9BzZyNiOCX%2FAC5keCLpNER5VCKWpjj9AQIIG0AE88fRMvPDCC6iIBVFdXoZoWRViFXUyMakpi%2BKUieOl8IsnMrjxhimYdsedOGXS2dJ88NlwRMqz6vrrr8d111%2BD7ngrFs59HxdccDoaW7vgUQPQlDIUbQ3prI2pU6fid9PvwaknDxY7JQp2aVuS5lSFypyihVdmPoPq6nLErQK6shSXFYWCQcED1%2B5tt9%2BO5UuXI950GFOu%2ByXue%2BBhBKIhcOTMe%2FqFF19GU3s3tmzYjGeffAqrv%2F1OijRO5ErBB168%2BNJMbNq4BXv27%2FtR2MLnyTOcBR1VLyW%2FO%2BFxSlXAX5cGraXPunTeiypXPvv%2FjV%2FLQilpUmjwq8GbJ4GYRFtVjHC9eS%2B8pJ4VCghQGZX3wGX7AUuHK0%2BifRY5sxXBEAfaOYH7g6qOiBaG26EK04JHV6CRcJdP4dO5szHjwYdx%2BOAxDBs%2BEg0Ne%2FDl5wvxy8suxqTx43DJRZdi7qIv8NHij0TR5XO5oXFx5jlTLyLDPFR69GTTmHzmJPSPRFBVVo6yynqs37AdNj3EFD%2FiGRtZhrTSzNahmkqRDUZSsp98JCIXtoUgn5OREjK86vGDBb1kawbI3aHSNIK8xegRTcZBItcnJ8bDQlcB%2FwxNlBmmawvrn503C46SHNHtcVBRUSkkao6RfcEAXEoBKSMuklcSPw2qv3j3yqbMw0%2FFpTuPRJqFImPTEnAXM8JRLLo1uItZlIV%2FtBbhKNYhKd9AUNflwPCoPhCBS2QIs1MJRKPI0pjRTKfw93feQ5ORRktnCzrizUh0p9Da2IR4W5sUJ4cON%2BCxxx%2BW8QtVq%2F%2F828uoq4ihd88hOGn4JHz0wX9QW16HaCiImupafPbFp%2BLBdfN1V6FnfR8cObQFJw6rw%2FN%2FnomUkcbo4QNR4fMiHKpGdU1fHD56BFkjA6QzooDKO1k88%2BxTCAdjqK%2Fug%2FryGtRFyxAMlCEWqcNZZ1wGx6ZVuYVoOADD8AhPJGfkQSQzl3PgLeow0xncP%2B1uvD5rNs6%2F%2BBKRPZJTeMrIcXju0SdE0cwxjcvrwskTxmHHxm3Ixcnr0mWsp%2BSL8LlVdKcyYlzbtz6Gm6%2BZjKXLl4JgBTlwfoXjO%2BYeRmBkaLtCZ3sbXrBw8UheMAU8mWQGuSx5WDQEZvFX4sDlycfJkx9H1FQVix2uH37PIpHrigIC3eVAU8g%2FLMAfCoNFMF20whzfUjhE1MN04HKrMtZjvUklLrldXOu83MmP482iMaCeBTi5RtTsETU0S6bFwWAY4YAqZHOKAah85KFKIrJKRIlIkzjCZ6WY4M%2FlKJgyQRZIsUhERlwcK59%2F9iTs2LIF8URSkBsKW8gfhJVGVTgk6z1D0MfjFa4aBQzkuFAIwD3KsXNQ98HOOFA9OjTheRVR4LiZaD3jwBIcq5MnxvzNAPImcPbpk7Bh%2FVohXpdVVJZybkWxTQ6cDSNJLppS4sepKlSqF5naYZWCxWOxcqSSGXkddJr3eb348%2B9%2Fjz%2F94VXh8PoCmnz%2Bfk3F%2BLFjsGnD5tKYVzzJKJNNwuvw9ZFnVlLVuRUVihagRAD5glsc7ItWDgGKC3JpxHQNRTuHRJxinVLxf%2B45Z2DttythET7M8zMKcnAmI05aN%2FAs4djTr4fESigdt0F7wgK5rkUWDxoU5mCyMA2XvNhYdHEsxYaOzRivNZ6fXH%2F83uEPIIfNrcCvB4S6IqpEMpH57FlLFFzyWTEflz%2BHo2Gu11QiDUY%2BCgfRzCHH%2BC%2FWFkSj6f%2BYpfFzaZ1zwsM1yLXDv58NAfmoOSMjnpF%2Bj4ZwUcG8D%2Bbgoit%2FjmB9lZxbTspAKAfUBqPwxcL403%2F%2BhaoedTIKHlxRg9OGj8LRxqPoTKexp%2BEobppyC1LJDkyaNAYnjR6KlSu%2FEaTtvf%2FMxpqvV6MiGkMw4kfKKCk3ycejWOmdN97FkCEDMHHSKShQrOYFEnkL2byFjG1ADehIctwdCkkTeMKJJ1DbhcqaKPyRMthuXczrO1JpWC4DLp8Dt04fTAWfLF6OZd%2BsFi5gQc3BG1SQyeexddcBhMpqcNo5ZyDvNjFy5CD0612DA%2FsPSXxlNhtHNKygYCfhUwk0qSDFKeDXYGa6fuTH0VnCETNa0ybvvAAl3w2lkMVjT72CEaPPkCIsnWxFe0sTzp50Fg4e70B30kBbaxO2rl0Birb0QBnefudjrNu4BYEwG8Ikcul2eF0cqbuxaesx3HLnnTDsDkw6uz8uvnAEPv9sYal%2BcHlg2myIFMx6712s%2FvZrVAZ9ksrAxr9Q4Lg6AIIws978N4b0741Jp58Grz8sanoW8YqM3W2Z%2FL09Zw6qetYLD%2FLnV1yGxkQKe493QCX9wcpg0MhRyBSLqO%2FbG%2BXVFcgUHEHaCBzxrI0ystTO465p0%2FCHV34vr9G2yHQs%2FcM1yu%2B5vuVffv%2Fjr1kOlNb%2F%2F%2BbXH9%2BilK4yWqUhq8dhQUcD15KXD2fzQhp0eXFg%2F1H07jUAn8z%2FRC4Odut0QJs69beIhatRVVmNQCgk%2FJOqigpUlYfx4LRbpKumRPvVP7%2BGm399Mx5%2BdDruve9u%2FPW1v6G%2BrheWLPkM%2B%2Ffuw5aN6%2FHaH18Cz66ih52gyiK6pCQlSZcjL5cisTHLv1mNo91JtHV3o72jFePGjofHo%2BLwoYMyvt21bQs8RY%2BQ8NnxarpfxkjsUqXzdFMR1YnTxo%2FB4s%2B%2Bwa9%2FfSvOOW8y6HCR6mjHsBOHIxIJo6aqAi8%2B96xs7qJXw8dzlqAsWo1oRSWqa2ux79BhjDtlIpYu%2Bw633XobJp1%2BJhJdOagkDudN2DmOBr2w3F5Qil6wDVHGgconkoTprSaWUm4cOXgQ1VWViJXXoFdFHRbPXwImJlx%2B9RV4%2FMlnJZCdP%2FftN1%2FD%2BDPOQLdp4MCBAxjUry%2BiUR2V5VG8%2BfaHwkkremmESv6hBpsjRcsSThlRpnQqL2OdRCaP6264VtA3XfVgxfJluP2O22RUTV4Bvc4eeGIGjnS2ounYAWzbugJX3XQtWowm6ZKamtpx2eTLZQTw7rzZ%2BGjO30XHP%2BnSSzH9oUfwwez3ke48hlRXEzo7k4hnbRw6fhx1PXoDakjSJPgZPPXE79DV2YV1a9eDh%2BKRtm5cfOGlGDFiFL788gshN%2FM6ymWomPWzGZWLi8iaxoKgCGzfTp5RGGdNOl0uYuEOEWWgR1ShgJbGI%2BjXpxe%2B37oLw4aPgp1KYfmSRbIWJBGFIkh6oPlDMj6lHwnXt4vkaKeAa66%2BFm%2B%2F%2BS5OGjUSp0w8WdR1TjaLYaNGQY%2FFEIto6FVXhe54WnIjA15NEOZ%2B%2FYYiGqtEfXkQ%2F%2FzzSzj1nPNk7OTKp3HlpRfg7fcXYMDQk3Hm6WeAFcqB%2FXtRU1WDqrIIasvL8N77Hwun0ejuxsRxYzF3wWL07DcItdEw5s5%2BH%2Bs2bEUwVoOqWBR%2FnPmCoH2BSOzHjpQFBi0TLNDcj3nGboW72RFhyP6G3ejV6wRkM3nOIKU4JDVBoa%2Bh42DQoEEIl0dQXVuPl198FR4ezgow76P3EC2LIhSMomevfsLF61FbCcWdx%2FKv1og1AWn4kRA5QlT7pkvWDeJY78XuXT%2BgT00lassqUBmIYOGCRcJtnXz5z%2FHnf7wuyI5jZjHr7Tdw1rnnyjj26KHDGDlkEMKhCMorKvHe7IVQ9DJUVFQgEPBh8ZLlgpz5%2FAoaGrZi9IgRyGez8JhpXH%2FVL%2FDG%2B3MxcPhInHrKaBjJNsClYezJZ0qxXV9VjueffQGaV8PBA3sk5%2FLfb7%2BN2uoe6BEM4%2BVnn5birK7fYCH5L%2FjoYymMRbVMYqPY4%2BQxbPhYVIYjqIhxH85BvuBFa1MrTh51EhLxdiQTXRg%2F4Qz86U9%2FQ015GXpUl2Pm8zORThmoqS4X5fenS5aV7HvcHhzatxeDBgyWz5d%2BZ4cPHkBNZSUqq8rRo6oei%2BYvAkWRk395BR57ciY8Lh9oZ%2F7e669h4ukTkTIy%2Fz0fYsEYyqNl%2BOSTpbAcFY%2FPeBqvvjQTHo%2BDjNGF4SNH4u13ZokYZNvm7zHxzLNlnfKi1CiOKjgoGgaGnjACwXAYPXvwXHwSZt6Ddz6YhyEDB%2BDY0YPim%2Ffgb6fjrrtuheLKo601jpEjxiMcrZbkj5dffFnWoaJ4JTIyFApILq%2B74GDFVysw9de%2FgVuj34YCcoMpssgk46LUdVHpnE2IOCBn5%2BW99e%2FTE4cO7MHIseMQiFYKkkwjqBOG9kRT4wGxxYCHBa5XgImibUmB5CmmoSk29h9pxrzFX%2BHXv7lNRGccE5OqHKQ%2FEsn2IR3xbBoeUl8KRUx%2F%2BCHcedc0dHZ044Ybb8bkX1yGsSf3L6HvXpL0ac1URCZnSdA8s35ZaHlU8rt0dCU6BPMhD5roM0fUtI%2Fi3UaRwN6GPShYnDKXElDI1c0aKUJ0CPgC0sBrfi%2BS2TT6njAAleVVKA%2BGUFNdjbMmnSFq%2F6ajh7Bp02a8%2Fu83hddMzhwR91AgLFxd0kFYYFP2YpqkIpFrrAmfkWgzTdb1gAaXR8XWzXtw6innIhwLQ48QCUyjV49yNDU14ejxFKqqh2PnrgZ4SRf6UewnaRcs2vOc5DDaMIPtO%2Fdg4ZIvMP2%2Be%2BAq5mSawILv%2BLEj6NunB9as%2F15oABQligm9B5i7YD7OOec8VFZWyMTrkRm%2Fw69vmwp6ot5w3VU46%2BxJmHTmWaXccarwA0F0dncJT3H8qFE4sHsPmltaQAoBZcws5kr%2F0BWghLr99F%2F4lcXc%2F%2FLX0qsvlUzIe8ht4OiGZlmlIk5V88g5aVx9w7XQwxW4%2BTfTsHP3Fky%2B4iKBLi1HgV3Q8MZbf0e8O4GO1iQSqTS64p1o7TwEw2jFH159GgqVfL46rN60HzwoX3r1aXg1C8OGDYYv2htDR52Gju4ufP%2FtUlwwuh%2F%2B9szjwpnoJkGfvBHHRt6xSp5ALDoVH3IuDbkCR1gcDZko2JYouYb0rcbe7Wvwt5lPoTYWQV3dALR308fLIxwEEl7dWkDy%2B8LBENZv24Bzzx2JP7%2F5FpYtXwSvYeCSSafjrVlv4ViiBd2dh%2FHDju%2Fx4ZKF2HngGH7%2F7L9wZEsr2o634FjOwXueAAAgAElEQVTbEVT37Y11237A%2BRdeiH%2F%2F63VsXP0FyjQLWiEnqIpNxENVkaaNh0dHkARXGvu4svB67VJXRZjULuKtN97EzkO7kDA7sGTuEjx0%2B4No7Erhzkd%2Bhy%2B%2F%2FBLprrisOhY5N027HXm%2FH%2B%2B%2BNxu7d2xHurMZCz%2Beh8d%2B9xL2HiTHhaNIBy6iPCQvUrPG7NJcGqeMHYO1GxsArRwFTxF79m2Hy5XH4gXzcdklv4CXr9xMQvc46N%2Bnr6RcEHllJ0VeYk68tPxwExnL5eEhf8dTwM49u9C7rA7njjgF%2F%2F776yivLkfvymrUlNWA6Ek0VIPe1f3w6DOvAPQy8pWjR30f8SFqbDyC3z5wPyoCUfSu7Yl7pt%2BH5as%2BQ7SchVYWLtsLj6PDJqeyCAQDGihuJ6JE0yzbRX5PXixQqGokksBRCeO8qJZzU4GrALbLj3ROwdMPP4gvFnwonNCiXMqOFHQseFk07joYx3vzluLS8yci5EqLKem903%2BHz1d8ge%2FWL4fXSuCUMWPw86m3ozGbQzJ5DPM%2B%2BAdGjpmI5vYsrHQGE0aPxtMv%2FwWtXUnEG7djy7rP0cXAeL8fbrsdIa%2BFux58EZ%2Bt2YvV334D3W3g9f%2B8hZ37diPe3YhPP52P6Q8%2BhubGBPz0ZUpm8NI%2F3sOmPYewdPEc3HvrVLz4t7fQ1GWhYf0GzPvPv9CVTKKbI16vJn6NZo4Xl0cSNm69%2BXaEY%2BUor6zAKzOfEvsQOv0XyPcpuqFTHUeHq2xcCoJ%2Fvv02Wrs70dLRic1rG7BozmK0NzbgqSfuxf7DR9EcN3DwUAuqKmqhuE1Mv%2B8uLFywtOSIXyyCNhuU1ZJr59gZUZXSemTOrA%2Bwd9d2ZDubsGTRZ7j37vvRlU7iV3ffgQVfLUc8S%2FZNEV%2FMX4Bf%2F%2FY%2B2H4d77%2F5Jg7v3omujv1Y%2BNknmPbw8zjQagiPbdq0aZg3dxk8Hh22Q%2BW5CT9th%2BIJqMUsgsjj9hkvYP6332Pdt%2FMQUZIYe8oF%2BOtbi9DW2Y3m1kZs374Tc%2BfORWtrE775bivGnHEu2rsT%2BGHdV%2Fj49b%2Fj220HYaiVeOiBO7Fs0SxBPj2KhgIbNq%2BK%2B2c8ia9WrUCi%2BziWfvIhHrr3IXR0WShkM1CcjNg8eYIBdJkKvv1%2BBxLxZmxZvxLv%2F%2Bdd7NraAIqn7pp2J%2BYu%2BASKTsTVEKWyt%2BiDu%2BhH0fbgzTffxL59DUjFU%2Fh03nzcf9c9OB5vw%2B2PPopFy75HvAtQCzZWLZ2Pm6fdDCfgwbvv%2FwcNO7Yi234cXy78HL%2B54yE0tVoYNngs9u%2FaC9vuwvYf1iNW3wP7jx4XxHnR%2FI9w7s9%2BjkIwhLzHgquQQTEZx3kTz8Ab78xGWyqBru4D2Lp1Nd758Atc96u7ccOUqzHr3X9hzbebsPa7TXj9ny8ik2rEmWdcjDffmI9UNoH2rmZs3bwFH388H2lmNdMwm5nO3gKOHDuMrjiV%2FrGSD6DilSxwHl00q2bn66foKN8NI9%2BFGX%2F4Pc6%2B8irURgPoPNAAs2jCouegNyAomuZKoWh3IcUS1RsRC5IAPSGJyhUL8LnaUch34p5HnsXVv7oPsfLq0liZYggAATONGIvdbDfcFMLZbnhcOq655mrU1%2FVE7%2F4TsXLFZtxx560la%2BlCGnBMuGmQVlSEz0ZuKaszilgU7l%2BDvqiaiLtqy%2Fw4fnAfli3%2FGkbBhVXrtuKLr1aKIwDNqHV3QCYRzFNiyBB1sK4CExlcIrxTIxVo2N2MzrY4urs60dlyBGtWfQVdC6BXfS989slcRINeUDDG0o2iGcmAdnhP0mRfR8ETFLM7scYmBYjTJ%2BL8BCAUBdliAZ2tbXAMQyycTMtAMUf7LT9UT1BG%2F0FGfOYS4qVKcQtUfk4FFOgJyNftxFEspDH96Zdw%2BZQ7xD4qQKm9UCuI6OZF2U46R8bMo%2BnIAfTrXYdw9UCMGX8qnnjgHqgM3PBEcdW1U9G7PorBNSHZO%2FfffRcownbz9ZLDSiTYW0q58hWBk086EWYxD1NqN5pA8xoUnpIUd0T9xe7lvyKJn0qi%2F%2B2v8napbmVGHhEPIh80NN3VsA2Dhw7AJZN%2FhraOOL5auVrUnP4AiwUmNngQjlUhnbHhLnKEpEmXkStQfZQV36%2BbplyDGY8%2BLETi7zf%2FgBdfeRnnX3gubrl5CvYf3Ie2rnZs2rYTL858DoMH9cXRvXuRS2Vw7bXXi0KzkExAC%2FrlwuGFTDUQFyc7IAkNpvyfXmuUZRWotnOguRx8PPs9dLU04%2Fv1mzBsxCi89%2F4H4r5MwrDFok6MYimjotUFEUG3mKDu27YNh%2Fd24pJzL0DP%2BjqUlYexfNmX2L2nAXU9%2ByNf0DFi1Fjsb9iGgpVCwaOLuStHKwLXFvJymYhSgPgEUw2ouvL5heRLQh65iEQJqcwjAirGw64iXnn5Zbw7bwH0YAWmXHk5giRtZwoYPnqCKAv37NqOPQ37sfWH3TjvvFMR0lx44unnMX%2Fx54iU1%2BL6a66Ck8lB8fqFt0VlJaF6jkFIuN%2B%2F94DI2x9%2B6Lf47NMvRVTRt29vLFqyAMlEEqtWf4fzz79A%2FgzINSoWcefNN6NnWRkCoXqMGX0W5s%2BZg96xGlSWxVBTVYlly76SEV0qR65XAFE9jCsumozm441Itneh6egO%2FOsvz%2BG3j8zA4UQL9icP4tEnH4FhkzAdxBxC7OEQRo4ahZUrvys5xhaAC847B%2BWVMVQGg%2Fj1LVPl%2BftUv%2FhoMU2GqjiO6fj%2BaGRN5arG2QQtcPKl%2FFh2%2BOTHUIHZp38v7N63D8NHnQz6rJ06ehiONGyTdW27feJwys%2FrgvPORX04ipNPPxfvfzgfQwf0hs%2BTF47Za%2F%2F4N6LlITIxsXPzJsRCIdxx7wOwaJdTtHHG6RMx4ZTTsGLlauzYshlhvw8XXjy5xDv0OIJaqOEYUjQzVunqauKv%2F34bwRjxLObKFvHcK3%2FC4qXfIBqpxWWXXCgCLIpfPFARDcfw9AsviJL0zAnjMKC%2BBvc%2FNANFzYs%2BPesQ8enYf%2FAwbHKpHPo6MmVCFVUg0YAP3nkHnakOHGs%2FghkzpgsCGwiExF%2BSfZ1lmQhqLmzZuBY79%2B7HJZdfgVh5Oci3Wf3NKhw9fBS%2BUFBMl4cO7IftW7ZIdii8PiHJjxozGgd3%2F4BEe0ZGvORucWQqhG0ZdQJ%2BXZER%2B9z5ixAqr8NVP%2F%2B5ICd5lwujJ5yM7q5WHDqwF3v2HcfOPYdwxmnj4deAp596Fh%2FM%2FghVFQNw8cWXociLUy7vAiaMH4vWY8fR3Z4S1Ju8H%2FrgEbFFskMyYv%2FwjzdQ0aMcfrWILRtWoWHfQZx%2F3sWor69HbVUlvvlsKQ4ePIyCy8QJJ1Th4suugWW7MbRfPW66%2BnIsXPIVlKCG4Sf0x%2BH923D08DHEUxbckTIRwLz08u8RqwhC9Tg4dcJonHbeBfh65SoEfD5RaJKLRT9EX6Qct995ryAkfXvWY%2FRIcuuKSMYzOPfcc7F%2Fz3YcO0xUQS2dGRY5qjp0KPjDzJfx%2FrwPoUd9uO7KKxHweBA3DAwbO0YUwD%2F8sBP7G%2FZg587tuOicU%2BRZPvbsi5i%2FeCkqKntg8s8vgoucOK%2BOsyZMxKZ1a5HJmFjy2VL87tHp2LP3B8m%2FPtzUhUlnni4FJXkFRbcLu7dvx%2F6DLbj4oktQFa1ARaQPvlm%2BFk1tHUjlgEdnPISPPvwAl1x2OV7%2B%2FR8R8nvww46NOHq0CedecAmCwYgQ%2F5d%2F%2BTn279kLPRARwQQzjUvqZkd4aG6XKkawpiSDaEhxkqGXRuX0igz4w3ji2RdwtKMNd%2F32PniLRfTu0UOafd4HqUxGzi2hC9D%2Bh8kBMmfjfstDV1SQk0eh2Idz3hcxzIU%2Fv1LoEtStCy2D5rUZAyf2H4S66mpUxELYse175HNZTJh4Nu558El0dibw7drvMX7cSdi2eS3yVhbjx45DGSlAoRi2bt0qqld6bP7UXJKGwHOf6Hf%2Ffn2xYN4c3Dp1KuqqavDEM8%2FjuhtulOlSiR9HL9QAqxWh43DSQ3oCrawoamKOD%2B9AIp0layxN9i8FFM889wJqa6oQDofQq2cfRGIVqKurwxeff4aedVWoiIZRES1DLBjCWWedhVQqJd6p9LEkZY%2B8yVyBXrAFDBzQVzxJaW3jVXxw%2BcqRy7nE7%2B%2FE4TH88MMWTDxtolhcMemGtk4cYZLvStyCEXGz57wvIqHJl18tLu9iAO0irQPoP6Avdu3%2BAaNHjxRVau%2F%2Bg7H%2F0HG0t%2B%2FF%2BrWrcNYpZ4NpZmkjj2FjTsYjMx5FV7wF61Z8ipNPGoId238Qk2Gqw7mWuPd5b%2FFOjXd2yXogT4%2FG0D%2BNXf%2Bf74VV8GOyyf92HfffVy8FncRgFBwk08y0ZKebx%2BDBg7Fv3z4sWrRILCd61tWLzJlGmpIeUSzKr0mgLBRomVCKg6HVh98XlA1Ksvbx40245577sHDhIgwcOBiJZBKzZ88u8SQcBy%2B%2B8Aw2bfoWoVAZPl78LZ586g%2F46N03EQsD7rAPSYOWDzqnlFBo9kkPNBEwcDxE41uPjFOpiMqR4%2BNx46qrrpLDeuSoEfhh907cNHUKysqiiMfjsqFI4iW5l4WLKBLzGeGkcPONHNYDe1oSONyeRmdrKzLxJjz7u8elA1jb8B0ONP2Alx9%2FEH3K2CXtk4uFnRM9N2kaXCh6YbAL0hQhS5PkbqeTiPp9NA0T9AS2F8eOd2BQ%2F94IasDxfbvkYjnUlsOReBLrv%2FsMYd1EIFIO1VeByeeejVVfLcPyzT%2FgkutuwpCqAI5uWoG%2B%2FQZi56E2tLY0Yt26ddDKgigWcmKgStWsSWm%2FCF00iWwbMmwozjzjFGxctxbZRAqXX345tu3che%2B37MRlV14jXkuJbBzwhLBx%2Bz789a030ZLmxjiK79Z%2Bgauvn4qmZAvaWg6huXk%2FLrnwfLm0P%2FnkE%2FTpOxButw9%2BXwhPPPkIhp00CDX1J%2BLOex7DH156BX0iNRhQXo%2FNmzaj6PZhz75GzJgxA63drejoaBKT5wXzF%2BCcC89HVyqOru4O3DLtDlzMwgZF2bAsnMhdYyEnz4%2BthcvB%2BDFDkU11Y%2FPO%2Fci7%2FbAsD3y%2BEAppIo1F2G4VhseLDNNNVAcBJYvzTh%2BHWR%2FMRcIAHC2AYGUlFixciP2tzejo7sCIUSNFVUo7BB9NWgExic6kMtA0XbpQ1mW8VArkbxYUaLqK%2Fv16y2jE63VLwgd9CDnCVdSA7Ili0YNs1imNOQo5OuLAU8zi4MH9iFQNwo59zTAy%2B9Cw4xv4SGh3UYxSckIPRzV4vQ7yuaIozDjOIVc1nU4J2svP3sXAavr3KQq6aeYrViI%2BdHenxP3fT7VcLgu3uyCvk3YfLMp4FOfSnQjoHvQ%2FYQQONnbCMUx0NB1Dd3cz7rj3LoR7DsDWhsNoP7wXr730NHr26oHlazYiWQzCpUdx%2FunDMe%2FtV6SYTKRtuHUd%2B%2Fbsx4ABw2R%2FHD64G30H9MHmw41o7s5i09pvEfMT6XeLD99V54zDN59%2BhGWb9uCSKXdgQE0YLQ0bUdWrPw51pNHcvB2H9m6RUTDPHHGD9xQxacIQvPnXl1Cw3IhEe8Jy0cOqCMQqBJ3nqM2iDiBfKvhHjhmBxo5mtDU1orOtHU0dcTz8yCOoqgqhtq4cBYcJKX65BWyLaDotEIBYuY5zzzsds2Z9jGCwCo7QANygPQWNYYl02k4RZjYOlVY4hgmTnl80QafQisi3j4hJKTeZ3EbVpwmnyDBzuPTs0VjwwT9FGdthOHD4%2FN1FNO%2FZi14VlTjU2YVj3Ql8v3o1Il4V0WC5WGpceuFofLNyHpZu24mLr7sFJ1SG0bhhDXr2G45thzvQ2XUcW9Z9B7FkQhF9aoKYNG4sdv%2FQjb17u3DG2KGwMm2Yu3wzjiUUTBo1AkErDjNtwSGqbdsY1L8ax5rb0BE3kGo5jmx7M6bd%2BSv4AkX4%2FLTdyUmxyI%2BdNij0oOvduyeaW1uQyKSQyHSiq70dv3vkEWlu6RzHu8M0DOGPcr26vEXhp8WCLtBVgCiRResVO4d81sT0R1%2FCjoYW%2FPH3ryIW9IkYg%2BPClpYWxDtSKNdd0ApF7NzViH4DxoKje8fsRlHNISPuBUX4fQGhnSz6bClWfLscteU%2BVJWPwFv%2Fnod3X34J1940He5wFbY1HEJ3ZzdSHc2YNK4fvv9uGeAtx4BhZ8BwA7361%2BG2X03BssVLhIq%2BefsuJJMJdMY7cPLok4T3Sz4X7TP43jwUNRTdYPoPeSNjT56AeKITzS2NWLhwPjZs2ICamkpBCvn7iWaz%2BCMHkcVWyb5HkXuTQpRSrAmnJkURoVCdT%2BX6I489gcamJiQScRzn%2Bu7oxNGjR3HxxReiva0N3fFOdHS1o6W9BatXLUeYee3k3ykKgrqGTCJJkzcRCxXkXNqJgmkhb9JXU8XR5k6ceEI9TSslLYgcX24UnkMknJIC41UVec2ptInPvvgSyz9bhIpYGMHISfjTPxbhjT%2B%2BhOsuv17OCf69PnceRiqJrCeGjEKHCBt%2FffkpZLoS2LKxAd9v3oSymhr0Hjwaih5E30ovpk25FF9%2B%2FQ3iWbpvUO3vFf4oG%2Fm8i7ZlMTH%2FJyBYkpXw6%2F81ahVkrvTa%2Bb%2F%2Fv%2Fwj75DdPKtqXlz8XmxAGNPlAj6aN1c4TqtWrcKoUaPwxaefSSXMkSX5RYQ7XQwtLhZE%2Fcifk8kYotxkV0GiZ0tzO2bOfBnvvTcLe%2FfuR79%2BA9DY2IgxY8bg%2Buuvxby5c5BItOHFmX9BawfNSB0kOo4jZ9jw6CGJYwlyckijShps2hQtlByguZ4Y30UPsqPHj2FA%2F0Gg%2Bo0FQeOxY0LeJhG8s71DvOPocM0IFfIwGBfE4o4%2Bedw4Y085FW0dKXz68SK4bAcuLYAZTz2P44ePoLP5OJZ9xU0NfPjxPFx60UXYvGGrpA%2FQl8ixDShaWDJxeYmWDD5LB52H%2Fjq2iXw%2BA4ts42At3pm9GMMG9YNWBDq7j6PvgL64e9r9UN0B2dzJTBKGXRBTxmm33oC1K7%2FEvE8%2Bx3kXXYFiluOcLHr0rMX90%2B%2BHHgxh1ZrVyKW6SMVGivFbcIltCw2E6Yj%2B2bKV6FFXhV49KsVjbP%2B%2BPRgzehTmzpuH5avW4KwLLhLTy1AkDMulorkri9NOmwgnbyJnm3Br9LJyCHrB52MUkAemEUc4FEI6k8OIkWNEcUppOP2qdjfsQkvbfrz06nN4cMYMHO5uQWu6EUMGDxDD6oKbljAKdIVqOq80B6KGIs%2BxUBQ%2BCVV%2BF110kRDZefj7fTqsbMlclgcBuzEiay6vV7gtl595JrZt2o5QKIx4dxxbdu3Ck88%2Bgz179mD40CHYvn0r0tk0XLoP9z4wHcs%2B%2F0IQ6ZSdF3WwP%2BiDX%2Fcia6bkIhU7miJFCPToywvy6feHMXzEaKTTWbz2x1fhsenx5sPGTdtx6MB%2BnHhCf4wdNwrpTBwfvPcWbMtAzrTwx7%2F8Qy5ynQeYPwqCVygaCLIR93jQ1tEpHev0B%2B4Xo9Svvl4pI25%2B%2FqqmldSq6Yx8NjzoaWPBjph2JrSvYN4fXyf%2FP1GEFoCyWKWYT5PDGgiGhRBPfiH3t%2BARP3oo0viUn6HqC2LM2JORTSexaP48SXahQvmxJx9HZ7ILu%2FftxSeffiqq5Xf%2F8zZOm3iKXKbwMOEkgHtvn4pN3y2DYaZQVHyw837MX7wM%2FXvVoswPHDt0QCxluKeIbK5ZvRpGMi0pLCTR3%2FGra7Hm6y%2Fx4aLPcc6ll8NKJxFvPSbN5W133A3FH8biJZ8i2d4s4gi%2BT0314OFpU7Bn82okUhbiJiONvMgJ2VJDMmeLqpERgrbjxumnnYNERws%2B%2Beh9GTPRDuXlF2cK6bz3wIGSY%2FWPP%2F1JLrFjx1rx8aJPcem5k6Az39YD3HjrrVixYgXiXQnx0srZBcyZ9Y54xDFFYNasD7F98%2Fc449SToQeZjU2POx2WSWMbW6w0qGBn3BSTUNKZpBTUfC7T77gBa76aj4RhwBWMiUF3wcmju7MVA%2Fv1x5133wN6pa3fsEFSMRyzIEX3tNt%2BgW9XL8IHS5bgzEt%2BgbyRRzFjoHd9PR544AE6cGDV%2BrVw8gaKzLfWvTj%2Fop%2FhsRkz4bJ1QS6vvOIi%2FOuNdzB23OkIuD1oOXIY48ZOxPqNOzB2%2FATxi%2Fvkww%2FhzhWEv%2Fj4sy8ik2wF%2BWiPPvI73DT1Vrz6yjN4%2BKH7kc25MP608wCXjXkfviOiCSr5n33hebR0tCBI77SCLfuX%2BHRVTSXaO1rQ0tIMM5uFZWXhcjNqyyfB8pzC3HbrzeL1N2vuAlRXVMvYzrBcGDVmPOqro1ixdDGsjIMN321BsjuLC847H7pSBCdKIC%2BPJtGwZILiuAJ48715aGltRGeiDZ3dW3Hj1Mvxq%2Bn3Y867v5czpcDcbaL8NKsyLAweOAidne3Y%2BcMOmUalUmm89%2B7bGDqYa4ZNm0dUx9yv5EoToae5M88o8uM4kaHNEFXVbGA4JTIzaTlvnnz8CUyePBlV1RUIh30yhaJ3Jv88ecb08JM9zz1FpTMdJ3yMSWRuaUGSjLoS5Pr54FX9CIbLxF6IwiAqdHmv01eQ5t2852h6znOXvoYcCys8f1MpmJkMQjRRz0NUo%2BMnjkLvPnX48tOl8Lr8%2BHb9LjQcPIZrrroUx49sx%2FAThmLD91vFhJr7F3oUUINwF3IoMArOH8J7s1k%2FtKGrox0dXQdw57QpuPvuu7B4%2Fizh4vXuPwBbtmxBc3Mz7rj9dqG3MC%2F%2Bn6%2B%2FieqqCgw%2FYTB69qrFsaZjwr8104yt9OHjT5agd686uixJg2%2FQI5CZsmJp5RaP09rqGjGj5jNkLVNymuMzLX33%2F0sR93%2B%2FD1mxVHcSpSMyZxCRCJQWFRcMFyQRES621uYmXPazycIFoGnfiBEjpYj7iYROw1J%2Bz8vWTz8008GyZV%2FLCDWdMsX7jPLmbdu2oW%2Ffvli3bi0GDBiAqvL%2BiESqMO3e%2B1Bb55fRYCQQgEuLwIYGpWChaBVg2Ib4RlFxBdOGpisounmRmeLx1H%2FgUBw6cgQDhwyW1x2OBMUegXYBTAxgFd%2FVFS9J7%2Bm75tIx%2BfIrMO3GqzHpzIloyThY8PkKvPLog%2BgdDsBfXo%2F6YSejX%2F8h6F0Vxbbv5qKq0gV%2F3QAkXWWYOuVGBApZXHHhJEy7%2FQ4MGTMJhouqzBxCKosxGz5fFOFQGZgGEFHzePSR6XAFe0GpGIAnHn0QmiuLk04ZgWA0iKE1taj1R7Dwi9Xw1%2FQT53FNs9GvbwQBvwN%2BJmNHT0LOqcHQYZPQoy6GHrUxEUJ8%2FfXXqIz44PM44kFGbhtHo%2BlEClv2HUGfYSPRo7oSnpyBObPfF%2B8wy0zj4MGDONzYgpHjThGjUdqBLF2xBnuONCHo12U0R8UtYW060jOyJ0%2BFMxXCQQ3xeAdu%2BfXtCEbKkLVzMvosFm0pnDz%2BoBwyJMaS9F9kxJZPxQcffYx%2Bg4eJ7xpJuxKDpTGSTC0pMj0u0H7i47kfIRwMwK3RtDUnqQ5MQ2ARx40rh5M%2FCHewGjfcdBuWL12IK889GX6%2Fglh9HV5%2B4z%2B459HHpQMMux2EPIzsCaHdVBGo7ovashCO7t4C%2BmGRN8L1TrNfhnrTrkXsG4q0eyiZTTNmyjby8GpBbNy0BbP%2F8wZqolGEyyox%2BfJrsfSzRSCvhN30wgUf45UXnkFNRTnqeo%2FEqWeeL4cy63kqZxnZpbioSM3DKKgYOnwUBtbpGFBXBn%2FZEHy5pkEk%2FarbECKw2%2B1CQIvAU1QlQi7vonk1o%2BRKwfBWoZQWEgl5xPaE3p2ZNH9%2BUbglfG%2FsxIk40sS2xDtx4DhMFnCk0UgjjG7DjW8%2B%2FRivPP4AwrEoymr7YtCJI9CnX2%2F0qgpj8%2FpvUdazLyI1vcSd%2FpqfXcQHIohvj%2FoaSTlp2LMDM556GmrZUGjh3njusWnw5%2BO4YNLpqKuuF8FURVkQ363bDF%2BoTBSRie44hg4egvLycqiKByNGjIA3EMHoMeNREw2gb69ahKr64Ou1G1EW0uGj0xxH7DkLA2rDCHlM7Dp4BFktKnxVu0AjGhWaP4iUmZIxlVX0iDr90w9m4%2FkZD8koKhgMYMjQ%2FghFQ3D8ZXjj%2FQ8x543X0Kcyhr4jx%2BPR51%2FF6ScNQMiJix9muEd%2F9O5Zg2MH9yJp0HS5Gj1qatCnqgy%2BQACPPf4kNq1bjeryCJJZQ2gEhUJJ3Un7Ijufgd8Xhqr6YaRTIurIWKVxX68qHwb2jGDHnt1wFE3seMgPPmnCOPiiYfSv64nKYBgLl32OUG21rIWQR8XA3hRVOFK0nzRuEjKuCIacOA6DqgPoXxWCv6IHvlyzAUHFhO7OwFaDOGHCOdjfcAC%2FvOwyaRxOP3UCWvbtxtUXXgCiyDmbY3imSbhA%2Fh85hs8%2B8CBq6CEYLcfAcRMQ8bnwzPR7sWbtZvx2%2BsO48crz0K8%2BghtueRDxXBAfL3gbLzxzH2pjlYgGyjF0zDho0RBcZgo%2BNricaNCEN%2BLGhFNHY8fG7Qgqfig%2BOgDk4HIYCeXDt9%2BtwSeff4Xf%2F3EmqmIB0DMzFKrA9u37oWl%2B%2FHHmk3jk%2FrtQUzkEV%2F78Nsyb%2FTZqyhXkcnFc%2Fn%2FYe%2FN427aqvvO32t2dc273Gh68B1VqQE0hSiMIghpRlE4RAeUJKIKIiA0IBFFRsKJGK9FEU1FLRZBWUPpIoxFQRA3GEo2JTRQEHgXvvXtPs7vV1uc7xpx773Pf01I%2F%2BaNuWOvefdZasxlzzjG73xpzzjEe%2FdUqz36OXv%2FW9%2BsFz%2F5mnRmVet1b3qVkdgfVzdIUhjfFnsrZOZXVQiht2MvZKrNWnfSao8KruF53vO5u%2Br7v%2ByY98ss%2FR%2Bf39%2FXp%2F8s99OJ%2F8UN67JNuNF166GbGwtDelBPjrQ5vuUVPefI36tyF6%2FWu33q3vu3p36w73uE6%2FeJLX2H7kB%2F7uMfrztffSecPZrr%2Bhjvqec97npgJjJwAACAASURBVC3dMrehYYCVMMYf%2BuzxySWT9GH8Y1TOlGad0pRxqjWrGnxEc7KaJdcuLXTzxUtm%2F8DU66x9DzrKjycj1In1mh9fNJvCqAPBcs2jHvVofeqn3lXvfc9v6SlPfpJuuMMd9LrX%2F6oZZP2BF32vnv3tz9aFc9fq0Y97sn759W%2FliJrp2GM9dDTOVC9P9LjHfo1m19xTr%2F0Pv6%2Bnf8Pjdbc7XaXXv%2FGtWmKHdsQpbLbU5hqP2YOXanmMjsjOVAndvGr0aXf9J3rY%2Fe6hOx1MdO6az9TzXvRTes2vvlKzg0433PkO%2Bp7nfpe%2B8ou%2BUNeevUrFtZ%2BlZ%2F%2FQz4iPkAmaDVm5wc75amkKin%2Fzve9VzanvttE%2B%2B%2FBt3yAgjm04EdCFd5PaOXDfBUZX6nPyjne8o7%2Ff%2Fe9rG1z3r%2F88O5b%2BhXc%2Fo3Nj9qKgwZu9SyP7Gj2euymeGctY1Uof%2BvCHdP8HPUjHR5jJyjQZl1quMLfjRq1h2T3vdS%2B95tW%2Fooc94hF6%2FRvfqDtcd63tI8PAsxsfx%2BRPopOTVve596P0hCfeqO%2F77ifq%2Bc99pn76379KbHfsR2ek9ULn8tqUvB51rrxS62OT2t39s%2B%2Br3%2FjNX1e7vqj9PUznMKmxV%2BnAlI02CQuPGJQeqZqzJHmghg2v3SWlk1LH2VkDdzOzx7XS4tIlTQ%2FOqZnNtEAqtf6Yzu%2Bl6jFton0tmmtMeed4tlbaH2pSo7jzan2k2bdlmjO6VUUL%2F9DyfaBv%2FY6n6r73%2BWw9%2FqseY0fcDzXWukERJWaZMMV1YvttuuVYbVfa6dcKo8Zpo1Gx1l51q532%2FMTJSOPpVW7br16qSy6ZAmB0lMxXvZps3xTcZuiGSmpVhzfr7N5Mj3nM1%2BmfP%2F%2B79F%2F%2B6L361m97gSqNlE721Fe32D6tvsfyOcdHG33Jw75M7JG6210%2FQ0%2F4xm%2FS8viiLkxr%2FcH7%2F0g%2F%2FrNv0Ld%2F23foEQ%2B%2Bhy5dXOiffvbniuXWM3u1FicrffEX36jXveZ1%2BufPfare%2Bc63mcoHBFGt6akqTF%2FAZ37WPXVueqCX%2FsLP65rrDjgjqFe%2F9CV62jOeo64o9Yxv%2FTb94A98r4ErJKToCjzXXdT73v8n%2Bprn%2F1u9%2Be3v1KdMVupXl9Tme6bepe%2FQop%2Ba2asORVBZolWa6%2BZlonN7U%2B2dfAy9CarZIF1M7NRZvVrrNa98hd7ypjfo1a99hZ0KTNgqsG50gILZurLtB4By9rChdoQTZu16oQxrI6glwXRNj4RxoovHJ8rNsvqJZv1FkzoeNxgBT9VXH9dvvf%2BP9S3f%2Fwt6w%2Bt%2BRZ%2B5f6hskuojR70SJAfVXAeFVHDELUl00rMpPNO5cwda3LLSBR2a4s6PpweIJzVd3mpf3h9f57bB9yoMrq2Xaq%2B5Th%2B99ZKumqHcFCsRC1PFkaO8uqm0HrM%2FvFa2qDUZH2jVTYVtw%2F1mqTpd69aznG6TRh%2B7KE5GLrtCl%2BpWDYdikpVm65s0zjLNs%2FOqetz4ysesWaWiByys7WDHq9%2F2Lr38dW9WmZamxuXcDIsaC7WLtQ7OXaWjHgsApdJ5YktRq0mirj3WdHHRTvhdbM8oKUuNk2Nl7VqTdKLVutKJGuWzfeXtnszkVbFW2VzSuDnUa1%2F5ar3y3R%2FQM773%2F9Ajv%2FrJevfb3qzPPFOZGb5b9662tniwukV7AN9krJP1WhXWNEZTtQ17gtEBdmKS9Gv3rlOz6nXR1A2NlLUsVy%2FVTl2p92t%2F%2FhV625veqNe89ueE3YLDZqTzZ69WP1%2FZ3ikOczHdjmv2hq0kTg0WmCNc2MEzFIFjuYIJxiSqI8zDLTSqbtLLXvYyvfrtv6fnvvDH9ZiveYbe9Y536IZza%2B1NUNLL2IDyY7OCqjrBYsFKZXuzUO5603xPk%2BkFzdpKyXqhvl%2Ba7eOjCnOEI7M8w9SVIJktZjo5yXRwJlea3mxWF5L0Gl26dalrzk61bnsd94XGZapk9TG3%2B9vP2O2pxThXlzfK1rfaAZH5qrSPj2x5k9qkVL9%2FFy3RsLz%2BqM5Mc7VNobpnGRy9gqXO9CdaLeZaJ%2FsaTVGJ9XEdXprr6d%2F%2BI%2FpXP%2FnvND27Eid7J90Zk5SORkst6oVtb8nKfbU1qqNQ57NQVR%2BjV0h1jW3iC9Z%2B63yhxeJmncG%2BW58omZ4xgNicHGsyw5zhWGvsHe91UnukZn5RB2eu1XF11rQoTOqLpibmEF180wNl60TN8lDj6dKsyxT9dTaOzEeoyFpoL82sH%2FDRySnxUdopx%2FpBVpiy7VvrRPnsQCtMzLWtGKUxaYatbdoh6pM6%2BcleVLtMRtTNoc6dG4lDP7%2F4klf5HrlwVDPp2MeOBeaGM2Gu5y2RHvLQh%2BmXXvoy%2B%2FAGkLDcyEfP%2FPhQT3jCE%2FQLv%2FBzBq7GqOZarQxQTWZsUUEHTq8U9TP5RIcFJ407nUtOlHe05H0dL%2FgwHCtL2fZy0VZsLi4AS4UOykqjvDe9pUi8k3RsqreQ2mOKjH3jOTNTu1Tbp1popn3UHn3i45qemekYE4Ndq332mY6mOqozrVhnxj50s9TZSaJ2dWwnc5VO1GVndYRN8P3C2i0WdjDzVfa9lou1nvjUp%2BlZz3mu7c1ji5ZJDw2hpWb%2BK%2B%2F9cIQpGzYjgdtTrlcqkGPJfn9%2FXwbo7nWfe%2Bo1b3yXsvP3sC%2BBL73XHVTUHzcJGPtUUP3BFwhLOwlLOjX7HhKtUImAgtTGDQJjSos9A1QOa%2FtnL1ytm2%2B51U6iEPfw%2BFgTk%2FqgI42vI2ybgtjYU4IeLcxAnWhUogy00ni0b%2BLfBvWjaacUU0P2xXi1GeRl%2BQCjwEfzxuzk5f1c41GmeoGZE5ZhOzPTUwsJHnYUx36KqkcFCpo3D7EjoSV7iLpURZep4BAD66pJpuO2U5dy1L1RUx9bB%2BnrVGdn12uxanTYHIuv7qLG2kSibnSNkiKz01t0ajr64uhW%2FfCPvkD%2F%2Bsdfqi95%2BEP08le9XodmxH2ski8q9EGxjtnUGpvyVdskZhrVUSg8Zp9Nc2SicZYNWKrDnh58zrAPu5ibBNUmh3RkiimXaxTmrnXuYCJsoI4nBzo5vKhpOTfx%2B7I5I5Qwgz9YTk1GB7bHjtNY5AXdSNCuF4nMhuTyoi0LJtMLpoOtbJdmKFvjfRP5p91S2NJFRQAbeDmY0nZYK1ho7%2FxZnaxQNJprf3TG9lqw55ANw2aSrK1t0sAiQZ1i9iaz5Rg2BK%2FqXhjF%2FpHnPUM%2F9pMv1R3v%2FcV68394m862t%2BraM1PddPFIZ8%2BeV8IEliSqmtSXh7O1sulITb6nxdFcFzJ0xmVaJ5ysW2tUIt1CCXavz3%2FQA%2FXGN7%2FB9BqxDAIdvuw45IJUiwYKoIv7TNhnWXSNnUxknwuKatdNZodC1s1CebpW2R3ryU%2F6ev3wj%2F6Mzl11tfrkWJ9xz%2FvpYTd%2Bl174gmfpzOpWVfOLSi9ca0vjJcseqDs4Wtr2gY6T0ScLW%2BbYxzbh6sSsVKyz1IzVj%2Fnm7BO14z2zjTlD71zR62iS6aRqNekKlehsXK81KzkhjF3mTvUYmWZq%2Fstlrdn5CzrEiHxWat3O1exlZobtQrGval6rxp4jSkZZBcd6yAhl0QvTscXevrQbqVq19iG3Wt6i%2FYPKANxDHnKjXvbKX9HZO18wnWflsjFdcP00taVj9rJNy5kSTLUhzUjYa5Rq2qw1LUc6ruy4kBIOa1VLTfmKThK1k1IXFysdjK4xcCItNMnmGjU3q606fc79HqdHPemZ%2BqW3%2FJre%2Futv0bS%2FVSNsLWd76tatztiHKBKqVOVorHrZWntjpxKWEOp%2BaRr%2Fu4uYIJtoXrK8tdIB%2FbRrNB%2BzjDTTpb%2B%2B2RRyv%2BnXXq%2FpmT2VkwPbJ5dhcB4F0nxQFbltrsccGlJvNtwjqTATZKbzrrT9oCx%2Fs42x6Y41Ko%2Bsv37pFz5WX%2FIVT9QvvfO39Ja3vkk3JHPl9ULdaKomQQnzzD76muZI5Qg9Twt16NwsrrF9vO36VjtsoHykBcq9g1oKbIlySGh%2BeEkHB%2BfVdmNT4j0ZL1QzDuR72t%2B7oNXxyg4ttGwdweQauuryQouTSxrtT8zGpkmwa9fLyQc%2FKzxswchLlC2jvw89g1j8wYYrFhnGNifwgYPNT7ZQMOayR7HMsHlb6D%2F%2Bxz%2FQo772cfqdP32frr7qgs41uZKm0xogw8G1cl%2BXjpZK0pFt1xhlKxvn2Ph%2B5uCCLn3sFqVFrmaENoReez17u1ZaYeu5b0znaNf1WqFjFak8p8BLliClo8OlWp1RkY406pa2LH2xXpui7myN%2FVkO431cU1QbrTDTJa1Ha6V5r7xhPY8PvpGZj0vRzLACxKAfpFBVTrTAvmiS6sxkKi3mZrJvvM8BBE6YyiVtWHJYN5AylUNJgqCEU6OFzZNptjahxJwPoXSs%2Ff2Jbrl4SeV4aitU6BtkTMJOMKtq2DGF30nS2yGh5fzYVq46Mx%2FXmqmsk8XClHefHB%2FqwmysLs10sctMQXR%2FdIv2y7HaJrfT%2F3aMr15qkjOeNFqkpUkRm6NLOn%2Bwb6t7qDth7uTwoY2dqCtKapunzpw5Z%2Fmjb7HKUtDHVkv148KkkmdRd7JcmZSR7QrramkfQieLY%2FtgmGH%2F%2BNj1sqLA%2B6RCMTcmAGknS6Xrtb73hS%2FU6MId9B3f%2BSxN2WvIfIaFHk45Uy7URvcrQ3BYi2A8tI%2BcjVqTKxPSnQJ097nvvfXLb3q3yjvc2%2FbcPOx%2Bd9Q0uWRHjxeYuSn2%2FPQgk13fmSQBO5F8da5Z%2BjKFpo3Z9aMDYRye0yxsEC5HE9ukzR437J0yU4KoiyKxE2iIlRt036FTDG31DDpZbyLng8kZ%2B3roC9twZKcR0yS3ZVcGzskoEw0yLfaswaOIETUn45xlTz%2BJi6JUP6fsk5ktmyF1SVHy6pK7Nev%2FlGG%2B1v5kzwwfYz4lH6HJHsPFK05W2z4ElMOOWk5p5kr2ZjpZnWiqxvYnLSs2vaZKpyP7Up%2B1TGRrNc0lM2%2BzkA8Ee8G%2FWlamC4ulTGztoRi0YRkt4aR%2BpiLfsyU1FNiSPqZf0MbO5tWu6bWqU9v07hr0Xcs%2B5oawQWmSoQ4JIgbIsyDJ%2B4QtQSs9Z%2BJ5JSsbKDFZlGDmrKW512rHlVarpfbSfTsxlKCpHpNvdaXZeKZRn2t5Mlc6YcM%2BRtx9P5tpi0efG8vOSaNlsjCD7wz2SVeoXRamE%2FC4xrRZo3OjUmxYxxIFEgZMMwFGsdHJUj%2FLB3290FnNtepSncxuML19s%2FqSkmalyd45Hc8XStCgPt0zTe8jzGYlKy2qleqCCbRUyT47Dh%2BM91Rj67RHMXCi5bI3qxo1lkewcxpOpbE0z4CDaS%2FaMe0bAAWoQzLHiev1cqEyYQ9moTY%2F0HzFl3anNKmUVCf66Ic%2Fqgc%2B8CFm8qhSq%2B%2F47mfrWd%2F9Y2Zg%2FnxypDLtdIKJOgY89L8xEGpq2v2xc8nk36yQIPQmnW37WkvKPEFixNJdpzpzCyjYpQCYL%2FcStWmqvB4pqzNTKIvB6oL2O5Lm7OlRpmk6s%2BWumuNgpl6A5eVEVbuwL%2FqEdtBlSlhixqA6H1OMeqiAQTTCgg6ne%2BsJ3LC2mxeYYvuE6dfKqwt28vUwvWTS90k1Mv1Qt7TH9iEyagv1GPdGgTI2mEd80FXKK06tpwYmTLs7jb6pNWobtX1rQAyrGvUqsy6Nnc7F0Uc0K%2BZ673t%2BXw97%2BFOVFFfpd%2F7sT1XuF7rqbKkaqTqKo7ORUtSM9JW6qZukmmhm9QrQuTQ%2FNKknE%2FGZFBu6tZoJksRek46DG%2BSztf23%2Bwm2Q%2FmIdKBAu2ACZY8pinexQ2vjGlLcrLCTonwcMLHSx%2Bm72GhmROKDjj1Sdb9Sn831%2B7%2FzPj3yy27UaHq13vKBD%2BjaO16ja5uVCqSoSa%2BqL9R2B5YvJFco52bJrUzHQuTDEtpkJq37RsvGpccFqwxdoyZlTF7p3N6eTo7nZtkDayBJPTcAtOhk4%2Fw4GZupqOO20nQ0U7rk62atYob9XT9NzGoHqyAoUkYxNvtAVxhY5wNg7gfk%2BszHMyS5GEyfFjPrV9nELc307GG2PtSZwutxjnqnVEcFyqtXutD11m855KJybGAA1RxIVDm8n%2FTHdigqy%2Fa0mB%2FrzCSzCf4S0vRypmLle8MXWW%2BSuxSAxgb%2BFpN7ExM8YHsWxfh8zKXJGQOZSLaqZqV0glL6hQ5sfK7VlbmpapoWF2xloM58HitR%2BIN0i6UpPga73uZA04VK%2FwEY88FejrScz3XA3sCus%2F7sdsbJX6a%2BRR28NC4QbCw1GvFhXAsl9ITnhD3tKkkmdAsDypwmp20BpJF6Mm4QlnZQ5mz%2F4MS7f%2FDmBcvolbVzTBhCiyVI6g%2B7x936yPb5Ndj3VaK87kyhOqfkUQtVhcNW%2BK6RmGKZoqs1S5gP%2BBg9Y3vZTbODaUqAHWv7iGDcunhxZUrYx2lreW5Qll%2BUAmDCPz7mULAOqLO%2BUjDHVUpGbPeRuuWx7b%2Bk763bRPn%2BWTsQyTacan5JZ1lZUa9bOaA2Gatcrs305xpBLSN3h0ZT1LIB6JjRRlZ%2B%2BuGVfp0CdEjoXvvm9yi%2F%2Bt5WyQ%2B51x00STH%2BuzZN1OiqYiLo6HwcTGBg54sfcS%2BYN5wJRqrBlbFOjX0%2FkLEfZLaj5VQcgA4aHO%2BLjMRuqcVDdQ8fO9BDfw%2FiQRZLA8JOO5tV1GVMwTIJAXY0AVf0fNQ%2FsH8hMUWChCWXSN27HfMeiF3daDRWHClBk6Kdxw9GAIBSbGv2HArp1aeN2hTljCj8dgWFKCYE8Vc%2By5n%2BJmi2GhufWqQCiLxtvkS7P6bgpSYZq0lK%2FyqAXt%2BZegDyjM3PNeJkjFx0NEQz3GN82%2FLJRcZlvzSeV8nMeJPCS6Pl5a0z7kgcjUtm95EN2aMesXWrtncRPzyj7viCMUCHmvSk0bpYGP9HAIMuVYuyWaQlpiIEBdQTl2ChBdqqKjO%2FNnON8UXDqdBedbFUm8JjJPilcrSKA8iLtaUz5nQSgw98putx8jjaD2apNkmNP9MWqVCm4%2By82iTTtD0RYnMMUZP%2FxOxihPZgbaVTk8oGIFrgBIsjDGwJ%2BSS8K5fMWpbGUlVIiZNWeY9VTzq6lcraj7Vv2lEC783D%2FrB%2FDSsR5LdKpkbH9paYZVXMxsFTTEFJ2Epe8%2BGiM8q6RONuYftErbxWU7VJqRv5aVraMV2AZUkuXyJAgkmbZmmWDxzefdkOwEPfWpStmjRRWY%2BVdYB0pi%2BsWczVpf6lCoJDpx8XdeN91%2BkaUAu8QZ8WfR7%2FLsFSAVJNwpEWhq0Tpd3Y7rwrqdSnSyV9rqxmKT1VXRyrS1v7QELDF%2B2Mq6Bf2BhAHUs1%2FGfRCSWswR1%2BswwFH8CdpE8%2FpP77bt%2Fd6e9a2g%2F6XXvWtoc0GWE7ry%2FLe2U0itb52ScV33vq6Qc2dpGA9xXaO3kw%2Fm9OwtFG%2BUU%2BuZoiTERZ0TmqzBhj3%2Fre7%2BEb5SUdxgtvO9uWRTzSQVLcse7tI6TxmImHyXNeuFUY9FqyHE8bZqnNAB2m0dIjG9vqZKKizTXBVqwaLQtv%2F%2FQ1yjNC0MxHS8Y4SNlievA2MYtAlG1R0M47TVCozU6pZGYHmBACcsChzn3P2RTdYH1u4xV9Cq6gvJax0tpQT7v0OkWPHCMj9CgX9z5deXn7kfMmjF%2B0L9r4kg9%2FNZq06OOD5Mz6bpX7eMP4wngHALb0OmTWUprM1SWNjbHqC5UtX%2BGpPB764FwyT53gzphkvEh8PG17xlOPQ30yZuZaqujwT7VID6x9Wb0Z5MEKgbcz%2BAdgpg0w%2F5kd9LBfi1UeGgrVTL%2BxtkqNpLZb1%2FuVtTX4F%2FmEtNcldHYax7hsFRHamY%2BVxuZNO3Wu8xf%2BxMv7eHzzO%2B3AL9Izbe02f8I%2FDoQwrzI%2BWjtVbeNAZeNzYnotGS%2BbHP43ZmEKu670V%2FhEn6Yc3pcZa%2F1QAmMK%2FCp62hd6QUehT9G3PDfUd45aIuaPfOX9x8YZhPS0v87GE%2Foe4J%2FmgRt1y3I2dTvPp0ZsWnPauhGAjrkkAjo%2B%2BG2prvf26H3f079S%2F0ZAZz0Pc0KgevZzICl77a%2F8qg6KE3Wtr7MnKao%2BfTAz5m0AnTM0NhgqzirSgBcTQQR0XqHWhP4OQOfxdwAdS5GYJMKOqdyCBQN7lXsHzJqZ6LhUIgORbY60wYGO4%2FmlW8bBljKQJ%2B9UfIP4xEjjoEFxCorL9yiEeNbAvSOVLQM4gzQLtaGRWoNyEKkeQMdE6XTTnj1OdA3y68CUAYOJGtCJSXcaHAM1gG6Zja3jjFhCNEDHpBr5bmOCDcyJbfGmQwAA8YdGp7Il7VRrVKjw1Q6qQR0FxusZijomPw66ONCgrNSddQrMmTV0sFbrwgeSCOgAPDYAJHxBsiQJ8GBg5rQkQArLFJ3abGG5LWps6yZeTwaGO7M0kDcO6FYFM0IjAJ13ep%2FYGUiM%2F2EwMjE55WKfoXItMgdOTHDwzQcQsuRftoAYBmo3tgxA9HKPWwAdoJn6t6Hf6jEPA74BigDo4BM8YdqjDdF%2BoOOX3ykzfCwwIu9Tj5U37X1ChTe0EyZT%2BLIsWMZmmRSpQCrTpm6L%2Fe7vEx6JuhJoQJjXiwOGsl9Z%2B6xRCGqA39uXD5wRQHRa597GsrYMgI7yN0ptYggGvwUgd2DjIJ0SxA8wShuAEB8tATAzyNsEFyYoBnPaL%2F0EoNKFiRx3%2BqPafcu%2FskOvGyZ4joiitjX0S9q3xQX4kDz7fdgkbdZd2bdDiLH3E06SMFHbhxyNG4W7LJXQjgClDhi0AQjej7ueLQi9Wpt4JNolEwZgnDGjSpG0JwbimQChSeuwZ9hiwISP0Cp8dFCG8AFr5XBg5%2BOG855o9kHL7lD2TzKuxLkTT%2BtBnoaBFfp5%2BABEim1p9pnlDwlqa0gwTFjo%2Ber4JJtZv1N2rJaPoX5qbW1sEh7agfOUMYC0J6zp8eGS5gZ0KQ%2B1C8DA5BsWghg3VnwIppVG%2FYkpFF%2FrrPUx2ivS%2FDpH56g0rZkcM63TsQFs2oyNIqa4lbIFwAtoMDd6DE3I7cr29pHHLO%2BAwYoI0Ax9d80HdtqKD1f7KG4mxo9FyUQsjauZ5aMqUBDlH4u0FiRtpojY2hnWGHzC5gObcRhatK82Y15J7cPU2mDGEjNgGf2bhQsIDNK4NJ%2F9oYwby3SfndgOxA3Q%2BbhLPdIXbZw0kM%2B4HxAKYNb47TpHrf0AygPw2bSPU4COZUt6gAscyLX1USu9j9f%2B7uORgTfih74Vgm1um6zEOcuELRtvZRhehZMGtJkX%2BdhhnkICz1gHAOvCPMwqHem2Dqj50GsZB1yw4nOs922rE0sm5pNcex%2F3cdrnXcrKxehDHyww85mwJxxAh165wqmEeSGOy%2F4hRGaJB1Dkgy%2FRvPBxY8ZKVe%2F9AX47HT4%2BV3ZQwsYqm7Eu66CW2pX15%2Frrr7cM%2BwzaYw4EI8u5MIX0DU9%2BlMkKouQDXR3eJb1pBau3pijRG4szhKHRrsif2KZDQ4rONB%2B%2FggsNZDesDXoMQqRKFwxf6jZu8wWGhC5VaQjbO5OHpPHFVDbRQ1oOPmPK3K3hWkPy7pFoGbwRKscuBD0aOeugfMnYaq7FYmjdXkzIzk6kAzbQ2MROCEYSjNJAiz1ZTGwhA3jzbDyiXPZtZJNfpG4Dv4VhYkURoq%2F9Rz4SzsrNzJjIAB30RoEVayZMBkLSt8lxh9metJc2xO8z531ims%2FNTowzK%2FI2DBxxoLD%2BaBIJvsa3HZBJ0zbu2o5AFE96x%2BTABxeySlTR2GXgP3T8kA6Dgw8KlBDYA8A1WLBTa6TBILHlIzuFiUEpcEeVi1nNRroT2qiFJ2kIhvzYc5iUYp7wJEjIpTnzTnxAnV9e7xbQQgaCZCJ1gO%2BP3o5jctBw2rRmmoj7gH28xKRB4kyoAAYkikjsYr7JFSAKsaMvJsS8GT1edi%2BrqN2S2LRuZSEoaXLxfW6TQyDGZOU8Tj0%2Fxk8P6Yz3L%2B4I2uCKfyBRfJaMAp%2Bs%2FjmZ7vyMfIg58vZMWOcW0igKbB96Jnlx6FCG9kcOKHrM96ZO4BdhGB84oIWtaZM1YUN223Ro7sSl9sgLXjbhGN9i7kgF4E4fdv7HD0%2F44nwOJbBGRaY8rvPN6zB6Qc2uTd342GAtylYGQt3Cc2sHHOdyoGkwnHgkh3%2B6O16QpqcbSVM2xoUEfYd9rpaTgOaGO30VHoXBIWSQD5BEbIlw4Og8oQ6xMgB9aITxmIT4kZdQD1YHMQMmtfTiGvmYb5O%2BOl%2BsMBY%2BNIoA8AlKe7A2QUGSTlUKgEs16lEGLlMqS7v0fFGXxIrjA1nz9oKbjaFGhxckSwwQM7%2FbcBxMQu2Ux8se2p%2FVv3%2FAWbsCj9pwy7ISoI15iNHPeeOE%2Fa%2BPExyDpa6JxHzqeSM5b%2FeQ8PzHevQRDBqhnjZMdLrQMCcbQ2Nud1P29uCBvKpiCruhjDehj8NYO3LTI533%2BJ7G6bomvuMDxgpKkBuopTw%2BGnpKsZyWRhw3woe754twnncrj7WFkDtWkEzBEv6ZcuZfLthhKy1hXNlIhJkffZ2EYDb%2FwRvrR75XDnfGAu%2FngZ4V0ChfsX%2Fe%2Bc53Wt6txkwvFQamM441%2B9d7VbmOm1jC25QZh41jaDgx8O79VLhdjzDwhcEPH%2BqSn08AUU4bmB6jWoWTXkiTD4uQFXcJ7jH8%2F8ed7MX4cSBmkOCKWfcmflk%2BNnRjg9w4bB7iwO8pRDBBuUJBNyEjL2loNFIr5O0EY3Zj4NoBp6H8G1LW0HeqJgwYW94Aqni7jE%2FGeAYcSstAEYaZwATLkQ3%2BLnVgsuLalpE0A00%2B%2FeNkZ1uDT%2FNumzrhKJO7BJKbovgDfuTFO2Qc%2FGL%2ByRdcYzCwgcGkNd7RCevh8bMZ0EhSY1YeZneb4XcqO%2FImDGaXZcZeYz49TWjvXkGCE%2FjmPux1czBEfmKLsTxYgEDD8uMxiO6utl5mG41DKULefjXZ8gAAIABJREFUCRcohUrAH%2FqBmjeCmNnddELLIn3z9mZlIU7zxvPifwOYM4ZTn%2F5xE%2FuKRwa0B5qRx57CLiHLdSz7qezhGD34hNrJF23EYS%2BkqF%2Bv48hL5mq%2FeGKSCa92hyOBKyS4kyiP%2BLhT5KfTiCQi5c09eDjFnQIbpfBxumn%2FkfYmtj%2FEPIQ7bYlJyjIC%2FVB2JvntRB%2F5Q5qUnwjkggj%2BwRgxyyneEcQza%2B3DQB65iGNvzItRJGAcIzyaLwwSAeSTGwh27l9Wps0rfCRETDgkHtD0po1ZS9gpc4gfS7UhZ3yh9vMNeNvWYaBtgXfT27obdNopo0MOb7%2FQgXubthXChS6101ahF8sV8hwzaFJ%2FXnbTjJ7xHvIWeA4lrlPZCm7b2%2Bk47h7cNmlFSvjyHN7%2FbsLbJHgKYZ0H1DEOtDu%2FrI%2FHcTK0fa9flm6CVDmUPsYhZgy65co2LUvCyJNfL1PkuSUMIQNqJqpwkBmIMvds%2BntMBD8TChjRMO77M%2B2cFGLe6Gub%2Bg40Q8gr%2FmYz7Qx7nHVjGxP3D86ageIzpX9pdH3LgcPbvbwj7Dbj2w32D3RkIKC6qILLJFlhwgNsbPB2yNupRhNT3OT7dn09lA2coVGFL3Aas31VUUBrJD6IudZpJk3yaJ5hCiW%2FoWVZmlGytA3mjehUM9p2vtjJOSm6ASG%2BpGgOkObHJlbLm3daAxS7ZbS1ndSGYwsBsLK9ej5Z2CDM0tbtDOTW2jdrQzt8DwPeJh%2FkYPPlfTlfeSdlB0pYB%2FUQTBDuRr1GUBM5aLTDH4pj5bqsA%2BK9ndhOpwsdUmWDNWpQaDeek5A%2BzrHMtK5Qptz2VyG9C4NSqDuvyshjHwh2U%2FQ8kubOQGFpeKY9pp03sVJ5XF%2BGwoH%2BFMNAy4csXy7Hn2qwlpAiMe5Umbw8VRncKQrJbQC0Z3gDruNgiXTU%2BpHtkbSshH7FUjm52imVE4yBQn1Zbs3N8hPLGMIy0CMVcZkyk623U8rDM2nQBvwC6Pj%2Bmti74z6fdAOevV%2FZfl3bgxOibtoEHKcdxY89P%2B9EeeGn%2BVEmWyIPEh%2FjU5ThEBd%2Fp0se%2BVm1h2f34Us%2FLi3FAE7PwoYI2%2FZIrE2lbCRFEcRvSxFqnQqExqZvOSXKsZsfr2Svp01NWTyXCHloPmagC2%2BQpMEsB2TE8RFnYm0O2k6TGnDVJ0hSI23nIeydKElQ14NkE3%2FosYHcSxKKH17gKY%2BRCqSDJKvj1HjkX5D6hrrG2ZtR4FskEYHDLkXGMeDcRhLDZrSY202tu%2BQaCZ%2FnzN6tzCE%2Ffe5LvGo5tAVJz7s9BkDNcywncclj5BH6D8yFPIbl%2Bc24Yvl2Hrg0KpabGEGSRqJW5%2BSdErl7YOtOid1%2FQzuU52%2B9WaZ3%2BB%2FHOnM%2FHWsn1GmPU2%2BE8rmD%2BqOPx7x6XQcOx4EoxEVi5zwrQrtjXzsSzDAG2J7fwMJNF879m5q82kcKbZNru4SbaeR0CGPNJfLHPyAtT8ZXX5kxUqHlxnbprPB4XprACW%2BEIc0r%2F2al4oQJp7QAdhcvokMLxaeNnWDcDraXFTZ0TGvwl3mdfoWJ%2FGgE8fl0iPjmwxoV6ozHHfo0Euu2oQMyPEeoQBivwDCuWKS%2FX7O1dK0jhnxtetZO%2FB0pgfUTaxkxIOG2YfGPkisbSCgHDW0z4dCwt4O5LTfGJUcrK7Rsw5plbcuz8GqSKN%2FHxz6Gv4ubnit4yZKcz4HhzYlZEVzSx4Cz%2B4upxfv2C33rcqouoXVKUhj4E9L1WFs%2BwfI46HlUz0ekvnvHf9saSMffQgqboKffGSgdON7mq29nAtuUgUAsaYZPCR%2B0Yp48vW0bY6Dzjb4kbr6nE7c2u%2Fmq9ZHEwRaBnZyFCY%2FB0ZfpT5MiBC7utymsPewQ8wy796a9bqnjYSAvEKeud3rLhqz3M88ivKAM%2FKirTTeBRijTJmLI5fad2H6wx9yYiO0gUQyxk%2Fc4%2BUSvLYvcJaQHRc81T9uyxXoh754t%2FnJqHduZ7uiTkfdIytPaISnCh3okDePNto3uyABCn%2FTlXw8H3VgG7qFPBzp%2BCxIOo0tRdsN7enjh6rz2%2FFsZdqqHvO%2B87tAhrrdRB227eYeq93lcoc%2FPU%2BMDhlRCnjfuHsf%2BWsY4UOOUtx8OFtjyY6md4oGDeO%2FX%2BIb8ODNCep6m%2B3p6G%2FZs8uH1a3WzceMhAD%2BLxh9iehobGpu0vKQWPXhys1gU3Zjsd%2BunQQqKv%2FEplmvTlyL%2FaMeAOt%2FTuWkLlg%2FfDhJJM0b4aosv8HleGf8RDni92di0k4bld1NmK%2BjW6XafLhsXrC%2Ft1uvpSLHom%2FsmbafDfkLLUyzEhrHwLgL3HZo7%2FDbXsPS7G50lU%2BNTuHk73KGx80hYr4%2F4Yed1ZrVM2Szj8OWyvhXy6S0HTtMWA%2F92MxPcYlvwpP8%2BfN7J5P%2FPHw0655zA41h9VWk2RXWCNCkiZGLTLSyAM4EVxkDfyG%2BPVhHUmL%2BxYdovryIGP38KoS0cEgsP566kgF4o%2F%2BanSmID4wiznaoJa%2B%2Bo8WBQMuWKfPRYQ4RKoIeD0Y6VFf1iSu7uExvnKwlvqr6FbUvbwI6iRyhyGo05nC8VWlaCHhsGF2iQHgNka6IC1H%2BQAjY%2BPX2%2B9FkKcXfPnS8op3bqKfKMpkiDJSdBOmanxlBgS%2BJs7kW1g38tsrmXpPsESQv%2FsnCyyhIWxs5JK7e9RNQEA4ifWOSN7mLTm7GJLgSN7RBqOzzslG%2Bscfw5BYqOCw9PHKh6HdrnUTBv7V3SNgVH9gdQ62Fj3ZB%2FD2s5tKqxP34y2urQ2Uj3xSdnr4q1Qm97NiyGfLo72QvSNiqMSDAC03QM0rQ7G%2FT8S9lPUSKJcbrxFCbRfKM2kdmDFFK15Wi%2BOMO7KVEMM0VIjLitSQQ8cfsGtwMEYbbYzU%2BI6u0vTNxEM1oMoewypJUjdYybkoNgwT6oyLfXPwX1fFJMT5uDKfh7XXlbtn6T%2BscA%2FCOkb%2BBGpUZn6gHWtteQNsQJ2U4JhyhCmwtzqMXz2BFO8OHgoAmJhuXH%2BB3SxSXlxHdlLYeJLZ7i3dC29sUJeloofaw0VtDufahgKgx9hRwYr%2BLHAS8MBByiYnuD6ZcOYwNSUaTUvixJjtkhZqfobf8TfY%2F02IxNPyF938xOe4p7G2N61t996rfDMMYHO1nvWWo4NEJPDhm3Jkerhi4vcTwx6QexfQxCAmtpYJGci5PK3PnGw8tO8IeKCDzB3doq0h4zVwVg9bEz7emf1Cn17f8AZ5x%2BJh6b9en1Pg4C4CKjuTPYcAoUNRmWm9BaYnvBjfENupmdcvV%2BRFqAHqvBkHGrfDWe0fAxRx8mFCtA4RSwtVuq0EplKmWs8JyUZcyP0l7r254vL0fgGy%2F8Apb3eiJ%2F5In%2B5W0mnNmzNurtlGi9SeLIEYfUbHwnHT7G7TSqH6ajCIxb5JuTvpCE3qbqzMHbD8Vj3IUT2DjlyWPyl4Munp%2BewzMkhDORQke2ZIyT%2Fgdvrni3xm3vDmwtvY1nCGwkt46naRKjtRUXqHLQxehn3n4tIYY7k4ZSy9CJeaXOwwDmyVvfM050Xqdrm88Ss3dN1CRF3RF1QbpcpENnMBiiysa0TCMbQJAQhJ5BOsQPZcV%2B9%2BYgmQ0Mzkffw0gOXYhhkaytwAQnwhjg7R1iVF5MJ2TpCr8ZJ93QudcKqxXs3USRr7GdQcH0tuSqrKNmKi2odWNryDDOOgsx4BsR7cfGWxo3tNwUDw0fE3JG25hHZyUSItbCwI%2BdXmOCiuGoDHsOsWyEcdDi7hDaUkRHnV%2FcY2vbDbPrTyOGeBhlrQt6c9khucmLdTy6ZsiDx%2BU9itVDitE%2FlGGbE2vCfsgi5tPKR9ffyWsKx4iFSAn%2BeJKW8%2BAcOGC6lbzM7hG8bd%2BVDzXJ7krTJutGy2JHbrmL%2Fd350HN5V2SlTQkhZyFvPoNbmciTfdHHTGzqcJf%2FgeW7ae%2FWr5fW8%2BlBvSoAUEjHkrjDz4lvuUY97KSzaYueGZ8o4LMF8pHfRgr3pyWE6TKkjfuW5obHJMjpwLh0atEDTVs229ax82OnEIbbnYfbnFIOV4njWaO9A8SY0Ok7DtxoLpsiWWRPM3IjNh9rF%2BblA%2FT2a9U5RXj3MUZ7g7WBz%2Bnhx5B5e3m3%2FHl2rVC0WYfbQfRpeXTqaWzfIZk4ASHLsH5kfNytMghva2c3rZhzLytMPFUCH%2FEtgoeETxTJ30Ia1jLJrXFo26HIZ8ir1zHDYuQ5A%2F5GxO4l2YQPdEgX1gUyLhsGEIb6sRt%2FwrgR%2BpaXgNr1MofgMbN%2BD0DA2mVMl4Jxam%2B3vVrOoOMZIUic0HwKjulHTro%2F3PAxzeN5Hmh%2FAUUGHlqSRnsL0L183kqcbw5reObJLsj68BXyRnsmD%2BSVULxH8b7nEV9r5xuGwDfCxqVmQvj8EFuBBfUibNu2TeLkz0cwKzlhXN5kA5px0T7UtmyP5TIXq1panadHbOdxHBd2mpFRDI0g5D2WMrDOSEPN5ssQxuhZOt6GNq3W8upstHQve9%2FmOHhEGtso9uT5jUy93BNf4l9WPvLmzkFGHBCVtZbt%2FsMNsy0sHI51Ayag9MGJ6jNBw24mQ9qb%2BZ3apME5IHMAuYMDnETY343EMHZwpxmy66ObtZeQljemkP6GuyE%2BYbZlv4w7V9yrtfE6ScQvzUdqK77KYavr2DIEe%2FIRfe0jHqzxNZ%2Blv7wUlhX7ysZnCPQ9X91AeZdewD%2BAL8su0pHUX9IjHvFlmp25qz52C0pQw0iEPpr2ktR%2FXI9%2B6D9TPv00fWguNP%2F41xiTg7UPBlf%2FEneRPp3Jsh7niE3j8xYU68HDxLftHfddv%2FAOmg3ALDStLd0QwwaQTSuFUcQhv1nMtcchMcujS15IITa4%2BGz%2BgJQQLvrHrLF3xfavxLLGXIeAUGZq9gGSBH2mII9WOvJlP3uz%2FJHTTfohT7wTBz9%2BVrzALJ5JZ5uGv2%2FTDbOT9R1CxrBb9w3BSDjkH5r%2B77Zp7gbdlMfK52UJJIw0Ll6m8BQ9iWiEdvJk%2BdvWhZfLU4g8cFrbMEYj0LGUrM6h6el6Gp4WbgzXhf31MJuA24JsSk768Xd5Oh6c3HjN8ISbzQOb%2FOBy2WV%2B2%2FxfTh%2Fv3Z%2FFxiHsPYMikIYyGICKCe8yxmhEvnpOY8PyOg1uMSHiWjlQzYLJIB%2Fst2UJmTIixA0Tpo%2B35uptC15cRps0QggKhi%2BhLMmY%2Fk77pFfxz%2FtfuEPC6HCjXIDpQAX3WHYjyp%2BQh532FMN4r93m3%2FhrnqfzDVnaCmshxNlUitEO8YOzJWs0Yn69bVm2dspIRmPOLNObsSW2s53KD%2B3K68LpbfO6E8545z72N6YXOA2%2FTqfl7Ir8tHvYuuh8d9peC54vjxHohD6xTXGHfigPNGM2uNsVHKK71a%2BN55ZqDGX162nHKnf68I3fpiyBEHWEu6Vjf0JInnfqByp22TzifRbexFJFjOQteLdMu7ShEP1O10GgvlPubZ2GrO74bfkT493G0zO7HX9iRi9L33nluSZvMS0LFl%2B4b%2BI5oRjDIhhjt3E9WiznNrz1A7htH3aX8d3S2EmHx530neM4Rbqn%2FT3vNqNay%2Fe4oQKNF1f%2BH0quBgWkaa6uQZFwayZpTBzZYJYKuyRjW%2BvrD0%2Bw2uMyt9pBFia6clqqqcNwOZ1ZTILRq5U%2B8Nvv1n52vR7yJQ9Wk0x1gpJm7zXS6kT%2F5Xd%2FW9fl1%2BtLH%2FwF0vS8bp67lIR8meAufMWZKyDRgOLm9j%2BwBkLFhkazaTukEBpNuHmam5fQeEJDj0WzOKFhbYKG3PLu1zZudNm9%2B8TC1LptdBY3EHB%2Fq0KPtnH3LHu88DW1LYZnbSchou3%2BdrzsMZDdBNqmG9KOkY3ObfNzit5OWNwvez0VNL6cDrNDPwQ47X%2BZI552Ee%2B2cd3N%2FSKdTZQY9dQ90AmB7BYjhnCRP9xPXbzuxAuPt82XeWwHP4dXu%2B%2BRashLfL0sH9H5730P8bnRjj3%2FOzPW7dK%2FLA%2BbOt0pO%2FHswo32HNp0dL7NPdDcSc8fY1o7tGPc24TdsDqGsLvXTfSjbKf7vQe%2BnXR26Hsd3k6YkNI2r9v6Pk03BAzezuudyGHc2O0c0PQrputvW%2Ffo72Uzd8%2FI1uM2T9C6nbqI8W6P%2BCkaMS%2FcuS4bp3CKtE4%2FWmj3inHN6e%2F4s5PW35av27jHOLG%2Bt%2BR3srVxPO12uiynSW%2Fpxsi3iRvrcBcAhcAe9vbaXaR2W%2FrR53%2FofVMo0tu9QvrBP45n27FyJ%2Bypgl8eL%2FD9VJiduPa45cM22Lb8IQuXR9q2tW2k3aZ2ekzdEHG6O1Fu2zBuJ6UryYkSSulIOUon22NhH9HE5SjzRR8ZWsPrsV75ht%2FQLev%2FrgPsDBGldB0%2BGUam10uTGmA5YpnKzFSphUqmp3zD03R8%2BCe6%2B93v7oJu8EWKPVKU1%2BZ6ylO%2BWTd9%2BL16wAMeIFVL7e%2F5EAPTfYtBQHBxctxUjudj%2BDtwYODAwIGBAwMHBg4MHPhk54ABuq7uVDeVGdkusM8a9uSqXusNr3iZrt67WuMi04Wzd9bFW9hU6KurLeuqaCfPU91w1TW65%2F2%2FWMdI4OAqa9hFqd%2F9wJ9KxUhjxNBti25Ow3rF1O3zvff%2F%2FoB07bVar5eG4OYol0f5RO32I23Jx8Dcabm%2F7b8YwN0ne%2Fsdyj9wYODAwIGBAwMHBg5EuSRawKfTsZaLVk2daIL1nmoppWN9xRO%2FUZ%2BY36Tfftev286UsvC9LzVGd9kVjm601YnGo1x11Ws89QNC7WJuBu8Bc8oTTdj4mJdat9LCTgqxx9VOX0jY9ByP7Pje2TMu2MWgM5eZIzWI5%2B%2Bna%2B12jlKfDjC8DRwYODBwYODAwIGBAwMH%2FqfnABsoNJpIy%2FmxxtNSWVoI299lgcUI7OYsTA9H25wYoGtqqa6lvXKkpsNkWC%2BVI%2F3533xYi36mNXbdJ1I221eHLh6UCS4WMnvLre%2B7G9thxU6qGyXj1CR56MJTX2nJqu9EyjNpuWw0mYQ9HpyOQDS4kcqZnDBU0O2Bvf%2Fp624o4MCBgQMDBwYODBwYODBwwDjgS67NXF1XqyxmKot9Fdi%2Frhr1wdiza%2F7GBJFrg0fxMGrYsjRRw2GIYs%2F2w03TRuew246mErTBmGboTJpkWjfHtjTbV9LYVL%2BkSqZjVwnASaQsVV5mmpXuxMEKwJwdjHBFTkOVDRwYODBwYODAwIGBAwMHBg7cDgdctJW0Kkeccm01P5qbJCwtJnZ4wc73trWm%2BwfSeq0UsIZKmlSquiaYW0LRLzqCcldXElQYmfgvKPlL89wOWExGnKpF0paqb1FMCTH2x2VqVvNoh1xFLnGQ1tQakPFT0rndktgRjl2H4XngwMCBgQMDBwYODBwYOPBJxQEDdHk50vz4ROMyExYMXIN3UEUCUMunWtQoClzbwVekZoRBgaTpqzv%2BsD79hqv1GZ%2F3lfrrpcSZClOIurpZ6udSMlbdTpR2rS3nLlJpbqeVOzsowUa5PiXtVsJiRayCzUN0uO0dnDdcAwcGDgwcGDgwcGDgwMCBT2YOGKCrqk57eweanxxpMhmrQgqHdvQs02O%2F4qs1G91R9%2Fv8L1W3ONTdPuUGTWfX6X2%2F94fKTKEcGiMLzab7mlcrlVNpbUIzlmIz3fiIR%2Bog%2FxQ94Asfqe7kFv3T6%2B6s85M76vf%2F8x%2FbEu7XPvThOjO6s%2B7%2FgC9XtzjW3T7lLtqbXK3f%2Fd0%2FNH14RmoHtbkGdKosoj0XMn4yV%2BJQ9oEDAwcGDgwcGDgwcOCTmwO2KtpUGNnItLe%2Fr%2FnyksrirNq2VpbketUvv9ns6CXjmZnl4lgDK6UcWuBqm7Gy4k76T3%2F0l6onM9dhZ1QLqdnTy3%2F1N6QCRIZZr5EZ1IEGWp3r5Uqv%2FLXfVF9dUjLaUyOPn6wl1NsRq%2Bmw%2F%2Bg2HW9bVYC5AdDdli%2BDy8CBgQMDBwYODBwYOPDJxAGDXhyGWC0bNX2jHssQnG9FJQlGaewEROMWiAFYba9J4dIx9sLleTDcnUml1lpjOSLfd0uIdap8NFNTL5Rkvbq6UjkqVZs9zlT5GDNAMjAHMOOgBecw7GBrwtJtY4alDdlZQAse%2Fgxgbpcbw%2FPAgYEDAwcGDgwcGDjwycsBE29xonQ8nelkcaKMfXRIz6rKDqu2iMkqxGWpkrTVqMCUc6emrlEvp8WqVct%2BOKw%2FrCqNciwTdmraTuk4M1useTG15dkC3SXNSlW7UOuyPBPDuTaT3IydowOPC%2FUo2JBboQ%2BPsHGFFU%2FyxG%2B4Bg4MHBg4MHBg4MDAgYEDAwd8vbLve9V1q8lsaiwBYBVlucVQgKyOQxG92nplYYqiMKW%2F43EmnNjbVoxn6tpUbdOozFL0BQtAuGrCcdW2VV%2BtNc5HBtIWi8poZdlIbdcFIOm14oK%2FRuMSfXid6UnZYrggnds6eKTh78CBgQMDBwYODBwYODBw4JOQAyahy4pUWOaqFq3SZKQOpb7rlbJeJjVDv%2FCiOrJl1zKbCgDY2rKpG%2FHGyAMCtJM6VZONlKal2qpWmQW1I3nvArW%2BVzKaqm9bM1k8RelckLytlg7uCgOPrufOvTgWcfvIbXtA4pOw5oYiDxwYODBwYODAwIGBAwMHAgcM0PV9q67rNBqNTFIHkCpHU3H6lavt1prOZiaG6%2BtaSYKKkVQdpyOw56rOpHVst%2BPAA%2BAwR4KHZK7v2ImnNZvjwkmHPCttObXG5ETCwYdE09m%2B2XLtiROWcPu2E4pRDPQlPG%2Fw36kKJAcO%2Bchv%2FG2XZv82%2F617JOBxe3Xi50T92d1iOrvJh3CYMzMyzrO%2FBYPu5C%2Fmcxsf3gU1f5sEYh65hwQ2fsPDwIGBAwMHBg4MHBg4MHAADjig61qVeaK%2BR4OcA5K%2B61WMUrVqzBxYmhRmyisZ%2BSa3ru2V57mQ7rHeyiGKHCtgbLmrXNqW5pnpDWZXXplhAiI1VShty%2FJtIpZtOWTRKgupVkoKQB6%2FTkU2VqLS4JXtuQM8gn8SqULa17sZMoAQue6xWWZa8Dp1AEhsxRpIIo1OprW4a133nToDn5SYq61Wbji2a7Vu10BUp4ruPLU6aZcW3tIhQo%2Be5aWLEtGAjG4%2BdRYu8tCyA9ALYA%2F3roU3UCHXQSFzKAA%2Ba35dY4ASEEnIyuGlpTEtxmrrzqSkgLwkTQyMWxmCaTXA%2Be6FvkCkqvFq2DQZLkA1frhF93jfjWOm2cgxeyfz3HUQJonakGYMy333OU1TZVnmbSXLLF7Jcj46DDdao50uWYIe7rEM0OIZGlwxbzE%2FoRgbd%2FtIgMNdt6Ef40Sa3HfzGGkM94EDAwcGDgwcGDhwpXLAAB2HG5CGASA43MCBhL5LVHWVqaPrWCJF3Vye2VIr%2FgA4Jk%2BwAzGZIDEF1laVmLDrpjZ%2FJnQka6hASVLWYFPzZ9IGGCAVHBel8ixXb4kAPCpsjxkgaxtATao%2BydWgzRjvZqkybcySRBoOUVABgJueo7LI%2F7LCAaS99arq5ebdzE84NrR9fsTNyrHjrCRTkRWq7DBGq76prXyjbGIQjH2BXBz6IO%2BG1lKkip0aSxf1LgCKWpi5BSPv4CelWaaqdsCrau3mMGrHkvCpQTmM8Qw7uADdRplxUGrWteq2FjzdlVXyvl6vDfREgEUeI4ChbjyOu0VwhD%2BgOtYF74Bx6gUQFIEV9%2Buuu87ex%2BOx%2BeFvdR6AFmEinUiTd8JAEwDGnff5fG538kSa5Jk8XU6PMuC2G86lyLXIR6QHDfLM5Xs7kRh31s5IN%2FpFYAdN8kYYnodr4MDAgYEDAwcGDlzpHDBARyGYVJkgmVjZx5bnqfI0B6qZapImSGJyk7YgUWlt8iQuEy4TJ5MjYA5aTKz7%2B%2Fs2ccaJHf8IFOLzajlX33KqotWyQ1cdxmBbaX0kpa2yPFfVNAbq2kJaVb2SdCH1R%2BqQ1EVoU4O0gJapASskbyYZayplajXFlhiUkdCZYDLVerlQyelcJGxcWa51jRSt0aQs1TdLJWWhHLljzxJzqyxl6bdWnjV20tcQb75SpYXJBqFUscTcrA1zAZDR0UzuKkAuNIqp1CJxYg9hqXYsVYXvR9zvG2WgwL5VWy%2B1Ny6VsRDbN8rHhZCUQpOyWa5Z%2Bu7l4PJ2ABDFgteTycTqiLqiPqivCJQAg1zUHeHwn81mdicu9Xnx4kUDjYAgLtpJjBfdoEf9AvR5jhdhAVXRbRd0RVqEie2EZy7aY4wTw0GffHJxJw60ufPDjfikQb739vbMnXfAYAxDuXjepW9Ehz8DBwYODBwYODBw4ArkgM26TG5MhEyM3JEosSza9m2QkHjJTk5ONDIJDZKQoFk4TO7T6XQzOQIWuBaLhUlB4qSJO2kw4TIxAwScTgAJABVJP%2FNvflJX7V%2BrWVqqAFzsX9Co2Nc4vaCf%2BPEfldpjfe2Xf5Fe98ZfM0AHuMnyXsvlwvb2QcP227EXL899ORUVKF2mPh%2B7jhVJ%2BxN06NVKi0yXTla2lDsqchUsD%2FeJElsS9uVUBIFj8r2emxytb9e2T9Bh1VyveeVLdNf%2F7f46qjztyWiKSM20MEds0%2FaJCvYRVsdS0ur7nvf9GpVj5elUD%2Fz8B%2BvoaKUkGcn0wHQOUKqqN8A2m%2B0rZXm1b0xyZ6AFWsZ%2FDwu%2F4S98heeAGOqW39HRkQFswsN7JFyEww%2BgE8MBcniGltPOjBYgLbYR3K0tIKEMgB5a%2FIjPL9LGP7rRRuJzBG2xbQC%2Boh%2FPxCc98gKwo1xcMZ88Uw4uwgIuY9gYBjrL5dLcj4%2BPN3kiLGnFuPYw%2FBk4MHBg4MDAgYEDVzAHDNAxqQK2mOSY%2BJg7mQwx7VWWI1tWTZNMBwcHWi6WWARTlhUbAEdYJt0osUG6wzN0ocmEywWIACgQFrDBJG0SobBuitwFmPhN3%2F5c3Vwdar767%2FqeZ32DHvjwr9FN9bGW3S163nOfKVVHKorEDhBwbgNJHTGMohP1AAAgAElEQVQnkz1b6k05gYtEkXT7zpZTV12iLk11XEvHbptM6tbqqxOjM94fq62QDLIMCj2kk7naNFMd9uolzVrj0nXyuT%2Fhaml1qNHqUPvnz2rJORFU5zWpNCrUsw8xlU5WncqCEq6V5Sf63md%2Fs17znt%2FTh5eV%2Bu7juuNspcc%2F%2BVt1S4fav0K97Tkcqe461UmuWy6d%2BDIuO%2FVQ%2F9K3Wi9PZHqf2efXdQIwccF36oQLcMM7vAYA4R7BDH4RWAHYcMef5%2Bgew0dJFzSgd%2F78ebvHuo3pQIMfYfCDTgRYSPli3qIb95jnmK%2F4TnshPG2EC3%2FaTUxjF%2BQB%2FnYvwlAO2mIEsJE%2Bd9LlDv3hGjgwcGDgwMCBgQNXOgdsNmPCY%2BJjkosTI5Mly61VtVbHKdjeAQL7vxBuYBqMeCzNcsXJFTfoxOWtOGly5wfowJ8fYS9dOlJngKS1Qw6J6azL2aQm9UsVaSUVe4axPKW1VM2VpJ3WFZYk%2FFwCkrJVkyvNUWK8VKaFOpZhk9wOc%2FQpC6USW%2Bsm49TAHIAPfXt9AJwdSBWpEwnVlYGbPClUJpLhuHykln1861oJgIWAxM0K9etWi7WEYM4EV%2BAUpFY9y8WeZoAu0ic%2Bpje9%2Fpf1b3%2F23wuBobpDvehF3623v%2B039J%2F%2F8KJqQCGYsOVwhEv8RuiA4VQxwcMSMXUVTyIDXuApF3yNgAzAwnu8x3omHGANP65Y7zxH8EacCMgA4ZE%2BQI30uBMGd8LxzjO%2FCOZIg4v3KBWMeTGPnT%2FsrSMceaGtIFWEFnnkxzP0ohtReScOF3nkmbiEoU1Cc7dshIMWYbhiXHsZ%2FgwcGDgwcGDgwMCBK5QDhpGQgDB5Iv1gYp7P%2FfwAKkNsMq1rFWEpLwI3ystkGH9MkEzYUYIS%2FYlPmN3JGD%2FeucrRyPfH2QlWAFji6k5sI1%2Bi%2BXJhkzZhHRt00sFILHm26vXIr3q6Jnmic2f29J73%2F6kL1%2BqL%2BuWf%2Fwk9%2FsnP0Nve9UfKi7Fm41wveNHPaF4jWyOdpV7wnd%2BpSban83mmz7vP%2FXRJ0iVbq62krNGLn%2F9CTZNCe2mi8%2Fvn9ee3LrUAgbH61671rGc%2FV0l5ThfKT9NTnv5C1f1Ehwj4bI%2BbW7fghC9HG5bVWmuwTT%2FSn%2F7XD%2Bvw0rH%2ByQ0H4hxxn431vB%2F4F9LJkT72F%2F9V01QqkkKzyVglUk5nlRvQTaS0zOwAL%2FsFWVtmeTyCoAhkIvCBbwbOA%2BhCchrrkDgRkBEvAh2ktbsAMYKyXVrEuxwMRVqEi4CJZ8Lt%2BkE%2F5iGmw512yJ0fF%2FkjX5FWbDPQo52SL%2B4RTAJEed6NQ3skPDQiHT42yANXpGkvw5%2BBAwMHBg4MHBg4cIVywAAdkzwTHxMkP1TOxT10LBMC1JhkmfDThOU8X3L1ydI3yDMxEjdOkIRnAmWC5eKZSR13JnOeic%2B%2BsDxLDDCiqgTZFLIvk1GxxDZBdYlfHJJ10xMrpUmvp9%2F4RH3djV%2Brrj3Stzzt6%2FXUZzxXxwicktpA26tf%2BQY94znfq8Ojj%2Bsv%2F%2FyP9bM%2F9ZP6sz%2F6iK2Jvug536G%2F%2FNBHtWxrLepj%2FbMH3k%2Bf%2B3kP06HN863e%2BPJf0Gfc9W5aV7VOVit9w5OfoAd%2F5WN1K6Cs6vQjz36O%2FubDH9GyaXVL83H91E%2F%2FG2XFxMAeQZKM5V6O0np5JuVIbDts61R1U%2Bgud%2F40nZ2N9MEP%2FzfN7nCVHnPj1%2Bnhj3qUtF7ZtjzUrlThsAIKnossVc4BCg5AsO%2FOlrwzpXmhcuyb%2FQOb7BYBTARp1AvP3COwob4i0Ip1Ff0jCKSOIlgkDDSiH3fcYp1H4LbrRmZifIAU15kzZywe4aIf7cTbnkuKCRfzHumRV654321b5AWQFvMS2x%2FhY7uMZYMebRr6kYYRHv4MHBg4MHBg4MDAgSuUAz5D7khxdsvBHro0dRNfTLwRgIHRWHKNkycTJhcTLZM6FxMs7nHCjJMpdHaBBSa%2F6hZJHzQwV9H4kifqRxr%2BZxrnpl44nOrMQZC2w%2B3%2FevWr9dhHP0hqFrrxUY9Qm2QO6LBmgSTt7AX9ylvfoHJ6QddefY2uKWvd%2FGf%2FSZp%2FQq9%2F0%2Bv17O95se1PQxr3zG%2F5Rt301x%2FSX%2FzJR9HPokd%2B3RP0NU96okS%2BkrW%2B8qseoao12Z5u%2FuDN%2BqWXvVrPfcHzVSMTTCpkcFpXR3YClfLXqEkBoKZ9OFnrGBXepclYTZ3oF1%2FyCt3j7vfSW9%2F6Vt14440bsLRRzxYewDFd26npXHK1rlbq%2BlrzsO%2BxqX1vHOnCZ36xHqwywp8IhGK4WDcAHC6WLHmOQA23COQjXfxZxuQeAdQu3Vi3MQ3CRTfoc7GPcjePPEOD9sXHBfmi7RB397r8PbY74pPP2P4oewR4xIceeeAiTuQN4Yk7XAMHBg4MHBg4MHDgSueAATomNiZLJj4mRuY49Myxhw59auyfi6cFuw7AsFX1wR46JsUI1OKkCj1%2BTJ5RMhMn1TiJ2sTa9cosJSR8HeIn5FskwFFas0SxmK%2FssIQxO88M9CUo80BahGPSaDk%2F1Hi253vSFiudLFa67xd8kS5cLa3aVtPxVH%2Fzl3%2BiRz%2Fmobrlox%2FUrZ841Oc%2B4AtU5nvK03P69M%2F4LPXzE%2B1zbrZf60P%2F7U90h2tu0Hg80fnRGT30IV%2BipOPwB5KjSllR6JrrblCmwk6sjnPp3NmpVgvf81aMJvpfr7%2BTinSscjLVKC30hje83TxXi0v6i7%2F4C%2F30z71Kf%2F3hW%2FTAe95XyK5%2B%2F%2F3v17Lr1YAxdrAMUASYvJwfazJyiSd75yZlobauTH0KfN89iAKggT%2FwHn4DvggDoIn1RXiuCHAISxuIgMs8ycqpttFv9sJR5xFUcY%2FhiAcd3mN7IA3CkC%2F8IngkLPlkuRWgiB%2FhuPOLeSMc%2BSYsd9yjP%2B%2BkFctImtDnEA%2Fh%2BJEubpEHpMEz8YZr4MDAgYEDAwcGDlzpHNhI6JjEmSCZ%2BJjjWHLtTEmvFxF9cFzrCpUPrraECRQAyGRMfCZIfkywTJi4Axr47U7AnoYv1bH0hW67Mi%2FM6oQJTJKcjWJShQLhXuloZNI58%2Bsb190GBGJSJ1MsBWeF5ivS4jjtVHvjkcYHU9tTN%2BEkRI89Mgd%2FGVKoVPqt975PR%2B2JFl2v41Wt6uiv9Ll3u06af1CPetRDdOMzn69LXaVbl3P99jvepjKtNR1zBoL9e2v99V99xJnTd2qrY80Pb9b5mVSAvtpcf%2FXRm1T3lep1q7qr9fCHP9ikfZ%2F6KWc1maV65nO%2FT%2FuzqZLViT7%2BwT9XleZ60EMfJPTtuQ5l3yMHOTDeZLanio14PdvpkFq62bCoQgYJF3yPkjDqE8BCfcBnLtzwj2AvunGnjnAHqO1ekQb1ycU7aXGHHhd30okgiXxwReAU65%2F2QjzS4I47tDhdHelbRMkAGn6xPRH33LlzG6lhpA0d0qWMPHNBH9Uq3PGLbuQzgkro8huugQMDBwYODBwYOHClc8BmOiZVlABHiQ2FYm8bS66cam2Q2gUpB1KPOAf6BJptJl4mXCZIJk1%2BgDwmVCblOKlyB1DEiZQ0q8pPMTZmZitMsAC6wm3LjsvCgRte2P2anFfdFcqCmVflUzv4kLVrjZjP%2B0yL1VrV8hLyM7uaFUunLvk6e8c76973%2Bzz9yx%2F%2BQaML2STYmRUSsDTXxUtzpWWhJWiqbnXjE54kLDssD2tdfZcblJYjvfmNb7QDsX%2Fwrvfp6d%2F6g5qOplod%2B4qx6QKuGuMbB4RJelxI9epI5z790%2FT4Jz1eP%2FZDPyCsh6Wjs3r6079Tn3%2F%2F%2B%2BjCObfUQcUgIY2iuqruVKal2cTtm61ZK9S3cCFBhbfwHZ5z8Q5Ao375AYAigIL%2FEVARJoaPoCiCJMLxIwz1BhjifVeKB13cuGI65CPSjO7mEP4QnnySDs%2FQvfwiL9Djgh7liSCNuLiRJ8LE9CKN3XLyTDiuKMUjzQguY5zhPnBg4MDAgYEDAweuVA5sAB3Aikk1TqAIOqqmMnUmgDj0zjGJMyE2DWAgSn%2B2G%2BuZZJmEmeC54p2JM06ou%2B4APdKzSR3zXmmiFJTGBchIJmqSUvXJrQbMMBsL2NK8V1LuK%2B1ZfsNtokWbaT%2BtVJjpiJFmZ6%2FVpD2Ua2aT8vEeAYUNWs2u0qve%2FA5V80PNkkzjNNEoS3Sv%2BzxI1TqVxjfoxT%2F04%2Fqx73%2Bmzo8nuua6a3XjU56uvbLUhRlmNGZ6%2B7t%2FWz%2F3735Ck3Sspz37xXr5G9%2BsdpFpr5TWWIbI0V88UtJlJg1sUTKslYoJalGm%2Bt%2F%2F1b%2FWPe5Y6C6zREl6ldq9u%2BiNr%2F5pnZU0yzslfWMmwLp2pb1RrkmRquIkcJspKZCEcjYj0aU5ll7dnJozzkFLBErwN4IhngFFEcxQL9RXBGnEp37xjyCNZ64I8GKdxjtAD%2Fr4R7cIJIkb06dtkB7tDHfSpE0QjzDxggbxI9giLOG4R%2FcI%2FgCxERRGGrHchCUe6fGMuhZoRokf4YgL3eEaODBwYODAwIGBA1c6B5J3vOMd%2FX3vd3%2B98nXv0OyO97LyfMUXXi9wi1tRNWOtNvEqYbebXI1GwF2E6ntX4hon1zgpQyxOxHHiZCJlgo0TcJoCIgnZKRtLxxcvapJyWpQDBSdY59RKB1o00kHOqmkt1SdSWqjJ9mxvWVkdmTSvSUZmm3WcoMit0Toba9VJM1M716scJeratYnQsF0LSI1X2yXqkfispWnJgYy12ixRlmbqOw42pKo5nStpBBOwx5qXQRyHumD%2FIeuaEQbCvFS1sC%2FWpo2yFL1ynSpOqmK%2Fq1ubGpMmm2lRS1Owomo1y4UODs7qcH5ievIa0802VgpKNBu0mDijIlIV05HaFcqJm41ElL1wgBcu6oLfLnihDuIF6CE89UEdEY93LgATy6CEB7RBhyvSj3FwA9jFcBE44U%2B86Ee9716Aqwi4oB3bBnfSAFxCg3jQiEAu0o1tirKx%2Fw56XMTnIjzPxCVsDI8fz7jHOBZh%2BDNwYODAwIGBAwMHrjAOvPOd77RVVj9TEE4uHoRlMjuLwPascEIzBzwBEJJeaY6peCZJNpr7BM2kyaQawQO8YMLEPU6ccZJnEmWS5%2BI5QeKGtKnulKcnKvCzFUCAQKEkL9SuK50ZlarWK%2BWYRsjP2NIrVFLAIBlGgtNIo1xaNJmyAsXI0oStczwUvcXp2J9HvnLOz3K6o1WrMfjQzIilYJmOSBNlSWN73%2FokN7UqfZDwWOax%2BrBcytZ900JlgcVYXyAtgZl1pb5OlARFxZkt7qa27y1D0sYSb1KaAmXyN2ml2vJQaDTZ1yICMpNc5qqbXmhCMcRauP1WMGHVNhplfgAiAh5AGqAHQIQi58jvWB%2BxfuB%2FBHoR7EQwR33FPW34xfojLs%2BALOjG%2BuUZN0AgUr%2BYRqQb77iTL4AUICyCvJhH8kRY8h9p0K4oG%2FGgHcuBO%2FEAhbjFCxrQxS0CxRiHO%2BGJRx52yxXjD%2FeBAwMHBg4MHBg4cKVxwBAZACCeCGRC5kKYAnBDQtUiHQlKh12BCNKPrXkpwjOJxkk9TqZMzEygu5NnnMDjZEw6Tef0AHPNCnUfiZpVoyyfqleh6agU%2B8bG5YjNbr50iq3Vnnwy8ZNZlmv9cGxWcELXT4aazIaDFB1LuEj9Mq2x30ocAmHsPoTt1DrIQ7CGSBApT5orTQqtO6Q5INVGq8a38gnrDXnCBi8sjCHT0khrJUBDgO%2BEE7B2dsNoNUs%2FVZpnqD8B7BYysWQTDvTCR9uyR7WAtXO1TR3OAAcLEWYaY2OOVmWw5xrBXOQ5fI6mwEgc4AJIisAGtyidoi6IRxzu1GX04x1%2F3onPj2fqNF68x3iAQMLE%2Bo3PpEs7wx1QRvj4EUAYLtxiOXiPNEiLPEWgGNPFnXLFMhGfa7f9ESa%2BE47wEbQSdrccke5wHzgwcGDgwMCBgQNXGgcM0MUJk0kzTqh1MC9FgeIJ1zhh4sbcSTwmXa5tPF%2FqY5JmAuUXwzDxx0mVuDxzkYnUHlNlOSKyVHnhd5SaMN1X9VYvWd2wz8qibsx2mQI4sFXp9mCBTFAwKws9uutKk8A1ajRKXV5mByzQtedCQk36TAWHLnqpnLC82ZtEzZaeCQQ6S1KT5lmpczQsu0UIrIxNVKggMsZbk8zsynK41gpoPKKQLLuivQ6ACSMDM22BuzN3FBAbsmswOQbgNJhnZsQsPCAYFBwkgtypG%2Bov8hQ3wEv0o34Iw48w%2FAjPtVsXu%2FHxox4BRPHOM1dsCxGMQSOmwTM%2F6p3wPHMB4HgmTmwvpBdp7qa9G4%2B4MTzPu%2BFoU9Etul9%2BtwDhTwwf6cW0d8MMzwMHBg4MHBg4MHDgSuOAzc5M%2FEy23OPkiyoMTlnWjYMCCsbk13bsyTKBmElcCB%2BBQ1xKi2F554qADgDBc5xU8QM4ghFaliGZrDmYQTz04PUsUSbCazJxBceEQUceUkMLDyoCNfUulXMq%2BJilVQvjoMkfwVAekvfUwVY8LWvgakNuA5dgkkES83e6DqccrTVdb7ZeWRZNkKxluQHNlFO6gB9PFFRimahNPsfSNZ6IyhDjVZbGWLmwDGEo1moHWR4%2FKQ9725AGIiFFrQxB4SsAC5ASeQ1p%2BLwL4KgrpGQRjEVQA8ACBFFfu2ALGrE9RODDciXXLpDj%2FXL3GDfWuUUKSoUjLfzic%2FQf7gMHBg4MHBg4MHBg4MA%2FnAMGGQBznGBFdQmA4ISzCAZnMMnlEhAAFBMwS7BROkY8rjjpxyUxwsW9VEz8hMMNAEFYAAXvgACAI8LAzEV06qql0rBUCRBasVcvAC7Cox8PEJDZkdeAlkBXXaou2Qi21LJcabkLfzqJvW2lkPkZlFJPQXhkSbavpbRWnzaqOeGLLr6EfXiFOArhIMtOJNiePBjXaKReI%2BVpq6ZamRmuZeOgLbFTlsCtIITjXndaLxrOpJrQrlmRJiFWtkQ7Uappj9oSbH2RfqXGwFyuhIC9tDxemdSR1eOqrdSqUpZvFeRGcA1VeAxQwy0CLpYbqeMI%2FAgTAR71B2%2FxI3x0JwwXdRmXK2M9EoZfBIe4E45fdMctpscycPSPkjQjPvwZODBwYODAwIGBAwMH%2FtEcMDjBxMrki%2FSGyXZvz5dUl%2Bul60Lrez9BgQSoY%2BkTiYxL7lBfAgiIkzNAgHf2UkGP5%2BhGLnEjLADAwUXPdjOTNIGu0O9me9362hTyjpFE2b9Wk%2FHIgF9dLdRjwcKWeylCUBx8GRsctgVBm724xM9RlBU9iMKiSIyUXPsbpByOhb12%2FrJxjTvIwJI9e87KHBOvdtYhLocWGadqnQ7StKTMNZpO1QOoOAHKHjyWbA2xJlZsgFoeECzKhV025xKwrmo02Rub9A7BKQC8KEfK8i1gApRFAAaPqVckdSjkhe%2F8eCccQItnfjEO9Y879lZ55op0qEt%2B0T3S4x6BHOkB3qIf8XkmHn5IAfHnPcaxRIY%2FAwcGDgwcGDgwcGDgwD%2BaAy4fWq0MHDDxRklL07SajCa25AmCW618QzthuEajLQgAsAEIAAmANCZrLoACkzduPEf6hIvPRZGqSAEVpTpbOs0M0DXrhcYjDHxhqz7Vqk9MAwgoqyh7dfVcSZ6ZVM6kXOgDdmhnOuuQHZpUDSCGh%2BGy1CR3yMig6ZYWfA9cENpZ0FxuUoy0bQ8ehaHYONieucbcI%2F2uGGvdu%2FUJkuLQQ8%2B5CFTaURwkkKampDJVJUWaa5SUarNUlVKtw7GHChUnSNYqqTbtKsgUKUCr8YjTr4XG8KtMtH8w1mJeablq1TYuIUPpLlfkL4CJukBCh8QUQBV%2FvO8qB471DuDm2gXh1FWsd%2BLH5xgONy7Swo%2B6BvThDj3ywYUfecOfi%2FzGtmIOw5%2BBAwMHBg4MHBg4MHDgH8UBQ15I05CcRCkNK2wshaJYuGkbpUlm9lyZmOOSG6kxYU8mow2Ii9IXQBx%2BgASWW5nA8cONCRywwDNAAx1v2IvlFGrXg378MEI%2BRk%2FbUn270hogkqR24MFKWZ8oG0nH80oVBwR8C50BNI5QbICYC5gMINo%2BtsAilmJtORYAiYoSO9vKcQaLaaBuQyNI5sJZiSC1I7bLzgiXoYWuXbFwavroVmvHf6ZgD8lc1MSC9QsIeXS1fWt66Uq5QudsXNhyL%2BrtpuMzKpJCk2ykPHc1IHXbaLFc2b5G6opfgY621pdE9xCthqVR%2BIs%2F%2FI4ACj%2FcoxSOurQ62FETEsEg4QBguz%2FCR8AW3S9cuGBuEbjhTpoo8uXOEivtIdLFn3bBnbhR2heqZrgNHBg4MHBg4MDAgYED%2FwgOGKBjwo0TNM%2FRClOZlyZt2qXLXrqwEmdAYbl0HWBM3tAA9PEDEDDJQ8%2BAx47UZpeeA6Pa13jTTKsu1Ut%2B%2FiWapgc6k%2B3pYDTRwf4F7Y0uKE%2F39S9%2F8Pul9kSP%2B%2FIv0q%2B%2B6a126CDgIycLAAsgzBz80Ko6Bala8DasZ2EDqOMABqdhAVdi71xEg7u5jUpb8EMvH9K9pbT%2BG73%2B5f%2Bn7n7%2FR%2BjDbIsDf4H0mlZqEgN5x7bnrlDbsL6cChthL3jOMzTOMo2TQp%2F%2FuV%2Bgm05OtAKcmjTxyJaVW%2FbT9UgUUYGSKWXfYpqr6RJNStSlrFVkVo0GjqKELfKfutitX8AUboA86guQxnu8cIMGdcZzpMP94sWLBtLwi0Dw8PDQ0gW4RzdAGjrmiAN45%2BJOPmJ7IOyuFDCmP9wHDgwcGDgwcGDgwMCBfzgHDAkwATN583MAsFWLkaJxl%2BW0YOqr65DcsHyWbfScMXHHH2GhB8CDVnyO95gOd8AEdPMEA%2Bq2Ncziff03PlWL9hYdNh%2FUM7%2FlRj3oyx%2Bp%2F2d9i5bdsZ773c%2BR0kp7o0xN78qAAXRbDIdGZLduEdnB8iqHJLhiOF849uVWhGYR4JluO1thZfMbYAQ1IwbfVBvQC%2Fv1AHMG1RZS3qpvajVJ4TrqSIh1UxTjpXacwWgQIyvHGHTVi1%2F4PXrXe96tw%2BObtF6d6E7XX6cnPPlppqCEcKazGX156NlDsbO5JSqyXAmSPlSvpJmK%2FP9l702gNbuqet%2F%2Fbr%2FmnDpVlZAQQisSvaLYPCEgREBElEYQSAi9iSh9LkjjFbzSSHNR331e33iKj6vSCCjNpVPRQXJBpFEaBYmIIH0giWkqVXXO%2Bb5v92%2F85trz1JcQSIAxHlay1qh99t6r3%2F%2F1jbH%2BNeeac4bQXRAlEsSKtQB%2FzsFBnFgHXx%2FIGs9OrFgXpKfU93YuVYX0Ud%2FvLm2jrato6Zu26%2BSMflhfkq834%2FhvgDvtfc5WMf6JCEQEIgIRgYhAROBbRsAInW%2FkbM5s4AhsPAoE6tAedWgfrFRR77FX932nw4cP71m8IrUh%2BcbNM5u5kwnu%2Fux1GKtFrdtX5kB37ytcP9rtqMhb9WlpkjgjXVCboVWPVUBuMRmM2FHGebR2QGJ2ldQflvodKWlNw7nbSgusV8cjdRMoXLstpZVWWJYiyRuZG3FUcSOi3culYSWME3Z6D%2B%2BVaugnMt2ozyqdqp9sKWlXmo%2BGsxYWDD9wQ7CsndmpPRhlL6129LY3v0m%2F%2B4pXK5ufKE1W%2Bi%2FPear%2B5i%2F%2BRh%2F52GWiWd9nmuTBbxshwliotkdFizq7loZOkOs0ISxWQAZiBbYk1pQzck7UHFsnWrz7eqyXQcxoS3IyRxvINxeJu68t79T3MvIZk74hglyU%2B7uXudrV52sdxz8RgYhARCAiEBGICHxLCBihQyJz9OhR24g93BO8AHtPrFphcMRcZYPnwD8JUsdmzQbOpuzPbOwuvXEVHBs6F%2B2dzNHOJEOm7kOaEyREpvyD0OGpNxuUYikaOIplmYXBGD6q6Qbd%2F4FP1P7soLamB%2FTBT%2FyzunRDKnq99Y%2F%2BQGc%2F%2FBy9670f0bRMdcLmXL%2Fx4leYiG7YWUn1rn7jxb%2BhJJtqPpvo9NPvrm2CZPB5RmgGvfAFL9Ys36ciSXTS1kFddgS3xOP5uCTTf37KM5SnJ2sjvY0e%2B9inahgwJMG3HpVSCYtdvmzoNQ3mJaam%2FeQnLtQll16mW93qNqMVsfQbL36pCCR70ec%2FpyIPcsFqqFU3u4YNCPVNo3x0Q1KW5sI4HNMbCZON5T5laDUSPMg268IakOeJd9bB1wtDCZ6p62uHFM3XDyMGnv08JOSP5GvJs5NE6tEHdSl3osj6k0e%2FzIV6MUUEIgIRgYhARCAi8O0hsCeh4xA7mywXhIR930N%2FuVEEGzMJYRwqV4ggfuF8E4cQsImTuHt9l85wJw%2FSwGYOeTS3J8VUSZoJqVmGBAsrgmJq5GtVV3vhrSY2W2Oamkw39aSf%2F3k97tEP09BcrGc84RF6%2BDlP0RVEaSAEWJrpjW%2F5kJ7xa7%2BjQ0cv0icvfJde%2Bfu%2Fo4%2B9%2F1OalLV%2B878%2BSx%2F8%2BKe17Ad1q4v1k2f8J93p7vfWAn7RNnrly%2F9At73z%2FXSkHzQ0l%2BuFT32E7nvfn9YhDsN1jV70tKfri5dUWvSDdtuL9Lo%2F%2FE0Vs7kuPmLRxAwDE6sZZJlwOYfFasP5sj7RrU77Xu3Pe115yUU6eJPT9OhzztM9731X5dVFFjVjSAhEVmhI53Yor8xKMyyAZO%2BbzdWYexh0373SLGAJaQJ38AVnLlefUraeD2ljDbweE2Y9WKNDhw7t1aUNJAxSCGknkbeeKMfogd8Oz5A0l9i6hI55QOhJjM04EDvuMUUEIgIRgYhARCAi8O0hYBSJjZZNmM09bNyhU6xci3LcxEcVWppCyBBidbZBT6fhzBZk7sCBA3uzYSN3AhdIYiB4vulzh1D0SO5aiCRMirBZqClNd2uH%2F9n8SXtyHGOaiaq20Ste%2B3o97Kx7Sf0RPeKhP61ytmUOgc2XCefM9p%2Bq1775jdqaznT7026jPG%2F1hc9%2B0lyHvPFPXq3n%2FcZL7RRcmgx6xtPP05cu%2BrI%2B%2BvEvmGuSc5%2F0eD30YQ8MbhUO5rgAACAASURBVFG6Rj97n5%2FU7qpTMZMO%2Fdvn9KbXvU7%2F5bkvNN9z%2BFNJulbLVjqwPzg3tiNtJt1EfSrlRSqLI5HlytJaRV7rz%2F7sjbrNrU%2FTO%2F%2F3%2Bfrpn7mvtib7VGDpizrY1N6JCs7ctYOWi5VqOh2klbs3QeU6gXAFgwWwAnfWkPWEXLG2TsY8H%2BxdYkY9LhJ1WRPi%2BvJbgLiRB9GjX%2FKcBHJnPPrhmfVnvWnDu9enDQnCR33euZgDeT62VYp%2FIgIRgYhARCAiEBH4lhAwQuebMxs%2BzyT2eKxcsVa0c25ta5s75IFU18EKEv90JA7MI3EJZSEPaRGbNhs9fUMw2Oipx6bOZh6InAJxomvrfvQNZ72F0GHIhGxmjIdUCme6Q4gigfHCoEolHorNNmCqru51xr3P0E1P4dwcZqdTfenL%2F6ZHPOZB6r56kQ4fqnS3O52uA8VcSXaSvut2P6hqsS21O9JwWJd%2F4eM65YSDmqUTnTg9VWfc%2B0ylk4OqOMKHK5Fiolvc%2FCSVTKrAp9xM9TDRVXUwcM2SSre%2F%2BU20hauX6URlNtWfvukvzLXKtL1Yn%2Fr4Z%2FU7L3%2BNvrLT6Yd%2F%2BHtUzmp98p8uVanbqq6IZZuqahfarg%2Bhs9WkTDW0dTCWMFzCOuFsmATOjr9L0JxMsaa%2BrtT1Z8iaJwgWUjTWjHzWxokgebxzuQSOO5eTOlfVMwevyzx45r69vW133hmLO%2BP4HH0e8R4RiAhEBCICEYGIwDePgLECNng2XDZnTxA3%2FKSVRakUtdgoWaF8tWpVlsFKEUkdGzabP4kNGtJGgiAguaH%2F9Y0bf2m8s6mbSjCfqMAilNhdqFtJdmisV72EISHdkiw4xWRujImA9cRN3UXDa5EVOq2OLlRSsW003TdVOulHI4g5CkUNqHOzRFduH9HGgVJ%2F9%2F73abdZqG1xoTFod%2FcS3flOd5Dape59r3voGU97ivq20pWLo%2FqrC96rNi2sPzPi6Cv9%2B6VftkgQxC7LsxA2C05pR%2F7SVP%2Fy%2Bc%2FqaL2tplqp6VZ62JkPsE%2F77tveUjc7SXrWs39NGyWK7U6f%2F%2By%2FadEO%2BtG7%2FYjZU7QVhKnSFFEd7j%2FwDVjObP7TIqxTPoZLQ2pKgtSRWAvwXccdSZqvgUvnsIL1ul4GeXM1KGVO4GhDckJmL%2BO7%2F24gap7oD8JGf%2FRDn%2FwW%2BG0wL%2Frheb2Nt433iEBEICIQEYgIRAS%2BOQSCmGeUsLG5svkincuyxCwovbtmlKZAHqbTcIaKTZozcGz2kDo2%2F5AX4of65r9OEuiPMbhITVupbiuzmlU%2FOhZGzNYGad%2BMA%2FptsFQ1noiTtiOHlA2NsryUaYSbRpNypnlfagKnKFodrS%2FX0XrHiCAcr6ulgrZtqpPvcHt934%2FcXv%2Fnb71IUKMBTebor85cui2WSlZwp%2BCoV6tKj%2F%2FFx6rOGmHgetNbnaQ8rfXmN7%2FRPJP8y4f%2FUeec82SpPqqtkY82nOWbb0lZYTrXvGcOnIAbNL317XTfMx%2Bk333Zf9OkRna4oec%2B63n63tNvpxNuE%2BaSDtJmcVAFTu3wNMzU%2B0a7VaUji6NKzFhkUN9x9XvECNJEAnvWg7RO7Cxj%2FIM0jXXzOtwhWb6OPLOeXE7aKLs2EgZ5ox5jcbG%2BkDrvgzzK%2BS2QTz%2FcyYspIhARiAhEBCICEYFvDwEjdAMH2UUIqV5FXpoFK6pQAm%2BlWWG%2B4pDmENWhRUw2%2BqGzjTmwPzsLl0NeMKxoWhX56L8uDaQvbOBYPlamVsWHGiwFtxtBvjTG7eKFc1dER%2BhLNX2u%2FRMkgOOHws62bqYh3VBb74a2ky3tVIPm2aCMeliCJrkObmSj9zl41SyIzrA%2BTQu94c%2F%2FyiRIeZKZZCtPprrjHe%2Bj3Z1O2jpJL3zxS%2FS8579AabZPNz%2F15vr5XzhXk36pCfOblnrP331Af%2FDy39ckLfX0Zz9Hb3vbn%2Bpg0ZnrOvOoUmRamno4EBZUoxuTxMipsi391u%2B%2FSjc%2F9aaaT%2BYWBmw%2B39I73vKKoHEeIWhWlQbOFqJqRZvcBR97kCuLY8u5R6sbpHGQOFSf3LkgT07AeIe8QbycnPFMHutIXZITL8poAzGDwFGHC%2Bkq7XmmLok6SFq9DvUhak78uDuRoy79eh88xxQRiAhEBCICEYGIwLeHQHL%2B%2BecPp9%2FxTvqzd7xb05vdyXo7%2B6duIWKhIt9huyV2QnDWywaeinP7lPHGHQ6FUrToE4t8sILRpCnczshfnuOLjHNuGEKUyonKQLgtztb1HEpLVE4gG0sN%2BH9DUke%2BcNo7USe8uB2bS9YvpSFXm1EmTcy0AalUUEUmyRidQBObP9TS4q46VgnkhZlTEkgJ3%2BnflODLjpTMwqCoagnuMNad4qcO0jQ6XU4G%2BktUJ4aU9XpM7gR2YYzAPhmF%2BuThpHicVBJw9FmFOLPBqR1V8DVXFjgTluB1kCkuCBLJyZfn8w7B8jvPECvKPc%2FbeR59XVt7yBnEkIQ0FjJGH%2Bv5Vvh1%2Fvg8vl7%2FlMcUEYgIRAQiAhGBiMA3j8AFF1ygffv2jQIsi3pw9U7YYp1rcLctd%2B%2FhWJm3wuEwsUdXDRQrNHZt2tA1aptKbdqb2jDr88CekDolgdrAFzBssIR1KP7uki2TKJVFz9E3tUYbITkbVg36FIiTE7nQHIpHCn%2FHvKtxhiA99NrcKd4jYRA5TxQg1TOzijGTeLNIKffqhP4gwV%2Bb3NOwl9DX2sz2Ogku8LyWoTKWcSvyYz7bXAKG1MslbLRz9amrM8lzsgQB8%2BR5ECzaeNnXa0896jAeZA5Sh0SOcbwP7%2Fva7tfV%2F7W1iXkRgYhARCAiEBGICFx%2FBEbR0bU3gEiEC6tTCME1yUkgY5zCmqJuNQLSWeaq6e1cGme81DfKcWmRIWnDmAJHdlyhvQnA6DpFolaoT3Bm3Khf1SqLqYaE0F2psU878cV5N2Zu8Ve%2F4Sdc%2B4cdZ7lOppg2z0jGIFWcT4OcQapQkZJcCgfZciIFEXMLWOpQn%2BQE7rraI7VjHEgcfbq61AmldfYN%2FlxX%2F9%2BgaSyKCEQEIgIRgYhAROB6IHB1NgRLcvXg1RqP0p212sbd1iRbDe4zCAmWp6ZQLCYEu8fjxqh3HUyJqGXTKSvoCBVeHwjj2G87CujSLFfbdEonQeYVlH1jE1zV2eNe7teKC6829%2BP%2FBRIFeYMYOUmDVEHiIG4QM8gWBAuyR%2BIOCSOPtljArhM5J4DkXVd7%2BmNcyCIXY5Lo9%2Fqk69P%2F9ekn1okIRAQiAhGBiEBE4NoRMCo1jGfDrlmFwsC1TB%2B6V7xGpSyvbweVRW5nu%2BoW68Veu7uHpAVhE5DQce4uMxXupMhUN2ZCarSs6xqtGiRMvSYYhK4w0MiVFHNTdXY4z92bR5gC9DJQzPFs397MbpgPEDO3JOYLIVVO8vz8G9at6xI36kHaIF0QMCd%2BEDhivEIASbShr2%2FUnnLmAEmkPmM6IXRyZ519nT%2FX1f%2FXaRazIwIRgYhARCAiEBG4nggEvmYEae%2Fxak2DJA4KF2gc7j2umTqMBFCDdtIkz0zqtrWxT5pMpeVKKlCZhpQKiZKfVuNgf25kMM%2BRDkpZmWpRtUbYlk1rsVxpaRrfsQ9kfcemce3zHqveIG6QKSRyrk6FWDnJgqBRjnUrd%2BKtupSOd5LXdVKHE2jaORm7rvbeD%2FVpR4IQQgwhd9eVrqv%2F62ofyyMCEYGIQEQgIhAR%2BMYIjLvx1TdlI0%2FDeCQOIschNyKRJsGIYU86ZtFJeyVFomW7MNcaGJgODeQMC86JNN1n7Y5Wuxq0q1TBghS7B9S7w5BoaHuLX2pcIZGmk%2BAbDalf1XaBzDHoyOIyM4ZgTl97pu8bf%2B7xWQohIzmRc2LnfuQgWV7HnTb7GTvKaAepQv1KcmkfZMxJ2jdq79I46rsUEIkexPD6pOua3%2FXpI9aJCEQEIgIRgYhARODrI3A1JkegBkt%2BtxcIXZCvYZF6TNK2x6%2Bs1gS%2FcxaJATVe6MZ8qOGBpNvVwQlGDYUS4cOssOgTdUPsUClNOuNq2URqBiRKoW8mh8QPOmNH%2B5gXFrlUCBwnDHS1%2BYasG9JfyJhLxiBzLoHzyBCQrHXCBjlzAwbKaENCykc%2F3J3AkX9d7V0968QOEuihvnxe3wjv6%2Br%2FG7WNZRGBiEBEICIQEYgIXDcCI6Hr9%2FyT1Vigjimo5GBOhDnojcyteLTyoII1jtUlSi1EVbBORZJXJ1I1TdSmjbJ0R0mzq7wrpQ62h%2BK1U1Z26pHa4XvOcuy4nUUAMzcmaHIHqUmC57a9YSkcY8pemwrY539DukOKSH6%2Ftm9zIwXInV%2FUcwK43p5y0rrK9Ou1t4qjmvWabb7RfLyd36%2Brf68X7xGBiEBEICIQEYgIfHMI7EnokL6w8eOcjtQRKQDnvk0tLXf1mLPP0nR%2Bc118GTFUCdkVArYjLSNMmCWiP6SFWuwgIB%2Bcl8O3XL2tRz30IZrNTtNFl0p4MtldLZWpUd%2Fs6HtPO03TPFOZJDrzoQ%2FVThOInR3PGkWCJqULoxyzxMWq1s7%2FeUG8RwQiAhGBiEBEICIQEbjxIWCEDoMEuBikjouzbFlZKjPnvoOFulosdi0uKRKZpsfRbfCBhghtUKOqXZpVal0Fy9iylfLuKn38PW%2FVvv2n6Qfu8VNqN%2FdrR0RckObTLXWLo3rsw87WC170Mq1WS%2FXNJfqn971TL%2Fsff6xd6hGRPm32Ii%2BYTJAZJxhVuGHFjW%2FR4hdHBCICEYGIQEQgIhARWEfACB2H5Dc2NuysFeet0O519UpDW8usFaqF%2Ftef%2F4WObn9RJ97EYs2P0exTDsgp0a4m%2BWBqVuwgVpA6eq4aPeUJT9Tll%2FyDTj%2F9jkK2V87Nz7DUNcpmW3r9m96mhz%2FmseHgXXtYT3zsWXrT296pr%2B5IkxlqxiARHGWA49zp3KZuyturl61%2FXnyOCEQEIgIRgYhARCAicMNHILCipNdisaPZfKK8SFVVQUKHOvVNf%2FIanbJ5G20VW9qa3kaXHJLK0eghBIhvpPawbnvTg7rD6T%2Brf19K%2BXS0SC1O1Af%2B9aua7t%2FQCclS2t22EK1buZT1jZTM1eYHtMMROgwdukppu1I%2FJMo4bgf%2BZgTh9G20hYDBRRZ3w%2F91xi%2BMCEQEIgIRgYhAROB6IWCEDjUqB9Zxg4Fri4mFGsUdSa6zHvkoXXr0c%2FrA%2B8%2BXphtqxzNt1EstKkEqLRttbuxTV1fKk6AMHYZWXVFoaHNiTSnvGmk6t%2BDyZgORJuZAeFG3mpuPW4wx5nrV696iMx90f809CMGQhRBio0zOeFxKdHocEJMCJ71eXxsrRQQiAhGBiEBEICIQEbgBImCytr4npBMhoIK%2FMvtOJGY4i%2BOo2nQMO7%2BsNd8XJGdzIg1gaZpOpY1b6xOfu0xdkqute%2BVDY6K0vs%2BVlVOpn6rtCqkrzYhhN5E2kkFpX2mr7KX2qOlpzzzrybpktamn%2FtJZOpCEYPXdUFgoMYjcxCwjIHPECMNSdmZThdJFgd0N8NcZPykiEBGICEQEIgIRgeuFgIm3kgQHs4PyvNAw9DK3ZZR4RIe%2BV71cKD14gna216I2JInMy0lSql5WJiuz8KtYx%2BJfjj6MhBXKzE%2FdSg0ccYL9BCSxl5rK2NjzX%2Fhi%2FcW7%2F15%2FfsH7dOoJG8JlbUM81ww3wqOqdc%2FUNcjm%2BMJjT9fre2OliEBEICIQEYgIRAQiAjc4BIzQpcNESZ9ruaqV5plZvEK2Bk6xcYatq7Q5ydXXRB2QCsRhfae67ZShGu0WKicpDkq0UKoKx3F4poNtdbRP1dWNNFkoKZ2c4XG4l5Jcr3vVm%2FXfX%2F4nevf7%2F1Z3vvMdTNpm9hhFIHNQP9fAKkWoODF1LasRJXM3uN9k%2FKCIQEQgIhARiAhEBL5JBIzQ1UbUCu3ft2Vn6PAj13ZYl2Ko0Ej5RDVhJHavUoaPOAZJixCTFea1faXucOtb6s53u68uuqJTOZ0ba%2BsbXJl00pCrKKfKhh2lXWhftVCxQW%2F8w1fol550nv7yXe%2FWHe%2F0I0bQ4IBodPFXR9pzUrLH3vZyrHwvO1SPfyMCEYGIQEQgIhARiAjcqBAwQpeXmalHD11xmaaceYMhIUprV3rEzz1YG%2BWtdZd73U9JfZV%2B4Ja30GR%2Bit79oY%2FJgg10tVRm6tMQGP7km2Qh9ipGE0OrR5%2F9EO2b3kx3usf91R0%2BpNuffKK2ipvpwn%2F9PL5R9IIX%2FpqqttY9736GJkmpSVpqns%2F1uj97m%2FBXzAT3CJvNK6wPjzb5G9VyxY%2BNCEQEIgIRgYhARCAi8LUImFEEESIWi4VuessTdWR722plaSGtOv3pO95p0jjUnKhOj%2B72yrZSI1lt06nISynf1Cc%2F%2B1mtyv3CVhXHxHlRiANzr%2F2zNwWXJHZwrjQDh1USNLkatvUvX%2FmKlO1Xp9yEgahw6YOzdqQwRnAiTJivBPmgBXZdZ3qhbvwbEYgIRAQiAhGBiEBE4MaIgBG6IemVpIOWy6Wm5cRUnMRQ1XS%2FNFRGyNq2Up7PtLGVGuFCQoZVrPkUUW6H3OiMK82CUYTKYIVKLqHC8pxOEzsPlyNeI65rkttROtygTMvCjBwwni0Ch7taHNJR2RvWKXR1Y1yz%2BM0RgYhARCAiEBGICEQEroaAaS3bXsrLQmkyKEuCY%2BEGMVlSjCapmTIkbqMKtEWd6gKyDrFZIGZp36qrd0fxW6KBjpVrtWqDxA4dbV9rol7UtXZ9agHiJ5NCq2VjUrrUJHEYwHYWqMJnbNI5fxnHj2rXNUDiY0QgIhARiAhEBCICN0oEjA9hhDAMg3IN6utaBW5FRrPSvmnUqtDSyFmvpO80LYq9c21DmpjxAn2kaapJMVFqdC%2B1c3X90Go6S83IAi1qmpVKhtFdCcwtz9T1jalSp%2FPCjFgRzjExVMFfm5jssdy983XHsuJTRCAiEBGICEQEIgIRgRsVAkboULeSkjRX3bbiFd%2FApLSYqlOqnLNyFoyrM3cm4xE3M4wgBwbWQvo46Ib9alMrzQp1%2BLgbWuVZeoyIdVJalrLQYRC3NNWAxI45JOHIHc94KDFLV2dtTNNVreStETtrHP9EBCICEYGIQEQgIhARuBEiEDSWzcJCfy36TMV0SwVn2HA1h%2FsSpWr7Rhkn54gcYU5LMpnAbgTMzsNBxvJcPbK7flBCDDA4V5JKSZC0Jf1g5%2FM8D8JHDNehbRWcGwdSh%2F86SCVSP4jiHm%2FDGOKaBhF7hTfC1YufHBGICEQEIgIRgYhARGDUbGpSlOr7Xv2QqOrb4HYEHjZKxiZppr5vAjEjvBcn4wIVNBDNgEJSVXemdtXQEeZBXVsbMUyUabWslGWJ%2BbmzgK5KTc3LIAnErqMtXBByN6pc18YIOl4ymBhMz7zhxUWMCEQEIgIRgYhARCAicKNHwCjToFSr1Up5NmhzNlVLrvkU7tTXK2XqVKSFunowQwbCvNZtL47CQbQSXBC3veZloqZdYv4qlVM7k5d0nRHE2XSmZdMqKQo1fae27wTREw6GcVqcopoNRhCEEyOwBBLCjj9fkyKh%2BxpIYkZEICIQEYgIRAQiAjdaBEZClwu%2Fc4S7r%2BtVkH3lWL4mKstMSbMjk7pNStWE4UqkWZ6qM0YXyB9n5DgHl5oEL1cz5EHMRguke8jWitzaE1sMMtfhsM68B4cwYGnSa4DN0bSUWbgWKXRxlMYhMTSpIapfP8V3o127%2BOERgYhARCAiEBGICEQEDAEjdF3TazqdWkZVE64roGMGCX0tVYf1qAfeV5ODt9OXrzTtqDI1yvI02EAktdQulSS5GUJUvUT4MFW70rAj1Vfowfe%2Ft%2FadfJouOjS2T7FiHfQ%2F%2F9%2FfU5omms%2FnmiZzPfJhZ5vAbtVLq1WQ7vlaIczDS4qJBs3tyfjuFeI9IhARiAhEBCICEYGIwI0QgSChwzChg2h1Kmd4iUOlWik1U9dOmhZa7S7UNamGDGtYkAqsr65wPNxIAyfrUtUdVqvh0mSij7333fquE07VT9ztLmqWralz0bCafUWS6Jee8ES1XadF1Wi1PKR%2F%2FOiH9bo3%2F6XZPkynGFNgORskdIxgcjne0fsG4eAxo4kb4QLGT44IRAQiAhGBiEBEICJg1KwsJ2YU0VSVGTUYacpSJclSqo8KFve%2F3vU3Wm1%2FRgfn0i5n3CwmhDQpsWTozEpip5U6ONggmZOTZacnP%2FkZ%2Btyn%2Fk4%2F85P3lIpcy17q3fC17TSsKiUpzoxXUlbo9t%2Fzn3Thv3zGDC%2FQyNpBuvEYHYpbsozBDb3douI1%2FogjAhGBiEBEICIQEbixI2CErq0bc%2BKbFblZnkKSClyNrBZ6%2Bxter5PKU7VRzLSxcTsd3ZYmGKU6cj260YW%2B9xa31I%2BdcU%2FtrKQJBKzvzdfc333q00pPPVVVtZRWjTbKwNGseZormcw19L0mk1Jf%2BddP6sILL9T97veA0Duzw3%2FJaEZrr6GhiwldO%2ByzifeIQEQgIhARiAhEBCICNzoEjNDlaXAnks4m2iaeK3ys6aXZQT3osY%2FT5dWX9IHz36Gh3DQJG0K46WioMED88kIN7oezYDChZRe8ihSjYUTemzuUrJyqaKQNVK70T4Mk1XOe9XTtKwqd9oN30blPeILOuONpJuFDktdB5sxNSav5MJLFLOcAns0geLj7zq4b%2FHX9%2BrqzWa90bc9jw2srIm8veQVDYDQY2SuMDxGBiEBEICIQEYgI3NgQMEJH2C8YWN8P5mCY03EZrkdQq6L3HHqVhOlKMzvbxrE5LE%2B7LkSXgM18%2FqsX6wN%2F%2B25tEDZsgjuSXquuU2tUp1de5hYntqftQP%2BpdhaVlf7mb%2F%2B2thdXadlfoY9%2B%2BIN68IOfaFSFefQiDgWkZTBeZ9zOHKnkFh6MDwin%2BW44S3dD%2B54bzsrEL4kIRAQiAhGBiMB%2FTASM0OHQN0kSU7cWRSEIWzfGbg2BXVM1LTEgCOElFRbnNUVIZoRMs6mGttFmnirjkBtXkSvLJsJBCf9ydap3j5orE%2Bjjatloc2MSnBfjWJhO24Ve8Jxn6a8veI8u35XqDg95%2BKsbpVAwHUKDGZULsrn%2FSORnnN7XX2mvcM27t1gTw13bd%2B0J5rz9euQM7yPeIwIRgYhARCAiEBG40SEwErrUIjgQmovDceUkSNCMriGGU6FyvqlusW1H2iws65Co6wa19ULqawv7hRa1y6U6NzsKpX2lRJXUdKqqRpP9MyWlyFGfEvarVbc6Gs7t4UkYotb3utVtb60E38RZQhTZkL%2B2NEFex9R5GsneWvlx%2FbhG6o7r74iTjwhEBCICEYGIQETg%2FzcEjND1OPQdBs1nM1WI50iJ1KzQjxZSI9WoY2eZFts1%2FMzighEurCDw6%2BpSfc9NT9D33%2Fkh%2BrerpAoOhjQPK9lmYX30SlWtjmh7JdVobzGDXe0qKysN7VJZOZNWvR7%2BqHP06Ec8VFuTMA0kg8NoUWuiP5PQBRoXpFjfeVLnArMw42%2FjL%2FrkvbBmSETDdc0ev0ZSd80K8T0iEBGICEQEIgIRgRsVAkbo8D8335jq0OVXaGM2N5kXeUWR6WEPfKBO3n%2Bq7nKPe6s5cpl%2B5Ptup82NE%2FXBv%2F8HKzdqlaQq53Plea7NecCv6WoNO9s698yH64Tyu3Tvnz5TWh7Wj37XLXRCcjt9%2FOOXWrivsx%2FwAG1u7FOeTjXbupVe%2BJv%2Fl573q09Qhs2EneWb8TcwTLN2beGalnOjWqn4sRGBiEBEICIQEYgIRAS%2BDgImS8OJMNK2k068iXZ2lyJCBHKxLMv0xre%2B3eK34lmuzosQ%2BusYxVI%2FZOqzk%2FTPX7xcXVeoaiSEa2k2VbLvZL3yre8KVhBJoWaYmI1FiXErgrW00Rve%2BW4LHdH3udJ8bpEndqtWm5Pczuet6k5zGpCCRYQyV0smqdVBMfudTddU%2B159Pj5dn2OQLPob92u2Xy9bL7%2F2fr%2B2v2u2j%2B8RgYhARCAiEBGICNyQETCGUJalRYk4evSoWbkSXjXHNQghHbhzoC3NLCQr9hAQCNzPkRJ8yZUH1A2ZhWWdF1LWD9ikqlOhJsXsdap%2BSFQkrWZQyMqEcwR31aBCSnOlBYQPQwhpNsGCFWMIaUosWRuJnEDgPDIFRAlV7jUJU5jZcfKXyUdGdpwsVpxmRCAiEBGICEQE%2FmMiYITOYi6kiSB2SOr2Ej7mIHNIwJJURRbUoJSHyFu4OulxeKKUeGCcrYOgpInaoVWqVMVo1GDlODEZWmXj%2BTiiQJgWlXEGKYc%2FplLT4%2ByEwK1DsJjFWEMc5UvV0N9yx8KNMdU9B8d7k%2F4OPIxuX3CQ7Alc6gaXKwggw%2Fw7i3fGOwYg1OXqZL5g%2BLaqVW9BcAm%2BsfZlg6ERrH2J0TYmDE1IqMdJrYXWgGyHM5GWCW5NqMc5Sa8bXNWwjmFu1PW1p74%2Fk79eh%2FZ%2BznI938fyu5d5Pz438v3Z50Ibf%2Faya47rdbxfr%2B%2Fjcffv9jrrZTw7DuttfX7XrBvfIwIRgYhARCAicDwhcHUd3jhzMoPQiL%2BpSeeautbQQ9JCpAdclrAZZmmmoBwNbuuaDpInlUmharkrgsSSZz7t%2BiS4KRkC77MN1gLDZqpq4rPKpHx5ijQOg4AxJmyC4%2BORtBAzdorrY4jfMXLznQTdSQF3LgjDkOCJJaiKsyxRXbfmGsZkimlqJMlIW3JMPFeUpdIss7i67kaG%2Fnj2BGbIP0mej2qcein%2BZ1ixNN0jTRAkXNFAcqhPXQiZt%2FU75bRj7tRf74M65C8WC2s%2FmaA69%2B8JhI%2FxSfTjc16fE%2BcrSfTFM9%2FBXOiXejyTuH89QkYZ7VerldVzguYEkzmTRx364PL%2BHQcfgz4op01MEYGIQEQgIhARON4RuNpuBgkh2Q3OANlKEvV9p2JSKs%2FT4BR4rGcbL%2F7pzPdwrxaXc5MUAZ25KplOSzv3lmS5KuNeE6nP0MkqSXvrs67hcbnKSfBJlwydVs3CpHsQoWZlFYwcXk79yAAAIABJREFUdX2jkjnhf63PNckD%2BflOLwIkDOKLM2YIAmQBiSQkzmRw3aBydKzcjoQjSQalQy%2Fe2663s4V8R920ShBTJoG8QPpqtzyWTIqaKrE1ok%2BIrhMTxobA8A4pYx7rRAqVOokyEiSH%2Bv5MOydm5Dnx4pn8%2BXy%2BJ%2BXyet7eiZGTKdrY72NN%2BuZtKPM5QNK8LWSM%2FuiDtLu7a3fyvS3l05HQezsIpic%2FPuDEjjpc%2Fi0%2BX%2FpYLpfeLN4jAhGBiEBEICJwXCOwRuigHqj2eg%2BdaiQFJ74mNULVN6SqKyQbgfSZVAWnwJyBG0nGHhk0khM2ZiOEcDC4A9KeFtcoSGakssjNkAIUayR6GrRRTOwEHoKowkihjBxNU4hMrw5SVxSq694cHYdRvoPrMAyqYaZ4YqkrzTc27JnoGE0bJFBkoGoNRKZX39RSDtHgjGAqYEQICR6hbsAbjCG7JEgKCSICweG7kQI6AWIOLsWiHqQFAoNkjbS1tWV3CA5SLUgO9Z0A0o8TLR%2BLd%2FrgTp6XQ5zow8eDHDIn7t4nd9pyZ25OwFyiRn3KnazRtxNQ8jc3N60%2F8mnLPOmL9vb9a5JLxiWRT13mR1onmPRDe%2F82CKrPxSrHPxGBiEBEICIQEThOETBCZ%2BfY%2BIB1K9LgY3jPECFN8RY8GElIrUGvjs2b%2FCQxqVI2VErrHXWouiwOa662TVQijVIL7zPhWoJTYQjg0HOMTsXIyMr5hpbVUhpq9audAGkirVadijKE%2BsIiN80wppDy8j%2BIQUQSzh8ikZvgT0%2FSoqrV4bsvz4x09cOxc21I3DACUdeqMjXmsRN1SEmDJjlw7cTOMErLxcLIVJpkmk1nI8HhuGJQVUKYnMRAUpy0QGD2799vxMglZtRFqgX5cSLEnCFRJCd4%2Fk4fnkcb2kKUIIy054KIQaS4M76TTN559jY8Q6S40y%2BXkzUfmzIuxqQ98%2BDdv4m%2B1tv4%2BLTnmbokv9vL%2BH304aSU%2FukrpohARCAiEBGICBzvCKxJ6AKpQEKWwpbGc27I7Zq2Uk5gh2EIm7U6NfXSVIyc56qqoOabplMlJk0JsCBQQg3ZVZWKtBBEjqNyeQkhKJTmmebTmaaT0ogJdGI63RDqyGJaSH1r5GY6DaRlu%2BlV5DPVq20LQ2bqzHD07ju6DpAIIOMMHHhg18A3QX7WE%2BSEA3LlpLT4uENTaTKfEfbWEsVLfDlnWBmjKgzfXa1Wms1HB38QE8brOFt3rHdXNZIDSYG0QKxYMycxzJNEXZ6dgFGH5HUhQn5OzckU%2FZHPHQmhn0Hjm7jIo5xrNpvZ3aVl9Lt%2B0aeTRSeVtOOZO4m5Ga6jVI485k25EzvIIG0YnzuJZ%2B%2FbMsbv4pn63j99exuvF%2B8RgYhARCAiEBE4XhEI%2Br1r%2BHFziR1bJFv95uZcZhQxpNrc3FLVbKsoAxcs0kyTCRYSg1amelypLDp1i0qzzYO2MeNGblEtlZdTO1OGNWhV76os5kbYOHOXIAWCrHhciLYz78FGLntpyVm9SWl%2B8ObTTuoXaoYtq8M8A%2FX5zixDlpfCgtVCooUTiCadQ52KlC61Q4Xj3IywDOpRQZqUrlOWF2at27WQsVBvueTcWKcJqs16FRYCiZV5kgnLVq8aTYrSCI6TG4iQkyOInZM1enXJFGTMJVOQGto46eOZNtwpWydi9MtFGe1pA4EiD2kdhMuJHs%2FeB%2BRpnXQxF8r87v36XCmDlPl8yacOd%2FJ9HB%2Bbdyd59Ln%2B3Y4L%2BTzTnr7822wS8U9EICIQEYgIRASOcwTWJHQ4GQnJjCMIzzW%2Bt3Z0i00wuJzgzJe714DIlGmiNEuVFxOl%2BCRh051N1He1mmalVd2oKINlqoYgSSmLcMbJ8WMTRzbDmK955Ws0KQ5olhaaZomSvNTG1k20VRzUS17yUml1SI9%2B4E%2FqzW95h5A5BfkSPdF36D%2F0e%2BydOuvXXt1REhmUjeNsrEPa0rs5dQljWAeeH6RdlCf9rv70ta%2FS9%2F%2FoXXRkhRoUghkMF7I0EepWjCRQPNvnozZGz9zX%2BrkHPUiTrZvr4isH8xCDsIw6s1lhBxVriG0SpHWzSWEq6jxNlGeZNvZtqmqCqhUSAwFyUsSXQKQgLyQnRRAayJcnJ1br5Im6rjalPuTHCZW3I4823j9jocrlncvb0T9zIw9CxTN3r%2Bfz8jv90zd1yPN8f6Y%2FJ4jUJR%2FpIHcnadvb20YsKWcelHGnHc%2FM09vaQ%2FwTEYgIRAQiAhGB4xwB42w4%2Fc0wNOgCCWl4HA0fIFSwmUk5NSvXBpKAVWqBajQ4piPO63K1UttUJqUy%2FSz9QWGMT4wki4214dwdm344AJ9hFJBzngvj115p3%2BlRP%2F8LqoYjWvaf0zOf%2BQjd58xH6lB1SMvmKr3kuc%2BSuoXSrDHXIBCxJVa2thBs3pX6rjGVZDiMFggZ9Va9haVVa0QNowNye0LVareBHIx80B4oZ%2BOvrRxVsTGtgdqV2nahAfLYY%2BBxWMVwVFW5X1fSD9Igvgc3LOZ%2BJVi7Mn43cOZQ%2BuTfnq%2BTpyfojDPOUJOfoKuGREswR1rZY30ZDCAqiAizGFotwdeIWqe2rrVq8NCMcDSQGiBwgsYdCZaTGf%2Bdkk8ehIrEM8lJjr2M0izKIFYuCXPSR55f3oeX%2Bbjk8wzJgkw56WJcl%2BI5AeN%2BzQT5gnj6OH6nvc%2FHx6CM5H0zF9ryTf69PhfGoj0SPfJiighEBCICEYGIwA0BAdvR2NgSZSb1YaNjezUDBixRu0ZtXakaN0dciSCxY7Nnw8TFXFVXJnkBkLA5I0UJqjw2T5JvxKjHKKM9bimQ8DV9pR6i1EBdUOkhvYNsLaR2ob6cabuTjWtRIopO1WpX2eh%2BY5JT1llkCnE2z9yiNOowG4VAQcHqzgw17AwfvTcYXfClvZEkjux1cFcnoPi7SwZ1SBc5mwVxSlKTkMH8cOFi%2Fo4hBUOlandb1TDRZF%2FgfU4m6R8Sayl4I5EWKz3%2B3HN12eWf1D3vflcc6imbBzLXDU1wWwJZM1IUZtmC0ypYqxrz5PwYXAxB3xBICphCljz5uTYID%2FhTjoSMBGHyO2vGunhizfhNUJc%2BnHB5G6R3nJPzseibxJ26EDjPox%2FquVSQPnwOTqqow9x8HPpiDkeOHAm%2FsfHMHXW4%2BN15fcYi0S%2FPjMPYHvWEPumfRDnPtHcCynNMEYGIQEQgIhARON4R2BNRuNNYNlL2Z6IbQBRI5l8tCe4ieGd%2FRKjCpsgzGzSbKJcTOO5sumy0EAqe3X0GfbCR0s4keN2gFdYABSHIErUcJkPO1dTamJRaVY1FqcAww3x7pJnlHzmyrfv%2B7DmaJJlOPumg3vvhf9FOD7s7oje9%2Bvd01sMeq%2Fe9%2F2PKkkQ3OXG%2Fnvei3wtWtmqU5YOeed55mqSF5kmiu97xdF22Iy3hJjjWq3b1zKf9srY292szSXTixn599tC2jnqYi3bQM571qyqKuU7Kv1tPecrzlZYzQacWcIQMotGorRZmLNE1KFxHSeL8gD7wqU9LUyx9V%2BLjOCZH4AeINWK3YrLPpJhFEaxm8zRXMZ1rUqQaRhISpJ%2BBqNlCja5KeIa8QLq4u%2FqUNYBEsSasjxMbSA71SKzhzs7OHnGiD0iREyBfY4geefTJRbrmM3m0hWR5mdelzPvkmX6d0DkBo901f0%2FUpZx%2BuLt0jnpc9MP34vLEyRp1yef3xhhOXtef6TemiEBEICIQEYgIHK8IGKFjY9u3b59thP4hHOTPkkx1U5sFaj%2BEs1R2Hiw9ZjEIsWOzZNOEKHBnI%2FXNGekMz2y%2BLpmh%2FsYGKttAAjdmhU48eEAcF0uLPMSRNcXlYE51s7IwY4hAORDH1Bq6Rk993C%2Folx53roZ%2BR48%2F59F6wlN%2BRQu4YD6oXW3r7X%2F1Xv3iU5%2BtoztX6BP%2F9CH9wct%2FTx%2F8wCdNTfqiZz5dn%2FviRar6QVWz0E%2F82J10xj1%2BUjsMMrR64%2BterR8%2F%2FW7a3V5qd7mtJz35Cbr3Q87SYcr7TL9%2B3tP01Ysv0VXbO7q8uUiv%2BqP%2FocWqUe2BLNJOqhfKJ1jrDirzINm0zyJGbjGB0SjtW6ldad%2BGhJTQdKgQr75RXR2THhWoPpNSVdMbdkWaqignpid2qRQ4gz1r4ESHO%2BSGMi6I24EDB6zeujEB60M5bekP4scza0QfvPs6cydBoCjjnbWH%2FNEPF32QRxkXdf034Hm8M1%2F6JnlfjEtb5spFfepQn0Qb8vx7vD%2Fakeffxe%2BNPAged%2FpiDB%2BXO8Q0pohARCAiEBGICBzvCOwROjY9Nl02RBJ7dt3WI%2FGSkTpIGIfxceg7DOGwOXssmyUbrks%2BuLMhkyCKJPpnA6We1yeffqrFjha720K3ydZO5ASxyaf4cAvREKhrMzMykQjDgD94zWt11s%2FdQ1pcqkc97AFataVFGFPdqZjO1M9P1FvefYFmG3Pd4pT9OmljosNf%2Fpx0%2BAr9zV%2B%2FU8950Ut1lGnWCz3nV56lr37lK%2Frnf%2F6ihjTTw849Vz931sNNpalSuucDf0qLqhcWu5d86kt665veoac%2F69k2DoTNiEeaa8hwLoxwrsHPhn17NxIWVMOW8ixolJNUnalWEx25MhiEIHXDJQlq1QLDCc7QEVGiwx1KY8E7FnWlpu%2F3yEhThwgLkBWwB19fR9bB14JyypCUstYkpGROmniHBFEPQkZa74tnJ0uUOenimf4gR5AtLoi8j0E7xqA%2B68%2FceHbyxRx4h5hRl4u2zGM9Mbf13xnt%2FZtoQyKPsbh7nhM7ytfH5R0SGlNEICIQEYgIRASOdwSM0LFJ%2B2bKRjryD5V5KSMLnN9qgrNaLF3L0WUJm6afZ6cP37TZSF0dxwbq777J%2BkZr4LERY3iRyvy3sS3nWS4zrLDNmfNhwQLW6mMdmxdqe86DzUwipmmmvtpVmk%2B14OhZPhVn6e5493vpwIkQwUSz6URf%2FPTHdPaZD1Rz6SX6%2FL9dqbvc%2BW7af%2BAEzTZvolve6raqjx6RljtKhlpXfuELOjA7qP3zEzXL9ul%2B97mPJnmhxS5TzVTmhW52y1tpwVm7LLcxIKd8Cm7mcCb3Pbe5rYpkrq19m0rSTK997ZuNIK5Wbfg%2BIY2kcqsT9kNkw88Jq97BrVI0hHBnkOJVOLOI75K%2Bb8xXnem8R%2BIF2SFBnB1jX4ewVscIkJMl1mydFEG8WTNIGYl%2BqMPvgmfyeWYMLyefi98Q41F%2BzTLeGYd5UM%2FHZywunydjuXTPOln7w9yo53OjLon2JMrp18dxdTFlPi7PzJUUpXMGQ%2FwTEYgIRAQiAjcABGxXZoPFQME3Q2wNIGo4ycVoAb9xvoH7uTrO2IWNPKjEeGbTZMMl0acTC%2FplsyVB%2FMj3cqQnOCTG8TDSKaRwptCzkAm5BtSTbWMny%2BqR8Gh3pZpQFOo1gzs0lSxiVl8j0ELOpO1Fo8nm1DScHa1xbMzGDwFToo190vs%2B%2BhFdsntIh7pBO%2F2gfnGp7nWn20vbl%2Bqn7vnjetJLflefW%2B1o2R3Rh9715xqqXW1MpFmRqq1qXXzJZcrGSA5pWShTg32EfUPTZvrMF7%2Bqpq%2B1u1io7RZ6zGPONHuG6RQx3CC1mYZkag5OFkcl3PkZ10CNbWfcWmWQbb60JULD3L6HLyQcG%2BpwrFIa8MmQZobwXAb0SFyc3PhasE4QICddXk4%2BzyQnXNy5PAQXfTAGeaw1776WtPM%2B1vvxPiinDSSMPqhLW%2Bpy8Q5R4%2B7EjDb8XryMcsgeeetltKdvfkv0SaINhM2JqNeB5DEnEvNwUmgZ8U9EICIQEYgIRASOUwRs92OjJM4nm6JLLdgXcWKSpZkSCNhIwsIGi7QlEDZcl7B5%2Bsbtd%2FJ8s%2BTOZguRYAzKuHjGenbVr%2BzMGGwFSmHeRNBdpnOl2VS5WrM0tYARmHZunqA%2BmVhge6Mg%2BUxdDzlgw2cl8P2Ra6tkbrwVBJ0IpqrpoOKWt9Ed7nQX%2FdaLXyyirhqRhExSB%2BFNh%2B3FoGXXBBXustfZD3m4Dk5nxge3Tj6obKPU29%2F8ZsEnP%2FKBD%2Bsx556nSdJoM3ANFRgC1HSWIHI0HHnrzRXKOFA%2BU5%2BURlg3phYJzL4fvWrf4ECXKBucRwxStykYQuLAEGMDpJVIxfJAkNbJEgQGcsPasiZg7aQGkgOBd2IDYtT19VpfQ%2F9N%2BJq5ytzXjzZe5oSSOoxxzbWmX8bhd8Az7XwsV6UyR8%2F3vqnP747%2B%2FT8GtsojMaMP2lGPtiTqMr7XI38dD58j7WKKCEQEIgIRgYjA8Y7AnoSOzY8NlI0TKReuRUhpWhgZ4ewcm2DbsBlD6DxgehCb%2BYbJpknyzZtnJxKUeblvvFYZfSsSotGZsbmwa7G8mKnpc6VDbYTO5CqoKOtUSbmpZMAnHixprnaYKkt2g4QrDdKm%2FvDFOsGc%2FELm9qvBsS%2BmsvsO6k%2F%2F8q%2BULQ7rBCRQHNpPMv3Q6ffWdpVK%2B07Vc1%2F0Mv3u88%2FTSelUJx%2B8mZ563q8r6Yg920sHJ3rne9%2BlV%2F7e%2F62NZKrznvYreue73q6iWymrR1IKkURaaX5QMi1HA4cSfJqFHvHA%2B2uzOFE%2Fdo97a6gWuu2Jp%2BjA%2Fpvpwx%2F%2Bp8BHTXJVqOuJBjE1R86rMSg9alYINqmGJA9BjQnmJCdJYMyzrw13J0xhnYN01duxNi7RWl8fyp3s0d6fGYt3iBRtV2sGMPxWqOdrzt3%2Fs0A%2BfUK6fBz68bnbwyid87qe5wSVd3%2F2Osx9PZHv%2FTM%2Bid%2B5j71eNz5HBCICEYGIQETgeEYgOf%2F884c7nX4XveGt%2F1vTm%2F6wfcvZP3Nr7ADUqycmBJ7hxm8k2oFULVtNZy6BYdMO7iKo5Bs3hIHE5snlGyuSOjZiEs%2BmXoNvlbmqBgneoAQuaQ58t01kVmUnCltEjq%2FndubrCE%2BqtYWrOBUdAVCl3WxiTng3%2Bm3lQ6Ih3Qzn8gazrwhzb3tleSuUsYmdZcstDFcy36clbusGaSPDB12lqs80Safu41cLVKKpNNdSHRas%2BYlBopcSyzXREmklJGeQcmLWonzlPBtYomXlo7uV8mSFIzwp25KSiXarcOyvWclUuvAyyM5itbTzhAia5tMNi7qxMZ1od7UMfQWGG%2BLDlqURJrBGLQmuEKx14wZfD%2B6sB3UhOOvSNM%2BjjpMgyJZLu8hnbX0NfV25Q6DoizInjE4QMcSYj%2FFoqcvl5NDHcQkbxjcQQu%2FT6zE3r8sz5STGcDUteV6Hu8%2Bb%2BbhrHtpQn98fc3YyaZ3FPxGBiEBEICIQETiOELjgggvMANWYGhsaGyEXz%2BMZc7NyDT7hQkB4%2F77plADox85A%2BabpEho2SvKcHJDviU2VMsYin3s7DDp01RENfack2LJCJyR8ymVTc24MmYO8cXbM8lUYzTRfbAnmsZ1wmVviKBjHxNlEXS2LfUokBVLSSVMcAqvU4RoWlRtDS2f7zI0xFqy5eevlACGSyanlK6mltNUMCWIr1X2ivNwMOlI6HnJ1fWYkGBnR0HOmDTIHM%2BVAXPh6us6zKWwC0ZblL1aVqYmJWTsLUdPUNBihhHNxkDkkl8vlrpq60%2FburjlhbjvcwRxzyYEKFSwhKJAVyBFkzteGteAiuWSLO6SHNiTak8jzfOpwUeaXk0V%2FZ6707cTQyZyX0ydkzvthTvRPuY9DHdqTfMx1ssXv0uePpI%2B21PP6lOM%2Fjzq0YwzHgrrMmXl6fX6j5NMupohARCAiEBGICBzvCBihY4Nk8%2FcNlX0VUoGVKxan3egcmA0SQwmSb65snIEEBgJBGZsneb5xuyTE69KWzZTEHS8dszkH%2Fjs7F2d2C5wmy2fCD8iUzdyMM6yJlM7MIpStOJy3s9hkdtZuSigvIlGoENpZuEqRcxqwN7KW4DBZg%2BYQMtRwbP7YVbR8c69JGc7fQQ2JiGEA5ehtiU7RYlCrEqkdSmAYIj7xIF0p310r4bwfDIwoG2047wYRtTQQsaKVJpzcIwRYqgkxbzlShw8%2BpHsY%2BOLWJNjNuhGrfQdlpu8e8W%2BbRkVxdTLOGrJO3MHWseYZkkeCcPHu600dV5vSFuLja0VdX1%2FaOGknn%2BT17GUkg%2FRBG58D7yTaMJYTO%2FJ4pi6JekgmScyHfCdtjOP9uKsRnwN9kjDeIHk9fodeh35cWrn%2B3XxTTBGBiEBEICIQETjeETC%2BwkZHQPP1TR9SsaxQ7Q0WKQIiQXmI9ho2TTZOl7Cw%2BbokzqUfvtFCGClnUybRjr54pw77MRI%2FTp%2FlWFGypxsnwjIjV6JOydCYD7hV06o1EllYFZPQQbggmpxbG6Qyn2lRtWowdMiJn0oM1CBly5JOaYXVbFAmawrJoA1qzlSrtlM%2FoKpDmtebCxMwaIhgO8tNYgePqw8Hg4mh7PBQYqpayEgaKKBJN1PO6wXOaN8NfzQCkUIGURO2JpUs8t4iYSwXjc0fJAj1NeB3bpRYmhUvMWcXS4ukkSbB4rTHP93o9gNcWQOwdqmZrwF3iIxjzztr54k2JO7kexn90Mbb8luhjPZOuryur6%2BvNe98r%2FftY0PIyOd9nXB5O%2Fp18kU5ZIwxmAMkzTAc%2FzPAs38j83csyPPfoY9DXe%2BLZ%2Bqut3Us4j0iEBGICEQEIgLHGwK2o%2FumyObJxrmzEwRBs8ksEDg232tsfkiGfKPm7hsoBMD7486m7v7AXDICSE4CeIZQccaME3sEyELq1qMdSyEZHLbfFZESUP%2FSR5JiLBAIHL7fOOUHq%2BqIUFG1puWcT3KtTFInFTBE45LBunSD76R5iv0sEjvUpJ1J%2BKBs2DGYLQMTafD9Bo1FmWtBH4w4lpsT1RWqxtSwMUvZAeqZQj%2BVEQyXVKM6DRa00M5iUkCRpQSrzZkZY9gHd5XmcxzsAsigLE0EaWu7OoSFDb1pY2NmUlNzWTLmuVQLvJ0IOdasB8SFBLFhrajneU7CuFNO8nXlnb6d9NCnk3bqsYa%2Bxk6UXLVJGe24%2Bxj0y7i8k08bT07sGNPWeFSd0r%2BXUR%2BS5olvI%2FkcePa5U9cJm%2Bd5X9yZG%2BPwHFNEICIQEYgIRASOdwSM0LH5ccYJKR2b36i5MukcPs5gXGzAvjEul5C28Olsmr4x%2B8bvd2r4hn7NPM7SUebEwjZl1LVtZ9EQEGKRGlOVzYw0of414tSNkpVR%2BoPckHNt2WQq%2FMGhA0VFO83hcY0SfNYNhXoICB0MEnYUQUY3qBpas%2BRFr5knndp%2BqYHDcjDNfK48gUCG%2BXCIruJMIEa4qIRR7TJO35ik7miF5S1uSiaI2UZRYziuhwPhTpWO1o1ahW8Jh%2FT6wGBHTF0KulztWmQO47VGXIIqnGpIMiE0uI%2BBBIGjkzgIE3hDriBkXJSzfk6mvC5rQKLMCdL4pbY%2BPHud9TGoSz7jcEG6KIdwMR5zIt%2FH8z4p8%2F4g%2BvTj4%2FKboNzfmRN9kOjPiR3Prk718emT8Xl34ua%2FV95pQx3Hhnskc74q8R4RiAhEBCICxzsCtpuziULKfCPmozhDB7HAxxnsjTLbGHuCviO1CeenynJiGy0bKRsq9Ug8%2BwbKO%2BVs1L7pQiDpD2KBi5Q8Q1nZKxsPnNW7taldCzurlcIqgm0B1qNZadIrxGyEyeIjkGjtNp2F7QrOg3tl6mRueY0oZeqTVLU5S5Zw4cYZNFKe5Oo5uIfl6dCpJIQXkrseiVVipwZz88tnLoo1wWmcaXlHs9cBiRO0Uto3yW0%2BRoSzIgwEgQQPztUNvTZKJJ%2BQVQwnmAEH8%2BZhLhyt42kgusWGWj%2B3mLAmOG7OhJqVaBWEVcMPoEvlrIMRawgM5Io7iWfWALy5szbcnTSxFuv9UMZFPheJtpAqyJATQvKpx%2B%2FH8yBbThB9HOo5ieI3QGJu%2FF78N%2BOGE%2F7uxI66PgfaMo5L6rwOfZFPPebD%2B%2FrdBryGVJFy5hRTRCAiEBGICEQEjncETC%2FomyEbIpsxyYjDeH6LdzZmNu0SldfA5hw2cpfU%2BUbKnYu%2BfPMN%2FQUpkdfzPj3yRFpmqnaPqLDIC7nKaWHOc%2B18mpEqpGzB4hOjB8KBBfOGTmmHitN8fXBSThNjRJAvyFiQQNEWkgY1cW0o0Sk8od40k1gKsXCFRKS1hgSVLlasqEFbO3vHNzNEsH2AYUIMGhWoSI2epcryTC3WrkSooIqRRFkYL9S9SObge8yqTiCQGFuEQBYIzZDygV8KgRsaI7CTaaF8VDfzuat61843QvDWpVE8gzOJZ%2FrhnXVmHX0NIDO8c1EHIkUZ6%2Bz9%2BW%2FDceK%2B91sYjSsgRk70eIZs0bf3523X23k%2FXuZ3l8Lx7sSOZ35P63d7Wavj82V8kr9f804Zdbw%2FL%2Ff%2B4j0iEBGICEQEIgLHIwLGdthEjx49ahu1WxBC2KA%2FhP7Cz1zdNLZRpynSGIhA2BjH%2FXPvsDrEgAQxoC82T64jR45YHhIV8ilf4bakH%2Bz8Wl9jXDBRg1SsJmBqq2RYGPNZ4RYkLdQQLavpVGSV1G4LmVdvrChs4gjYLGFyahOD0gX3ID1kBjUn%2FuuGRg0%2BTTjjVwepW4d6FDWpWa%2BG5ilSRc6w4esupadUCyIsgBpDGjsEKA7tc34uVzvkWiywdkVqGM798YKgbLduzS%2Be8eSmEnHCur4yEgpqJg%2Bkbyxzs0xlOVeOpTG%2B%2B3rU3J2atlZXNTYnI80d5OuY5ShYg61fEDIS7xAq7iQnd6wHeZAnnml%2F4MABiyRBPaRmlJHP74Q7F%2Fm806cnyBEX5dy9nHfmyt0lhTxT7vPzPuI9IhARiAhEBCICEYFvHgHbjdnQcebK5sqFJjJIiULoL7ol1JRJXcpSZZmaSpZ28AM2ddpzZ6PmghxwOcGDAJDow6WAYbq9GR6gaV0qV5PP9ZpX%2F0%2Ftz0vtL%2FZpkpSaFwc1LU5RWezXf3vZC6T6Ip370Hvp1a9%2Fq3axO0DzmcicBU%2FgK3aho8ykdpTkldDTYLCAmjKF9A2JUgihqXGRzEFcU1UdnArXmJYIAAAekklEQVRTi14l7jcCXzSfdfMNXI40qqptKW%2FUNUel%2Bohe%2F0d%2FpNv90L10lL7mUzXNoATyacSyVVJ0KsqpUgw0kkoqK%2FU7l%2BnsMx%2BkfVs31xVHA6GzY3dwUFNpd%2Bpa9LVI70YjC6SDuUxiV7eNGUiwDk62AqaBsIG9kzgIFcSMd66grg1xWr2NkzH8uXl%2FSOt8LfF1x%2FoxHn277ztfV347Xk4d2nLxzJp7O%2B5YPlPGmDFFBCICEYGIQEQgIvDtIWCEzjddiBgb9XgMzlxvFBgZmAornHVCkkdC0hIIQjgvRzskbr5BQwhCu7BhM4a3Y9NnLM5spUmm%2BRTjgnCcDEnVYx%2F%2FSzrSXqYjzZf0jKedox9%2F0EN1SXOprmqO6Nef91yp3VExVErziQ5X0goVMCrLPNFQI6YjcgSRGILTjz5L1Sa5VubrLVFFMHtjfY2ZnyLEQo7VtaP7EqaM1US9MAML%2BqbXLsmEGzmI4GTK97XKJqhqUcemSsuD2mll45gvOawZcHA34L8vUdPjQgW22euf3v8e3eKU2%2Bhed78rHWtZSyuEhPC2hPNfQZJm5%2FzsEaIMEU2UZ4Wd%2BZtMpirnU6VZUG%2BDIWSJNYBAu%2BoTvCFbrB3lEDR3znv48GEjYeQ5IXepnKslacMzF%2BtKfyTWP%2FwHILR18kgZvwWvQzv6IFGfxNozZkwRgYhARCAiEBGICHz7CJjYh42Yzd8lOnTL%2FotjYaQwxBJFQoc0a1JOjPj0fWsbshM32vBMH5A1khMKf%2BbOxg65gwyE1Ktra2V5aRQLAoMqNccYo7pc80mvHufGkABTR7ZSMdWRZaO8nFioLPjXspHKvpfxz%2BoQk7GzcEleCmoBdYBf0c88n6irDoczbEmuNt%2FU0R3pJIRv%2BLjr8VkHaRkIlqpuIh1qpFnBWa5CRAbLTO%2B6HYjjkOro9lJZUYojhlA9o5LMlwklGHykNn%2BUwO3OUo%2F7hXN08Vc%2FpA9%2B%2FHPKppvmtoUuoT3d0I5n9lIl5k0YpPAh16jIStXNSlmRm8EEMXYx3vDwbGAPacJilPXg3SVvvh5O1OjVVezjYtiaskbk04eNnIcwb%2FRD3%2BsEjbrks%2B7c%2BS2RnOw5%2BYPA8ezEjjrrz9Yo%2FokIRAQiAhGBiEBE4FtCwHZfNmFclrDheyKsVIfFJ%2Bagw7BH%2BDhTh5YMy1Q2bYwnaA9x4CKPjZ2LPn1DZ%2FPmQirjZC5IdzqleThLlVCWFcrNHUgqlYOWq6PKykLL0RDBPO%2B2nfbt268rDh3S%2FR7wi9pMp7rlyQf1jxd%2BSsLQYZLqDX%2F4Cj3owY%2FUez54oTbKRAfmE%2F3my15lQrdsVSkrUj33V35V%2BWyfpkWu%2B9znJyymqh2QQzqnTi%2F45edqa7qlrXJDtzrl5vrKoV0jhBnywL7Vc37tRcqzk7W%2FOFXnPe1ZdsZtxfE%2B2OOojqY%2FhHQkiGff9Mrn%2B%2FTRT39O2r%2BlaVGqqzqbNmSuHghdlhrB64ZeK0R3nCFse3GmzxTHGZatpVpCTJgXlmCtCamyccYoDY49mLM2vHMHd9aaO8lJGs%2BsJUQQFakTP8qR6NE%2Fa%2Bh3%2BvMxqUvftKcO%2FxGgHeSdfOp5u3XJnLe3icQ%2FEYGIQEQgIhARiAh8SwgEccp4%2BJ0NOGy6WAkGx7b06kYRkDRXnSJxYaNm8%2BbO5s5GzTv9cEfKQx4EjjqkQALDO6q92WyiNM1UQBzH82zm9I2wWepUTFN1fa3pXnB7%2BumU9pWe%2Bfgn6hcfd46G9lI96dEP0JnnPEGXII5LZkpnJ%2Bodf%2FEP%2BsVffqEOLy%2FVZz71N%2Fp%2Ffut5%2BvKFn5HSpf7rU56of%2F3KYR3G1Ulzqc644y11%2Bt1%2BRlcglJrmeuUf%2F5Fud5f762g7aHXlF%2FScn3%2BgznrAQ2Sa4%2F6Inv%2F0J%2Brjnz2qq4ZBR4aL9eo%2F%2Be86snvIJHThWBjGAUjVEqV5qrrrzaeelcG7WrwNT5UOUymdqxq1jx1nFfm%2BFDcljYWbRaUKbqwD8WYxwFitak2LiRE6cGRtIFWsA%2FhD2Jxk0ZY81gPCRZkTNtbF61GHfpz4%2Bbqybqw3vw3K6IM7vwXakiB8JPJJjMkzd34LfIu38zbk%2B7M1in8iAhGBiEBEICIQEfiWEDBCx8brRIwNGO5FKC780KWjaw%2FOurHZb21t2YH%2FlhimJq0JbXlm0ydBBLjYxJ3UUc6GTh4X7xACXJAQ5qqGwKHnha8xK86QEYUBawcsYYMCNJQPtdp6qd9%2F7ev08AefIbVH9cizflbzAyfJaMWQW9xVbZ2kt%2F71mzXLJrr5TfbrlJvs06cu%2FKi0OKL3nP8unfeMXx3dmjT61Wc%2FXV%2B99BJd%2BKkvmYL23F94jM58zM%2BaGxJY1NkPvK8Wi8rO6m1%2F%2FvN6w2tfr2c%2F94WmytXQqK63te%2FEE3R0CeFissR57ZQhEesH87OHT72Gg3LBX4kZWSSEyMAdS8qJPKxbCXUGQZY2NvYpScOZNax0%2B6GzGLbcSfioY0KoRsHTMaYMjCFZYO7JcYfMsZbUh8S5lMx%2FB%2FwGnOTRnrXkzvrSzi9%2BC07yWGf6Ivn6ex%2FkQSLJp%2B363cf2OcZ7RCAiEBGICEQEIgLfPAKj6WQwbJiOUjTvBpWrRUAYfbmhZs1QrYXz7eM5rdCFEwTaQhRIEAPf5HmHMHCRXBXHs%2FmKg7gRJBWlJq5LTJRVqG0y5VlwxBtkfJU0ycy9CT7ZLC8NZ7s4e9daF6nKftCP%2FdRddeJBRtjQfOMUXfjJT6hIM21%2F%2Bu912WVX6l53uQvhHpR0u0bCuuKg8uyIqTgPXXypbvX9P6jF9kIHdcTI1oE73l89xKvfr0m5pdO%2B%2B6ayr%2B8rlUmhRVOqLsJ5vay5Sj%2F43bfXF796ueoUTjrRq177Dj327PuEg3L9UsoatR1RJwbDFJVs%2BEaDSHW9srqQOl%2BagF6wgh2ZrxFAMIcoQdogUuCO6tTXgh7JczLm60I5eby7NM3reVsn4k7UIIQuAWQ9XcpGPdpwUZf%2BMI6gnHrkOYFjTH4DzDGmiEBEICIQEYgIRAS%2BPQRMfMPmDBHwzX53N6hcM6w6m9oMIjCKYGPe2d3ZGxFVH2el2KidqPG8vlk7KXCVnEt8cHNCXSR%2FRYrFbFAfEjvV5HEwm3ZQWWANyaF%2FJzu9VFcmLaJvIzj8SQrVqyoYRUAS00FdEiwte5OCTcy3m%2BqVeiw2Z1P93T9%2BRLvNjp1Fa9pORxeHdOf%2F4welaql73PV0PeuXn6K2Oqwrqx29573vFd7ljuwyFGfMlvrCZz6hic0gU1uBQaoyNxtbFZNSn%2Fril7Qc3X5U%2FUoPf%2BR9tEK1ConDWKLvjRgh4cPCFkLHF2HgMJ8VxmvdENT47hgDbN%2FmpgkzcwtjhuQznItjYSBRkCbWCqx9XShjXUiUO%2Bkiz9dsneRRj3zq0of3xTu%2FF%2B7Uh5B5O35D5NOOC8Lm%2FTMel0vq6D%2BSOVuO%2BCciEBGICEQEIgLfNgJG6CBbQZXa2OaMqzUEaRAriEEySl4gCzidxbEwiY0cVRsbNRs%2Bifps6mzWrgrkmXok6kIQnAjiLLfvK3U4%2BiViQrmpBKMI%2FK%2BlnbKuMuva8YhZcDhXzFRVjXmVs1EzfOPNtYkTXqaWSbvCcjYQwQJfIG1qwj8Vufbf%2FGY67Ud%2BSC996UuCdle4I0lNS2pRHIZMQxNIDG7jtNzVIx71CA1Jpv37pQOnzDXZbPXXf%2FkWDX2rj77nA%2FrPv%2Fxcpc1SmNSax72Bv8RztY82soZ6uUQrXSJGxL8cjogLFXliZ%2BOQLlrgsEFaLZC0FUGNPYrthr5WVe3oqiuuNCtbDFfaHjyPnUVzcgXOECpfF7BHsubJ1wgS5skJn635SMp4Zt1J9MU7UjcngeTTjn5YZ8pZa9aY8UnMhfr8HhiX%2BtxJPl97iX8iAhGBiEBEICIQEfiWEDA%2BxCbsBMs3YTZcznIRqxUpGpIV6rQNZC1VlhW2gTtJYANn02aDpj%2BS371PNn3qcLH5U5d2JFSKRGSgbHd7IaUwn5mW9SA1O%2BLNeE0ykwZIHxK%2BQBigQYuqVdGt1GPUgJ%2B4jS2lzS5xHzBIDVEgEIPRycZ%2BveOvz1e7u6tZQlzYTLPZpu56%2BgO0fRVirv160Ut%2FW89%2FwfOUplMdPPGmevLTztMkq7WEE81Lnf%2Fe9%2BiPX%2FFyzfKJnvHsl%2BgNb3q7psNKJ2LjMECecH2SShOMGQqLUzvLG1X1FeqbSg%2F%2FuYfopP231Z3v%2FtNqjvy7vu%2Bmp%2BjUm56qj3zo7zW0IS5s3zVq%2B5WSfFDdr0xayjk8IkeAFSpwBIR8EusFcSL5HSLm2EPGcCZMGesCqcKBMOSLtWBtSeSzBtTztfF1ow%2FKka5yno71c0LGWL62%2BLvj2SV59EsfSHRJzJVn5uFjWEH8ExGICEQEIgIRgYjAt4RAcv755w8%2FesfT9da%2FfJ%2FyE3%2FANvj73e1kTZJBvcUuHYxg5CalSdV0rZB4cdAfX3QW8xWHuKOEzskAm7YTOjZ%2FCIOTBWZKGXXKyczCiuEEGLclkBgNmHiupGlvDnlrbZhik9NWGcKtBOfGg5p0vxlLlBYvIlU7zIzd5APSoaWGyYa5GcEZS2axXDsRWLUeamXKlA%2B4ZEmNHKHSRFxnSkk73E9IslRJQRixxiJHrJC42Yk8HBL3GvjmIcRqhVWtmLakTdSmQ6s%2B4Yxfoh4fxzkuSQ6rNJxQt8JeIZgT0S%2FUFLqTIc1iMnAzbpy%2Fs6%2FvlHOWDgMKeiVMGgRVWJJm5jTYjVIgcawDJAvCBOmCtEGqfE3IZ80oI89JIG2pu14O6XNiSB8usfO1pg%2FWlj7II%2FFMXfri8ugT3v96XWsQ%2F0QEIgIRgYhARCAi8E0jcMEFF5jAxkRpbMK2Ybet3RGwGWmwv505seUMHWK0PMs1YKiJWxOIXYcK7di5LZfYOHFgZqjoyIckOHHgbheB4UfpWwkdqispm0nFTMgIV12tjYyn1AiWiaM0M%2FLF5Hsmk0zU1JWyvA0GFgm%2B1DbsDBoSuiSTtle1ZrPSTqhlSPlgWRAlYrzmhXlKMZLFuTQawP0wcGiDmjLF516waVXXpcqGVAl1SUQvC9MwypdYpAr4WHBbkqfi6J6y2QQaCqfU0CZKirlWdaeVWk3LPJyha1olWBb3QeucTXhEvYxBycpwqHd7lbPxzOFokcx6gDNSMQjUeoKAgTX4k5yAOWmDWHuCmHm%2B31HJrxN0%2BuI342vNM3WdzNEXz04MncyR73OD7EEo138nPod4jwhEBCICEYGIQETgm0MgHHwbVW1stmzSHKtCnYfjWiRMkDk2aK7gQCQMwjsEADLoGzMbO4kNm42fBNGgnkvxIAfW11iO5pCabbWU6UhhPBbiddA0g5zkautwHs4IXZqp6cJ7hlity1XkxJLtzBBioUFVEmxAUX8mQ6f5LESbILdvkXYhi2v2xsNeIEOMl7Rqm101WqhLiMGKj7yJGCdTYZcGq6zd7WCFyhRwo8eXQ42W3cqsVxN1IQ4ssVinlOVCI9wPSTgnOHA%2BbaJ5masfcNsSyKXxRiKKFYHUQRsxlhjUqa6qQOY6i0pmwEHmwN0ldOAL9qjDHXMnUKyH5%2FmasjZO6mhHua8RdUisL3muWvX%2ByKM%2B1%2FqaMh%2Bvw%2B%2BKfvlt%2BW%2BCPOr778UGiX8iAhGBiEBEICIQEfiWEDBCh%2F1Bko3RHnosS2VRCcq0DGpH1ITuRBhGZa2CKo8XNue66cynnG%2F8OSpU6vaDiulUC4uxCjNBxZeaS44szcxTCSG9IF6cDTPfc4i7MBQoE5OyIS2zUGBI49SKoPRpNt0jB8YGIUo9MVqR5Y2SMyAxftmZhAsKh0eUEj9wWCAgiaMqKtakt%2FioSPzyaSli2EIyncD27aC%2BoR%2BIH450G21shjNhwode0puEre1rldlUOUSUEBH%2FX3vnFirJVUbhVVW7Lt2nzzkzOplcUQiCJIiDCj5oDERFghJFIolKFM178mBAH3wRXyQiCnnKgyhBQYKomIw%2BCL6oSQQvE43R0RgyJlEMTsbMuXR1dd1k%2Fbt2T48zRxBhmLZXQZ%2FqrsuuXd8emMX%2F7%2F0vCly%2FuBSRycGxea%2B2ZgrrT7PNlIHBUA%2BGYUW6jlWdCUK%2BkU8%2BJzan0To2tBlGPYg0%2FuYYUCwxWheiaCFNSpEVRJrhGQQ4RV24d1mg89hy20GALV%2FPa9gut9A27wkin8cp5HgP98ttLLdtDeiPCIiACIiACIjAf03AUq59zPlYQMEJ84lVhUPCdKJNuDf1Zj6iSZyiafkfM0uLUNjkJjw45YvxsszFdpw%2BphGNSSmU4sSiVvVQcoM30Ls1o2rkQlY%2BhHZXnLNHYUmXhwyoqLGY%2BqXmoigbhBn3Gb1YeShiX3tEzGmyraiw5%2Fs1mX5OnCmwiMV6va4adIsPfwVcrOrLy%2FnApW1ZM8WOsmqhzDAaL57ifWMpyviMOGM1PN8K599xEhy3iOeH77wu99%2FZdb8Nzw4dNRtYf5LPjVGYVLUXGe4xO9lw%2B7APgiocDsIr%2FA7Cjr95bbg%2B7HmcAj2cX94vC7R%2FF2LL7drNS%2BKOv8P1YR%2Bu0V4EREAEREAEROB%2FJ2DSwObgW1DLK6cQKDJ1NDzDEn6ckJ%2Fwwg61%2BZ16zcYpWFlK%2B3kM9lZBnPgIGMVf7mITcj3r3bkUJVeB8oQJPwog%2BoJSpnnxw3l81h6NUX2ozEfT%2BHgTgv5Sv2DA38PULOetUXaZ9OK19l5sycft7Kfd6o%2FZUxYHl47Z9byHx%2F7DtniGfxSfyz6wL4u2h%2Fb9pcMzhvvC7f45jIQOfeZ%2B2HjOt3n%2BveG89iIgAiIgAiIgAutNYFArFHI9YosmLQmYhajo%2FJyzoZRb1yfIEp9uZMSLAS4TMj1Tnn6xQVd5qVWzvEbX%2BugVI2VxhjmrreVj7%2BpA%2FnGBvk2R2eT9Es18igQdZns7KIJNlqk0GplS8LD4rk9xmnBb7zHU24uACIiACIiACKw5Aa%2FeaLnFOWQMD%2FVDdM3nW33EiIsi%2Bs4SiVOmXCNf7mPGFamcUkfhx8LAaJHQKoERpTSztQMMwE1Y%2FqSdoa85Wc6nYMuuX1iaMuJWm4UC24rBWmucbD%2FZ2PLDw5SueZ1agtWnX4dgnk8Qr%2Fko6vVFQAREQAREQATWmoCpt8iqoHXoqb4W6Uz%2F24J0TK%2FGjiYIiJhyZUCvBfIsB50eoqFum1d%2FCZoo9usNrGbaDGheAeIJ6hzYszpywDiU%2FCD%2BvkVWsEYIV536mmwdU65c7EqD%2ByzE4UxywgxVfebV5tJZdHCth1EvLwIiIAIiIAIisM4EhgidnzvHCfwW8eKctbAOgeptvo873ncrDh26Bn87M0z4pz8qdZ2tPOV3ikEubOBqUWBeN4hpQN%2BztEeHO2%2B%2FA%2FnWMZyZ2gJWFkNBxJgfrR36Gqhm%2BPiHPoI8LvDYr35viduq7eDSIObscf6PzxAHXWn7pbP6KgIiIAIiIAIiIAJrRWCYMOetpjgvjeG3lvos4iIH%2Fq69pyonyrmRFROumV21xRHUcak5InDPyBklYRo1GDmKuR08%2BeMfYnN8Ld54823ArEVJX3pzOaVqZOSvsfYffujreObpP%2BDo4aNAMvYz8RxdHFgLb5g6Z0MzdHmthkkvKwIiIAIiIAIiIAIHExjUkY%2B2UcDxGwUdI3UsjGuCLunwrUe%2BjzOnn8UVh3wRXbR0ZfBC0NysqP2SDG2fY86CwUzfzvZx7z334K%2FP%2FxG33HQTMBrBHMRYqcRUIcuadGimJb5w%2F5fwtQcfxFZBN4XOksDUjFEc5vQxyxvbxy%2BM8CKP8TtJvIMHWGdEQAREQAREQAT%2B%2Fwl4LdT7IrAd%2FakYoQPM7J5FfB%2F%2B6oM4MroORbKJV01ej5dP2zQ7IPXmYHFTAmdfwBteewSve%2FM78Y8YKKPU%2FEkxuRo%2FOfEUtl7tsF29CLR7VkjY6hS7wVoBDp%2F53P248dhbccOxY9hKeyTYt6IfDXO33LxxhK9nx9%2BOxXob8zV11I7%2BKv0VAREQAREQAREQgbUkYIIu6nrMyxmyUYF%2BKPBb5M5cHu68%2B5M4XZ7C44%2F9CFmxibb3K06Dx2lE1%2FlRYQVquzjFdB4qsDnMWaykmJi5vav3kLvErFrpCmEqLerx3DPP4OHvfBdffuABa6edTdG1tSV73XkLJ%2Fz4MBDY8iyL5bGd8FnL4dNLi4AIiIAIiIAIiIDXXmaDtbm5jarpzVaLNlRVuYNxlvsCuXGLutzBfGfX7uBi1FHmBi1FG60CT73wEqZRjLICJoNgm3HPcFwSo2xbVHWErS06PBB9bSnZz376Ptz9ibtw1XVXAqfPoMjHSLKJCboZ%2FSfaHnnkQJtVZ6lgajh7gMZPBERABERABERABEQgTD%2FLEofdszvoXIbEZZbCHI9o6Eqnh8TsqybFCMnmhgk21vqlqKrpF8Z5buMNmzPHBa%2Bb1ID07epipGH%2BW7mPfDxCko3wz12YzRjp%2F%2BLxJ%2FDCqedw36fuHSqexNibzbE%2F4%2Fw8bgncYMvFAxlF3WCkYOeVa9U%2FYhEQAREQAREQARHw6wnoEMHI2KzpkI7H2N8rh0LBABqmNh3qqkFb74MZVs6xo1tEavPomASt7MMsqJWkSxOrRGL5XJYkGcVo6ynaqjRFRo3IENyjx3%2BAXz95ClddeQR5EuHKKw7j7y%2Fv4L1vezfe9I7bsDedou1pfO%2BtwXhP0vlFEHwqLcvCAgmNpQiIgAiIgAiIgAisKwHTXPW8tXIkNGWvqhIbk5EvS9J5JwhghHLeI3U1eIpiisWDq4o%2Bq0ydvoLrrzmKm99%2BC2alRxkximdOEoylZahpbZ91yBnwoxiLR%2Fj8F7%2BC%2FfYs9qczVF2Nl87u4urXXIPjT%2FwMJ376KA6Nx0hN%2FQ1huWGUfGCOvfBtDYe1EwEREAEREAEREIG1JGCCLis2UFVzK%2B5L1wa6sVroqzqLu95%2FKybZEbznAx9FffZFXL%2B9iYm7Cr%2F87fNIrQZJBfRTjHNgf7e0LC3TsM10hjia42MfvB2j%2FAa85V0fRrtzCjceOYpJcS1%2B%2Fptn0XUZEOXooxyIHLpyBx1XuPYlmLktGMiravSRQ29LY72w69EgBuvT0ZJsLcdNLy0CIiACIiACIiACCwJW5I2py67rkGcOLBViKVU4xEWObz5yHOi3ARejol9rmnmjMKY%2BKQfrBijG%2BN2zf0EfHcKcLhFzINsogGaOb3z7e3jIZeiQwrWckxejjG0BrfeAhZ8vN6taFEcO48Sf%2F4T9mHIO6OZzZFlhET3G46yWsYXnTIcuXkJfREAEREAEREAERGCdCZiga7oGaUqV1Zp3Kp0cmiZC5rjY4dzKgyylMONSBR%2FAszPpJpiS5eQ4Rsuy2IJunmk6tvIiLFEccbLbEGVj%2B%2BeKx8XWnrNcbGoNMzLHwJvLMvvC55iEG7oSsRyK9YQPW%2Bfh07uLgAiIgAiIgAiIgF80irb1SdZyNsXGxoZppCTOrd5b21bITPbRRYLWXr4E3DkhRXlHgeVFmumrhciyG8OphfgyQejvMKm2uDzy1593fji5uMbuYy8UpVsg1BcREAEREAEREIG1JmCqyDmHOI6xvb2N3d1dA8LAHEuTpG4Qa2uNSS8vAiIgAiIgAiIgApcvARN0TdOgLEtMp1OMRkyf%2BkxrmjjUjY%2FeXb6voJ6JgAiIgAiIgAiIwHoTMEHH1apMtTJSF0WRLWowLBEUoVvvfx96exEQAREQAREQgRUgYIKubVuLztV1bYKOaxHatkeaZ7LZWoFBVBdFQAREQAREQATWm4AJOhYUTpIERVGA4o5bkkSoZ%2FP1pqO3FwEREAEREAEREIEVIGCCrqoqKxLMCB031pGzLWG5kfPXlw5ntBMBERABERABERABEbhMCJig4wpXFhbu%2B95Wu5oBBDvYcp2rrBguk7FSN0RABERABERABETgogRM0F30jA6KgAiIgAiIgAiIgAisBAEJupUYJnVSBERABERABERABA4mIEF3MBudEQEREAEREAEREIGVICBBtxLDpE6KgAiIgAiIgAiIwMEEJOgOZqMzIiACIiACIiACIrASBCToVmKY1EkREAEREAEREAEROJhATKsvbSIgAiIgAiIgAiIgAqtHgDqOn5g16LSJgAiIgAiIgAiIgAisHgHqOAm61Rs39VgEREAEREAEREAEFgQo6OzjnFsc1BcREAEREAEREAEREIHVIUAdJ0G3OuOlnoqACIiACIiACIjABQQo6EzUKUJ3ARsdEAEREAEREAEREIGVILAQdFmWrUSH1UkREAEREAEREAEREIHzCVDHJUmC6OTJk%2F18Pgc%2FTdMsPl3XgZ%2B%2B78%2B%2FU79EQAREQAREQAREQAQuGYFhFavNlQsROe4p5sLH8Qsv5Ikg6JbFnATdJRsvPUgEREAEREAEREAELiBAnXYxUcfIXJqm9jFBx9URbduaqAtRubC%2FoFUdEAEREAEREAEREAERuKQEgqALe4o5fhiQ4%2F5f4askfaIRB8gAAAAASUVORK5CYII%3D)%0A%0A%0A%0A%0A%E4%BB%8E%E4%B8%8A%E9%9D%A2%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BA%EF%BC%8C%E5%BD%93Thread-0%E8%BF%9B%E5%85%A5%E7%9D%A1%E7%9C%A0%E7%8A%B6%E6%80%81%E4%B9%8B%E5%90%8E%EF%BC%8CThread-1%E5%B9%B6%E6%B2%A1%E6%9C%89%E5%8E%BB%E6%89%A7%E8%A1%8C%E5%85%B7%E4%BD%93%E7%9A%84%E4%BB%BB%E5%8A%A1%E3%80%82%E5%8F%AA%E6%9C%89%E5%BD%93Thread-0%E6%89%A7%E8%A1%8C%E5%AE%8C%E4%B9%8B%E5%90%8E%EF%BC%8C%E6%AD%A4%E6%97%B6Thread-0%E9%87%8A%E6%94%BE%E4%BA%86%E5%AF%B9%E8%B1%A1%E9%94%81%EF%BC%8CThread-1%E6%89%8D%E5%BC%80%E5%A7%8B%E6%89%A7%E8%A1%8C%E3%80%82%0A%0A%E6%B3%A8%E6%84%8F%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%B0%83%E7%94%A8%E4%BA%86sleep%E6%96%B9%E6%B3%95%EF%BC%8C%E5%BF%85%E9%A1%BB%E6%8D%95%E8%8E%B7InterruptedException%E5%BC%82%E5%B8%B8%E6%88%96%E8%80%85%E5%B0%86%E8%AF%A5%E5%BC%82%E5%B8%B8%E5%90%91%E4%B8%8A%E5%B1%82%E6%8A%9B%E5%87%BA%E3%80%82%E5%BD%93%E7%BA%BF%E7%A8%8B%E7%9D%A1%E7%9C%A0%E6%97%B6%E9%97%B4%E6%BB%A1%E5%90%8E%EF%BC%8C%E4%B8%8D%E4%B8%80%E5%AE%9A%E4%BC%9A%E7%AB%8B%E5%8D%B3%E5%BE%97%E5%88%B0%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%AD%A4%E6%97%B6%E5%8F%AF%E8%83%BDCPU%E6%AD%A3%E5%9C%A8%E6%89%A7%E8%A1%8C%E5%85%B6%E4%BB%96%E7%9A%84%E4%BB%BB%E5%8A%A1%E3%80%82%E6%89%80%E4%BB%A5%E8%AF%B4%E8%B0%83%E7%94%A8sleep%E6%96%B9%E6%B3%95%E7%9B%B8%E5%BD%93%E4%BA%8E%E8%AE%A9%E7%BA%BF%E7%A8%8B%E8%BF%9B%E5%85%A5%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%E3%80%82%0A%0A%23%23%23%23%23%205.4%20yield%E6%96%B9%E6%B3%95%0A%0A%3E%20%E8%B0%83%E7%94%A8yield%E6%96%B9%E6%B3%95%E4%BC%9A%E8%AE%A9%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E4%BA%A4%E5%87%BACPU%E6%9D%83%E9%99%90%EF%BC%8C%E8%AE%A9CPU%E5%8E%BB%E6%89%A7%E8%A1%8C%E5%85%B6%E4%BB%96%E7%9A%84%E7%BA%BF%E7%A8%8B%E3%80%82%0A%3E%0A%3E%20%E5%AE%83%E8%B7%9Fsleep%E6%96%B9%E6%B3%95%E7%B1%BB%E4%BC%BC%EF%BC%8C%E5%90%8C%E6%A0%B7%E4%B8%8D%E4%BC%9A%E9%87%8A%E6%94%BE%E9%94%81%0A%3E%0A%3E%20%E4%BD%86%E6%98%AFyield%E4%B8%8D%E8%83%BD%E6%8E%A7%E5%88%B6%E5%85%B7%E4%BD%93%E7%9A%84%E4%BA%A4%E5%87%BACPU%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%8C%E5%8F%A6%E5%A4%96%EF%BC%8Cyield%E6%96%B9%E6%B3%95%E5%8F%AA%E8%83%BD%60%E8%AE%A9%E6%8B%A5%E6%9C%89%E7%9B%B8%E5%90%8C%E4%BC%98%E5%85%88%E7%BA%A7%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%9C%89%E8%8E%B7%E5%8F%96CPU%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E7%9A%84%E6%9C%BA%E4%BC%9A%60%E3%80%82%0A%0A%3E%20%E6%B3%A8%E6%84%8F%EF%BC%8C%E8%B0%83%E7%94%A8yield%E6%96%B9%E6%B3%95%E5%B9%B6%E4%B8%8D%E4%BC%9A%E8%AE%A9%E7%BA%BF%E7%A8%8B%E8%BF%9B%E5%85%A5%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%EF%BC%8C%E8%80%8C%E6%98%AF%E8%AE%A9%E7%BA%BF%E7%A8%8B%60%E9%87%8D%E5%9B%9E%E5%B0%B1%E7%BB%AA%E7%8A%B6%E6%80%81%60%EF%BC%8C%E5%AE%83%E5%8F%AA%E9%9C%80%E8%A6%81%E7%AD%89%E5%BE%85%E9%87%8D%E6%96%B0%E8%8E%B7%E5%8F%96CPU%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%8C%E8%BF%99%E4%B8%80%E7%82%B9%E6%98%AF%E5%92%8Csleep%E6%96%B9%E6%B3%95%E4%B8%8D%E4%B8%80%E6%A0%B7%E7%9A%84%E3%80%82%0A%0A%23%23%23%23%23%205.5%20join%E6%96%B9%E6%B3%95%0A%0Ajoin%E6%96%B9%E6%B3%95%E6%9C%89%E4%B8%89%E4%B8%AA%E9%87%8D%E8%BD%BD%E7%89%88%E6%9C%AC%EF%BC%9A%0A%0A%60%60%60%0Ajoin()%20%0Ajoin(long%20millis)%20%20%20%20%20%2F%2F%E5%8F%82%E6%95%B0%E4%B8%BA%E6%AF%AB%E7%A7%92%0Ajoin(long%20millis%2Cint%20nanoseconds)%20%20%20%20%2F%2F%E7%AC%AC%E4%B8%80%E5%8F%82%E6%95%B0%E4%B8%BA%E6%AF%AB%E7%A7%92%EF%BC%8C%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%8F%82%E6%95%B0%E4%B8%BA%E7%BA%B3%E7%A7%92%0A%60%60%60%0A%0A%3E%20%E5%81%87%E5%A6%82%E5%9C%A8main%E7%BA%BF%E7%A8%8B%E4%B8%AD%EF%BC%8C%E8%B0%83%E7%94%A8thread.join%E6%96%B9%E6%B3%95%EF%BC%8C%E5%88%99main%E6%96%B9%E6%B3%95%E4%BC%9A%E7%AD%89%E5%BE%85thread%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%E6%88%96%E8%80%85%E7%AD%89%E5%BE%85%E4%B8%80%E5%AE%9A%E7%9A%84%E6%97%B6%E9%97%B4%E3%80%82%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E8%B0%83%E7%94%A8%E7%9A%84%E6%98%AF%E6%97%A0%E5%8F%82join%E6%96%B9%E6%B3%95%EF%BC%8C%E5%88%99%E7%AD%89%E5%BE%85thread%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%B0%83%E7%94%A8%E7%9A%84%E6%98%AF%E6%8C%87%E5%AE%9A%E4%BA%86%E6%97%B6%E9%97%B4%E5%8F%82%E6%95%B0%E7%9A%84join%E6%96%B9%E6%B3%95%EF%BC%8C%E5%88%99%E7%AD%89%E5%BE%85%E4%B8%80%E5%AE%9A%E7%9A%84%E6%97%B6%E9%97%B4%E3%80%82%0A%3E%0A%3E%20%60join%E6%96%B9%E6%B3%95%E4%BC%9A%E8%AE%A9%E7%BA%BF%E7%A8%8B%E8%BF%9B%E5%85%A5%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BC%9A%E9%87%8A%E6%94%BE%E7%BA%BF%E7%A8%8B%E5%8D%A0%E6%9C%89%E7%9A%84%E9%94%81%EF%BC%8C%E5%B9%B6%E4%BA%A4%E5%87%BACPU%E6%89%A7%E8%A1%8C%E6%9D%83%E9%99%90%E3%80%82%60%0A%0A%E7%9C%8B%E4%B8%8B%E9%9D%A2%E4%B8%80%E4%B8%AA%E4%BE%8B%E5%AD%90%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20class%20Test%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20IOException%20%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E8%BF%9B%E5%85%A5%E7%BA%BF%E7%A8%8B%22%2BThread.currentThread().getName())%3B%0A%20%20%20%20%20%20%20%20Test%20test%20%3D%20new%20Test()%3B%0A%20%20%20%20%20%20%20%20MyThread%20thread1%20%3D%20test.new%20MyThread()%3B%0A%20%20%20%20%20%20%20%20thread1.start()%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%BA%BF%E7%A8%8B%22%2BThread.currentThread().getName()%2B%22%E7%AD%89%E5%BE%85%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20thread1.join()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%BA%BF%E7%A8%8B%22%2BThread.currentThread().getName()%2B%22%E7%BB%A7%E7%BB%AD%E6%89%A7%E8%A1%8C%22)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20TODO%20Auto-generated%20catch%20block%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%20%0A%20%0A%20%20%20%20class%20MyThread%20extends%20Thread%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E8%BF%9B%E5%85%A5%E7%BA%BF%E7%A8%8B%22%2BThread.currentThread().getName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Thread.currentThread().sleep(5000)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20TODO%3A%20handle%20exception%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%BA%BF%E7%A8%8B%22%2BThread.currentThread().getName()%2B%22%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%0A!%5B76fe687bc9f25be04d3707ad3cd12417.png%5D(en-resource%3A%2F%2Fdatabase%2F1065%3A1)%0A%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BA%EF%BC%8C%E5%BD%93%E8%B0%83%E7%94%A8thread1.join()%E6%96%B9%E6%B3%95%E5%90%8E%EF%BC%8Cmain%E7%BA%BF%E7%A8%8B%E4%BC%9A%E8%BF%9B%E5%85%A5%E7%AD%89%E5%BE%85%EF%BC%8C%E7%84%B6%E5%90%8E%E7%AD%89%E5%BE%85thread1%E6%89%A7%E8%A1%8C%E5%AE%8C%E4%B9%8B%E5%90%8E%E5%86%8D%E7%BB%A7%E7%BB%AD%E6%89%A7%E8%A1%8C%E3%80%82%0A%3E%0A%3E%20%E5%AE%9E%E9%99%85%E4%B8%8A%E8%B0%83%E7%94%A8join%E6%96%B9%E6%B3%95%E6%98%AF%E8%B0%83%E7%94%A8%E4%BA%86Object%E7%9A%84wait%E6%96%B9%E6%B3%95%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E6%9F%A5%E7%9C%8B%E6%BA%90%E7%A0%81%E5%BE%97%E7%9F%A5%EF%BC%9A%0A%0A!%5B4215789f955512da0381fd6136a133c8.png%5D(en-resource%3A%2F%2Fdatabase%2F1063%3A1)%0A%0A%0A%23%23%23%23%23%205.6%20wait%E6%96%B9%E6%B3%95%0A%0A%0A%60%60%60%0Await%E6%96%B9%E6%B3%95%E4%BC%9A%E8%AE%A9%E7%BA%BF%E7%A8%8B%E8%BF%9B%E5%85%A5%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BC%9A%E9%87%8A%E6%94%BE%E7%BA%BF%E7%A8%8B%E5%8D%A0%E6%9C%89%E7%9A%84%E9%94%81%EF%BC%8C%E5%B9%B6%E4%BA%A4%E5%87%BACPU%E6%89%A7%E8%A1%8C%E6%9D%83%E9%99%90%E3%80%82%0A%60%60%60%0A%0A%E7%94%B1%E4%BA%8Ewait%E6%96%B9%E6%B3%95%E4%BC%9A%E8%AE%A9%E7%BA%BF%E7%A8%8B%E9%87%8A%E6%94%BE%E5%AF%B9%E8%B1%A1%E9%94%81%EF%BC%8C%E6%89%80%E4%BB%A5join%E6%96%B9%E6%B3%95%E5%90%8C%E6%A0%B7%E4%BC%9A%E8%AE%A9%E7%BA%BF%E7%A8%8B%E9%87%8A%E6%94%BE%E5%AF%B9%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E6%8C%81%E6%9C%89%E7%9A%84%E9%94%81%E3%80%82%0A%0A%23%23%23%23%23%205.6%20interrupt%E6%96%B9%E6%B3%95%0A%0A%3E%0A%3E%20%E7%94%A8%E6%9D%A5%60%E4%B8%AD%E6%96%AD%E4%B8%80%E4%B8%AA%E6%AD%A3%E5%A4%84%E4%BA%8E%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%E7%9A%84%E7%BA%BF%E7%A8%8B%60%EF%BC%9B%0A%3E%0A%3E%20%E8%B0%83%E7%94%A8interrupt%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E4%BD%BF%E5%BE%97%E5%A4%84%E4%BA%8E%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%E5%BC%82%E5%B8%B8%EF%BC%8C%0A%3E%0A%3E%20%E9%80%9A%E8%BF%87interrupt%E6%96%B9%E6%B3%95%E5%92%8CisInterrupted()%E6%96%B9%E6%B3%95%E6%9D%A5%E5%81%9C%E6%AD%A2%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84%E7%BA%BF%E7%A8%8B%E3%80%82%0A%0A%E4%B8%8B%E9%9D%A2%E7%9C%8B%E4%B8%80%E4%B8%AA%E4%BE%8B%E5%AD%90%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20class%20Test%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20IOException%20%20%7B%0A%20%20%20%20%20%20%20%20Test%20test%20%3D%20new%20Test()%3B%0A%20%20%20%20%20%20%20%20MyThread%20thread%20%3D%20test.new%20MyThread()%3B%0A%20%20%20%20%20%20%20%20thread.start()%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.currentThread().sleep(2000)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20thread.interrupt()%3B%0A%20%20%20%20%7D%0A%20%20%20%20class%20MyThread%20extends%20Thread%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E8%BF%9B%E5%85%A5%E7%9D%A1%E7%9C%A0%E7%8A%B6%E6%80%81%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Thread.currentThread().sleep(10000)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%9D%A1%E7%9C%A0%E5%AE%8C%E6%AF%95%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E5%BE%97%E5%88%B0%E4%B8%AD%E6%96%AD%E5%BC%82%E5%B8%B8%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22run%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%EF%BC%9A%0A%0A!%5B4756b7a82ef4f434b603304746189f15.png%5D(en-resource%3A%2F%2Fdatabase%2F1064%3A1)%0A%0A%E4%BB%8E%E8%BF%99%E9%87%8C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BA%EF%BC%8C%60%E9%80%9A%E8%BF%87interrupt%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E4%B8%AD%E6%96%AD%E5%A4%84%E4%BA%8E%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%E7%9A%84%E7%BA%BF%E7%A8%8B%60%20%E9%82%A3%E4%B9%88%E8%83%BD%E4%B8%8D%E8%83%BD%E4%B8%AD%E6%96%AD%E5%A4%84%E4%BA%8E%E9%9D%9E%E9%98%BB%E5%A1%9E%E7%8A%B6%E6%80%81%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%91%A2%EF%BC%9F%E7%9C%8B%E4%B8%8B%E9%9D%A2%E8%BF%99%E4%B8%AA%E4%BE%8B%E5%AD%90%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20class%20Test%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20IOException%20%20%7B%0A%20%20%20%20%20%20%20%20Test%20test%20%3D%20new%20Test()%3B%0A%20%20%20%20%20%20%20%20MyThread%20thread%20%3D%20test.new%20MyThread()%3B%0A%20%20%20%20%20%20%20%20thread.start()%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.currentThread().sleep(2000)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20thread.interrupt()%3B%0A%20%20%20%20%7D%20%0A%20%0A%20%20%20%20class%20MyThread%20extends%20Thread%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20i%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20while(i%3CInteger.MAX_VALUE)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(i%2B%22%20while%E5%BE%AA%E7%8E%AF%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20i%2B%2B%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%7D%0A%60%60%60%0A%0A%0A%E8%BF%90%E8%A1%8C%E8%AF%A5%E7%A8%8B%E5%BA%8F%E4%BC%9A%E5%8F%91%E7%8E%B0%EF%BC%8Cwhile%E5%BE%AA%E7%8E%AF%E4%BC%9A%E4%B8%80%E7%9B%B4%E8%BF%90%E8%A1%8C%E7%9B%B4%E5%88%B0%E5%8F%98%E9%87%8Fi%E7%9A%84%E5%80%BC%E8%B6%85%E5%87%BAInteger.MAX_VALUE%E3%80%82%E6%89%80%E4%BB%A5%E8%AF%B4%3A%0A%0A%3E%20%E7%9B%B4%E6%8E%A5%E8%B0%83%E7%94%A8interrupt%E6%96%B9%E6%B3%95%E4%B8%8D%E8%83%BD%E4%B8%AD%E6%96%AD%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E4%B8%AD%E7%9A%84%E7%BA%BF%E7%A8%8B%E3%80%82%0A%0A%E4%BD%86%E6%98%AF%E5%A6%82%E6%9E%9C%E9%85%8D%E5%90%88%60isInterrupted()%60%E8%83%BD%E5%A4%9F%E4%B8%AD%E6%96%AD%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%9B%A0%E4%B8%BA%60%E8%B0%83%E7%94%A8interrupt%E6%96%B9%E6%B3%95%E7%9B%B8%E5%BD%93%E4%BA%8E%E5%B0%86%E4%B8%AD%E6%96%AD%E6%A0%87%E5%BF%97%E4%BD%8D%E7%BD%AE%E4%B8%BAtrue%EF%BC%8C%E9%82%A3%E4%B9%88%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E8%B0%83%E7%94%A8isInterrupted()%E5%88%A4%E6%96%AD%E4%B8%AD%E6%96%AD%E6%A0%87%E5%BF%97%E6%98%AF%E5%90%A6%E8%A2%AB%E7%BD%AE%E4%BD%8D%E6%9D%A5%E4%B8%AD%E6%96%AD%E7%BA%BF%E7%A8%8B%E7%9A%84%E6%89%A7%E8%A1%8C%60%E3%80%82%0A%0A%E6%AF%94%E5%A6%82%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20class%20Test%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20IOException%20%20%7B%0A%20%20%20%20%20%20%20%20Test%20test%20%3D%20new%20Test()%3B%0A%20%20%20%20%20%20%20%20MyThread%20thread%20%3D%20test.new%20MyThread()%3B%0A%20%20%20%20%20%20%20%20thread.start()%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.currentThread().sleep(2000)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20thread.interrupt()%3B%0A%20%20%20%20%7D%20%0A%0A%20%20%20%20class%20MyThread%20extends%20Thread%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20i%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20while(!isInterrupted()%20%26%26%20i%3CInteger.MAX_VALUE)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(i%2B%22%20while%E5%BE%AA%E7%8E%AF%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20i%2B%2B%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%7D%0A%60%60%60%0A%E8%BF%90%E8%A1%8C%E4%BC%9A%E5%8F%91%E7%8E%B0%EF%BC%8C%E6%89%93%E5%8D%B0%E8%8B%A5%E5%B9%B2%E4%B8%AA%E5%80%BC%E4%B9%8B%E5%90%8E%EF%BC%8Cwhile%E5%BE%AA%E7%8E%AF%E5%B0%B1%E5%81%9C%E6%AD%A2%E6%89%93%E5%8D%B0%E4%BA%86%E3%80%82%0A%0A%E4%BD%86%E6%98%AF%E4%B8%80%E8%88%AC%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%8D%E5%BB%BA%E8%AE%AE%E9%80%9A%E8%BF%87%E8%BF%99%E7%A7%8D%E6%96%B9%E5%BC%8F%E6%9D%A5%E4%B8%AD%E6%96%AD%E7%BA%BF%E7%A8%8B%EF%BC%8C%0A%0A%60%60%60%0A%E4%B8%80%E8%88%AC%E4%BC%9A%E5%9C%A8MyThread%E7%B1%BB%E4%B8%AD%E5%A2%9E%E5%8A%A0%E4%B8%80%E4%B8%AA%E5%B1%9E%E6%80%A7%20isStop%E6%9D%A5%E6%A0%87%E5%BF%97%E6%98%AF%E5%90%A6%E7%BB%93%E6%9D%9Fwhile%E5%BE%AA%E7%8E%AF%EF%BC%8C%E7%84%B6%E5%90%8E%E5%86%8D%E5%9C%A8while%E5%BE%AA%E7%8E%AF%E4%B8%AD%E5%88%A4%E6%96%ADisStop%E7%9A%84%E5%80%BC%0A%60%60%60%0A%0A%60%60%60java%0A%20class%20MyThread%20extends%20Thread%7B%0A%20%20%20private%20volatile%20boolean%20isStop%20%3D%20false%3B%0A%20%20%20%0A%20%20%20%40Override%0A%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20int%20i%20%3D%200%3B%0A%20%20%20%20%20%20%20while(!isStop)%7B%0A%20%20%20%20%20%20%20%20%20i%2B%2B%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20%0A%09public%20void%20setStop(boolean%20stop)%7B%0A%20%20%20%20%20%20%20%20%09this.isStop%20%3D%20stop%3B%0A%20%20%20%20%09%7D%0A%7D%0A%60%60%60%0A%E9%82%A3%E4%B9%88%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%A4%96%E9%9D%A2%E9%80%9A%E8%BF%87%E8%B0%83%E7%94%A8setStop%E6%96%B9%E6%B3%95%E6%9D%A5%E7%BB%88%E6%AD%A2while%E5%BE%AA%E7%8E%AF%E3%80%82%0A%0A7%EF%BC%89stop%E6%96%B9%E6%B3%95%0A%0Astop%E6%96%B9%E6%B3%95%E5%B7%B2%E7%BB%8F%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BA%9F%E5%BC%83%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%AE%83%E6%98%AF%E4%B8%80%E4%B8%AA%E4%B8%8D%E5%AE%89%E5%85%A8%E7%9A%84%E6%96%B9%E6%B3%95%E3%80%82%E5%9B%A0%E4%B8%BA%E8%B0%83%E7%94%A8stop%E6%96%B9%E6%B3%95%E4%BC%9A%E7%9B%B4%E6%8E%A5%E7%BB%88%E6%AD%A2run%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BC%9A%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AAThreadDeath%E9%94%99%E8%AF%AF%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%BA%BF%E7%A8%8B%E6%8C%81%E6%9C%89%E6%9F%90%E4%B8%AA%E5%AF%B9%E8%B1%A1%E9%94%81%E7%9A%84%E8%AF%9D%EF%BC%8C%E4%BC%9A%E5%AE%8C%E5%85%A8%E9%87%8A%E6%94%BE%E9%94%81%EF%BC%8C%E5%AF%BC%E8%87%B4%E5%AF%B9%E8%B1%A1%E7%8A%B6%E6%80%81%E4%B8%8D%E4%B8%80%E8%87%B4%E3%80%82%E6%89%80%E4%BB%A5stop%E6%96%B9%E6%B3%95%E5%9F%BA%E6%9C%AC%E6%98%AF%E4%B8%8D%E4%BC%9A%E8%A2%AB%E7%94%A8%E5%88%B0%E7%9A%84%E3%80%82%0A%0A8%EF%BC%89destroy%E6%96%B9%E6%B3%95%0A%0Adestroy%E6%96%B9%E6%B3%95%E4%B9%9F%E6%98%AF%E5%BA%9F%E5%BC%83%E7%9A%84%E6%96%B9%E6%B3%95%E3%80%82%E5%9F%BA%E6%9C%AC%E4%B8%8D%E4%BC%9A%E8%A2%AB%E4%BD%BF%E7%94%A8%E5%88%B0%E3%80%82%0A%0A%E4%BB%A5%E4%B8%8B%E6%98%AF%E5%85%B3%E7%B3%BB%E5%88%B0%E7%BA%BF%E7%A8%8B%E5%B1%9E%E6%80%A7%E7%9A%84%E5%87%A0%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%9A%0A%3E%201%EF%BC%89getId%20%E7%94%A8%E6%9D%A5%E5%BE%97%E5%88%B0%E7%BA%BF%E7%A8%8BID%0A2%EF%BC%89getName%E5%92%8CsetName%20%E7%94%A8%E6%9D%A5%E5%BE%97%E5%88%B0%E6%88%96%E8%80%85%E8%AE%BE%E7%BD%AE%E7%BA%BF%E7%A8%8B%E5%90%8D%E7%A7%B0%E3%80%82%0A3%EF%BC%89getPriority%E5%92%8CsetPriority%20%E7%94%A8%E6%9D%A5%E8%8E%B7%E5%8F%96%E5%92%8C%E8%AE%BE%E7%BD%AE%E7%BA%BF%E7%A8%8B%E4%BC%98%E5%85%88%E7%BA%A7%E3%80%82%0A4%EF%BC%89setDaemon%E5%92%8CisDaemon%20%E7%94%A8%E6%9D%A5%E8%AE%BE%E7%BD%AE%E7%BA%BF%E7%A8%8B%E6%98%AF%E5%90%A6%E6%88%90%E4%B8%BA%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%E5%92%8C%E5%88%A4%E6%96%AD%E7%BA%BF%E7%A8%8B%E6%98%AF%E5%90%A6%E6%98%AF%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%0A%0A%23%23%23%23%206.%20%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%E5%92%8C%E7%94%A8%E6%88%B7%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%8C%BA%E5%88%AB%0A%0A%3E%20%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%E4%BE%9D%E8%B5%96%E4%BA%8E%E5%88%9B%E5%BB%BA%E5%AE%83%E7%9A%84%E7%BA%BF%E7%A8%8B%EF%BC%8C%E8%80%8C%E7%94%A8%E6%88%B7%E7%BA%BF%E7%A8%8B%E5%88%99%E4%B8%8D%E4%BE%9D%E8%B5%96%E3%80%82%E4%B8%BE%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E4%BE%8B%E5%AD%90%EF%BC%9A%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E5%9C%A8main%E7%BA%BF%E7%A8%8B%E4%B8%AD%E5%88%9B%E5%BB%BA%E4%BA%86%E4%B8%80%E4%B8%AA%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%BD%93main%E6%96%B9%E6%B3%95%E8%BF%90%E8%A1%8C%E5%AE%8C%E6%AF%95%E4%B9%8B%E5%90%8E%EF%BC%8C%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%E4%B9%9F%E4%BC%9A%E9%9A%8F%E7%9D%80%E6%B6%88%E4%BA%A1%E3%80%82%0A%3E%20%E8%80%8C%E7%94%A8%E6%88%B7%E7%BA%BF%E7%A8%8B%E5%88%99%E4%B8%8D%E4%BC%9A%EF%BC%8C%E7%94%A8%E6%88%B7%E7%BA%BF%E7%A8%8B%E4%BC%9A%E4%B8%80%E7%9B%B4%E8%BF%90%E8%A1%8C%E7%9B%B4%E5%88%B0%E5%85%B6%E8%BF%90%E8%A1%8C%E5%AE%8C%E6%AF%95%E3%80%82%E5%9C%A8JVM%E4%B8%AD%EF%BC%8C%E5%83%8F%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E7%BA%BF%E7%A8%8B%E5%B0%B1%E6%98%AF%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B%E3%80%82%0A%0A%60%60%60%0AThread%E7%B1%BB%E6%9C%89%E4%B8%80%E4%B8%AA%E6%AF%94%E8%BE%83%E5%B8%B8%E7%94%A8%E7%9A%84%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95currentThread()%E7%94%A8%E6%9D%A5%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E3%80%82%0A%60%60%60%0A%0A%E5%9C%A8%E4%B8%8A%E9%9D%A2%E5%B7%B2%E7%BB%8F%E8%AF%B4%E5%88%B0%E4%BA%86Thread%E7%B1%BB%E4%B8%AD%E7%9A%84%E5%A4%A7%E9%83%A8%E5%88%86%E6%96%B9%E6%B3%95%EF%BC%8C%E9%82%A3%E4%B9%88Thread%E7%B1%BB%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%E5%88%B0%E5%BA%95%E4%BC%9A%E5%BC%95%E8%B5%B7%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81%E5%8F%91%E7%94%9F%E6%80%8E%E6%A0%B7%E7%9A%84%E5%8F%98%E5%8C%96%E5%91%A2%EF%BC%9F%E4%B8%8B%E9%9D%A2%E4%B8%80%E5%B9%85%E5%9B%BE%E5%B0%B1%E6%98%AF%E5%9C%A8%E4%B8%8A%E9%9D%A2%E7%9A%84%E5%9B%BE%E4%B8%8A%E8%BF%9B%E8%A1%8C%E6%94%B9%E8%BF%9B%E8%80%8C%E6%9D%A5%E7%9A%84%EF%BC%9A%0A%0A!%5B2997d494c79fe6081c9a6a5cfea2a3db.png%5D(en-resource%3A%2F%2Fdatabase%2F1062%3A1)%0A%0A

varchar(M)

创建时间:2022/3/5 12:07
更新时间:2022/3/6 0:17
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247513150&idx=1&sn=03945b317ebcad9805457a549a99383e&chksm=fd63a481ca142d978200d3d49a068e80d4054470a772fdd0210fc05840ba66bc79b94f1347b9&mpshare=1&scene=24&srcid=0225idj0I0rtzayphLwWS8YL&sharer_sharetime=1645774571844&sharer_shareid=5b3482cc84e779e76f71a8abd134e217&key=829ed4c67e70c1618174d16f111f978428735a6794baf1685d615b4258368fa44c46403b33b3c8a7a3aa0653c7d722d963073ef48f6bdc11df97b45ee5d96d242f6b809214c44956558e2b2dca9e003f669cf08268f0663d24e3c9c60ce94495c00c6a87696691da1cdea0367bb6189ba547ea4a2f941557ae390da22c56794d&ascene=0&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=6305002e&lang=zh_CN&exportkey=ARprA4A5hyu4tIRH4DbspQM%3D&acctmode=0&pass_ticket=F2WPyhtVOS4aqijC75%2BDP8V9An66kaJoq3LHMntICwvBAD2QifB75XNpT52fOADr&wx_header=0&fontgear=2

1. InnoDB行格式

我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为行格式或者记录格式。行格式有4种,分别是Dynamic、Compact、Redundant和Compressed

SHOW VARIABLES LIKE "innodb_default_row_format"

2. 变长字段长度列表

  • innodb怎么知道varchar真正有多长?— 变长字段长度列表
  • 变长字段数据占用的字节数按照列的顺序逆序存放
  • innodb最多分配2个字节去表示这个L,就像unsigned short类型,2个字节,寄存器最多只有16位来让你存这个长度,所以L记录范围是2^16 - 1 = 65535

这些变长字段(比如varchar)占用的存储空间分为两部分:

CREATE TABLE test ( 
c1 VARCHAR(10), 
c2 VARCHAR(10) NOT NULL, 
c3 CHAR(10), 
c4 VARCHAR(10)) CHARSET = utf8mb4;

INSERT INTO test ( c1, c2, c3, c4 )
VALUES('aaaa', '你好啊', 'cc', 'd'),('eeee', 'fff', NULL, NULL);

select length(c2), char_length(c2) from test;

3. varchar(M)能存多少个字符,为什么提示最大16383?

假设某个字符集中最多需要W字节来表示一个字符

- utf8mb4字符集中的W就是4
- utf8字符集中W就是3
- gbk字符集中的W就是2
- ascii字符集中的W就是1
CREATE TABLE test2 (
c1 VARCHAR(65500) not null,
c2 char(34) not null) CHARSET = ascii;

[42000][1118] Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

CREATE TABLE test2 (
c1 VARCHAR(65500) not null,
c2 char(33) not null) CHARSET = ascii;
CREATE TABLE test3 (
c1 char(65534) not null) CHARSET = ascii;

[42000][1074] Column length too big for column 'c1' (max = 255); use BLOB or TEXT instead

CHAR和VARCHAR

VARCHAR(4),最多存储4个字符,有几个字符存储几个。
存储字节数 = 数据值的字节和 + 1字节(长度标识位)

CHAR(4),最多存储4个字符,不足4个尾部用空格填满。
存储字节数 = 数据值的字节和 + 补位空格数概括地说,

VARCHAR和CHAR都是MySQL的字符串类型,存储多个字符、可设置最大存储的字符数,存储开销都与数据长度、字符集有关

w = 字符集单字符最大字节数
len = VARCHAR的长度标识位
VARCHAR的长度标识位: 存储开销是小于255只要1字节、大于255后使用两字节
n = 列宽度
N = NULL标识列占用字节数
假设一张表中存在N个可空字段,NULL标识位需要[N/8](向上取整)个字节

VARCHAR的宽度=(最大行大小 - N - (n* w + len)) / w

65535 行记录最大字节数
(128x2)为宽度x字符集占用字节数,gbk为两个字节
+2 因为128x2=256,超过255,VARCHAR的长度标识位: 存储开销是小于255只要1字节、大于255后使用两字节
如果把65019全部存储为一个varchar字段,同理VARCHAR的长度标识位需要两个字节即(65019-2)
(65019-2)/2 即为在gbk下的整个varchar字段宽度

# 65535-([(128x2)+2]+[(128x2)+2])=65019
# vm=(65019-2)/2=32508
create table test_varchar_length
(
    v1 varchar(128)   not null,
    v2 varchar(128)   not null,
    vm varchar(32508) not null
) CHARSET = gbk;

65535 行记录最大字节数
-2 即为NULL标识列占用字节数为两个节, 8个char(1)+ v1 varchar(128),超过8个bit需要用两个字节表示
(1x2x8) 为char(1)宽度x字符集占用字节数x8个char(1),gbk为两个字节
(128x2) 为宽度x字符集占用字节数,gbk为两个字节
+2 因为128x2=256,超过255,VARCHAR的长度标识位: 存储开销是小于255只要1字节、大于255后使用两字节
如果把65019全部存储为一个varchar字段,同理VARCHAR的长度标识位需要两个字节即(65019-2)
(65019-2)/2 即为在gbk下的整个varchar字段宽度

# 65535-2-((1x2x8)+[(128x2)+2]+[(128x2)+2])=65001
# vm=(65009-2)/2=32499
create table test_varchar_length2
(
    c1 char(1),
    c2 char(1),
    c3 char(1),
    c4 char(1),
    c5 char(1),
    c6 char(1),
    c7 char(1),
    c8 char(1),
    v1 varchar(128)  ,
    v2 varchar(128)  not null,
    vm varchar(32499) not null
) CHARSET = GBK;
%5Btoc%5D%0A%0A%23%23%201.%20InnoDB%E8%A1%8C%E6%A0%BC%E5%BC%8F%0A%0A%E6%88%91%E4%BB%AC%E5%B9%B3%E6%97%B6%E6%98%AF%E4%BB%A5%E8%AE%B0%E5%BD%95%E4%B8%BA%E5%8D%95%E4%BD%8D%E6%9D%A5%E5%90%91%E8%A1%A8%E4%B8%AD%E6%8F%92%E5%85%A5%E6%95%B0%E6%8D%AE%E7%9A%84%EF%BC%8C%E8%BF%99%E4%BA%9B%E8%AE%B0%E5%BD%95%E5%9C%A8%E7%A3%81%E7%9B%98%E4%B8%8A%E7%9A%84%E5%AD%98%E6%94%BE%E6%96%B9%E5%BC%8F%E4%B9%9F%E8%A2%AB%E7%A7%B0%E4%B8%BA%E8%A1%8C%E6%A0%BC%E5%BC%8F%E6%88%96%E8%80%85%E8%AE%B0%E5%BD%95%E6%A0%BC%E5%BC%8F%E3%80%82%E8%A1%8C%E6%A0%BC%E5%BC%8F%E6%9C%894%E7%A7%8D%EF%BC%8C%E5%88%86%E5%88%AB%E6%98%AFDynamic%E3%80%81Compact%E3%80%81Redundant%E5%92%8CCompressed%0A%0A!%5B9a4a106d645d8495313a5049b796036b.png%5D(en-resource%3A%2F%2Fdatabase%2F1375%3A1)%0A%0A%60%60%60sql%0ASHOW%C2%A0VARIABLES%C2%A0LIKE%C2%A0%22innodb_default_row_format%22%0A%60%60%60%0A%0A%23%23%202.%20%E5%8F%98%E9%95%BF%E5%AD%97%E6%AE%B5%E9%95%BF%E5%BA%A6%E5%88%97%E8%A1%A8%0A%3E%20-%20innodb%E6%80%8E%E4%B9%88%E7%9F%A5%E9%81%93varchar%E7%9C%9F%E6%AD%A3%E6%9C%89%E5%A4%9A%E9%95%BF%EF%BC%9F%E2%80%94%20%E5%8F%98%E9%95%BF%E5%AD%97%E6%AE%B5%E9%95%BF%E5%BA%A6%E5%88%97%E8%A1%A8%0A%3E%20-%20%E5%8F%98%E9%95%BF%E5%AD%97%E6%AE%B5%E6%95%B0%E6%8D%AE%E5%8D%A0%E7%94%A8%E7%9A%84%E5%AD%97%E8%8A%82%E6%95%B0%E6%8C%89%E7%85%A7%E5%88%97%E7%9A%84%E9%A1%BA%E5%BA%8F%E9%80%86%E5%BA%8F%E5%AD%98%E6%94%BE%0A%3E%20-%20%20**innodb%E6%9C%80%E5%A4%9A%E5%88%86%E9%85%8D2%E4%B8%AA%E5%AD%97%E8%8A%82%E5%8E%BB%E8%A1%A8%E7%A4%BA%E8%BF%99%E4%B8%AAL**%EF%BC%8C%E5%B0%B1%E5%83%8Funsigned%20short%E7%B1%BB%E5%9E%8B%EF%BC%8C2%E4%B8%AA%E5%AD%97%E8%8A%82%EF%BC%8C%E5%AF%84%E5%AD%98%E5%99%A8%E6%9C%80%E5%A4%9A%E5%8F%AA%E6%9C%8916%E4%BD%8D%E6%9D%A5%E8%AE%A9%E4%BD%A0%E5%AD%98%E8%BF%99%E4%B8%AA%E9%95%BF%E5%BA%A6%EF%BC%8C%E6%89%80%E4%BB%A5L%E8%AE%B0%E5%BD%95%E8%8C%83%E5%9B%B4%E6%98%AF%602%5E16%20-%201%20%3D%2065535%60%0A%0A%0A%3E%20%E8%BF%99%E4%BA%9B%E5%8F%98%E9%95%BF%E5%AD%97%E6%AE%B5(%E6%AF%94%E5%A6%82varchar)%E5%8D%A0%E7%94%A8%E7%9A%84%E5%AD%98%E5%82%A8%E7%A9%BA%E9%97%B4%E5%88%86%E4%B8%BA%E4%B8%A4%E9%83%A8%E5%88%86%EF%BC%9A%0A-%20%E7%9C%9F%E6%AD%A3%E7%9A%84%E6%95%B0%E6%8D%AE%E5%86%85%E5%AE%B9%E9%83%A8%E5%88%86%EF%BC%8C%E6%94%BE%E5%9C%A8%E5%AF%B9%E5%BA%94%E7%9A%84%E5%88%97%0A-%20%E7%9C%9F%E5%AE%9E%E5%8D%A0%E7%94%A8%E7%9A%84%E5%AD%97%E8%8A%82%E6%95%B0%EF%BC%8C%E6%94%BE%E5%9C%A8%E5%8F%98%E9%95%BF%E5%AD%97%E6%AE%B5%E5%88%97%E8%A1%A8%E9%83%A8%E5%88%86%0A%0A%60%60%60sql%0ACREATE%20TABLE%20test%20(%20%0Ac1%20VARCHAR(10)%2C%20%0Ac2%20VARCHAR(10)%20NOT%20NULL%2C%20%0Ac3%20CHAR(10)%2C%20%0Ac4%20VARCHAR(10))%20CHARSET%20%3D%20utf8mb4%3B%0A%0AINSERT%20INTO%20test%20(%20c1%2C%20c2%2C%20c3%2C%20c4%20)%0AVALUES('aaaa'%2C%20'%E4%BD%A0%E5%A5%BD%E5%95%8A'%2C%20'cc'%2C%20'd')%2C('eeee'%2C%20'fff'%2C%20NULL%2C%20NULL)%3B%0A%60%60%60%0A%0A%3E%20%60select%20length(c2)%2C%20char_length(c2)%20from%20test%3B%60%0A%0A!%5B10a827ff7dd22086f85547508bf44fb1.png%5D(en-resource%3A%2F%2Fdatabase%2F1377%3A1)%0A%0A%0A%23%23%203.%20varchar(M)%E8%83%BD%E5%AD%98%E5%A4%9A%E5%B0%91%E4%B8%AA%E5%AD%97%E7%AC%A6%2C%E4%B8%BA%E4%BB%80%E4%B9%88%E6%8F%90%E7%A4%BA%E6%9C%80%E5%A4%A716383%EF%BC%9F%0A%0A%0A%3E%20%E5%81%87%E8%AE%BE%E6%9F%90%E4%B8%AA%E5%AD%97%E7%AC%A6%E9%9B%86%E4%B8%AD%E6%9C%80%E5%A4%9A%E9%9C%80%E8%A6%81W%E5%AD%97%E8%8A%82%E6%9D%A5%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%0A%60%60%60%0A-%20utf8mb4%E5%AD%97%E7%AC%A6%E9%9B%86%E4%B8%AD%E7%9A%84W%E5%B0%B1%E6%98%AF4%0A-%20utf8%E5%AD%97%E7%AC%A6%E9%9B%86%E4%B8%ADW%E5%B0%B1%E6%98%AF3%0A-%20gbk%E5%AD%97%E7%AC%A6%E9%9B%86%E4%B8%AD%E7%9A%84W%E5%B0%B1%E6%98%AF2%0A-%20ascii%E5%AD%97%E7%AC%A6%E9%9B%86%E4%B8%AD%E7%9A%84W%E5%B0%B1%E6%98%AF1%0A%60%60%60%0A%0A-%20%E5%AF%B9%E4%BA%8E%E5%8F%98%E9%95%BF%E7%B1%BB%E5%9E%8BVARCHAR(M)%E6%9D%A5%E8%AF%B4%EF%BC%8C%E8%BF%99%E7%A7%8D%E7%B1%BB%E5%9E%8B%E8%A1%A8%E7%A4%BA%E8%83%BD%E5%AD%98%E5%82%A8%E6%9C%80%E5%A4%9AM%E4%B8%AA%E5%AD%97%E7%AC%A6%EF%BC%88%E6%B3%A8%E6%84%8F%E6%98%AF%E5%AD%97%E7%AC%A6%E4%B8%8D%E6%98%AF%E5%AD%97%E8%8A%82%EF%BC%89%E6%89%80%E4%BB%A5%E8%BF%99%E4%B8%AA%E7%B1%BB%E5%9E%8B%E8%83%BD%E8%A1%A8%E7%A4%BA%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%9C%80%E5%A4%9A%E5%8D%A0%E7%94%A8%E7%9A%84%E5%AD%97%E8%8A%82%E6%95%B0%E5%B0%B1%E6%98%AFM%20%C3%97%20W%0A-%20%E5%81%87%E8%AE%BE%E5%AE%83%E5%AE%9E%E9%99%85%E5%AD%98%E5%82%A8%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8D%A0%E7%94%A8%E7%9A%84%E5%AD%97%E8%8A%82%E6%95%B0%E6%98%AFL%0A-%20innodb%E4%B8%BA%E4%BA%86%E8%AE%B0%E5%BD%95%E4%B8%80%E4%B8%8Bvarchar%E7%9C%9F%E5%AE%9E%E5%AD%98%E5%82%A8%E5%A4%9A%E5%B0%91%E4%B8%AA%E5%AD%97%E8%8A%82%EF%BC%8C%E6%9C%80%E5%A4%9A%E5%88%86%E9%85%8D2%E4%B8%AA%E5%AD%97%E8%8A%82%E7%9A%84%E7%A9%BA%E9%97%B4%E5%8E%BB%E8%AE%B0%E5%BD%95%EF%BC%8C2%E4%B8%AA%E5%AD%97%E8%8A%8216%E4%B8%AA%E6%AF%94%E7%89%B9%E4%BD%8D%EF%BC%8C%E5%85%A8%E9%83%A8%E4%B8%BA1%EF%BC%8C%E6%9C%80%E5%A4%A7%E8%83%BD%E8%AE%B0%E5%BD%95%E7%9A%84%E6%95%B0%E5%AD%97%E6%98%AF2%5E16-1%E6%98%AF65535%E4%B8%AA%EF%BC%8Cinnodb%E6%9C%80%E5%A4%A7%E8%83%BD%E8%AE%B0%E5%BD%95varchar%E5%8D%A0%E7%94%A8%E7%9A%84%E5%AD%97%E8%8A%82%E6%95%B0%E5%B0%B1%E6%98%AF65535%E4%B8%AA%EF%BC%8Cutf8mb4%E5%AD%97%E7%AC%A6%E9%9B%86%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E6%98%AF%E6%9C%80%E5%A4%A7%E6%98%AF4%E4%B8%AA%E5%AD%97%E8%8A%82%0A65535%20%2F%204%20%3D%2016383.75%EF%BC%8C%E5%8F%AA%E8%A6%81varchar%E5%AD%97%E7%AC%A6%E6%95%B0%E4%B8%8D%E8%B6%85%E8%BF%8716383%E4%B8%AA%EF%BC%8Cinnodb%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%AE%B0%E5%BD%95%E7%9C%9F%E5%AE%9E%E5%8D%A0%E7%94%A8%E7%9A%84%E9%95%BF%E5%BA%A6L%EF%BC%8C%E5%86%8D%E5%A4%9A%E5%B0%B1%E8%AE%B0%E5%BD%95%E4%B8%8D%E4%BA%86%E4%BA%86%EF%BC%81%E6%89%80%E4%BB%A5%E5%B0%B1%E8%83%BD%E8%A7%A3%E9%87%8A%E5%88%9A%E5%88%9A%E7%9A%84%E5%9B%BE%E4%BA%86%EF%BC%8Cvarchar(20000)%E4%B8%8D%E8%A1%8C%EF%BC%8C%E6%9C%80%E5%A4%A7%E4%B9%9F%E5%B0%B116383%E4%B8%AA%E5%AD%97%E7%AC%A6%0A%0A%0A%60%60%60%0ACREATE%20TABLE%20test2%20(%0Ac1%20VARCHAR(65500)%20not%20null%2C%0Ac2%20char(34)%20not%20null)%20CHARSET%20%3D%20ascii%3B%0A%60%60%60%0A%0A%5B42000%5D%5B1118%5D%20Row%20size%20too%20large.%20The%20maximum%20row%20size%20for%20the%20used%20table%20type%2C%20not%20counting%20BLOBs%2C%20is%2065535.%20This%20includes%20storage%20overhead%2C%20check%20the%20manual.%20You%20have%20to%20change%20some%20columns%20to%20TEXT%20or%20BLOBs%0A%0A%0A%60%60%60%0ACREATE%20TABLE%20test2%20(%0Ac1%20VARCHAR(65500)%20not%20null%2C%0Ac2%20char(33)%20not%20null)%20CHARSET%20%3D%20ascii%3B%0A%60%60%60%0A%0A%0A%0A%60%60%60%0ACREATE%20TABLE%20test3%20(%0Ac1%20char(65534)%20not%20null)%20CHARSET%20%3D%20ascii%3B%0A%60%60%60%0A%5B42000%5D%5B1074%5D%20Column%20length%20too%20big%20for%20column%20'c1'%20(max%20%3D%20255)%3B%20use%20BLOB%20or%20TEXT%20instead%0A%0A%23%23%20CHAR%E5%92%8CVARCHAR%0A%0A%3E%20VARCHAR(4)%EF%BC%8C%E6%9C%80%E5%A4%9A%E5%AD%98%E5%82%A84%E4%B8%AA%E5%AD%97%E7%AC%A6%EF%BC%8C%E6%9C%89%E5%87%A0%E4%B8%AA%E5%AD%97%E7%AC%A6%E5%AD%98%E5%82%A8%E5%87%A0%E4%B8%AA%E3%80%82%0A%3E%20%E5%AD%98%E5%82%A8%E5%AD%97%E8%8A%82%E6%95%B0%20%3D%20%E6%95%B0%E6%8D%AE%E5%80%BC%E7%9A%84%E5%AD%97%E8%8A%82%E5%92%8C%20%2B%201%E5%AD%97%E8%8A%82%EF%BC%88%E9%95%BF%E5%BA%A6%E6%A0%87%E8%AF%86%E4%BD%8D%EF%BC%89%0A%0A%3E%20CHAR(4)%EF%BC%8C%E6%9C%80%E5%A4%9A%E5%AD%98%E5%82%A84%E4%B8%AA%E5%AD%97%E7%AC%A6%EF%BC%8C%E4%B8%8D%E8%B6%B34%E4%B8%AA%E5%B0%BE%E9%83%A8%E7%94%A8%E7%A9%BA%E6%A0%BC%E5%A1%AB%E6%BB%A1%E3%80%82%0A%3E%20%E5%AD%98%E5%82%A8%E5%AD%97%E8%8A%82%E6%95%B0%20%3D%20%E6%95%B0%E6%8D%AE%E5%80%BC%E7%9A%84%E5%AD%97%E8%8A%82%E5%92%8C%20%2B%20%E8%A1%A5%E4%BD%8D%E7%A9%BA%E6%A0%BC%E6%95%B0%E6%A6%82%E6%8B%AC%E5%9C%B0%E8%AF%B4%EF%BC%8C%0A%0A%3E%20VARCHAR%E5%92%8CCHAR%E9%83%BD%E6%98%AFMySQL%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%AD%98%E5%82%A8%E5%A4%9A%E4%B8%AA%E5%AD%97%E7%AC%A6%E3%80%81%E5%8F%AF%E8%AE%BE%E7%BD%AE%E6%9C%80%E5%A4%A7%E5%AD%98%E5%82%A8%E7%9A%84%E5%AD%97%E7%AC%A6%E6%95%B0%EF%BC%8C%E5%AD%98%E5%82%A8%E5%BC%80%E9%94%80%E9%83%BD%E4%B8%8E%E6%95%B0%E6%8D%AE%E9%95%BF%E5%BA%A6%E3%80%81%E5%AD%97%E7%AC%A6%E9%9B%86%E6%9C%89%E5%85%B3%0A%0A%3E%20w%20%3D%20%E5%AD%97%E7%AC%A6%E9%9B%86%E5%8D%95%E5%AD%97%E7%AC%A6%E6%9C%80%E5%A4%A7%E5%AD%97%E8%8A%82%E6%95%B0%0A%3E%20len%20%3D%20VARCHAR%E7%9A%84%E9%95%BF%E5%BA%A6%E6%A0%87%E8%AF%86%E4%BD%8D%0A%3E%20VARCHAR%E7%9A%84%E9%95%BF%E5%BA%A6%E6%A0%87%E8%AF%86%E4%BD%8D%3A%20%E5%AD%98%E5%82%A8%E5%BC%80%E9%94%80%E6%98%AF%E5%B0%8F%E4%BA%8E255%E5%8F%AA%E8%A6%811%E5%AD%97%E8%8A%82%E3%80%81%E5%A4%A7%E4%BA%8E255%E5%90%8E%E4%BD%BF%E7%94%A8%E4%B8%A4%E5%AD%97%E8%8A%82%20%20%20%20%0A%3E%20n%20%3D%20%E5%88%97%E5%AE%BD%E5%BA%A6%20%20%0A%3E%20N%20%3D%20NULL%E6%A0%87%E8%AF%86%E5%88%97%E5%8D%A0%E7%94%A8%E5%AD%97%E8%8A%82%E6%95%B0%0A%3E%20%E5%81%87%E8%AE%BE%E4%B8%80%E5%BC%A0%E8%A1%A8%E4%B8%AD%E5%AD%98%E5%9C%A8N%E4%B8%AA%E5%8F%AF%E7%A9%BA%E5%AD%97%E6%AE%B5%EF%BC%8CNULL%E6%A0%87%E8%AF%86%E4%BD%8D%E9%9C%80%E8%A6%81%5BN%2F8%5D%EF%BC%88%E5%90%91%E4%B8%8A%E5%8F%96%E6%95%B4%EF%BC%89%E4%B8%AA%E5%AD%97%E8%8A%82%0A%60%60%60%0AVARCHAR%E7%9A%84%E5%AE%BD%E5%BA%A6%3D(%E6%9C%80%E5%A4%A7%E8%A1%8C%E5%A4%A7%E5%B0%8F%20-%20N%20-%20(n*%20w%20%2B%20len))%20%2F%20w%0A%60%60%60%0A%0A%0A%3E%2065535%20%E8%A1%8C%E8%AE%B0%E5%BD%95%E6%9C%80%E5%A4%A7%E5%AD%97%E8%8A%82%E6%95%B0%0A%3E%20(128x2)%E4%B8%BA%E5%AE%BD%E5%BA%A6x%E5%AD%97%E7%AC%A6%E9%9B%86%E5%8D%A0%E7%94%A8%E5%AD%97%E8%8A%82%E6%95%B0%EF%BC%8Cgbk%E4%B8%BA%E4%B8%A4%E4%B8%AA%E5%AD%97%E8%8A%82%0A%3E%20%2B2%20%E5%9B%A0%E4%B8%BA128x2%3D256%EF%BC%8C%E8%B6%85%E8%BF%87255%EF%BC%8CVARCHAR%E7%9A%84%E9%95%BF%E5%BA%A6%E6%A0%87%E8%AF%86%E4%BD%8D%3A%20%E5%AD%98%E5%82%A8%E5%BC%80%E9%94%80%E6%98%AF%E5%B0%8F%E4%BA%8E255%E5%8F%AA%E8%A6%811%E5%AD%97%E8%8A%82%E3%80%81%E5%A4%A7%E4%BA%8E255%E5%90%8E%E4%BD%BF%E7%94%A8%E4%B8%A4%E5%AD%97%E8%8A%82%0A%3E%20%E5%A6%82%E6%9E%9C%E6%8A%8A65019%E5%85%A8%E9%83%A8%E5%AD%98%E5%82%A8%E4%B8%BA%E4%B8%80%E4%B8%AAvarchar%E5%AD%97%E6%AE%B5%EF%BC%8C%E5%90%8C%E7%90%86VARCHAR%E7%9A%84%E9%95%BF%E5%BA%A6%E6%A0%87%E8%AF%86%E4%BD%8D%E9%9C%80%E8%A6%81%E4%B8%A4%E4%B8%AA%E5%AD%97%E8%8A%82%E5%8D%B3(65019-2)%0A%3E%20(65019-2)%2F2%20%E5%8D%B3%E4%B8%BA%E5%9C%A8gbk%E4%B8%8B%E7%9A%84%E6%95%B4%E4%B8%AAvarchar%E5%AD%97%E6%AE%B5%E5%AE%BD%E5%BA%A6%0A%60%60%60sql%0A%23%2065535-(%5B(128x2)%2B2%5D%2B%5B(128x2)%2B2%5D)%3D65019%0A%23%20vm%3D(65019-2)%2F2%3D32508%0Acreate%20table%20test_varchar_length%0A(%0A%20%20%20%20v1%20varchar(128)%20%20%20not%20null%2C%0A%20%20%20%20v2%20varchar(128)%20%20%20not%20null%2C%0A%20%20%20%20vm%20varchar(32508)%20not%20null%0A)%20CHARSET%20%3D%20gbk%3B%0A%60%60%60%0A%0A%3E%2065535%20%E8%A1%8C%E8%AE%B0%E5%BD%95%E6%9C%80%E5%A4%A7%E5%AD%97%E8%8A%82%E6%95%B0%0A%3E%20%60-2%60%20%E5%8D%B3%E4%B8%BANULL%E6%A0%87%E8%AF%86%E5%88%97%E5%8D%A0%E7%94%A8%E5%AD%97%E8%8A%82%E6%95%B0%E4%B8%BA%E4%B8%A4%E4%B8%AA%E8%8A%82%EF%BC%8C%20%608%E4%B8%AAchar(1)%60%2B%20%60v1%20varchar(128)%60%2C%E8%B6%85%E8%BF%878%E4%B8%AAbit%E9%9C%80%E8%A6%81%E7%94%A8%E4%B8%A4%E4%B8%AA%E5%AD%97%E8%8A%82%E8%A1%A8%E7%A4%BA%0A%3E%20%60(1x2x8)%60%20%E4%B8%BAchar(1)%E5%AE%BD%E5%BA%A6x%E5%AD%97%E7%AC%A6%E9%9B%86%E5%8D%A0%E7%94%A8%E5%AD%97%E8%8A%82%E6%95%B0x8%E4%B8%AAchar(1)%EF%BC%8Cgbk%E4%B8%BA%E4%B8%A4%E4%B8%AA%E5%AD%97%E8%8A%82%0A%3E%20%60(128x2)%60%20%E4%B8%BA%E5%AE%BD%E5%BA%A6x%E5%AD%97%E7%AC%A6%E9%9B%86%E5%8D%A0%E7%94%A8%E5%AD%97%E8%8A%82%E6%95%B0%EF%BC%8Cgbk%E4%B8%BA%E4%B8%A4%E4%B8%AA%E5%AD%97%E8%8A%82%0A%3E%20%60%2B2%60%20%E5%9B%A0%E4%B8%BA128x2%3D256%EF%BC%8C%E8%B6%85%E8%BF%87255%EF%BC%8CVARCHAR%E7%9A%84%E9%95%BF%E5%BA%A6%E6%A0%87%E8%AF%86%E4%BD%8D%3A%20%E5%AD%98%E5%82%A8%E5%BC%80%E9%94%80%E6%98%AF%E5%B0%8F%E4%BA%8E255%E5%8F%AA%E8%A6%811%E5%AD%97%E8%8A%82%E3%80%81%E5%A4%A7%E4%BA%8E255%E5%90%8E%E4%BD%BF%E7%94%A8%E4%B8%A4%E5%AD%97%E8%8A%82%0A%3E%20%E5%A6%82%E6%9E%9C%E6%8A%8A65019%E5%85%A8%E9%83%A8%E5%AD%98%E5%82%A8%E4%B8%BA%E4%B8%80%E4%B8%AAvarchar%E5%AD%97%E6%AE%B5%EF%BC%8C%E5%90%8C%E7%90%86VARCHAR%E7%9A%84%E9%95%BF%E5%BA%A6%E6%A0%87%E8%AF%86%E4%BD%8D%E9%9C%80%E8%A6%81%E4%B8%A4%E4%B8%AA%E5%AD%97%E8%8A%82%E5%8D%B3(65019-2)%0A%3E%20%60(65019-2)%2F2%60%20%E5%8D%B3%E4%B8%BA%E5%9C%A8gbk%E4%B8%8B%E7%9A%84%E6%95%B4%E4%B8%AAvarchar%E5%AD%97%E6%AE%B5%E5%AE%BD%E5%BA%A6%0A%60%60%60sql%0A%23%2065535-2-((1x2x8)%2B%5B(128x2)%2B2%5D%2B%5B(128x2)%2B2%5D)%3D65001%0A%23%20vm%3D(65009-2)%2F2%3D32499%0Acreate%20table%20test_varchar_length2%0A(%0A%20%20%20%20c1%20char(1)%2C%0A%20%20%20%20c2%20char(1)%2C%0A%20%20%20%20c3%20char(1)%2C%0A%20%20%20%20c4%20char(1)%2C%0A%20%20%20%20c5%20char(1)%2C%0A%20%20%20%20c6%20char(1)%2C%0A%20%20%20%20c7%20char(1)%2C%0A%20%20%20%20c8%20char(1)%2C%0A%20%20%20%20v1%20varchar(128)%20%20%2C%0A%20%20%20%20v2%20varchar(128)%20%20not%20null%2C%0A%20%20%20%20vm%20varchar(32499)%20not%20null%0A)%20CHARSET%20%3D%20GBK%3B%0A%60%60%60

index

创建时间:2022/1/26 11:26
更新时间:2022/2/21 23:38
作者:Chris
来源:https://dev.mysql.com/doc/refman/8.0/en/create-index.html#create-index-multi-valued

CREATE INDEX Statement

When the innodb_stats_persistent setting is enabled, run the ANALYZE TABLE statement for an InnoDB table after creating an index on that table.

MySQL InnoDB配置统计信息

A key_part specification can end with ASC or DESC to specify whether index values are stored in ascending or descending order. The default is ascending if no order specifier is given.
 ASC and DESC are not permitted for HASH indexes. 
 ASC and DESC are also not supported for multi-valued indexes.
 As of MySQL 8.0.12, ASC and DESC are not permitted for SPATIAL indexes.

Column Prefix Key Parts

For string columns, indexes can be created that use only the leading part of column values, using col_name(length) syntax to specify an index prefix length:
Prefixes can be specified for CHAR,VARCHARBINARY, and VARBINARY key parts.

Prefixes must be specified for BLOB and TEXT key parts.

If names in the column usually differ in the first 10 characters, lookups performed using this index should not be much slower than using an index created from the entire name column. Also, using column prefixes for indexes can make the index file much smaller, which could save a lot of disk space and might also speed up INSERT operations.

CREATE INDEX part_of_name ON customer (name(10));

the index entry for a given t1 row includes the full col1 value and a prefix of the col2 value consisting of its first 10 characters

CREATE TABLE t1 (
  col1 VARCHAR(10),
  col2 VARCHAR(20),
  INDEX (col1, col2(10))
);

Functional Key Parts

MySQL 8.0.13 and higher supports functional key parts

CREATE TABLE t1 (col1 INT, col2 INT, INDEX func_index ((ABS(col1))));
CREATE INDEX idx1 ON t1 ((col1 + col2));
CREATE INDEX idx2 ON t1 ((col1 + col2), (col1 - col2), col1);
ALTER TABLE t1 ADD INDEX ((col1 * 40) DESC);
  • In index definitions, enclose expressions within parentheses to distinguish them from columns or column prefixes.
INDEX ((col1 + col2), (col3 - col4))

This produces an error; the expressions are not enclosed within parentheses:

INDEX (col1 + col2, col3 - col4)
  • A functional key part cannot consist solely of a column name. For example, this is not permitted:
INDEX ((col1), (col2))

Instead, write the key parts as nonfunctional key parts, without parentheses:

INDEX (col1, col2)
  • A functional key part expression cannot refer to column prefixes.
    For a workaround, see the discussion of SUBSTRING() and CAST()

the WHERE clause must contain SUBSTRING() with the same arguments.
In the following example, only the second SELECT is able to use the index because that is the only query in which the arguments to SUBSTRING() match the index specification

CREATE TABLE tbl (
  col1 LONGTEXT,
  INDEX idx1 ((SUBSTRING(col1, 1, 10)))
);
SELECT * FROM tbl WHERE SUBSTRING(col1, 1, 9) = '123456789';
SELECT * FROM tbl WHERE SUBSTRING(col1, 1, 10) = '1234567890';
  • Functional indexes are implemented as hidden virtual generated columns
  • The virtual generated column itself requires no storage. The index itself takes up storage space as any other index.
  • primary keys cannot include functional key parts, A primary key requires the generated column to be stored, but functional key parts are implemented as virtual generated columns, not stored generated columns.
  • SPATIAL and FULLTEXT indexes cannot have functional key parts.
  • If a table contains no primary key, InnoDB automatically promotes the first UNIQUE NOT NULL index to the primary key. This is not supported for UNIQUE NOT NULL indexes that have functional key parts.
  • To remove a column that is referenced by a functional key part, the index must be removed first. Otherwise, an error occurs.

https://blog.csdn.net/freshlover/article/details/8634610
https://www.cnblogs.com/gengyufei/p/14295405.html
https://blog.csdn.net/bigtree_3721/article/details/87478706

%5Btoc%5D%0A%0A%5BCREATE%20INDEX%20Statement%5D(https%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2F8.0%2Fen%2Fcreate-index.html%23create-index-multi-valued)%0A%0A!%5Bd12796069784da137d208feb4abd01dd.png%5D(en-resource%3A%2F%2Fdatabase%2F1261%3A1)%0A%0A%3E%20When%20the%C2%A0%60innodb_stats_persistent%60%C2%A0setting%20is%20enabled%2C%20run%20the%C2%A0%60ANALYZE%20TABLE%60%C2%A0statement%20for%20an%C2%A0InnoDB%C2%A0table%20after%20creating%20an%20index%20on%20that%20table.%0A%0A%5BMySQL%20InnoDB%E9%85%8D%E7%BD%AE%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF%5D(https%3A%2F%2Fblog.csdn.net%2Fwanbin6470398%2Farticle%2Fdetails%2F82182239)%0A%0A%0A%3E%20A%C2%A0key_part%C2%A0specification%20can%20end%20with%C2%A0**ASC**%C2%A0or%C2%A0**DESC**%C2%A0to%20specify%20whether%20index%20values%20are%20stored%20in%20ascending%20or%20descending%20order.%20The%20default%20is%20ascending%20if%20no%20order%20specifier%20is%20given.%0A%3E%20%C2%A0ASC%C2%A0and%C2%A0DESC%C2%A0are%20not%20permitted%20for%C2%A0HASH%C2%A0indexes.%C2%A0%0A%3E%20%C2%A0ASC%C2%A0and%C2%A0DESC%C2%A0are%20also%20not%20supported%20for%20multi-valued%20indexes.%20%0A%3E%20%C2%A0As%20of%20MySQL%208.0.12%2C%C2%A0ASC%C2%A0and%C2%A0DESC%C2%A0are%20not%20permitted%20for%C2%A0SPATIAL%C2%A0indexes.%0A%0A%0A%0A%23%23%23%23%20Column%20Prefix%20Key%20Parts%0A%3E%20**For%20string%20columns**%2C%20indexes%20can%20be%20created%20that%20use%20only%20the%20leading%20part%20of%20column%20values%2C%20using%C2%A0%60col_name(length)%60%C2%A0syntax%20to%20specify%20an%20index%20prefix%20length%3A%0A%3E%20Prefixes%20can%20be%20specified%20for%C2%A0%3Cu%3ECHAR%3C%2Fu%3E%2C%3Cu%3EVARCHAR%3C%2Fu%3E%2C%C2%A0%3Cu%3EBINARY%3C%2Fu%3E%2C%20and%C2%A0%3Cu%3EVARBINARY%3C%2Fu%3E%C2%A0key%20parts.%0A%0A%3E%20Prefixes%C2%A0must%C2%A0be%20specified%20for%C2%A0BLOB%C2%A0and%C2%A0TEXT%C2%A0key%20parts.%0A%0A%3EIf%20names%20in%20the%20column%20usually%20differ%20in%20the%20first%2010%20characters%2C%20lookups%20performed%20using%20this%20index%20should%20not%20be%20much%20slower%20than%20using%20an%20index%20created%20from%20the%20entire%C2%A0name%C2%A0column.%20Also%2C%20using%20column%20prefixes%20for%20indexes%20can%20make%20the%20index%20file%20much%20smaller%2C%20which%20could%20save%20a%20lot%20of%20disk%20space%20and%20might%20also%20speed%20up%C2%A0INSERT%C2%A0operations.%0A%0A%60%60%60sql%0ACREATE%20INDEX%20part_of_name%20ON%20customer%20(name(10))%3B%0A%60%60%60%0A%0A%3E%20the%20index%20entry%20for%20a%20given%C2%A0t1%C2%A0row%20includes%20the%20full%C2%A0col1%C2%A0value%20and%20a%20prefix%20of%20the%C2%A0col2%C2%A0value%20consisting%20of%20its%20first%2010%20characters%0A%60%60%60sql%0ACREATE%20TABLE%20t1%20(%0A%20%20col1%20VARCHAR(10)%2C%0A%20%20col2%20VARCHAR(20)%2C%0A%20%20INDEX%20(col1%2C%20col2(10))%0A)%3B%0A%60%60%60%0A%0A%23%23%23%23%20Functional%20Key%20Parts%0A%3E%20%60MySQL%208.0.13%60%20and%20higher%20supports%20functional%20key%20parts%C2%A0%0A%0A%60%60%60sql%0ACREATE%20TABLE%20t1%20(col1%20INT%2C%20col2%20INT%2C%20INDEX%20func_index%20((ABS(col1))))%3B%0ACREATE%20INDEX%20idx1%20ON%20t1%20((col1%20%2B%20col2))%3B%0ACREATE%20INDEX%20idx2%20ON%20t1%20((col1%20%2B%20col2)%2C%20(col1%20-%20col2)%2C%20col1)%3B%0AALTER%20TABLE%20t1%20ADD%20INDEX%20((col1%20*%2040)%20DESC)%3B%0A%60%60%60%0A%3E%20-%20In%20index%20definitions%2C%20enclose%20expressions%20within%20parentheses%20to%20distinguish%20them%20from%20columns%20or%20column%20prefixes.%C2%A0%0A%60%60%60sqk%0AINDEX%20((col1%20%2B%20col2)%2C%20(col3%20-%20col4))%0A%60%60%60%0A%0A%3E%20%20This%20produces%20an%20error%3B%20the%20expressions%20are%20not%20enclosed%20within%20parentheses%3A%0A%60%60%60sql%0AINDEX%20(col1%20%2B%20col2%2C%20col3%20-%20col4)%0A%60%60%60%0A%0A%3E%20-%20A%20functional%20key%20part%20cannot%20consist%20solely%20of%20a%20column%20name.%20For%20example%2C%20this%20is%20not%20permitted%3A%0A%0A%60%60%60sql%0AINDEX%20((col1)%2C%20(col2))%0A%60%60%60%0A%0A%3E%20Instead%2C%20write%20the%20key%20parts%20as%20nonfunctional%20key%20parts%2C%20without%20parentheses%3A%0A%0A%60%60%60sql%0AINDEX%20(col1%2C%20col2)%0A%60%60%60%0A%3E%20-%20A%20functional%20key%20part%20expression%20cannot%20refer%20to%20column%20prefixes.%0A%3E%20For%20a%20workaround%2C%20see%20the%20discussion%20of%C2%A0SUBSTRING()%C2%A0and%C2%A0CAST()%0A%3E%20%0A%3E%20the%C2%A0%60WHERE%60%C2%A0clause%20must%20contain%C2%A0SUBSTRING()%C2%A0with%20the%20same%20arguments.%0A%3E%20In%20the%20following%20example%2C%20only%20the%20second%C2%A0SELECT%C2%A0is%20able%20to%20use%20the%20index%20because%20that%20is%20the%20only%20query%20in%20which%20the%20arguments%20to%C2%A0SUBSTRING()%C2%A0match%20the%20index%20specification%0A%0A%60%60%60sql%0ACREATE%20TABLE%20tbl%20(%0A%20%20col1%20LONGTEXT%2C%0A%20%20INDEX%20idx1%20((SUBSTRING(col1%2C%201%2C%2010)))%0A)%3B%0ASELECT%20*%20FROM%20tbl%20WHERE%20SUBSTRING(col1%2C%201%2C%209)%20%3D%20'123456789'%3B%0ASELECT%20*%20FROM%20tbl%20WHERE%20SUBSTRING(col1%2C%201%2C%2010)%20%3D%20'1234567890'%3B%0A%60%60%60%0A%0A%3E%20-%20Functional%20indexes%20are%20implemented%20as%20hidden%20virtual%20generated%20columns%0A%0A%3E%20-%20The%20virtual%20generated%20column%20itself%20requires%20no%20storage.%20The%20index%20itself%20takes%20up%20storage%20space%20as%20any%20other%20index.%0A%0A%3E%20-%20primary%20keys%20cannot%20include%20functional%20key%20parts%2C%20A%20primary%20key%20requires%20the%20generated%20column%20to%20be%20stored%2C%20but%20functional%20key%20parts%20are%20implemented%20as%20virtual%20generated%20columns%2C%20not%20stored%20generated%20columns.%0A%0A%3E%20-%20%60SPATIAL%60%C2%A0and%C2%A0%60FULLTEXT%60%C2%A0indexes%20cannot%20have%20functional%20key%20parts.%0A%0A%3E%20-%20If%20a%20table%20contains%20no%20primary%20key%2C%C2%A0InnoDB%C2%A0automatically%20promotes%20the%20first%C2%A0%60UNIQUE%20NOT%20NULL%60%C2%A0index%20to%20the%20primary%20key.%20This%20is%20not%20supported%20for%C2%A0UNIQUE%20NOT%20NULL%C2%A0indexes%20that%20have%20functional%20key%20parts.%0A%0A%3E%20-%20To%20remove%20a%20column%20that%20is%20referenced%20by%20a%20functional%20key%20part%2C%20the%20index%20must%20be%20removed%20first.%20Otherwise%2C%20an%20error%20occurs.%0A%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2Ffreshlover%2Farticle%2Fdetails%2F8634610%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fgengyufei%2Fp%2F14295405.html%0Ahttps%3A%2F%2Fblog.csdn.net%2Fbigtree_3721%2Farticle%2Fdetails%2F87478706

ProxyFactory

创建时间:2022/1/30 0:12
更新时间:2022/2/21 21:31
作者:Chris
来源:https://blog.csdn.net/sunnycoco05/article/details/78901449

ProxyFactory

1 创建需要代理的类

package com.chris.springboot2022.bean.proxy;

public class MyTarget {

    public boolean printName() {
        System.out.println("name:Target-");
        return true;
    }
}

2 创建需要代理的接口及其实现类

public interface IHelloService {
    void sayHello();
}

@Service
@Data
public class HelloServiceImpl1 implements IHelloService {
    private String name = "HelloServiceImpl1";

    @Override
    public void sayHello() {
        System.out.println("hello, this is " + name);
    }
}

@Service
@Data
public class HelloServiceImpl2 implements IHelloService {
    private String name = "HelloServiceImpl2";

    @Override
    public void sayHello() {
        System.out.println("hello, this is " + name);
    }
}

3 创建一个MethodInterceptor实现方法调用的前后拦截

package com.chris.springboot2022.bean.proxy;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AroundInteceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println(invocation.getMethod().getName() + " before invoke");
        Object proceed = invocation.proceed();
        System.out.println(invocation.getMethod().getName() + " after invoke");
        return proceed;
    }
}

4 测试类

使用spring-aop包中的ProxyFactory创建代理,
并通过addAdvice增加一个环绕方式的拦截

package com.chris.springboot2022;

import com.chris.springboot2022.bean.processor.service.IHelloService;
import com.chris.springboot2022.bean.processor.service.impl.HelloServiceImpl1;
import com.chris.springboot2022.bean.proxy.AroundInteceptor;
import com.chris.springboot2022.bean.proxy.MyTarget;
import org.junit.jupiter.api.Test;
import org.springframework.aop.framework.ProxyFactory;


public class ProxyFactoryTest {

    @Test
    public void classProxy() {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(new MyTarget());
        proxyFactory.addAdvice(new AroundInteceptor());
        MyTarget targetProxy = (MyTarget) proxyFactory.getProxy();
        targetProxy.printName();
        System.out.println(targetProxy.getClass().getName());
    }

    @Test
    public void interfaceProxy() {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setInterfaces(IHelloService.class);
        proxyFactory.addAdvice(new AroundInteceptor());
        proxyFactory.setTarget(new HelloServiceImpl1());
        IHelloService targetProxy = (IHelloService) proxyFactory.getProxy();
        targetProxy.sayHello();
        System.out.println(targetProxy.getClass().getName());
    }
}

5 输出结果

5.1 classProxy 输出结果
printName before invoke
name:Target-
printName after invoke
com.chris.springboot2022.bean.proxy.MyTarget$$EnhancerBySpringCGLIB$$d8c382a4A
5.2 interfaceProxy 输出结果
sayHello before invoke
hello, this is HelloServiceImpl1
sayHello after invoke
com.sun.proxy.$Proxy9


注释掉后的输出
// proxyFactory.setInterfaces(IHelloService.class);

sayHello before invoke
hello, this is HelloServiceImpl1
sayHello after invoke
com.chris.springboot2022.bean.processor.service.impl.HelloServiceImpl1$$EnhancerBySpringCGLIB$$7b87800d

6 总结

从运行结果的代理类的class name , 可以看到Spring中的代理对象其实是JDK Proxy和CGLIB Proxy 的结合

  • 对于指定接口的代理类使用的是JDK的Proxy
  • 对于不指定接口的代理类使用CGLIB的Proxy。

7 CGLIB

7.1 是什么

CGLIB是一个强大的、高性能的代码生成库。
其被广泛应用于AOP框架(Spring、dynaop)中,用以提供方法拦截操作。
Hibernate作为一个比较受欢迎的ORM框架,同样使用CGLIB来代理单端(多对一和一对一)关联(延迟提取集合使用的另一种机制)。
CGLIB作为一个开源项目,其代码托管在github,地址为:https://github.com/cglib/cglib

7.2 能干什么

CGLIB代理主要通过对字节码的操作,为对象引入间接级别,以控制对象的访问。
我们知道Java中有一个动态代理也是做这个事情的,那我们为什么不直接使用Java动态代理,而要使用CGLIB呢?答案是CGLIB相比于JDK动态代理更加强大,JDK动态代理虽然简单易用,但是其有一个致命缺陷是,只能对接口进行代理。如果要代理的类为一个普通类、没有接口,那么Java动态代理就没法使用了。关于Java动态代理,可以参者这里 Java动态代理分析

%5BProxyFactory%5D(https%3A%2F%2Fblog.csdn.net%2Fsunnycoco05%2Farticle%2Fdetails%2F78901449)%0A%0A%5Btoc%5D%0A%0A%23%23%23%23%201%20%E5%88%9B%E5%BB%BA%E9%9C%80%E8%A6%81%E4%BB%A3%E7%90%86%E7%9A%84%E7%B1%BB%0A%60%60%60java%0Apackage%20com.chris.springboot2022.bean.proxy%3B%0A%0Apublic%20class%20MyTarget%20%7B%0A%0A%20%20%20%20public%20boolean%20printName()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22name%3ATarget-%22)%3B%0A%20%20%20%20%20%20%20%20return%20true%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202%20%20%E5%88%9B%E5%BB%BA%E9%9C%80%E8%A6%81%E4%BB%A3%E7%90%86%E7%9A%84%E6%8E%A5%E5%8F%A3%E5%8F%8A%E5%85%B6%E5%AE%9E%E7%8E%B0%E7%B1%BB%0A%60%60%60java%0Apublic%20interface%20IHelloService%20%7B%0A%20%20%20%20void%20sayHello()%3B%0A%7D%0A%0A%40Service%0A%40Data%0Apublic%20class%20HelloServiceImpl1%20implements%20IHelloService%20%7B%0A%20%20%20%20private%20String%20name%20%3D%20%22HelloServiceImpl1%22%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20sayHello()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22hello%2C%20this%20is%20%22%20%2B%20name)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%40Service%0A%40Data%0Apublic%20class%20HelloServiceImpl2%20implements%20IHelloService%20%7B%0A%20%20%20%20private%20String%20name%20%3D%20%22HelloServiceImpl2%22%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20sayHello()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22hello%2C%20this%20is%20%22%20%2B%20name)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%23%23%23%23%203%20%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAMethodInterceptor%E5%AE%9E%E7%8E%B0%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%E7%9A%84%E5%89%8D%E5%90%8E%E6%8B%A6%E6%88%AA%0A%60%60%60java%0Apackage%20com.chris.springboot2022.bean.proxy%3B%0A%0Aimport%20org.aopalliance.intercept.MethodInterceptor%3B%0Aimport%20org.aopalliance.intercept.MethodInvocation%3B%0A%0Apublic%20class%20AroundInteceptor%20implements%20MethodInterceptor%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20Object%20invoke(MethodInvocation%20invocation)%20throws%20Throwable%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(invocation.getMethod().getName()%20%2B%20%22%20before%20invoke%22)%3B%0A%20%20%20%20%20%20%20%20Object%20proceed%20%3D%20invocation.proceed()%3B%0A%20%20%20%20%20%20%20%20System.out.println(invocation.getMethod().getName()%20%2B%20%22%20after%20invoke%22)%3B%0A%20%20%20%20%20%20%20%20return%20proceed%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%204%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%3E%20%E4%BD%BF%E7%94%A8spring-aop%E5%8C%85%E4%B8%AD%E7%9A%84ProxyFactory%E5%88%9B%E5%BB%BA%E4%BB%A3%E7%90%86%EF%BC%8C%0A%3E%20%E5%B9%B6%E9%80%9A%E8%BF%87addAdvice%E5%A2%9E%E5%8A%A0%E4%B8%80%E4%B8%AA%E7%8E%AF%E7%BB%95%E6%96%B9%E5%BC%8F%E7%9A%84%E6%8B%A6%E6%88%AA%0A%60%60%60java%0Apackage%20com.chris.springboot2022%3B%0A%0Aimport%20com.chris.springboot2022.bean.processor.service.IHelloService%3B%0Aimport%20com.chris.springboot2022.bean.processor.service.impl.HelloServiceImpl1%3B%0Aimport%20com.chris.springboot2022.bean.proxy.AroundInteceptor%3B%0Aimport%20com.chris.springboot2022.bean.proxy.MyTarget%3B%0Aimport%20org.junit.jupiter.api.Test%3B%0Aimport%20org.springframework.aop.framework.ProxyFactory%3B%0A%0A%0Apublic%20class%20ProxyFactoryTest%20%7B%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20classProxy()%20%7B%0A%20%20%20%20%20%20%20%20ProxyFactory%20proxyFactory%20%3D%20new%20ProxyFactory()%3B%0A%20%20%20%20%20%20%20%20proxyFactory.setTarget(new%20MyTarget())%3B%0A%20%20%20%20%20%20%20%20proxyFactory.addAdvice(new%20AroundInteceptor())%3B%0A%20%20%20%20%20%20%20%20MyTarget%20targetProxy%20%3D%20(MyTarget)%20proxyFactory.getProxy()%3B%0A%20%20%20%20%20%20%20%20targetProxy.printName()%3B%0A%20%20%20%20%20%20%20%20System.out.println(targetProxy.getClass().getName())%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20interfaceProxy()%20%7B%0A%20%20%20%20%20%20%20%20ProxyFactory%20proxyFactory%20%3D%20new%20ProxyFactory()%3B%0A%20%20%20%20%20%20%20%20proxyFactory.setInterfaces(IHelloService.class)%3B%0A%20%20%20%20%20%20%20%20proxyFactory.addAdvice(new%20AroundInteceptor())%3B%0A%20%20%20%20%20%20%20%20proxyFactory.setTarget(new%20HelloServiceImpl1())%3B%0A%20%20%20%20%20%20%20%20IHelloService%20targetProxy%20%3D%20(IHelloService)%20proxyFactory.getProxy()%3B%0A%20%20%20%20%20%20%20%20targetProxy.sayHello()%3B%0A%20%20%20%20%20%20%20%20System.out.println(targetProxy.getClass().getName())%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%205%20%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%0A%23%23%23%23%23%205.1%20classProxy%20%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%0A%60%60%60%0AprintName%20before%20invoke%0Aname%3ATarget-%0AprintName%20after%20invoke%0Acom.chris.springboot2022.bean.proxy.MyTarget%24%24EnhancerBySpringCGLIB%24%24d8c382a4A%0A%60%60%60%0A%0A%23%23%23%23%23%205.2%20interfaceProxy%20%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%0A%60%60%60%0AsayHello%20before%20invoke%0Ahello%2C%20this%20is%20HelloServiceImpl1%0AsayHello%20after%20invoke%0Acom.sun.proxy.%24Proxy9%0A%60%60%60%0A!%5Bf69310ce05e6702c2a9c7aa17590b83c.png%5D(en-resource%3A%2F%2Fdatabase%2F1342%3A1)%0A!%5Be409d3bce8f228a472ed72b7c3aa87df.png%5D(en-resource%3A%2F%2Fdatabase%2F1340%3A1)%0A%0A%0A%3E%20%E6%B3%A8%E9%87%8A%E6%8E%89%E5%90%8E%E7%9A%84%E8%BE%93%E5%87%BA%0A%3E%20%2F%2F%20proxyFactory.setInterfaces(IHelloService.class)%3B%0A%0A!%5B8cf570266c3ff40717c9f19ff8a4537d.png%5D(en-resource%3A%2F%2Fdatabase%2F1344%3A1)%0A%0A%60%60%60%0AsayHello%20before%20invoke%0Ahello%2C%20this%20is%20HelloServiceImpl1%0AsayHello%20after%20invoke%0Acom.chris.springboot2022.bean.processor.service.impl.HelloServiceImpl1%24%24EnhancerBySpringCGLIB%24%247b87800d%0A%60%60%60%0A%0A%23%23%23%23%206%20%E6%80%BB%E7%BB%93%0A%3E%20%E4%BB%8E%E8%BF%90%E8%A1%8C%E7%BB%93%E6%9E%9C%E7%9A%84%E4%BB%A3%E7%90%86%E7%B1%BB%E7%9A%84class%20name%20%2C%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0Spring%E4%B8%AD%E7%9A%84%E4%BB%A3%E7%90%86%E5%AF%B9%E8%B1%A1%E5%85%B6%E5%AE%9E%E6%98%AFJDK%20Proxy%E5%92%8CCGLIB%20Proxy%20%E7%9A%84%E7%BB%93%E5%90%88%0A%3E%20-%20%E5%AF%B9%E4%BA%8E%E6%8C%87%E5%AE%9A%E6%8E%A5%E5%8F%A3%E7%9A%84%E4%BB%A3%E7%90%86%E7%B1%BB%E4%BD%BF%E7%94%A8%E7%9A%84%E6%98%AFJDK%E7%9A%84Proxy%0A%3E%20-%20%E5%AF%B9%E4%BA%8E%E4%B8%8D%E6%8C%87%E5%AE%9A%E6%8E%A5%E5%8F%A3%E7%9A%84%E4%BB%A3%E7%90%86%E7%B1%BB%E4%BD%BF%E7%94%A8CGLIB%E7%9A%84Proxy%E3%80%82%0A%0A%0A%23%23%23%23%207%20CGLIB%0A%23%23%23%23%23%207.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20CGLIB%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84%E3%80%81%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90%E5%BA%93%E3%80%82%0A%3E%20%E5%85%B6%E8%A2%AB%E5%B9%BF%E6%B3%9B%E5%BA%94%E7%94%A8%E4%BA%8EAOP%E6%A1%86%E6%9E%B6%EF%BC%88Spring%E3%80%81dynaop%EF%BC%89%E4%B8%AD%EF%BC%8C%E7%94%A8%E4%BB%A5%E6%8F%90%E4%BE%9B%E6%96%B9%E6%B3%95%E6%8B%A6%E6%88%AA%E6%93%8D%E4%BD%9C%E3%80%82%0A%3E%20Hibernate%E4%BD%9C%E4%B8%BA%E4%B8%80%E4%B8%AA%E6%AF%94%E8%BE%83%E5%8F%97%E6%AC%A2%E8%BF%8E%E7%9A%84ORM%E6%A1%86%E6%9E%B6%EF%BC%8C%E5%90%8C%E6%A0%B7%E4%BD%BF%E7%94%A8CGLIB%E6%9D%A5%E4%BB%A3%E7%90%86%E5%8D%95%E7%AB%AF%EF%BC%88%E5%A4%9A%E5%AF%B9%E4%B8%80%E5%92%8C%E4%B8%80%E5%AF%B9%E4%B8%80%EF%BC%89%E5%85%B3%E8%81%94%EF%BC%88%E5%BB%B6%E8%BF%9F%E6%8F%90%E5%8F%96%E9%9B%86%E5%90%88%E4%BD%BF%E7%94%A8%E7%9A%84%E5%8F%A6%E4%B8%80%E7%A7%8D%E6%9C%BA%E5%88%B6%EF%BC%89%E3%80%82%0A%3E%20CGLIB%E4%BD%9C%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%EF%BC%8C%E5%85%B6%E4%BB%A3%E7%A0%81%E6%89%98%E7%AE%A1%E5%9C%A8github%EF%BC%8C%E5%9C%B0%E5%9D%80%E4%B8%BA%EF%BC%9Ahttps%3A%2F%2Fgithub.com%2Fcglib%2Fcglib%0A%0A%23%23%23%23%23%207.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%20CGLIB%E4%BB%A3%E7%90%86%E4%B8%BB%E8%A6%81%E9%80%9A%E8%BF%87%E5%AF%B9%E5%AD%97%E8%8A%82%E7%A0%81%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%B8%BA%E5%AF%B9%E8%B1%A1%E5%BC%95%E5%85%A5%E9%97%B4%E6%8E%A5%E7%BA%A7%E5%88%AB%EF%BC%8C%E4%BB%A5%E6%8E%A7%E5%88%B6%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%AE%BF%E9%97%AE%E3%80%82%0A%3E%20%E6%88%91%E4%BB%AC%E7%9F%A5%E9%81%93Java%E4%B8%AD%E6%9C%89%E4%B8%80%E4%B8%AA%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E4%B9%9F%E6%98%AF%E5%81%9A%E8%BF%99%E4%B8%AA%E4%BA%8B%E6%83%85%E7%9A%84%EF%BC%8C%E9%82%A3%E6%88%91%E4%BB%AC%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8Java%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%EF%BC%8C%E8%80%8C%E8%A6%81%E4%BD%BF%E7%94%A8CGLIB%E5%91%A2%EF%BC%9F%E7%AD%94%E6%A1%88%E6%98%AFCGLIB%E7%9B%B8%E6%AF%94%E4%BA%8EJDK%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E6%9B%B4%E5%8A%A0%E5%BC%BA%E5%A4%A7%EF%BC%8C*%3Cu%3E**JDK%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E8%99%BD%E7%84%B6%E7%AE%80%E5%8D%95%E6%98%93%E7%94%A8%EF%BC%8C%E4%BD%86%E6%98%AF%E5%85%B6%E6%9C%89%E4%B8%80%E4%B8%AA%E8%87%B4%E5%91%BD%E7%BC%BA%E9%99%B7%E6%98%AF%EF%BC%8C%E5%8F%AA%E8%83%BD%E5%AF%B9%E6%8E%A5%E5%8F%A3%E8%BF%9B%E8%A1%8C%E4%BB%A3%E7%90%86%E3%80%82%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BB%A3%E7%90%86%E7%9A%84%E7%B1%BB%E4%B8%BA%E4%B8%80%E4%B8%AA%E6%99%AE%E9%80%9A%E7%B1%BB%E3%80%81%E6%B2%A1%E6%9C%89%E6%8E%A5%E5%8F%A3%EF%BC%8C%E9%82%A3%E4%B9%88Java%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E5%B0%B1%E6%B2%A1%E6%B3%95%E4%BD%BF%E7%94%A8%E4%BA%86**%3C%2Fu%3E*%E3%80%82%E5%85%B3%E4%BA%8EJava%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%8F%82%E8%80%85%E8%BF%99%E9%87%8C%20%5BJava%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E5%88%86%E6%9E%90%5D(https%3A%2F%2Fblog.csdn.net%2Fdanchu%2Farticle%2Fdetails%2F70146985)%0A

Bean的加载和执行顺序

创建时间:2022/2/21 15:25
更新时间:2022/2/21 15:45
作者:Chris
来源:https://blog.csdn.net/yaomingyang/article/details/86649072

@Order或Ordered

注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,
Bean的加载顺序不受@Order或Ordered接口的影响;

%5Btoc%5D%0A%0A%0A%23%23%20%40Order%E6%88%96Ordered%0A%3E%20%E6%B3%A8%E8%A7%A3%40Order%E6%88%96%E8%80%85%E6%8E%A5%E5%8F%A3Ordered%E7%9A%84%E4%BD%9C%E7%94%A8%E6%98%AF%E5%AE%9A%E4%B9%89Spring%20IOC%E5%AE%B9%E5%99%A8%E4%B8%ADBean%E7%9A%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%98%AF%E5%AE%9A%E4%B9%89Bean%E7%9A%84%E5%8A%A0%E8%BD%BD%E9%A1%BA%E5%BA%8F%EF%BC%8C%0A%3E%20Bean%E7%9A%84%E5%8A%A0%E8%BD%BD%E9%A1%BA%E5%BA%8F%E4%B8%8D%E5%8F%97%40Order%E6%88%96Ordered%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%BD%B1%E5%93%8D%EF%BC%9B%0A%0A%0A

自定义starter

创建时间:2020/9/8 15:13
更新时间:2022/2/21 10:49
作者:Chris

1. 自定义starter

1.1 官网地址

https://docs.spring.io/spring-boot/docs/2.3.3.RELEASE/reference/htmlsingle/#using-boot-starter

1.2 自动配置

1.2.1 需要用到的注解
//用来指定这个类为配置类
@Configuration 

//在指定条件满足的情况下自动配置类生效
@ConditionalOnXXX
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)

//指定自动配置类的顺序
@AutoConfigureAfter(DataSourceAutoConfiguration.class)

//为容器中添加属性
@Bean

//结合xxxProperties类绑定相应的配置
@ConfigurationProperties(prefix = Constants.MYBATIS_PLUS)

//将xxxProperties类注入到容器中使之生效
@EnableConfigurationProperties(MybatisPlusProperties.class)
1.2.2 自动加载配置类

需要启动就加载的自动配置类,配置在\META-INF\spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration
1.2.3 启动器

一个空的jar文件,只用来提供辅助性的依赖管理,这些jar文件可能用于自动装配或者其它类库

启动器依赖自动配置

命名:moduleName-spring-boot-starter

1.3 编写自动配置

1.3.1 启动器
  1. 建module

    这是一个空工程,不需要任何src,resource目录只保留一个pom文件

       <groupId>com.chris</groupId>
       <artifactId>helloworld-starter</artifactId>
    
1.3.2 自动配置类
  1. 建module

    <groupId>com.chris</groupId>
    <artifactId>helloworld-starter-autoconfigurer</artifactId>
    
  2. 改pom

    <!--所有starter需要引入的基本配置-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    
  3. properties类

    package com.chris.config;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @ConfigurationProperties(prefix = "helloworld.chris")
    @Data
    public class HelloWorldProperties {
        private String prefix;
        private String suffix;
    }
    
    
  4. 业务类

    package com.chris.service;
    
    import com.chris.config.HelloWorldProperties;
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class HelloWorldService {
        HelloWorldProperties helloWorldProperties;
    
        public String sayHello(String info) {
            return helloWorldProperties.getPrefix() + "-" + info + "-" + helloWorldProperties.getSuffix();
        }
    }
    
    
  5. 自动配置类

    package com.chris.config;
    
    import com.chris.service.HelloWorldService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @EnableConfigurationProperties(HelloWorldProperties.class)
    public class HelloworldServiceAutoConfiguration {
        @Autowired
        HelloWorldProperties helloWorldProperties;
    
        @Bean
        @ConditionalOnClass(HelloWorldProperties.class)
        public HelloWorldService helloWorldService() {
            HelloWorldService helloWorldService = new HelloWorldService();
            helloWorldService.setHelloWorldProperties(helloWorldProperties);
            return helloWorldService;
        }
    }
    
    
  6. 建spring.factories

    在resources目录下建META-INF,然后在中建spring.factories

    将自动配置类配置到spring.factories文件中

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.chris.config.HelloworldServiceAutoConfiguration
    
  7. 将自动配置模块引入到启动器模块的pom文件中

    <!--引入自动配置模块-->
    <dependency>
    	<groupId>com.chris</groupId>
    	<artifactId>helloworld-starter-autoconfigurer</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    </dependency>
    
1.3.3 构建模块
  1. 构建自动配置模块

    cd helloworld-spring-boot-starter-autoconfigurer
    mvn clean install
    
  2. 构建启动器模块

    cd helloworld-spring-boot-starter
    mvn clean install
    
1.3.4 引用启动器模块
  1. 改pom

    <dependency>
        <groupId>com.chris</groupId>
        <artifactId>helloworld-starter</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    
  2. 业务类

    @RestController
    @Slf4j
    @RequestMapping("/hello")
    public class HelloWorldController {
        @Autowired
        private HelloWorldService helloWorldService;
    
        @GetMapping("/sayHello")
        public String helloworld(@RequestParam("info") String info) {
            return helloWorldService.sayHello(info);
        }
    }
    
  3. 配置yml文件

    helloworld:  
        chris:    
            prefix: My name is    
            suffix: Say hello to the world!
    
  4. 测试

    request:
    http://localhost:4003/api/hello/sayHello?info=Chris
    
    response:
    My name is-Chris-Say hello to the world!
    
%5Btoc%5D%0A%0A%0A%23%23%201.%20%E8%87%AA%E5%AE%9A%E4%B9%89starter%0A%0A%23%23%23%23%201.1%20%E5%AE%98%E7%BD%91%E5%9C%B0%E5%9D%80%0A%0Ahttps%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.3.3.RELEASE%2Freference%2Fhtmlsingle%2F%23using-boot-starter%0A%0A%23%23%23%23%201.2%20%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%0A%0A%23%23%23%23%23%201.2.1%20%E9%9C%80%E8%A6%81%E7%94%A8%E5%88%B0%E7%9A%84%E6%B3%A8%E8%A7%A3%0A%0A%60%60%60java%0A%2F%2F%E7%94%A8%E6%9D%A5%E6%8C%87%E5%AE%9A%E8%BF%99%E4%B8%AA%E7%B1%BB%E4%B8%BA%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%40Configuration%20%0A%0A%2F%2F%E5%9C%A8%E6%8C%87%E5%AE%9A%E6%9D%A1%E4%BB%B6%E6%BB%A1%E8%B6%B3%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%94%9F%E6%95%88%0A%40ConditionalOnXXX%0A%40ConditionalOnClass(%7BSqlSessionFactory.class%2C%20SqlSessionFactoryBean.class%7D)%0A%40ConditionalOnSingleCandidate(DataSource.class)%0A%0A%2F%2F%E6%8C%87%E5%AE%9A%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%9A%84%E9%A1%BA%E5%BA%8F%0A%40AutoConfigureAfter(DataSourceAutoConfiguration.class)%0A%0A%2F%2F%E4%B8%BA%E5%AE%B9%E5%99%A8%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%B1%9E%E6%80%A7%0A%40Bean%0A%0A%2F%2F%E7%BB%93%E5%90%88xxxProperties%E7%B1%BB%E7%BB%91%E5%AE%9A%E7%9B%B8%E5%BA%94%E7%9A%84%E9%85%8D%E7%BD%AE%0A%40ConfigurationProperties(prefix%20%3D%20Constants.MYBATIS_PLUS)%0A%0A%2F%2F%E5%B0%86xxxProperties%E7%B1%BB%E6%B3%A8%E5%85%A5%E5%88%B0%E5%AE%B9%E5%99%A8%E4%B8%AD%E4%BD%BF%E4%B9%8B%E7%94%9F%E6%95%88%0A%40EnableConfigurationProperties(MybatisPlusProperties.class)%0A%60%60%60%0A%0A%23%23%23%23%23%201.2.2%20%E8%87%AA%E5%8A%A8%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A%3E%20%E9%9C%80%E8%A6%81%E5%90%AF%E5%8A%A8%E5%B0%B1%E5%8A%A0%E8%BD%BD%E7%9A%84%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E9%85%8D%E7%BD%AE%E5%9C%A8%5CMETA-INF%5Cspring.factories%0A%60%60%60%0Aorg.springframework.boot.autoconfigure.EnableAutoConfiguration%3D%5C%0A%20%20com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration%0A%60%60%60%0A%0A%23%23%23%23%23%201.2.3%20%E5%90%AF%E5%8A%A8%E5%99%A8%0A%0A%3E%20%E4%B8%80%E4%B8%AA%E7%A9%BA%E7%9A%84jar%E6%96%87%E4%BB%B6%EF%BC%8C%E5%8F%AA%E7%94%A8%E6%9D%A5%E6%8F%90%E4%BE%9B%E8%BE%85%E5%8A%A9%E6%80%A7%E7%9A%84%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86%EF%BC%8C%E8%BF%99%E4%BA%9Bjar%E6%96%87%E4%BB%B6%E5%8F%AF%E8%83%BD%E7%94%A8%E4%BA%8E%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%E6%88%96%E8%80%85%E5%85%B6%E5%AE%83%E7%B1%BB%E5%BA%93%0A%3E%0A%3E%20%E5%90%AF%E5%8A%A8%E5%99%A8%E4%BE%9D%E8%B5%96%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%0A%0A%3E%20%E5%91%BD%E5%90%8D%EF%BC%9AmoduleName-spring-boot-starter%0A%0A%23%23%23%23%201.3%20%E7%BC%96%E5%86%99%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%0A%0A%23%23%23%23%23%201.3.1%20%E5%90%AF%E5%8A%A8%E5%99%A8%0A1.%20%E5%BB%BAmodule%0A%20%20%20%20%3E%20%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E7%A9%BA%E5%B7%A5%E7%A8%8B%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E4%BB%BB%E4%BD%95src%2Cresource%E7%9B%AE%E5%BD%95%E5%8F%AA%E4%BF%9D%E7%95%99%E4%B8%80%E4%B8%AApom%E6%96%87%E4%BB%B6%0A%20%20%20%20%60%60%60xml%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.chris%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Ehelloworld-starter%3C%2FartifactId%3E%0A%20%20%20%20%60%60%60%0A%0A%23%23%23%23%23%201.3.2%20%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A1.%20%E5%BB%BAmodule%0A%20%20%20%0A%20%20%20%20%60%60%60xml%0A%20%20%20%20%3CgroupId%3Ecom.chris%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Ehelloworld-starter-autoconfigurer%3C%2FartifactId%3E%0A%20%20%20%20%60%60%60%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E6%89%80%E6%9C%89starter%E9%9C%80%E8%A6%81%E5%BC%95%E5%85%A5%E7%9A%84%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3Coptional%3Etrue%3C%2Foptional%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20properties%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.config%3B%0A%20%20%20%0A%20%20%20import%20lombok.Data%3B%0A%20%20%20import%20org.springframework.boot.context.properties.ConfigurationProperties%3B%0A%20%20%20%0A%20%20%20%40ConfigurationProperties(prefix%20%3D%20%22helloworld.chris%22)%0A%20%20%20%40Data%0A%20%20%20public%20class%20HelloWorldProperties%20%7B%0A%20%20%20%20%20%20%20private%20String%20prefix%3B%0A%20%20%20%20%20%20%20private%20String%20suffix%3B%0A%20%20%20%7D%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.service%3B%0A%20%20%20%0A%20%20%20import%20com.chris.config.HelloWorldProperties%3B%0A%20%20%20import%20lombok.Getter%3B%0A%20%20%20import%20lombok.Setter%3B%0A%20%20%20%0A%20%20%20%40Getter%0A%20%20%20%40Setter%0A%20%20%20public%20class%20HelloWorldService%20%7B%0A%20%20%20%20%20%20%20HelloWorldProperties%20helloWorldProperties%3B%0A%20%20%20%0A%20%20%20%20%20%20%20public%20String%20sayHello(String%20info)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20helloWorldProperties.getPrefix()%20%2B%20%22-%22%20%2B%20info%20%2B%20%22-%22%20%2B%20helloWorldProperties.getSuffix()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A5.%20%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.config%3B%0A%20%20%20%0A%20%20%20import%20com.chris.service.HelloWorldService%3B%0A%20%20%20import%20org.springframework.beans.factory.annotation.Autowired%3B%0A%20%20%20import%20org.springframework.boot.autoconfigure.condition.ConditionalOnClass%3B%0A%20%20%20import%20org.springframework.boot.context.properties.EnableConfigurationProperties%3B%0A%20%20%20import%20org.springframework.context.annotation.Bean%3B%0A%20%20%20import%20org.springframework.context.annotation.Configuration%3B%0A%20%20%20%0A%20%20%20%40Configuration%0A%20%20%20%40EnableConfigurationProperties(HelloWorldProperties.class)%0A%20%20%20public%20class%20HelloworldServiceAutoConfiguration%20%7B%0A%20%20%20%20%20%20%20%40Autowired%0A%20%20%20%20%20%20%20HelloWorldProperties%20helloWorldProperties%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20%40ConditionalOnClass(HelloWorldProperties.class)%0A%20%20%20%20%20%20%20public%20HelloWorldService%20helloWorldService()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20HelloWorldService%20helloWorldService%20%3D%20new%20HelloWorldService()%3B%0A%20%20%20%20%20%20%20%20%20%20%20helloWorldService.setHelloWorldProperties(helloWorldProperties)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20helloWorldService%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A6.%20%E5%BB%BAspring.factories%0A%0A%20%20%20%3E%20%E5%9C%A8resources%E7%9B%AE%E5%BD%95%E4%B8%8B%E5%BB%BAMETA-INF%EF%BC%8C%E7%84%B6%E5%90%8E%E5%9C%A8%E4%B8%AD%E5%BB%BAspring.factories%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%B0%86%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%E9%85%8D%E7%BD%AE%E5%88%B0spring.factories%E6%96%87%E4%BB%B6%E4%B8%AD%0A%0A%20%20%20%60%60%60%0A%20%20%20org.springframework.boot.autoconfigure.EnableAutoConfiguration%3D%5C%0A%20%20%20com.chris.config.HelloworldServiceAutoConfiguration%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A7.%20%E5%B0%86%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E6%A8%A1%E5%9D%97%E5%BC%95%E5%85%A5%E5%88%B0%E5%90%AF%E5%8A%A8%E5%99%A8%E6%A8%A1%E5%9D%97%E7%9A%84pom%E6%96%87%E4%BB%B6%E4%B8%AD%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E6%A8%A1%E5%9D%97--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%09%3CgroupId%3Ecom.chris%3C%2FgroupId%3E%0A%20%20%20%09%3CartifactId%3Ehelloworld-starter-autoconfigurer%3C%2FartifactId%3E%0A%20%20%20%09%3Cversion%3E0.0.1-SNAPSHOT%3C%2Fversion%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%201.3.3%20%E6%9E%84%E5%BB%BA%E6%A8%A1%E5%9D%97%0A%0A1.%20%E6%9E%84%E5%BB%BA%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E6%A8%A1%E5%9D%97%0A%0A%20%20%20%60%60%60%0A%20%20%20cd%20helloworld-spring-boot-starter-autoconfigurer%0A%20%20%20mvn%20clean%20install%0A%20%20%20%60%60%60%0A%0A2.%20%E6%9E%84%E5%BB%BA%E5%90%AF%E5%8A%A8%E5%99%A8%E6%A8%A1%E5%9D%97%0A%0A%20%20%20%60%60%60%0A%20%20%20cd%20helloworld-spring-boot-starter%0A%20%20%20mvn%20clean%20install%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%201.3.4%20%E5%BC%95%E7%94%A8%E5%90%AF%E5%8A%A8%E5%99%A8%E6%A8%A1%E5%9D%97%0A%0A1.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.chris%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Ehelloworld-starter%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3Cversion%3E1.0-SNAPSHOT%3C%2Fversion%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40Slf4j%0A%20%20%20%40RequestMapping(%22%2Fhello%22)%0A%20%20%20public%20class%20HelloWorldController%20%7B%0A%20%20%20%20%20%20%20%40Autowired%0A%20%20%20%20%20%20%20private%20HelloWorldService%20helloWorldService%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40GetMapping(%22%2FsayHello%22)%0A%20%20%20%20%20%20%20public%20String%20helloworld(%40RequestParam(%22info%22)%20String%20info)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20helloWorldService.sayHello(info)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%203.%20%E9%85%8D%E7%BD%AEyml%E6%96%87%E4%BB%B6%0A%0A%20%20%20%20%60%60%60yml%0A%20%20%20%20helloworld%3A%C2%A0%20%0A%20%20%20%20%20%20%20%20chris%3A%C2%A0%C2%A0%C2%A0%20%0A%20%20%20%20%20%20%20%20%20%20%20%20prefix%3A%20My%20name%20is%C2%A0%C2%A0%C2%A0%20%0A%20%20%20%20%20%20%20%20%20%20%20%20suffix%3A%20Say%20hello%20to%20the%20world!%0A%20%20%20%20%60%60%60%0A%0A4.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%60%60%60%0A%20%20%20request%3A%0A%20%20%20http%3A%2F%2Flocalhost%3A4003%2Fapi%2Fhello%2FsayHello%3Finfo%3DChris%0A%20%20%20%0A%20%20%20response%3A%0A%20%20%20My%20name%20is-Chris-Say%20hello%20to%20the%20world!%0A%20%20%20%60%60%60%0A%0A%20%20%20

SpringBoot线程池

创建时间:2022/2/17 21:21
更新时间:2022/2/17 21:21
作者:Chris

后面就想到了线程池ThreadPoolExecutor,而用的是
SpringBoot项目,可以用Spring提供的对ThreadPoolExecutor封装的线程池ThreadPoolTaskExecutor,直接使用注解启用

1.使用步骤

1.1 增加配置

在application.yml中添加配置

async:
  executor:
    thread:
      queue_capacity: 99999  # 配置队列大小
      name_prefix: async-service- # 配置线程池中的线程的名称前缀
1.2 增加配置类
package com.chris.mybatisplus.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @Author Lilun
 * @Date 2021-06-08 10:45
 * @Description
 **/
@ConfigurationProperties(prefix = "async.executor.thread")
@Data
public class ThreadPoolConfigBean {
    private int corePoolSize;
    private int maxPoolSize;
    private int queueCapacity;
    private String namePrefix;
}
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
@MapperScan("com.chris.mybatisplus.dao.mapper")
@ConfigurationPropertiesScan("com.chris.mybatisplus.config")
public class MybatisPlusMain {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusMain.class, args);
    }
}

1.3 SpringBoot启用线程池的两种方式
1.3.1 通过java配置的方式启用

使用@Configuration和 ==@EnableAsync== 这两个注解,表示这是个配置类,同时启动Spring的异步线程

package com.chris.mybatisplus.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author Lilun
 * @Date 2021-06-07 20:19
 * @Description
 **/
@Configuration
@Slf4j
@EnableAsync
//@EnableConfigurationProperties(ThreadPoolConfigBean.class)
public class ExecutorConfig {
    @Resource
    private ThreadPoolConfigBean configBean;

    private static final int corePoolSize = 10 * Runtime.getRuntime().availableProcessors();

    private static final int maxPoolSize = corePoolSize * 2;

    @Bean(name = "asyncServiceExecutor")
    public Executor asyncServiceExecutor() {
        log.info("start asyncServiceExecutor, corePoolSize:{}, maxPoolSize:{}", corePoolSize, maxPoolSize);
        // ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(configBean.getQueueCapacity());
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(configBean.getNamePrefix());

        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
}
1.3.2 在主启动类配置的方式启用
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
@MapperScan("com.chris.mybatisplus.dao.mapper")
@ConfigurationPropertiesScan("com.chris.mybatisplus.config")
@EnableAsync
public class MybatisPlusMain {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusMain.class, args);
    }
}

1.4 创建异步服务接口
public interface IAsyncService {
    /**
     * 执行异步任务
     * 可以根据需求,自己加参数拟定,我这里就做个测试演示
     */
    void executeAsync();
    
    /**
     * 异步调用返回Future
     *
     * @param i input param
     * @return Future
     */
    Future<String> asyncInvokeReturnFuture(int i);
}
1.5 实现异步服务接口

在executeAsync()方法上增加注解@Async("asyncServiceExecutor")
asyncServiceExecutor方法是前面ExecutorConfig.java中的方法名,表明executeAsync方法进入的线程池是asyncServiceExecutor方法创建的

@Service
@Slf4j
public class AsyncServiceImpl implements IAsyncService {

    /**
     * 将Service层的服务异步化
     * '@Async' 表明executeAsync方法进入的线程池是asyncServiceExecutor方法创建的
     */
    @Override
    @Async("asyncServiceExecutor")
    public void executeAsync() {
        log.info("start executeAsync");

        log.info("异步线程要做的事情");
        log.info("可以在这里执行批量插入等耗时的事情");

        log.info("end executeAsync");
    }
    
    @SneakyThrows
    @Async("asyncServiceExecutor")
    public Future<String> asyncInvokeReturnFuture(int i) {
        log.info("asyncInvokeReturnFuture, param:{}", i);
        Future<String> future = null;
        try {
            TimeUnit.SECONDS.sleep(5);
            future = new AsyncResult<>("invoke success:" + i);
        } catch (InterruptedException e) {
            e.printStackTrace();
            future = new AsyncResult<>("invoke error:" + e.getMessage());
        }
        return future;
    }
    
}
1.6 创建Controller
@RestController
@Slf4j
public class AsyncController {

    @Resource
    private IAsyncService asyncService;

    @GetMapping("async")
    public void async() {
        asyncService.executeAsync();
    }
    
    @GetMapping("asyncInvokeReturnFuture")
    public String asyncInvokeReturnFuture(@RequestParam("key") int key) {
      String result = "";
      try {
          result = asyncService.asyncInvokeReturnFuture(key).get();
      } catch (InterruptedException | ExecutionException e) {
          e.printStackTrace();
      }
      return result;
  }
}
1.7 用postmain多次测试请求一下
用postmain或者其他工具来多次测试请求一下
 2021-04-16 22:15:47.655  INFO 10516 --- [async-service-5] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:15:47.655  INFO 10516 --- [async-service-5] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
2021-04-16 22:15:47.770  INFO 10516 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:15:47.770  INFO 10516 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
2021-04-16 22:15:47.816  INFO 10516 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:15:47.816  INFO 10516 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
2021-04-16 22:15:48.833  INFO 10516 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:15:48.834  INFO 10516 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
2021-04-16 22:15:48.986  INFO 10516 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:15:48.987  INFO 10516 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
1.8 升级ThreadPoolTaskExecutor打印当前线程池的运行状况
通过以上日志可以发现,[async-service-]是有多个线程的,显然已经在我们配置的线程池中执行了,
并且每次请求中,controller的起始和结束日志都是连续打印的,表明每次请求都快速响应了,
而耗时的操作都留给线程池中的线程去异步执行;
虽然我们已经用上了线程池,但是还不清楚线程池当时的情况,有多少线程在执行,多少在队列中等待呢?
这里我创建了一个ThreadPoolTaskExecutor的子类,在每次提交线程的时候都会将当前线程池的运行状况打印出来

@Slf4j
public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {

    private void showThreadPoolInfo(String prefix) {
        ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();

        log.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]",
                this.getThreadNamePrefix(),
                prefix,
                threadPoolExecutor.getTaskCount(),
                threadPoolExecutor.getCompletedTaskCount(),
                threadPoolExecutor.getActiveCount(),
                threadPoolExecutor.getQueue().size());
    }

    @Override
    public void execute(Runnable task) {
        showThreadPoolInfo("1. do execute");
        super.execute(task);
    }

    @Override
    public void execute(Runnable task, long startTimeout) {
        showThreadPoolInfo("2. do execute");
        super.execute(task, startTimeout);
    }

    @Override
    public Future<?> submit(Runnable task) {
        showThreadPoolInfo("1. do submit");
        return super.submit(task);
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        showThreadPoolInfo("2. do submit");
        return super.submit(task);
    }

    @Override
    public ListenableFuture<?> submitListenable(Runnable task) {
        showThreadPoolInfo("1. do submitListenable");
        return super.submitListenable(task);
    }

    @Override
    public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
        showThreadPoolInfo("2. do submitListenable");
        return super.submitListenable(task);
    }

}
2021-04-16 22:23:30.951  INFO 14088 --- [nio-8087-exec-2] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [0], completedTaskCount [0], activeCount [0], queueSize [0]
2021-04-16 22:23:30.952  INFO 14088 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:23:30.953  INFO 14088 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
2021-04-16 22:23:31.351  INFO 14088 --- [nio-8087-exec-3] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [1], completedTaskCount [1], activeCount [0], queueSize [0]
2021-04-16 22:23:31.353  INFO 14088 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:23:31.353  INFO 14088 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
2021-04-16 22:23:31.927  INFO 14088 --- [nio-8087-exec-5] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [2], completedTaskCount [2], activeCount [0], queueSize [0]
2021-04-16 22:23:31.929  INFO 14088 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:23:31.930  INFO 14088 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
2021-04-16 22:23:32.496  INFO 14088 --- [nio-8087-exec-7] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [3], completedTaskCount [3], activeCount [0], queueSize [0]
2021-04-16 22:23:32.498  INFO 14088 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl   : start executeAsync
异步线程要做的事情
可以在这里执行批量插入等耗时的事情
2021-04-16 22:23:32.499  INFO 14088 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl   : end executeAsync
注意这一行日志:
2021-04-16 22:23:32.496  INFO 14088 --- [nio-8087-exec-7] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [3], completedTaskCount [3], activeCount [0], queueSize [0]

2. SpringBoot自定义线程池的三种方式

自定义线程池,可对系统中线程池更加细粒度的控制,方便调整线程池大小配置,线程执行异常控制和处理。
在设置系统自定义线程池代替默认线程池时,虽可通过多种模式设置,但替换默认线程池最终产生的线程池有且只能设置一个(不能设置多个类继承AsyncConfigurer)

org.springframework.scheduling.annotation.AbstractAsyncConfiguration#setConfigurers
/**
 * Collect any {@link AsyncConfigurer} beans through autowiring.
 */
@Autowired
void setConfigurers(ObjectProvider<AsyncConfigurer> configurers) {
    Supplier<AsyncConfigurer> configurer = SingletonSupplier.of(() -> {
        List<AsyncConfigurer> candidates = configurers.stream().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(candidates)) {
            return null;
        }
        if (candidates.size() > 1) {
            throw new IllegalStateException("Only one AsyncConfigurer may exist");
        }
        return candidates.get(0);
    });
    this.executor = adapt(configurer, AsyncConfigurer::getAsyncExecutor);
    this.exceptionHandler = adapt(configurer, AsyncConfigurer::getAsyncUncaughtExceptionHandler);
}

自定义线程池有如下模式:
无论是继承或者重新实现接口,都需指定一个线程池。且重新实现 public Executor getAsyncExecutor()方法。

2.1 重新实现接口AsyncConfigurer
2.2 继承AsyncConfigurerSupport
2.3 配置由自定义的TaskExecutor替代内置的任务执行器

由于AsyncConfigurer的默认线程池在源码中为空,Spring通过beanFactory.getBean(TaskExecutor.class)先查看是否有线程池,未配置时,通过beanFactory.getBean(==DEFAULT_TASK_EXECUTOR_BEAN_NAME==, Executor.class),
又查询是否存在默认名称为TaskExecutor的线程池。所以可在项目中,定义名称为TaskExecutor的bean生成一个默认线程池。也可不指定线程池的名称,申明一个线程池,本身底层是基于==TaskExecutor.class==便可。

%5Btoc%5D%0A%0A%0A%0A%3E%20%E5%90%8E%E9%9D%A2%E5%B0%B1%E6%83%B3%E5%88%B0%E4%BA%86%E7%BA%BF%E7%A8%8B%E6%B1%A0ThreadPoolExecutor%EF%BC%8C%E8%80%8C%E7%94%A8%E7%9A%84%E6%98%AF%0A%3E%20SpringBoot%E9%A1%B9%E7%9B%AE%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8Spring%E6%8F%90%E4%BE%9B%E7%9A%84%E5%AF%B9ThreadPoolExecutor%E5%B0%81%E8%A3%85%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0ThreadPoolTaskExecutor%EF%BC%8C%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E6%B3%A8%E8%A7%A3%E5%90%AF%E7%94%A8%0A%0A%0A%23%23%23%23%201.%E4%BD%BF%E7%94%A8%E6%AD%A5%E9%AA%A4%0A%23%23%23%23%23%201.1%20%E5%A2%9E%E5%8A%A0%E9%85%8D%E7%BD%AE%0A%3E%20%E5%9C%A8application.yml%E4%B8%AD%E6%B7%BB%E5%8A%A0%E9%85%8D%E7%BD%AE%0A%0A%60%60%60%0Aasync%3A%0A%20%20executor%3A%0A%20%20%20%20thread%3A%0A%20%20%20%20%20%20queue_capacity%3A%2099999%20%20%23%20%E9%85%8D%E7%BD%AE%E9%98%9F%E5%88%97%E5%A4%A7%E5%B0%8F%0A%20%20%20%20%20%20name_prefix%3A%20async-service-%20%23%20%E9%85%8D%E7%BD%AE%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B8%AD%E7%9A%84%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%90%8D%E7%A7%B0%E5%89%8D%E7%BC%80%0A%60%60%60%0A%0A%23%23%23%23%23%201.2%20%E5%A2%9E%E5%8A%A0%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%60%60%60java%0Apackage%20com.chris.mybatisplus.config%3B%0A%0Aimport%20lombok.Data%3B%0Aimport%20org.springframework.boot.context.properties.ConfigurationProperties%3B%0A%0A%2F**%0A%20*%20%40Author%20Lilun%0A%20*%20%40Date%202021-06-08%2010%3A45%0A%20*%20%40Description%0A%20**%2F%0A%40ConfigurationProperties(prefix%20%3D%20%22async.executor.thread%22)%0A%40Data%0Apublic%20class%20ThreadPoolConfigBean%20%7B%0A%20%20%20%20private%20int%20corePoolSize%3B%0A%20%20%20%20private%20int%20maxPoolSize%3B%0A%20%20%20%20private%20int%20queueCapacity%3B%0A%20%20%20%20private%20String%20namePrefix%3B%0A%7D%0A%60%60%60%0A%0A%0A%60%60%60%0A%40SpringBootApplication(exclude%20%3D%20DruidDataSourceAutoConfigure.class)%0A%40MapperScan(%22com.chris.mybatisplus.dao.mapper%22)%0A%40ConfigurationPropertiesScan(%22com.chris.mybatisplus.config%22)%0Apublic%20class%20MybatisPlusMain%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20SpringApplication.run(MybatisPlusMain.class%2C%20args)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%0A%23%23%23%23%23%201.3%20SpringBoot%E5%90%AF%E7%94%A8%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E4%B8%A4%E7%A7%8D%E6%96%B9%E5%BC%8F%0A%23%23%23%23%23%23%201.3.1%20%E9%80%9A%E8%BF%87java%E9%85%8D%E7%BD%AE%E7%9A%84%E6%96%B9%E5%BC%8F%E5%90%AF%E7%94%A8%0A%3E%20%E4%BD%BF%E7%94%A8%40Configuration%E5%92%8C%20%3D%3D%40EnableAsync%3D%3D%20%E8%BF%99%E4%B8%A4%E4%B8%AA%E6%B3%A8%E8%A7%A3%EF%BC%8C%E8%A1%A8%E7%A4%BA%E8%BF%99%E6%98%AF%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%2C%E5%90%8C%E6%97%B6%E5%90%AF%E5%8A%A8Spring%E7%9A%84%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%0A%0A%60%60%60java%0Apackage%20com.chris.mybatisplus.config%3B%0A%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.context.annotation.Bean%3B%0Aimport%20org.springframework.context.annotation.Configuration%3B%0Aimport%20org.springframework.scheduling.annotation.EnableAsync%3B%0Aimport%20org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor%3B%0A%0Aimport%20javax.annotation.Resource%3B%0Aimport%20java.util.concurrent.Executor%3B%0Aimport%20java.util.concurrent.ThreadPoolExecutor%3B%0A%0A%2F**%0A%20*%20%40Author%20Lilun%0A%20*%20%40Date%202021-06-07%2020%3A19%0A%20*%20%40Description%0A%20**%2F%0A%40Configuration%0A%40Slf4j%0A%40EnableAsync%0A%2F%2F%40EnableConfigurationProperties(ThreadPoolConfigBean.class)%0Apublic%20class%20ExecutorConfig%20%7B%0A%20%20%20%20%40Resource%0A%20%20%20%20private%20ThreadPoolConfigBean%20configBean%3B%0A%0A%20%20%20%20private%20static%20final%20int%20corePoolSize%20%3D%2010%20*%20Runtime.getRuntime().availableProcessors()%3B%0A%0A%20%20%20%20private%20static%20final%20int%20maxPoolSize%20%3D%20corePoolSize%20*%202%3B%0A%0A%20%20%20%20%40Bean(name%20%3D%20%22asyncServiceExecutor%22)%0A%20%20%20%20public%20Executor%20asyncServiceExecutor()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22start%20asyncServiceExecutor%2C%20corePoolSize%3A%7B%7D%2C%20maxPoolSize%3A%7B%7D%22%2C%20corePoolSize%2C%20maxPoolSize)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20ThreadPoolTaskExecutor%20executor%20%3D%20new%20ThreadPoolTaskExecutor()%3B%0A%0A%20%20%20%20%20%20%20%20ThreadPoolTaskExecutor%20executor%20%3D%20new%20VisiableThreadPoolTaskExecutor()%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E9%85%8D%E7%BD%AE%E6%A0%B8%E5%BF%83%E7%BA%BF%E7%A8%8B%E6%95%B0%0A%20%20%20%20%20%20%20%20executor.setCorePoolSize(corePoolSize)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E9%85%8D%E7%BD%AE%E6%9C%80%E5%A4%A7%E7%BA%BF%E7%A8%8B%E6%95%B0%0A%20%20%20%20%20%20%20%20executor.setMaxPoolSize(maxPoolSize)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E9%85%8D%E7%BD%AE%E9%98%9F%E5%88%97%E5%A4%A7%E5%B0%8F%0A%20%20%20%20%20%20%20%20executor.setQueueCapacity(configBean.getQueueCapacity())%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E9%85%8D%E7%BD%AE%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B8%AD%E7%9A%84%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%90%8D%E7%A7%B0%E5%89%8D%E7%BC%80%0A%20%20%20%20%20%20%20%20executor.setThreadNamePrefix(configBean.getNamePrefix())%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20rejection-policy%EF%BC%9A%E5%BD%93pool%E5%B7%B2%E7%BB%8F%E8%BE%BE%E5%88%B0max%20size%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86%E6%96%B0%E4%BB%BB%E5%8A%A1%0A%20%20%20%20%20%20%20%20%2F%2F%20CALLER_RUNS%EF%BC%9A%E4%B8%8D%E5%9C%A8%E6%96%B0%E7%BA%BF%E7%A8%8B%E4%B8%AD%E6%89%A7%E8%A1%8C%E4%BB%BB%E5%8A%A1%EF%BC%8C%E8%80%8C%E6%98%AF%E6%9C%89%E8%B0%83%E7%94%A8%E8%80%85%E6%89%80%E5%9C%A8%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%9D%A5%E6%89%A7%E8%A1%8C%0A%20%20%20%20%20%20%20%20executor.setRejectedExecutionHandler(new%20ThreadPoolExecutor.CallerRunsPolicy())%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E6%89%A7%E8%A1%8C%E5%88%9D%E5%A7%8B%E5%8C%96%0A%20%20%20%20%20%20%20%20executor.initialize()%3B%0A%20%20%20%20%20%20%20%20return%20executor%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%201.3.2%20%E5%9C%A8%E4%B8%BB%E5%90%AF%E5%8A%A8%E7%B1%BB%E9%85%8D%E7%BD%AE%E7%9A%84%E6%96%B9%E5%BC%8F%E5%90%AF%E7%94%A8%0A%0A%60%60%60java%0A%40SpringBootApplication(exclude%20%3D%20DruidDataSourceAutoConfigure.class)%0A%40MapperScan(%22com.chris.mybatisplus.dao.mapper%22)%0A%40ConfigurationPropertiesScan(%22com.chris.mybatisplus.config%22)%0A%40EnableAsync%0Apublic%20class%20MybatisPlusMain%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20SpringApplication.run(MybatisPlusMain.class%2C%20args)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%0A%23%23%23%23%23%201.4%20%E5%88%9B%E5%BB%BA%E5%BC%82%E6%AD%A5%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3%0A%0A%60%60%60%0Apublic%20interface%20IAsyncService%20%7B%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E6%89%A7%E8%A1%8C%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%0A%20%20%20%20%20*%20%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E9%9C%80%E6%B1%82%EF%BC%8C%E8%87%AA%E5%B7%B1%E5%8A%A0%E5%8F%82%E6%95%B0%E6%8B%9F%E5%AE%9A%EF%BC%8C%E6%88%91%E8%BF%99%E9%87%8C%E5%B0%B1%E5%81%9A%E4%B8%AA%E6%B5%8B%E8%AF%95%E6%BC%94%E7%A4%BA%0A%20%20%20%20%20*%2F%0A%20%20%20%20void%20executeAsync()%3B%0A%20%20%20%20%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%BC%82%E6%AD%A5%E8%B0%83%E7%94%A8%E8%BF%94%E5%9B%9EFuture%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%40param%20i%20input%20param%0A%20%20%20%20%20*%20%40return%20Future%0A%20%20%20%20%20*%2F%0A%20%20%20%20Future%3CString%3E%20asyncInvokeReturnFuture(int%20i)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%201.5%20%E5%AE%9E%E7%8E%B0%E5%BC%82%E6%AD%A5%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3%0A%3E%20%E5%9C%A8executeAsync()%E6%96%B9%E6%B3%95%E4%B8%8A%E5%A2%9E%E5%8A%A0%E6%B3%A8%E8%A7%A3%40Async(%22asyncServiceExecutor%22)%20%20%0A%3E%20asyncServiceExecutor%E6%96%B9%E6%B3%95%E6%98%AF%E5%89%8D%E9%9D%A2ExecutorConfig.java%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95%E5%90%8D%EF%BC%8C%E8%A1%A8%E6%98%8EexecuteAsync%E6%96%B9%E6%B3%95%E8%BF%9B%E5%85%A5%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%98%AFasyncServiceExecutor%E6%96%B9%E6%B3%95%E5%88%9B%E5%BB%BA%E7%9A%84%0A%0A%60%60%60java%0A%40Service%0A%40Slf4j%0Apublic%20class%20AsyncServiceImpl%20implements%20IAsyncService%20%7B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E5%B0%86Service%E5%B1%82%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%BC%82%E6%AD%A5%E5%8C%96%0A%20%20%20%20%20*%20'%40Async'%20%E8%A1%A8%E6%98%8EexecuteAsync%E6%96%B9%E6%B3%95%E8%BF%9B%E5%85%A5%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%98%AFasyncServiceExecutor%E6%96%B9%E6%B3%95%E5%88%9B%E5%BB%BA%E7%9A%84%0A%20%20%20%20%20*%2F%0A%20%20%20%20%40Override%0A%20%20%20%20%40Async(%22asyncServiceExecutor%22)%0A%20%20%20%20public%20void%20executeAsync()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22start%20executeAsync%22)%3B%0A%0A%20%20%20%20%20%20%20%20log.info(%22%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%22)%3B%0A%20%20%20%20%20%20%20%20log.info(%22%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%22)%3B%0A%0A%20%20%20%20%20%20%20%20log.info(%22end%20executeAsync%22)%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20%40SneakyThrows%0A%20%20%20%20%40Async(%22asyncServiceExecutor%22)%0A%20%20%20%20public%20Future%3CString%3E%20asyncInvokeReturnFuture(int%20i)%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22asyncInvokeReturnFuture%2C%20param%3A%7B%7D%22%2C%20i)%3B%0A%20%20%20%20%20%20%20%20Future%3CString%3E%20future%20%3D%20null%3B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(5)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20future%20%3D%20new%20AsyncResult%3C%3E(%22invoke%20success%3A%22%20%2B%20i)%3B%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20future%20%3D%20new%20AsyncResult%3C%3E(%22invoke%20error%3A%22%20%2B%20e.getMessage())%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20future%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%201.6%20%E5%88%9B%E5%BB%BAController%0A%0A%60%60%60java%0A%40RestController%0A%40Slf4j%0Apublic%20class%20AsyncController%20%7B%0A%0A%20%20%20%20%40Resource%0A%20%20%20%20private%20IAsyncService%20asyncService%3B%0A%0A%20%20%20%20%40GetMapping(%22async%22)%0A%20%20%20%20public%20void%20async()%20%7B%0A%20%20%20%20%20%20%20%20asyncService.executeAsync()%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20%40GetMapping(%22asyncInvokeReturnFuture%22)%0A%20%20%20%20public%20String%20asyncInvokeReturnFuture(%40RequestParam(%22key%22)%20int%20key)%20%7B%0A%20%20%20%20%20%20String%20result%20%3D%20%22%22%3B%0A%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20result%20%3D%20asyncService.asyncInvokeReturnFuture(key).get()%3B%0A%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20%7C%20ExecutionException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20return%20result%3B%0A%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%201.7%20%E7%94%A8postmain%E5%A4%9A%E6%AC%A1%E6%B5%8B%E8%AF%95%E8%AF%B7%E6%B1%82%E4%B8%80%E4%B8%8B%0A%0A%0A%60%60%60%0A%E7%94%A8postmain%E6%88%96%E8%80%85%E5%85%B6%E4%BB%96%E5%B7%A5%E5%85%B7%E6%9D%A5%E5%A4%9A%E6%AC%A1%E6%B5%8B%E8%AF%95%E8%AF%B7%E6%B1%82%E4%B8%80%E4%B8%8B%0A%202021-04-16%2022%3A15%3A47.655%20%20INFO%2010516%20---%20%5Basync-service-5%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A15%3A47.655%20%20INFO%2010516%20---%20%5Basync-service-5%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A2021-04-16%2022%3A15%3A47.770%20%20INFO%2010516%20---%20%5Basync-service-1%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A15%3A47.770%20%20INFO%2010516%20---%20%5Basync-service-1%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A2021-04-16%2022%3A15%3A47.816%20%20INFO%2010516%20---%20%5Basync-service-2%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A15%3A47.816%20%20INFO%2010516%20---%20%5Basync-service-2%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A2021-04-16%2022%3A15%3A48.833%20%20INFO%2010516%20---%20%5Basync-service-3%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A15%3A48.834%20%20INFO%2010516%20---%20%5Basync-service-3%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A2021-04-16%2022%3A15%3A48.986%20%20INFO%2010516%20---%20%5Basync-service-4%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A15%3A48.987%20%20INFO%2010516%20---%20%5Basync-service-4%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A%60%60%60%0A%23%23%23%23%23%201.8%20%E5%8D%87%E7%BA%A7ThreadPoolTaskExecutor%E6%89%93%E5%8D%B0%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E8%BF%90%E8%A1%8C%E7%8A%B6%E5%86%B5%0A%0A%60%60%60%0A%E9%80%9A%E8%BF%87%E4%BB%A5%E4%B8%8A%E6%97%A5%E5%BF%97%E5%8F%AF%E4%BB%A5%E5%8F%91%E7%8E%B0%EF%BC%8C%5Basync-service-%5D%E6%98%AF%E6%9C%89%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%9A%84%EF%BC%8C%E6%98%BE%E7%84%B6%E5%B7%B2%E7%BB%8F%E5%9C%A8%E6%88%91%E4%BB%AC%E9%85%8D%E7%BD%AE%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B8%AD%E6%89%A7%E8%A1%8C%E4%BA%86%EF%BC%8C%0A%E5%B9%B6%E4%B8%94%E6%AF%8F%E6%AC%A1%E8%AF%B7%E6%B1%82%E4%B8%AD%EF%BC%8Ccontroller%E7%9A%84%E8%B5%B7%E5%A7%8B%E5%92%8C%E7%BB%93%E6%9D%9F%E6%97%A5%E5%BF%97%E9%83%BD%E6%98%AF%E8%BF%9E%E7%BB%AD%E6%89%93%E5%8D%B0%E7%9A%84%EF%BC%8C%E8%A1%A8%E6%98%8E%E6%AF%8F%E6%AC%A1%E8%AF%B7%E6%B1%82%E9%83%BD%E5%BF%AB%E9%80%9F%E5%93%8D%E5%BA%94%E4%BA%86%EF%BC%8C%0A%E8%80%8C%E8%80%97%E6%97%B6%E7%9A%84%E6%93%8D%E4%BD%9C%E9%83%BD%E7%95%99%E7%BB%99%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B8%AD%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%8E%BB%E5%BC%82%E6%AD%A5%E6%89%A7%E8%A1%8C%EF%BC%9B%0A%E8%99%BD%E7%84%B6%E6%88%91%E4%BB%AC%E5%B7%B2%E7%BB%8F%E7%94%A8%E4%B8%8A%E4%BA%86%E7%BA%BF%E7%A8%8B%E6%B1%A0%EF%BC%8C%E4%BD%86%E6%98%AF%E8%BF%98%E4%B8%8D%E6%B8%85%E6%A5%9A%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%BD%93%E6%97%B6%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%8C%E6%9C%89%E5%A4%9A%E5%B0%91%E7%BA%BF%E7%A8%8B%E5%9C%A8%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%A4%9A%E5%B0%91%E5%9C%A8%E9%98%9F%E5%88%97%E4%B8%AD%E7%AD%89%E5%BE%85%E5%91%A2%EF%BC%9F%0A%E8%BF%99%E9%87%8C%E6%88%91%E5%88%9B%E5%BB%BA%E4%BA%86%E4%B8%80%E4%B8%AAThreadPoolTaskExecutor%E7%9A%84%E5%AD%90%E7%B1%BB%EF%BC%8C%E5%9C%A8%E6%AF%8F%E6%AC%A1%E6%8F%90%E4%BA%A4%E7%BA%BF%E7%A8%8B%E7%9A%84%E6%97%B6%E5%80%99%E9%83%BD%E4%BC%9A%E5%B0%86%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E8%BF%90%E8%A1%8C%E7%8A%B6%E5%86%B5%E6%89%93%E5%8D%B0%E5%87%BA%E6%9D%A5%0A%60%60%60%0A%0A%60%60%60java%0A%0A%40Slf4j%0Apublic%20class%20VisiableThreadPoolTaskExecutor%20extends%20ThreadPoolTaskExecutor%20%7B%0A%0A%20%20%20%20private%20void%20showThreadPoolInfo(String%20prefix)%20%7B%0A%20%20%20%20%20%20%20%20ThreadPoolExecutor%20threadPoolExecutor%20%3D%20getThreadPoolExecutor()%3B%0A%0A%20%20%20%20%20%20%20%20log.info(%22%7B%7D%2C%20%7B%7D%2CtaskCount%20%5B%7B%7D%5D%2C%20completedTaskCount%20%5B%7B%7D%5D%2C%20activeCount%20%5B%7B%7D%5D%2C%20queueSize%20%5B%7B%7D%5D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.getThreadNamePrefix()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20prefix%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20threadPoolExecutor.getTaskCount()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20threadPoolExecutor.getCompletedTaskCount()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20threadPoolExecutor.getActiveCount()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20threadPoolExecutor.getQueue().size())%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20execute(Runnable%20task)%20%7B%0A%20%20%20%20%20%20%20%20showThreadPoolInfo(%221.%20do%20execute%22)%3B%0A%20%20%20%20%20%20%20%20super.execute(task)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20execute(Runnable%20task%2C%20long%20startTimeout)%20%7B%0A%20%20%20%20%20%20%20%20showThreadPoolInfo(%222.%20do%20execute%22)%3B%0A%20%20%20%20%20%20%20%20super.execute(task%2C%20startTimeout)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20Future%3C%3F%3E%20submit(Runnable%20task)%20%7B%0A%20%20%20%20%20%20%20%20showThreadPoolInfo(%221.%20do%20submit%22)%3B%0A%20%20%20%20%20%20%20%20return%20super.submit(task)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20%3CT%3E%20Future%3CT%3E%20submit(Callable%3CT%3E%20task)%20%7B%0A%20%20%20%20%20%20%20%20showThreadPoolInfo(%222.%20do%20submit%22)%3B%0A%20%20%20%20%20%20%20%20return%20super.submit(task)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20ListenableFuture%3C%3F%3E%20submitListenable(Runnable%20task)%20%7B%0A%20%20%20%20%20%20%20%20showThreadPoolInfo(%221.%20do%20submitListenable%22)%3B%0A%20%20%20%20%20%20%20%20return%20super.submitListenable(task)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20%3CT%3E%20ListenableFuture%3CT%3E%20submitListenable(Callable%3CT%3E%20task)%20%7B%0A%20%20%20%20%20%20%20%20showThreadPoolInfo(%222.%20do%20submitListenable%22)%3B%0A%20%20%20%20%20%20%20%20return%20super.submitListenable(task)%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%60%60%60%0A%0A%0A%60%60%60%0A2021-04-16%2022%3A23%3A30.951%20%20INFO%2014088%20---%20%5Bnio-8087-exec-2%5D%20u.d.e.e.i.VisiableThreadPoolTaskExecutor%20%3A%20async-service-%2C%202.%20do%20submit%2CtaskCount%20%5B0%5D%2C%20completedTaskCount%20%5B0%5D%2C%20activeCount%20%5B0%5D%2C%20queueSize%20%5B0%5D%0A2021-04-16%2022%3A23%3A30.952%20%20INFO%2014088%20---%20%5Basync-service-1%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A23%3A30.953%20%20INFO%2014088%20---%20%5Basync-service-1%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A2021-04-16%2022%3A23%3A31.351%20%20INFO%2014088%20---%20%5Bnio-8087-exec-3%5D%20u.d.e.e.i.VisiableThreadPoolTaskExecutor%20%3A%20async-service-%2C%202.%20do%20submit%2CtaskCount%20%5B1%5D%2C%20completedTaskCount%20%5B1%5D%2C%20activeCount%20%5B0%5D%2C%20queueSize%20%5B0%5D%0A2021-04-16%2022%3A23%3A31.353%20%20INFO%2014088%20---%20%5Basync-service-2%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A23%3A31.353%20%20INFO%2014088%20---%20%5Basync-service-2%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A2021-04-16%2022%3A23%3A31.927%20%20INFO%2014088%20---%20%5Bnio-8087-exec-5%5D%20u.d.e.e.i.VisiableThreadPoolTaskExecutor%20%3A%20async-service-%2C%202.%20do%20submit%2CtaskCount%20%5B2%5D%2C%20completedTaskCount%20%5B2%5D%2C%20activeCount%20%5B0%5D%2C%20queueSize%20%5B0%5D%0A2021-04-16%2022%3A23%3A31.929%20%20INFO%2014088%20---%20%5Basync-service-3%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A23%3A31.930%20%20INFO%2014088%20---%20%5Basync-service-3%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A2021-04-16%2022%3A23%3A32.496%20%20INFO%2014088%20---%20%5Bnio-8087-exec-7%5D%20u.d.e.e.i.VisiableThreadPoolTaskExecutor%20%3A%20async-service-%2C%202.%20do%20submit%2CtaskCount%20%5B3%5D%2C%20completedTaskCount%20%5B3%5D%2C%20activeCount%20%5B0%5D%2C%20queueSize%20%5B0%5D%0A2021-04-16%2022%3A23%3A32.498%20%20INFO%2014088%20---%20%5Basync-service-4%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20start%20executeAsync%0A%E5%BC%82%E6%AD%A5%E7%BA%BF%E7%A8%8B%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%0A%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%99%E9%87%8C%E6%89%A7%E8%A1%8C%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E7%AD%89%E8%80%97%E6%97%B6%E7%9A%84%E4%BA%8B%E6%83%85%0A2021-04-16%2022%3A23%3A32.499%20%20INFO%2014088%20---%20%5Basync-service-4%5D%20c.u.d.e.executor.impl.AsyncServiceImpl%20%20%20%3A%20end%20executeAsync%0A%E6%B3%A8%E6%84%8F%E8%BF%99%E4%B8%80%E8%A1%8C%E6%97%A5%E5%BF%97%EF%BC%9A%0A2021-04-16%2022%3A23%3A32.496%20%20INFO%2014088%20---%20%5Bnio-8087-exec-7%5D%20u.d.e.e.i.VisiableThreadPoolTaskExecutor%20%3A%20async-service-%2C%202.%20do%20submit%2CtaskCount%20%5B3%5D%2C%20completedTaskCount%20%5B3%5D%2C%20activeCount%20%5B0%5D%2C%20queueSize%20%5B0%5D%0A%60%60%60%0A%0A%23%23%23%23%202.%20SpringBoot%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E4%B8%89%E7%A7%8D%E6%96%B9%E5%BC%8F%0A%3E%20%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BA%BF%E7%A8%8B%E6%B1%A0%EF%BC%8C%E5%8F%AF%E5%AF%B9%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%9B%B4%E5%8A%A0%E7%BB%86%E7%B2%92%E5%BA%A6%E7%9A%84%E6%8E%A7%E5%88%B6%EF%BC%8C%E6%96%B9%E4%BE%BF%E8%B0%83%E6%95%B4%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%A4%A7%E5%B0%8F%E9%85%8D%E7%BD%AE%EF%BC%8C%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E5%BC%82%E5%B8%B8%E6%8E%A7%E5%88%B6%E5%92%8C%E5%A4%84%E7%90%86%E3%80%82%20%20%0A%3E%20%E5%9C%A8%E8%AE%BE%E7%BD%AE%E7%B3%BB%E7%BB%9F%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BB%A3%E6%9B%BF%E9%BB%98%E8%AE%A4%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%97%B6%EF%BC%8C%E8%99%BD%E5%8F%AF%E9%80%9A%E8%BF%87%E5%A4%9A%E7%A7%8D%E6%A8%A1%E5%BC%8F%E8%AE%BE%E7%BD%AE%EF%BC%8C%E4%BD%86%E6%9B%BF%E6%8D%A2%E9%BB%98%E8%AE%A4%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%9C%80%E7%BB%88%E4%BA%A7%E7%94%9F%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%9C%89%E4%B8%94%E5%8F%AA%E8%83%BD%E8%AE%BE%E7%BD%AE%E4%B8%80%E4%B8%AA%EF%BC%88%E4%B8%8D%E8%83%BD%E8%AE%BE%E7%BD%AE%E5%A4%9A%E4%B8%AA%E7%B1%BB%E7%BB%A7%E6%89%BFAsyncConfigurer%EF%BC%89%20%20%0A%0A%0A%60%60%60%0Aorg.springframework.scheduling.annotation.AbstractAsyncConfiguration%23setConfigurers%0A%60%60%60%0A%0A%60%60%60java%0A%2F**%0A%20*%20Collect%20any%20%7B%40link%20AsyncConfigurer%7D%20beans%20through%20autowiring.%0A%20*%2F%0A%40Autowired%0Avoid%20setConfigurers(ObjectProvider%3CAsyncConfigurer%3E%20configurers)%20%7B%0A%20%20%20%20Supplier%3CAsyncConfigurer%3E%20configurer%20%3D%20SingletonSupplier.of(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20List%3CAsyncConfigurer%3E%20candidates%20%3D%20configurers.stream().collect(Collectors.toList())%3B%0A%20%20%20%20%20%20%20%20if%20(CollectionUtils.isEmpty(candidates))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(candidates.size()%20%3E%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20IllegalStateException(%22Only%20one%20AsyncConfigurer%20may%20exist%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20candidates.get(0)%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20this.executor%20%3D%20adapt(configurer%2C%20AsyncConfigurer%3A%3AgetAsyncExecutor)%3B%0A%20%20%20%20this.exceptionHandler%20%3D%20adapt(configurer%2C%20AsyncConfigurer%3A%3AgetAsyncUncaughtExceptionHandler)%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%9C%89%E5%A6%82%E4%B8%8B%E6%A8%A1%E5%BC%8F%EF%BC%9A%20%20%0A%E6%97%A0%E8%AE%BA%E6%98%AF%E7%BB%A7%E6%89%BF%E6%88%96%E8%80%85%E9%87%8D%E6%96%B0%E5%AE%9E%E7%8E%B0%E6%8E%A5%E5%8F%A3%EF%BC%8C%E9%83%BD%E9%9C%80%E6%8C%87%E5%AE%9A%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%B1%A0%E3%80%82%E4%B8%94%E9%87%8D%E6%96%B0%E5%AE%9E%E7%8E%B0%20public%20Executor%20getAsyncExecutor()%E6%96%B9%E6%B3%95%E3%80%82%0A%0A%23%23%23%23%23%202.1%20%E9%87%8D%E6%96%B0%E5%AE%9E%E7%8E%B0%E6%8E%A5%E5%8F%A3AsyncConfigurer%0A%23%23%23%23%23%202.2%20%E7%BB%A7%E6%89%BFAsyncConfigurerSupport%0A%23%23%23%23%23%202.3%20%E9%85%8D%E7%BD%AE%E7%94%B1%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84TaskExecutor%E6%9B%BF%E4%BB%A3%E5%86%85%E7%BD%AE%E7%9A%84%E4%BB%BB%E5%8A%A1%E6%89%A7%E8%A1%8C%E5%99%A8%0A%20%3E%20%E7%94%B1%E4%BA%8EAsyncConfigurer%E7%9A%84%E9%BB%98%E8%AE%A4%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%9C%A8%E6%BA%90%E7%A0%81%E4%B8%AD%E4%B8%BA%E7%A9%BA%EF%BC%8CSpring%E9%80%9A%E8%BF%87beanFactory.getBean(TaskExecutor.class)%E5%85%88%E6%9F%A5%E7%9C%8B%E6%98%AF%E5%90%A6%E6%9C%89%E7%BA%BF%E7%A8%8B%E6%B1%A0%EF%BC%8C%E6%9C%AA%E9%85%8D%E7%BD%AE%E6%97%B6%EF%BC%8C%E9%80%9A%E8%BF%87beanFactory.getBean(%3D%3DDEFAULT_TASK_EXECUTOR_BEAN_NAME%3D%3D%2C%20Executor.class)%EF%BC%8C%20%20%0A%20%E5%8F%88%E6%9F%A5%E8%AF%A2%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E9%BB%98%E8%AE%A4%E5%90%8D%E7%A7%B0%E4%B8%BATaskExecutor%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%B1%A0%E3%80%82%E6%89%80%E4%BB%A5%E5%8F%AF%E5%9C%A8%E9%A1%B9%E7%9B%AE%E4%B8%AD%EF%BC%8C%E5%AE%9A%E4%B9%89%E5%90%8D%E7%A7%B0%E4%B8%BATaskExecutor%E7%9A%84bean%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E9%BB%98%E8%AE%A4%E7%BA%BF%E7%A8%8B%E6%B1%A0%E3%80%82%E4%B9%9F%E5%8F%AF%E4%B8%8D%E6%8C%87%E5%AE%9A%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E5%90%8D%E7%A7%B0%EF%BC%8C%E7%94%B3%E6%98%8E%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%B1%A0%EF%BC%8C%E6%9C%AC%E8%BA%AB%E5%BA%95%E5%B1%82%E6%98%AF%E5%9F%BA%E4%BA%8E%3D%3DTaskExecutor.class%3D%3D%E4%BE%BF%E5%8F%AF%E3%80%82%0A%20%0A%20%0A%0A

ListenableFuture

创建时间:2022/2/17 17:40
作者:Chris


事件监听 EventListener

创建时间:2022/1/6 17:33
更新时间:2022/2/17 15:40
作者:Chris
来源:https://www.cnblogs.com/itplay/p/10982072.html

1 是什么

1.1 组成部分

spring的事件监听有三个部分组成,
事件(ApplicationEvent)
监听器 (ApplicationListener)
事件发布操作 (ApplicationContext.publishEvent)

1.2 原理

如果在上下文中部署一个实现了ApplicationListener接口的bean, 每当在一个ApplicationEvent发布到 ApplicationContext 时,这个bean得到通知。其实这就是标准的 Oberver 设计模式。

2 怎么玩

2.1 传统实现

2.1.1 ApplicationEvent 事件

继承ApplicationListener抽象类

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;

@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
public class EmailEvent extends ApplicationEvent {
    private String address;
    private String text;

    public EmailEvent(Object source) {
        super(source);
    }


    public EmailEvent(Object source, String address, String text) {
        super(source);
        this.address = address;
        this.text = text;
    }

    public void print() {
        System.out.println("hello Spring ApplicationEvent!");
    }
}
2.1.2 ApplicationListener 监听

实现ApplicationListener接口并覆写onApplicationEvent

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class EmailListener implements ApplicationListener<EmailEvent> {
    @Override
    public void onApplicationEvent(EmailEvent emailEvent) {
        emailEvent.print();
        System.out.println("the source is :" + emailEvent.getSource());
        System.out.println("the address is :" + emailEvent.getAddress());
        System.out.println("the text is :" + emailEvent.getText());
    }
}

2.1.3 事件发布
@SpringBootTest
class Springboot2022ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    void listenerTest() {
        EmailEvent emailEvent = new EmailEvent("hello", "chris@163.com", "this's a email text.");
        applicationContext.publishEvent(emailEvent);
    }
}
hello Spring ApplicationEvent!
the source is :hello
the address is :chris@163.com
the text is :this's a email text.

2.2 注解实现

2.2.1 Event 事件
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class BlogModifyEvent {

    private String text;
    private boolean isChanged;

    public void print() {
        System.out.println("hello Spring BlogModifyEvent!");
    }
}

2.2.2 绑定监听
import com.chris.springboot2022.listener.BlogModifyEvent;

public interface IListenerService {

    void modifyBlog(BlogModifyEvent blogModifyEvent);
}
import cn.hutool.json.JSONUtil;
import com.chris.springboot2022.listener.BlogModifyEvent;
import com.chris.springboot2022.service.IListenerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class ListernerServiceImpl implements IListenerService {

    @Override
    @EventListener
    public void modifyBlog(BlogModifyEvent blogModifyEvent) {
        blogModifyEvent.print();
        log.info("blogModifyEvent:{}", JSONUtil.toJsonStr(blogModifyEvent));
    }
}

Spring会为事件创建一个ApplicationListener实例,并从方法参数中获取事件的类型。
一个类中被事件注释的方法数量没有限制,所有相关的事件句柄都会分组到一个类中。

2.2.3 事件发布
@SpringBootTest
class Springboot2022ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    void listener2Test() {
        BlogModifyEvent blogModifyEvent = new BlogModifyEvent("this's my first blog.", false);
        applicationContext.publishEvent(blogModifyEvent);
    }
}
hello Spring BlogModifyEvent!
2022-01-07 11:35:25.041  INFO 48388 --- [           main] c.c.s.service.impl.ListernerServiceImpl  : blogModifyEvent:{"isChanged":false,"text":"this's my first blog."}

2.3 有条件的事件处理

@Override
@EventListener(condition = "#blogModifyEvent.isChanged")
public void modifyBlogWhenChanged(BlogModifyEvent blogModifyEvent) {
    System.out.println("blog has been changed!");
    log.info("blogModifyEvent:{}", JSONUtil.toJsonStr(blogModifyEvent));
}
@SpringBootTest
class Springboot2022ApplicationTests {
    @Autowired
    private ApplicationContext applicationContext;

    @Test
    void listener2Test() {
        BlogModifyEvent blogModifyEvent = new BlogModifyEvent("this's my first blog.", true);
        applicationContext.publishEvent(blogModifyEvent);
    }
}
blog has been changed!
2022-01-07 11:39:36.153  INFO 47168 --- [           main] c.c.s.service.impl.ListernerServiceImpl  : blogModifyEvent:{"isChanged":true,"text":"this's my first blog."}
hello Spring BlogModifyEvent!
2022-01-07 11:39:36.154  INFO 47168 --- [           main] c.c.s.service.impl.ListernerServiceImpl  : blogModifyEvent:{"isChanged":true,"text":"this's my first blog."}

因为我们绑定了两个监听,所以以isChanged=true时会打印两个监听日志

2.4 异步事件处理

注释@EventListener 还可以与注释 @Async 进行组合使用,以提供异步事件处理的机制。
下面的代码中,指定的事件监听器既不会阻塞主要的代码执行,又不会被其它的监听器处理。

%5Btoc%5D%0A%23%23%201%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%23%23%23%23%201.1%20%E7%BB%84%E6%88%90%E9%83%A8%E5%88%86%20%0A%3E%20spring%E7%9A%84%E4%BA%8B%E4%BB%B6%E7%9B%91%E5%90%AC%E6%9C%89%E4%B8%89%E4%B8%AA%E9%83%A8%E5%88%86%E7%BB%84%E6%88%90%EF%BC%8C%0A%3E%20%E4%BA%8B%E4%BB%B6%EF%BC%88ApplicationEvent)%0A%3E%20%E7%9B%91%E5%90%AC%E5%99%A8%20(ApplicationListener)%0A%3E%20%E4%BA%8B%E4%BB%B6%E5%8F%91%E5%B8%83%E6%93%8D%E4%BD%9C%20(ApplicationContext.publishEvent)%0A%0A%23%23%23%23%201.2%20%E5%8E%9F%E7%90%86%0A%3E%20%E5%A6%82%E6%9E%9C%E5%9C%A8%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%E9%83%A8%E7%BD%B2%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%8E%B0%E4%BA%86%60ApplicationListener%60%E6%8E%A5%E5%8F%A3%E7%9A%84bean%2C%20%E6%AF%8F%E5%BD%93%E5%9C%A8%E4%B8%80%E4%B8%AA%60ApplicationEvent%60%E5%8F%91%E5%B8%83%E5%88%B0%20%60ApplicationContext%60%20%E6%97%B6%EF%BC%8C%E8%BF%99%E4%B8%AAbean%E5%BE%97%E5%88%B0%E9%80%9A%E7%9F%A5%E3%80%82%E5%85%B6%E5%AE%9E%E8%BF%99%E5%B0%B1%E6%98%AF%E6%A0%87%E5%87%86%E7%9A%84%20%60Oberver%60%20%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%82%0A%0A%0A%23%23%202%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%202.1%20%E4%BC%A0%E7%BB%9F%E5%AE%9E%E7%8E%B0%0A%0A%23%23%23%23%23%202.1.1%20ApplicationEvent%20%E4%BA%8B%E4%BB%B6%0A%3E%20%E7%BB%A7%E6%89%BFApplicationListener%E6%8A%BD%E8%B1%A1%E7%B1%BB%0A%0A%60%60%60java%0Aimport%20lombok.EqualsAndHashCode%3B%0Aimport%20lombok.Getter%3B%0Aimport%20lombok.Setter%3B%0Aimport%20org.springframework.context.ApplicationEvent%3B%0A%0A%40Getter%0A%40Setter%0A%40EqualsAndHashCode(callSuper%20%3D%20true)%0Apublic%20class%20EmailEvent%20extends%20ApplicationEvent%20%7B%0A%20%20%20%20private%20String%20address%3B%0A%20%20%20%20private%20String%20text%3B%0A%0A%20%20%20%20public%20EmailEvent(Object%20source)%20%7B%0A%20%20%20%20%20%20%20%20super(source)%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20public%20EmailEvent(Object%20source%2C%20String%20address%2C%20String%20text)%20%7B%0A%20%20%20%20%20%20%20%20super(source)%3B%0A%20%20%20%20%20%20%20%20this.address%20%3D%20address%3B%0A%20%20%20%20%20%20%20%20this.text%20%3D%20text%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20void%20print()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22hello%20Spring%20ApplicationEvent!%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%202.1.2%20ApplicationListener%20%E7%9B%91%E5%90%AC%0A%3E%20%E5%AE%9E%E7%8E%B0ApplicationListener%E6%8E%A5%E5%8F%A3%E5%B9%B6%E8%A6%86%E5%86%99onApplicationEvent%0A%0A%60%60%60java%0Aimport%20org.springframework.context.ApplicationListener%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0A%40Component%0Apublic%20class%20EmailListener%20implements%20ApplicationListener%3CEmailEvent%3E%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20onApplicationEvent(EmailEvent%20emailEvent)%20%7B%0A%20%20%20%20%20%20%20%20emailEvent.print()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22the%20source%20is%20%3A%22%20%2B%20emailEvent.getSource())%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22the%20address%20is%20%3A%22%20%2B%20emailEvent.getAddress())%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22the%20text%20is%20%3A%22%20%2B%20emailEvent.getText())%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%23%202.1.3%20%E4%BA%8B%E4%BB%B6%E5%8F%91%E5%B8%83%0A%0A%60%60%60java%0A%40SpringBootTest%0Aclass%20Springboot2022ApplicationTests%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20ApplicationContext%20applicationContext%3B%0A%0A%20%20%20%20%40Test%0A%20%20%20%20void%20listenerTest()%20%7B%0A%20%20%20%20%20%20%20%20EmailEvent%20emailEvent%20%3D%20new%20EmailEvent(%22hello%22%2C%20%22chris%40163.com%22%2C%20%22this's%20a%20email%20text.%22)%3B%0A%20%20%20%20%20%20%20%20applicationContext.publishEvent(emailEvent)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60%0Ahello%20Spring%20ApplicationEvent!%0Athe%20source%20is%20%3Ahello%0Athe%20address%20is%20%3Achris%40163.com%0Athe%20text%20is%20%3Athis's%20a%20email%20text.%0A%60%60%60%0A%0A%0A%23%23%23%23%202.2%20%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0%0A%0A%23%23%23%23%23%202.2.1%20Event%20%E4%BA%8B%E4%BB%B6%0A%60%60%60java%0Aimport%20lombok.AllArgsConstructor%3B%0Aimport%20lombok.Data%3B%0A%0A%40Data%0A%40AllArgsConstructor%0Apublic%20class%20BlogModifyEvent%20%7B%0A%0A%20%20%20%20private%20String%20text%3B%0A%20%20%20%20private%20boolean%20isChanged%3B%0A%0A%20%20%20%20public%20void%20print()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22hello%20Spring%20BlogModifyEvent!%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%23%23%23%23%23%202.2.2%20%E7%BB%91%E5%AE%9A%E7%9B%91%E5%90%AC%0A%0A%60%60%60java%0Aimport%20com.chris.springboot2022.listener.BlogModifyEvent%3B%0A%0Apublic%20interface%20IListenerService%20%7B%0A%0A%20%20%20%20void%20modifyBlog(BlogModifyEvent%20blogModifyEvent)%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0Aimport%20cn.hutool.json.JSONUtil%3B%0Aimport%20com.chris.springboot2022.listener.BlogModifyEvent%3B%0Aimport%20com.chris.springboot2022.service.IListenerService%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.context.event.EventListener%3B%0Aimport%20org.springframework.stereotype.Service%3B%0A%0A%40Service%0A%40Slf4j%0Apublic%20class%20ListernerServiceImpl%20implements%20IListenerService%20%7B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20%40EventListener%0A%20%20%20%20public%20void%20modifyBlog(BlogModifyEvent%20blogModifyEvent)%20%7B%0A%20%20%20%20%20%20%20%20blogModifyEvent.print()%3B%0A%20%20%20%20%20%20%20%20log.info(%22blogModifyEvent%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(blogModifyEvent))%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%3E%20Spring%E4%BC%9A%E4%B8%BA%E4%BA%8B%E4%BB%B6%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAApplicationListener%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%B9%B6%E4%BB%8E%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E4%B8%AD%E8%8E%B7%E5%8F%96%E4%BA%8B%E4%BB%B6%E7%9A%84%E7%B1%BB%E5%9E%8B%E3%80%82%0A%3E%20%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%AD%E8%A2%AB%E4%BA%8B%E4%BB%B6%E6%B3%A8%E9%87%8A%E7%9A%84%E6%96%B9%E6%B3%95%E6%95%B0%E9%87%8F%E6%B2%A1%E6%9C%89%E9%99%90%E5%88%B6%EF%BC%8C%E6%89%80%E6%9C%89%E7%9B%B8%E5%85%B3%E7%9A%84%E4%BA%8B%E4%BB%B6%E5%8F%A5%E6%9F%84%E9%83%BD%E4%BC%9A%E5%88%86%E7%BB%84%E5%88%B0%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%AD%E3%80%82%0A%0A%23%23%23%23%23%202.2.3%20%E4%BA%8B%E4%BB%B6%E5%8F%91%E5%B8%83%0A%0A%60%60%60java%0A%40SpringBootTest%0Aclass%20Springboot2022ApplicationTests%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20ApplicationContext%20applicationContext%3B%0A%0A%20%20%20%20%40Test%0A%20%20%20%20void%20listener2Test()%20%7B%0A%20%20%20%20%20%20%20%20BlogModifyEvent%20blogModifyEvent%20%3D%20new%20BlogModifyEvent(%22this's%20my%20first%20blog.%22%2C%20false)%3B%0A%20%20%20%20%20%20%20%20applicationContext.publishEvent(blogModifyEvent)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60%0Ahello%20Spring%20BlogModifyEvent!%0A2022-01-07%2011%3A35%3A25.041%20%20INFO%2048388%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.s.service.impl.ListernerServiceImpl%20%20%3A%20blogModifyEvent%3A%7B%22isChanged%22%3Afalse%2C%22text%22%3A%22this's%20my%20first%20blog.%22%7D%0A%60%60%60%0A%0A%0A%23%23%23%23%202.3%20%E6%9C%89%E6%9D%A1%E4%BB%B6%E7%9A%84%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%0A%0A%60%60%60java%0A%40Override%0A%40EventListener(condition%20%3D%20%22%23blogModifyEvent.isChanged%22)%0Apublic%20void%20modifyBlogWhenChanged(BlogModifyEvent%20blogModifyEvent)%20%7B%0A%20%20%20%20System.out.println(%22blog%20has%20been%20changed!%22)%3B%0A%20%20%20%20log.info(%22blogModifyEvent%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(blogModifyEvent))%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%40SpringBootTest%0Aclass%20Springboot2022ApplicationTests%20%7B%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20ApplicationContext%20applicationContext%3B%0A%0A%20%20%20%20%40Test%0A%20%20%20%20void%20listener2Test()%20%7B%0A%20%20%20%20%20%20%20%20BlogModifyEvent%20blogModifyEvent%20%3D%20new%20BlogModifyEvent(%22this's%20my%20first%20blog.%22%2C%20true)%3B%0A%20%20%20%20%20%20%20%20applicationContext.publishEvent(blogModifyEvent)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60%0Ablog%20has%20been%20changed!%0A2022-01-07%2011%3A39%3A36.153%20%20INFO%2047168%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.s.service.impl.ListernerServiceImpl%20%20%3A%20blogModifyEvent%3A%7B%22isChanged%22%3Atrue%2C%22text%22%3A%22this's%20my%20first%20blog.%22%7D%0Ahello%20Spring%20BlogModifyEvent!%0A2022-01-07%2011%3A39%3A36.154%20%20INFO%2047168%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.s.service.impl.ListernerServiceImpl%20%20%3A%20blogModifyEvent%3A%7B%22isChanged%22%3Atrue%2C%22text%22%3A%22this's%20my%20first%20blog.%22%7D%0A%60%60%60%0A%0A%3E%20%E5%9B%A0%E4%B8%BA%E6%88%91%E4%BB%AC%E7%BB%91%E5%AE%9A%E4%BA%86%E4%B8%A4%E4%B8%AA%E7%9B%91%E5%90%AC%EF%BC%8C%E6%89%80%E4%BB%A5%E4%BB%A5isChanged%3Dtrue%E6%97%B6%E4%BC%9A%E6%89%93%E5%8D%B0%E4%B8%A4%E4%B8%AA%E7%9B%91%E5%90%AC%E6%97%A5%E5%BF%97%0A%0A%23%23%23%23%202.4%20%E5%BC%82%E6%AD%A5%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%0A%3E%20%E6%B3%A8%E9%87%8A%60%40EventListener%60%20%E8%BF%98%E5%8F%AF%E4%BB%A5%E4%B8%8E%E6%B3%A8%E9%87%8A%20%60%40Async%60%20%E8%BF%9B%E8%A1%8C%E7%BB%84%E5%90%88%E4%BD%BF%E7%94%A8%EF%BC%8C%E4%BB%A5%E6%8F%90%E4%BE%9B%E5%BC%82%E6%AD%A5%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%E7%9A%84%E6%9C%BA%E5%88%B6%E3%80%82%0A%3E%20%E4%B8%8B%E9%9D%A2%E7%9A%84%E4%BB%A3%E7%A0%81%E4%B8%AD%EF%BC%8C%E6%8C%87%E5%AE%9A%E7%9A%84%E4%BA%8B%E4%BB%B6%E7%9B%91%E5%90%AC%E5%99%A8%E6%97%A2%E4%B8%8D%E4%BC%9A%E9%98%BB%E5%A1%9E%E4%B8%BB%E8%A6%81%E7%9A%84%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%8F%88%E4%B8%8D%E4%BC%9A%E8%A2%AB%E5%85%B6%E5%AE%83%E7%9A%84%E7%9B%91%E5%90%AC%E5%99%A8%E5%A4%84%E7%90%86%E3%80%82%0A%0A!%5B74858f6063dcb21711705e18adc35b76.png%5D(en-resource%3A%2F%2Fdatabase%2F1280%3A1)%0A%0A

github token

创建时间:2022/2/1 15:47
更新时间:2024/5/26 22:12
作者:Chris

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
%60%60%60%0A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%0A%60%60%60

Bean初始化

创建时间:2022/1/30 18:21
更新时间:2022/2/1 15:40
作者:Chris
来源:https://blog.csdn.net/geekjoker/article/details/79868945

BeanPostProcessor的妙用

1 BeanPostProcessor 后置处理器

1.1 定义

作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑

可以定义一个或多个BeanPostProcessor 接口实现类,然后注册到Spring IoC容器中.
多个后置处理器也可以通过实现Ordered接口getOrder方法来定义执行顺序

实现Ordered接口getOrder方法,该方法返回一整数,默认值为 0,优先级最高,值越大优先级越低

ApplicationContext 会自动检测在配置文件中实现了BeanPostProcessor 接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用它,因此部署一个后置处理器同部署其他的bean并没有什么区别。

1.2 实例
package com.chris.springboot2022.bean.processor;

import com.chris.springboot2022.bean.processor.annotation.RountingInjected;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Map;


@Component
@Slf4j
public class HelloServiceInjectProcessor implements BeanPostProcessor {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("begin postProcessBeforeInitialization, bean:{}, name:{}", bean.toString(), beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("begin postProcessAfterInitialization, bean:{}, name:{}", bean.toString(), beanName);

        Class<?> clz = bean.getClass();
        Field[] declaredFields = clz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.isAnnotationPresent(RountingInjected.class)) {
                if (!field.getType().isInterface()) {
                    throw new BeanCreationException("RountingInjected field:{} must bea declared as an interface" +
                            "@Class:{}", field.getName(), clz.getSimpleName());
                }

                try {
                    handleRoutingInjected(field, bean, field.getType());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return bean;
    }

    private void handleRoutingInjected(Field field, Object bean, Class<?> type) throws IllegalAccessException {
        Map<String, ?> candidates = applicationContext.getBeansOfType(type);
        field.setAccessible(true);
        if (candidates.size() == 1) {
            field.set(bean, candidates.values().iterator().next());
        } else if (candidates.size() >1) {
            String injectVal = field.getAnnotation(RountingInjected.class).value();
            Object proxy = RoutingBeanProxyFactroy.createProxy(injectVal, type, candidates);
            field.set(bean, proxy);
        }
    }
}

package com.chris.springboot2022.bean.processor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;

import java.util.Map;
import java.util.Objects;

public class RoutingBeanProxyFactroy {
    private final static String DEFAULT_BEAN_NAME = "helloServiceImpl1";

    public static Object createProxy(String name, Class<?> type, Map<String, ?> candidates) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setInterfaces(type);
        proxyFactory.addAdvice(new VersionRoutingMethodInterceptor(name, candidates));
        return proxyFactory.getProxy();
    }

    static class VersionRoutingMethodInterceptor implements MethodInterceptor {

        private Object targetObject;

        public VersionRoutingMethodInterceptor(String name, Map<String, ?> beans) {
            this.targetObject = beans.get(name);
            if (Objects.isNull(this.targetObject)) {
                this.targetObject = beans.get(DEFAULT_BEAN_NAME);
            }
        }

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            return invocation.getMethod().invoke(this.targetObject, invocation.getArguments());
        }
    }
}
@Test
public void testHelloWorldTest() {
    helloServiceTest.getHelloService().sayHello();
    Map<String, IHelloService> beansOfType = applicationContext.getBeansOfType(IHelloService.class);
    if (CollUtil.isNotEmpty(beansOfType)) {
        beansOfType.forEach((k, v) -> {
            log.info("k:{}, v:{}", k, v.getClass().getName());
        });
    }

}

2 InitializingBean

InitializingBean 接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法。

public interface IHelloService extends InitializingBean {
    void sayHello();

    void initName();
}

3 init-method

@Configuration
public class InitBeanConfig {

    @Bean(initMethod = "initName")
    public IHelloService helloServiceImpl_1() {
        return new HelloServiceImpl1();
    }

    @Bean(initMethod = "initName")
    public IHelloService helloServiceImpl_2() {
        return new HelloServiceImpl2();
    }
}

4 @PostConstruct

注解形式的初始化使用过BeanPostProcessor实现的,spring会注册一个common的processor,然后再实例化bean以后,会调用所有的postProcessor,该common的processor就会扫描出被@PostConstruct标注的方法,然后调用之。

@Service
@Slf4j
public class HelloServiceImpl1 implements IHelloService {

    public HelloServiceImpl1() {
        log.info("construct HelloServiceImpl1 success");
    }

    private String name;


    @Override
    public void sayHello() {
        System.out.println("hello, this is " + name);
    }

    @Override
    public void afterPropertiesSet() {
        this.name = "HelloServiceImpl1";
        log.info("do afterPropertiesSet success, name:{}", name);
    }

    public void initName() {
        this.name = "HelloServiceImpl1";
        log.info("init name success, name:{}", name);
    }

    @PostConstruct
    public void init() {
        this.name = "HelloServiceImpl1";
        log.info("do post construct success, name:{}", name);
    }

}

5 初始化顺序

construct

BeanPostProcessor > postProcessBeforeInitialization

PostConstruct

InitializingBean > afterPropertiesSet

init-method

BeanPostProcessor > postProcessAfterInitialization

2022-02-01 15:22:03.514  INFO 33596 --- [           main] c.c.c.b.p.s.impl.HelloServiceImpl1       : construct HelloServiceImpl1 success
2022-02-01 15:22:03.514  INFO 33596 --- [           main] c.c.c.b.p.HelloServiceInjectProcessor    : begin postProcessBeforeInitialization, bean:com.chris.cloud.bean.processor.service.impl.HelloServiceImpl1@109a2025, name:helloServiceImpl_1
2022-02-01 15:22:03.514  INFO 33596 --- [           main] c.c.c.b.p.s.impl.HelloServiceImpl1       : do post construct success, name:HelloServiceImpl1
2022-02-01 15:22:03.514  INFO 33596 --- [           main] c.c.c.b.p.s.impl.HelloServiceImpl1       : do afterPropertiesSet success, name:HelloServiceImpl1
2022-02-01 15:22:03.515  INFO 33596 --- [           main] c.c.c.b.p.s.impl.HelloServiceImpl1       : init name success, name:HelloServiceImpl1
2022-02-01 15:22:03.515  INFO 33596 --- [           main] c.c.c.b.p.HelloServiceInjectProcessor    : begin postProcessAfterInitialization, bean:com.chris.cloud.bean.processor.service.impl.HelloServiceImpl1@109a2025, name:helloServiceImpl_1
%5Btoc%5D%0A%0A%5BBeanPostProcessor%E7%9A%84%E5%A6%99%E7%94%A8%5D(https%3A%2F%2Fblog.csdn.net%2Fgeekjoker%2Farticle%2Fdetails%2F79868945)%0A%0A%23%23%23%23%201%20BeanPostProcessor%20%E5%90%8E%E7%BD%AE%E5%A4%84%E7%90%86%E5%99%A8%0A%23%23%23%23%23%201.1%20%E5%AE%9A%E4%B9%89%0A%3E%20%E4%BD%9C%E7%94%A8%E6%98%AF%E5%9C%A8Bean%E5%AF%B9%E8%B1%A1%E5%9C%A8%E5%AE%9E%E4%BE%8B%E5%8C%96%E5%92%8C%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E5%AE%8C%E6%AF%95%E5%90%8E%EF%BC%8C%E5%9C%A8%E6%98%BE%E7%A4%BA%E8%B0%83%E7%94%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E6%96%B9%E6%B3%95%E7%9A%84%E5%89%8D%E5%90%8E%E6%B7%BB%E5%8A%A0%E6%88%91%E4%BB%AC%E8%87%AA%E5%B7%B1%E7%9A%84%E9%80%BB%E8%BE%91%0A%0A!%5Becae878cf5310a99cdae53fc859a9d64.png%5D(en-resource%3A%2F%2Fdatabase%2F1283%3A1)%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%60BeanPostProcessor%60%20%E6%8E%A5%E5%8F%A3%E5%AE%9E%E7%8E%B0%E7%B1%BB%EF%BC%8C%E7%84%B6%E5%90%8E%E6%B3%A8%E5%86%8C%E5%88%B0Spring%20IoC%E5%AE%B9%E5%99%A8%E4%B8%AD.%0A%3E%20%E5%A4%9A%E4%B8%AA%E5%90%8E%E7%BD%AE%E5%A4%84%E7%90%86%E5%99%A8%E4%B9%9F%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%AE%9E%E7%8E%B0Ordered%E6%8E%A5%E5%8F%A3getOrder%E6%96%B9%E6%B3%95%E6%9D%A5%E5%AE%9A%E4%B9%89%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%0A%0A%60%60%60java%0A%E5%AE%9E%E7%8E%B0Ordered%E6%8E%A5%E5%8F%A3getOrder%E6%96%B9%E6%B3%95%EF%BC%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E4%B8%80%E6%95%B4%E6%95%B0%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%80%BC%E4%B8%BA%200%EF%BC%8C%E4%BC%98%E5%85%88%E7%BA%A7%E6%9C%80%E9%AB%98%EF%BC%8C%E5%80%BC%E8%B6%8A%E5%A4%A7%E4%BC%98%E5%85%88%E7%BA%A7%E8%B6%8A%E4%BD%8E%0A%60%60%60%0A%0A%3E%20%60ApplicationContext%60%20%E4%BC%9A%E8%87%AA%E5%8A%A8%E6%A3%80%E6%B5%8B%E5%9C%A8%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E5%AE%9E%E7%8E%B0%E4%BA%86%60BeanPostProcessor%60%20%E6%8E%A5%E5%8F%A3%E7%9A%84%E6%89%80%E6%9C%89bean%EF%BC%8C%E5%B9%B6%E6%8A%8A%E5%AE%83%E4%BB%AC%E6%B3%A8%E5%86%8C%E4%B8%BA%E5%90%8E%E7%BD%AE%E5%A4%84%E7%90%86%E5%99%A8%EF%BC%8C%E7%84%B6%E5%90%8E%E5%9C%A8%E5%AE%B9%E5%99%A8%E5%88%9B%E5%BB%BAbean%E7%9A%84%E9%80%82%E5%BD%93%E6%97%B6%E5%80%99%E8%B0%83%E7%94%A8%E5%AE%83%EF%BC%8C%E5%9B%A0%E6%AD%A4%E9%83%A8%E7%BD%B2%E4%B8%80%E4%B8%AA%E5%90%8E%E7%BD%AE%E5%A4%84%E7%90%86%E5%99%A8%E5%90%8C%E9%83%A8%E7%BD%B2%E5%85%B6%E4%BB%96%E7%9A%84bean%E5%B9%B6%E6%B2%A1%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%E3%80%82%0A%0A%23%23%23%23%23%201.2%20%E5%AE%9E%E4%BE%8B%0A%60%60%60java%0Apackage%20com.chris.springboot2022.bean.processor%3B%0A%0Aimport%20com.chris.springboot2022.bean.processor.annotation.RountingInjected%3B%0Aimport%20lombok.extern.slf4j.Slf4j%3B%0Aimport%20org.springframework.beans.BeansException%3B%0Aimport%20org.springframework.beans.factory.BeanCreationException%3B%0Aimport%20org.springframework.beans.factory.annotation.Autowired%3B%0Aimport%20org.springframework.beans.factory.config.BeanPostProcessor%3B%0Aimport%20org.springframework.context.ApplicationContext%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0Aimport%20java.lang.reflect.Field%3B%0Aimport%20java.util.Map%3B%0A%0A%0A%40Component%0A%40Slf4j%0Apublic%20class%20HelloServiceInjectProcessor%20implements%20BeanPostProcessor%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20ApplicationContext%20applicationContext%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20Object%20postProcessBeforeInitialization(Object%20bean%2C%20String%20beanName)%20throws%20BeansException%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20postProcessBeforeInitialization%2C%20bean%3A%7B%7D%2C%20name%3A%7B%7D%22%2C%20bean.toString()%2C%20beanName)%3B%0A%20%20%20%20%20%20%20%20return%20bean%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20Object%20postProcessAfterInitialization(Object%20bean%2C%20String%20beanName)%20throws%20BeansException%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22begin%20postProcessAfterInitialization%2C%20bean%3A%7B%7D%2C%20name%3A%7B%7D%22%2C%20bean.toString()%2C%20beanName)%3B%0A%0A%20%20%20%20%20%20%20%20Class%3C%3F%3E%20clz%20%3D%20bean.getClass()%3B%0A%20%20%20%20%20%20%20%20Field%5B%5D%20declaredFields%20%3D%20clz.getDeclaredFields()%3B%0A%20%20%20%20%20%20%20%20for%20(Field%20field%20%3A%20declaredFields)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(field.isAnnotationPresent(RountingInjected.class))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!field.getType().isInterface())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20BeanCreationException(%22RountingInjected%20field%3A%7B%7D%20must%20bea%20declared%20as%20an%20interface%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%40Class%3A%7B%7D%22%2C%20field.getName()%2C%20clz.getSimpleName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20handleRoutingInjected(field%2C%20bean%2C%20field.getType())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(IllegalAccessException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20bean%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20private%20void%20handleRoutingInjected(Field%20field%2C%20Object%20bean%2C%20Class%3C%3F%3E%20type)%20throws%20IllegalAccessException%20%7B%0A%20%20%20%20%20%20%20%20Map%3CString%2C%20%3F%3E%20candidates%20%3D%20applicationContext.getBeansOfType(type)%3B%0A%20%20%20%20%20%20%20%20field.setAccessible(true)%3B%0A%20%20%20%20%20%20%20%20if%20(candidates.size()%20%3D%3D%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20field.set(bean%2C%20candidates.values().iterator().next())%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(candidates.size()%20%3E1)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20String%20injectVal%20%3D%20field.getAnnotation(RountingInjected.class).value()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Object%20proxy%20%3D%20RoutingBeanProxyFactroy.createProxy(injectVal%2C%20type%2C%20candidates)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20field.set(bean%2C%20proxy)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%60%60%60java%0Apackage%20com.chris.springboot2022.bean.processor%3B%0A%0Aimport%20org.aopalliance.intercept.MethodInterceptor%3B%0Aimport%20org.aopalliance.intercept.MethodInvocation%3B%0Aimport%20org.springframework.aop.framework.ProxyFactory%3B%0A%0Aimport%20java.util.Map%3B%0Aimport%20java.util.Objects%3B%0A%0Apublic%20class%20RoutingBeanProxyFactroy%20%7B%0A%20%20%20%20private%20final%20static%20String%20DEFAULT_BEAN_NAME%20%3D%20%22helloServiceImpl1%22%3B%0A%0A%20%20%20%20public%20static%20Object%20createProxy(String%20name%2C%20Class%3C%3F%3E%20type%2C%20Map%3CString%2C%20%3F%3E%20candidates)%20%7B%0A%20%20%20%20%20%20%20%20ProxyFactory%20proxyFactory%20%3D%20new%20ProxyFactory()%3B%0A%20%20%20%20%20%20%20%20proxyFactory.setInterfaces(type)%3B%0A%20%20%20%20%20%20%20%20proxyFactory.addAdvice(new%20VersionRoutingMethodInterceptor(name%2C%20candidates))%3B%0A%20%20%20%20%20%20%20%20return%20proxyFactory.getProxy()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20static%20class%20VersionRoutingMethodInterceptor%20implements%20MethodInterceptor%20%7B%0A%0A%20%20%20%20%20%20%20%20private%20Object%20targetObject%3B%0A%0A%20%20%20%20%20%20%20%20public%20VersionRoutingMethodInterceptor(String%20name%2C%20Map%3CString%2C%20%3F%3E%20beans)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.targetObject%20%3D%20beans.get(name)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(Objects.isNull(this.targetObject))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.targetObject%20%3D%20beans.get(DEFAULT_BEAN_NAME)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20Object%20invoke(MethodInvocation%20invocation)%20throws%20Throwable%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20invocation.getMethod().invoke(this.targetObject%2C%20invocation.getArguments())%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20testHelloWorldTest()%20%7B%0A%20%20%20%20helloServiceTest.getHelloService().sayHello()%3B%0A%20%20%20%20Map%3CString%2C%20IHelloService%3E%20beansOfType%20%3D%20applicationContext.getBeansOfType(IHelloService.class)%3B%0A%20%20%20%20if%20(CollUtil.isNotEmpty(beansOfType))%20%7B%0A%20%20%20%20%20%20%20%20beansOfType.forEach((k%2C%20v)%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20log.info(%22k%3A%7B%7D%2C%20v%3A%7B%7D%22%2C%20k%2C%20v.getClass().getName())%3B%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202%20InitializingBean%0A%3E%20%60InitializingBean%60%20%E6%8E%A5%E5%8F%A3%E4%B8%BAbean%E6%8F%90%E4%BE%9B%E4%BA%86%E5%88%9D%E5%A7%8B%E5%8C%96%E6%96%B9%E6%B3%95%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%AE%83%E5%8F%AA%E5%8C%85%E6%8B%AC%60afterPropertiesSet%60%E6%96%B9%E6%B3%95%EF%BC%8C%E5%87%A1%E6%98%AF%E7%BB%A7%E6%89%BF%E8%AF%A5%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%EF%BC%8C%E5%9C%A8%E5%88%9D%E5%A7%8B%E5%8C%96bean%E7%9A%84%E6%97%B6%E5%80%99%E4%BC%9A%E6%89%A7%E8%A1%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E3%80%82%0A%0A%60%60%60java%0Apublic%20interface%20IHelloService%20extends%20InitializingBean%20%7B%0A%20%20%20%20void%20sayHello()%3B%0A%0A%20%20%20%20void%20initName()%3B%0A%7D%0A%0A%60%60%60%0A%23%23%23%23%203%20init-method%0A%0A%60%60%60java%0A%40Configuration%0Apublic%20class%20InitBeanConfig%20%7B%0A%0A%20%20%20%20%40Bean(initMethod%20%3D%20%22initName%22)%0A%20%20%20%20public%20IHelloService%20helloServiceImpl_1()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20HelloServiceImpl1()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Bean(initMethod%20%3D%20%22initName%22)%0A%20%20%20%20public%20IHelloService%20helloServiceImpl_2()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20HelloServiceImpl2()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%0A%23%23%23%23%204%20%40PostConstruct%0A%3E%20%E6%B3%A8%E8%A7%A3%E5%BD%A2%E5%BC%8F%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E4%BD%BF%E7%94%A8%E8%BF%87BeanPostProcessor%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8Cspring%E4%BC%9A%E6%B3%A8%E5%86%8C%E4%B8%80%E4%B8%AAcommon%E7%9A%84processor%EF%BC%8C%E7%84%B6%E5%90%8E%E5%86%8D%E5%AE%9E%E4%BE%8B%E5%8C%96bean%E4%BB%A5%E5%90%8E%EF%BC%8C%E4%BC%9A%E8%B0%83%E7%94%A8%E6%89%80%E6%9C%89%E7%9A%84postProcessor%EF%BC%8C%E8%AF%A5common%E7%9A%84processor%E5%B0%B1%E4%BC%9A%E6%89%AB%E6%8F%8F%E5%87%BA%E8%A2%AB%40PostConstruct%E6%A0%87%E6%B3%A8%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E7%84%B6%E5%90%8E%E8%B0%83%E7%94%A8%E4%B9%8B%E3%80%82%0A%0A%60%60%60java%0A%40Service%0A%40Slf4j%0Apublic%20class%20HelloServiceImpl1%20implements%20IHelloService%20%7B%0A%0A%20%20%20%20public%20HelloServiceImpl1()%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22construct%20HelloServiceImpl1%20success%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20private%20String%20name%3B%0A%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20sayHello()%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22hello%2C%20this%20is%20%22%20%2B%20name)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20afterPropertiesSet()%20%7B%0A%20%20%20%20%20%20%20%20this.name%20%3D%20%22HelloServiceImpl1%22%3B%0A%20%20%20%20%20%20%20%20log.info(%22do%20afterPropertiesSet%20success%2C%20name%3A%7B%7D%22%2C%20name)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20void%20initName()%20%7B%0A%20%20%20%20%20%20%20%20this.name%20%3D%20%22HelloServiceImpl1%22%3B%0A%20%20%20%20%20%20%20%20log.info(%22init%20name%20success%2C%20name%3A%7B%7D%22%2C%20name)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40PostConstruct%0A%20%20%20%20public%20void%20init()%20%7B%0A%20%20%20%20%20%20%20%20this.name%20%3D%20%22HelloServiceImpl1%22%3B%0A%20%20%20%20%20%20%20%20log.info(%22do%20post%20construct%20success%2C%20name%3A%7B%7D%22%2C%20name)%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%205%20%E5%88%9D%E5%A7%8B%E5%8C%96%E9%A1%BA%E5%BA%8F%0A%3E%20construct%0A%3E%20%3E%20BeanPostProcessor%20%3E%20postProcessBeforeInitialization%0A%3E%20%3E%20%3E%20PostConstruct%20%0A%3E%20%3E%20%3E%20%3E%20InitializingBean%20%3E%20afterPropertiesSet%0A%3E%20%3E%20%3E%20%3E%20%3E%20init-method%0A%3E%20%3E%20%3E%20%3E%20%3E%20%3E%20BeanPostProcessor%20%3E%20postProcessAfterInitialization%0A%0A!%5Bab38569b019980147ff09b53b1740b36.png%5D(en-resource%3A%2F%2Fdatabase%2F1289%3A0)%0A%0A%60%60%60java%0A2022-02-01%2015%3A22%3A03.514%20%20INFO%2033596%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.c.b.p.s.impl.HelloServiceImpl1%20%20%20%20%20%20%20%3A%20construct%20HelloServiceImpl1%20success%0A2022-02-01%2015%3A22%3A03.514%20%20INFO%2033596%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.c.b.p.HelloServiceInjectProcessor%20%20%20%20%3A%20begin%20postProcessBeforeInitialization%2C%20bean%3Acom.chris.cloud.bean.processor.service.impl.HelloServiceImpl1%40109a2025%2C%20name%3AhelloServiceImpl_1%0A2022-02-01%2015%3A22%3A03.514%20%20INFO%2033596%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.c.b.p.s.impl.HelloServiceImpl1%20%20%20%20%20%20%20%3A%20do%20post%20construct%20success%2C%20name%3AHelloServiceImpl1%0A2022-02-01%2015%3A22%3A03.514%20%20INFO%2033596%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.c.b.p.s.impl.HelloServiceImpl1%20%20%20%20%20%20%20%3A%20do%20afterPropertiesSet%20success%2C%20name%3AHelloServiceImpl1%0A2022-02-01%2015%3A22%3A03.515%20%20INFO%2033596%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.c.b.p.s.impl.HelloServiceImpl1%20%20%20%20%20%20%20%3A%20init%20name%20success%2C%20name%3AHelloServiceImpl1%0A2022-02-01%2015%3A22%3A03.515%20%20INFO%2033596%20---%20%5B%20%20%20%20%20%20%20%20%20%20%20main%5D%20c.c.c.b.p.HelloServiceInjectProcessor%20%20%20%20%3A%20begin%20postProcessAfterInitialization%2C%20bean%3Acom.chris.cloud.bean.processor.service.impl.HelloServiceImpl1%40109a2025%2C%20name%3AhelloServiceImpl_1%0A%60%60%60%0A

lombok

创建时间:2022/1/29 11:48
更新时间:2023/6/4 15:24
作者:Chris
来源:https://blog.csdn.net/weixin_41540822/article/details/86606562#commentsedit

@Builder
@Data
@Accessors(fluent = true)
@AllArgsConstructor
public class User {
    private Integer id;
    private final String zipCode = "215500";
    private String userName;
    private String password;

    private List<String> hobbies;
}

@Builder

生成相对略微复杂的构建器API。@Builder可以让你以下面显示的那样调用你的代码.

@Test
    public void testBuilder() {
        User user = User.builder()
                .id(1212)
                .userName("chris")
                .password("12121")
                .hobbies(Arrays.asList("reading", "running")).build();
        log.info("user:{}", JSONUtil.toJsonStr(user));
    }
@Singular

在使用@Singular 注释注释一个集合字段(使用@Builder注释类),
lombok会将该构建器节点视为一个集合,并生成两个adder方法而不是setter方法。
一个向集合添加单个元素,一个将另一个集合的所有元素添加到集合中。

@Test
public void testBuilder() {
User user = User.builder()
        .id(1212)
        .userName("chris")
        .password("12121")
        .hobby("coding")
        .hobby("teaching")
        .hobbies(Arrays.asList("reading", "running")).build();
log.info("user:{}", JSONUtil.toJsonStr(user));
}

编译后的代码

public User.UserBuilder hobby(final String hobby) {
    if (this.hobbies == null) {
        this.hobbies = new ArrayList();
    }

    this.hobbies.add(hobby);
    return this;
 }

public User.UserBuilder hobbies(final Collection<? extends String> hobbies) {
    if (hobbies == null) {
        throw new NullPointerException("hobbies cannot be null");
    } else {
        if (this.hobbies == null) {
            this.hobbies = new ArrayList();
        }

        this.hobbies.addAll(hobbies);
        return this;
    }
}

public User.UserBuilder clearHobbies() {
    if (this.hobbies != null) {
        this.hobbies.clear();
    }

    return this;
}

public User build() {
    List hobbies;
    switch(this.hobbies == null ? 0 : this.hobbies.size()) {
    case 0:
        hobbies = Collections.emptyList();
        break;
    case 1:
        hobbies = Collections.singletonList(this.hobbies.get(0));
        break;
    default:
        hobbies = Collections.unmodifiableList(new ArrayList(this.hobbies));
    }

    return new User(this.id, this.userName, this.password, hobbies);
}

@Accessors

* Using this annotation does nothing by itself; an annotation that makes lombok generate getters and setters,
* such as {@link lombok.Setter} or {@link lombok.Data} is also required.

1 @Accessors(fluent = true)

将属性的getter和setter方法去掉前缀get和set,仅保留属性名称
如果没有设置chain,则chain会设置为true

2 @Accessors(chain = true)

如果为true, setter将返回 this 而不是void
编译后的代码如下:

3 Setter-Getter方法的坑

Lombok对于第一个字母小写,第二个字母大写的属性生成的get-set方法和Mybatis以及idea或者说是Java官方认可的get-set方法生成的不一样:

@Data
public class NMetaVerify {
    private Long id;
    private NMetaType nMetaType;
}

Lombok生成的get-set方:

public void lombokFound(){
        NMetaVerify nMetaVerify = new NMetaVerify();
        nMetaVerify.setNMetaType(NMetaType.TWO); //注意:nMetaType的set方法为setNMetaType,第一个n字母大写了,
        nMetaVerify.getNMetaType();              //getxxxx方法也是大写
}

Java官方认可的get-set方法生成的:

public NMetaType getnMetaType() {//注意:nMetaType属性的第一个字母小写
        return nMetaType;
}

public void setnMetaType(NMetaType nMetaType) {//注意:nMetaType属性的第一个字母小写
    this.nMetaType = nMetaType;
}

Mybatis解析get-set方法为属性名字测试
org.apache.ibatis.reflection.property.PropertyNamer

public static String methodToProperty(String name) {
      if (name.startsWith("is")) {//is开头的一般是bool类型,直接从第二个(索引)开始截取(简单粗暴)
          name = name.substring(2);
      } else if (name.startsWith("get") || name.startsWith("set")) {//set-get的就从第三个(索引)开始截取
          name = name.substring(3);
      } else {
          throw new ReflectionException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");
      }
           //下面这个判断很重要,可以分成两句话开始解释,解释如下
            //第一句话:name.length()==1
            //       对于属性只有一个字母的,例如private int x;
            //          对应的get-set方法是getX();setX(int x);
            //第二句话:name.length() > 1 && !Character.isUpperCase(name.charAt(1)))
            //      属性名字长度大于1,并且第二个(代码中的charAt(1),这个1是数组下标)字母是小写的
            //      如果第二个char是大写的,那就直接返回name
      if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
          name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);//让属性名第一个字母小写,然后加上后面的内容
      }

      return name;
}
@Test
public void foundPropertyNamer() {
    String isName = "isName";
    String getName = "getName";
    String getnMetaType = "getnMetaType";
    String getNMetaType = "getNMetaType";

    Stream.of(isName,getName,getnMetaType,getNMetaType)
            .forEach(methodName->System.out.println("方法名字是:"+methodName+" 属性名字:"+ PropertyNamer.methodToProperty(methodName)));
}

方法名字是:isName 属性名字:name 
方法名字是:getName 属性名字:name 
方法名字是:getnMetaType 属性名字:nMetaType //这个以及下面的属性第二个字母都是大写,所以直接返回name
方法名字是:getNMetaType 属性名字:NMetaType

解决方案

  1. 修改属性名字,让第二个字母小写,或者说是规定所有的属性的前两个字母必须小写
  2. 如果数据库已经设计好,并且前后端接口对接好了,不想修改,那就专门为这种特殊的属性使用idea生成get-set方法复制代码

4 @Accessor(chain = true)注解的问题

在使用 easyexcel 导出的时候,发现以前的实体类导出都很正常,但是现在新加的实体类不正常了,比对了发现,新加的实体类增加了@Accessor(chain = true)注解

easyexcel底层使用的是cglib来做反射工具包的:

com.alibaba.excel.read.listener.ModelBuildEventListener 类的第130行
BeanMap.create(resultModel).putAll(map);

最底层的是cglib的BeanMap的这个方法调用
abstract public Object put(Object bean, Object key, Object value);

但是cglib使用的是Java的rt.jar里面的一个Introspector这个类的方法:Introspector.java 第520行

if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
   pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
   //下面这行判断,只获取返回值是void类型的setxxxx方法
 } else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
    // Simple setter
    pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
    if (throwsException(method, PropertyVetoException.class)) {
       pd.setConstrained(true);
    }
}

解决方案

  1. 去掉Accessor注解。要么就等待easyexcel的作者替换掉底层的cglib
  2. 或者是其他,反正是支持获取返回值不是void的setxxx方法就行复制代码。
%5BTOC%5D%0A%60%60%60java%0A%40Builder%0A%40Data%0A%40Accessors(fluent%20%3D%20true)%0A%40AllArgsConstructor%0Apublic%20class%20User%20%7B%0A%20%20%20%20private%20Integer%20id%3B%0A%20%20%20%20private%20final%20String%20zipCode%20%3D%20%22215500%22%3B%0A%20%20%20%20private%20String%20userName%3B%0A%20%20%20%20private%20String%20password%3B%0A%0A%20%20%20%20private%20List%3CString%3E%20hobbies%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%20%40Builder%0A%3E%20%E7%94%9F%E6%88%90%E7%9B%B8%E5%AF%B9%E7%95%A5%E5%BE%AE%E5%A4%8D%E6%9D%82%E7%9A%84%E6%9E%84%E5%BB%BA%E5%99%A8API%E3%80%82%40Builder%E5%8F%AF%E4%BB%A5%E8%AE%A9%E4%BD%A0%E4%BB%A5%E4%B8%8B%E9%9D%A2%E6%98%BE%E7%A4%BA%E7%9A%84%E9%82%A3%E6%A0%B7%E8%B0%83%E7%94%A8%E4%BD%A0%E7%9A%84%E4%BB%A3%E7%A0%81.%0A%60%60%60java%0A%40Test%0A%20%20%20%20public%20void%20testBuilder()%20%7B%0A%20%20%20%20%20%20%20%20User%20user%20%3D%20User.builder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.id(1212)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.userName(%22chris%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.password(%2212121%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.hobbies(Arrays.asList(%22reading%22%2C%20%22running%22)).build()%3B%0A%20%20%20%20%20%20%20%20log.info(%22user%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(user))%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%23%23%23%23%23%20%40Singular%0A%0A%3E%20%E5%9C%A8%E4%BD%BF%E7%94%A8%60%40Singular%60%20%E6%B3%A8%E9%87%8A%E6%B3%A8%E9%87%8A%E4%B8%80%E4%B8%AA%E9%9B%86%E5%90%88%E5%AD%97%E6%AE%B5%EF%BC%88%E4%BD%BF%E7%94%A8%40Builder%E6%B3%A8%E9%87%8A%E7%B1%BB%EF%BC%89%EF%BC%8C%0A%3E%20lombok%E4%BC%9A%E5%B0%86%E8%AF%A5%E6%9E%84%E5%BB%BA%E5%99%A8%E8%8A%82%E7%82%B9%E8%A7%86%E4%B8%BA%E4%B8%80%E4%B8%AA%E9%9B%86%E5%90%88%EF%BC%8C%E5%B9%B6%E7%94%9F%E6%88%90%E4%B8%A4%E4%B8%AAadder%E6%96%B9%E6%B3%95%E8%80%8C%E4%B8%8D%E6%98%AFsetter%E6%96%B9%E6%B3%95%E3%80%82%0A%3E%20%E4%B8%80%E4%B8%AA%E5%90%91%E9%9B%86%E5%90%88%E6%B7%BB%E5%8A%A0%E5%8D%95%E4%B8%AA%E5%85%83%E7%B4%A0%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%B0%86%E5%8F%A6%E4%B8%80%E4%B8%AA%E9%9B%86%E5%90%88%E7%9A%84%E6%89%80%E6%9C%89%E5%85%83%E7%B4%A0%E6%B7%BB%E5%8A%A0%E5%88%B0%E9%9B%86%E5%90%88%E4%B8%AD%E3%80%82%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20testBuilder()%20%7B%0AUser%20user%20%3D%20User.builder()%0A%20%20%20%20%20%20%20%20.id(1212)%0A%20%20%20%20%20%20%20%20.userName(%22chris%22)%0A%20%20%20%20%20%20%20%20.password(%2212121%22)%0A%20%20%20%20%20%20%20%20.hobby(%22coding%22)%0A%20%20%20%20%20%20%20%20.hobby(%22teaching%22)%0A%20%20%20%20%20%20%20%20.hobbies(Arrays.asList(%22reading%22%2C%20%22running%22)).build()%3B%0Alog.info(%22user%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(user))%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E7%BC%96%E8%AF%91%E5%90%8E%E7%9A%84%E4%BB%A3%E7%A0%81%0A%60%60%60java%0Apublic%20User.UserBuilder%20hobby(final%20String%20hobby)%20%7B%0A%20%20%20%20if%20(this.hobbies%20%3D%3D%20null)%20%7B%0A%20%20%20%20%20%20%20%20this.hobbies%20%3D%20new%20ArrayList()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20this.hobbies.add(hobby)%3B%0A%20%20%20%20return%20this%3B%0A%20%7D%0A%0Apublic%20User.UserBuilder%20hobbies(final%20Collection%3C%3F%20extends%20String%3E%20hobbies)%20%7B%0A%20%20%20%20if%20(hobbies%20%3D%3D%20null)%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20NullPointerException(%22hobbies%20cannot%20be%20null%22)%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20if%20(this.hobbies%20%3D%3D%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.hobbies%20%3D%20new%20ArrayList()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20this.hobbies.addAll(hobbies)%3B%0A%20%20%20%20%20%20%20%20return%20this%3B%0A%20%20%20%20%7D%0A%7D%0A%0Apublic%20User.UserBuilder%20clearHobbies()%20%7B%0A%20%20%20%20if%20(this.hobbies%20!%3D%20null)%20%7B%0A%20%20%20%20%20%20%20%20this.hobbies.clear()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20return%20this%3B%0A%7D%0A%0Apublic%20User%20build()%20%7B%0A%20%20%20%20List%20hobbies%3B%0A%20%20%20%20switch(this.hobbies%20%3D%3D%20null%20%3F%200%20%3A%20this.hobbies.size())%20%7B%0A%20%20%20%20case%200%3A%0A%20%20%20%20%20%20%20%20hobbies%20%3D%20Collections.emptyList()%3B%0A%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20case%201%3A%0A%20%20%20%20%20%20%20%20hobbies%20%3D%20Collections.singletonList(this.hobbies.get(0))%3B%0A%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20default%3A%0A%20%20%20%20%20%20%20%20hobbies%20%3D%20Collections.unmodifiableList(new%20ArrayList(this.hobbies))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20return%20new%20User(this.id%2C%20this.userName%2C%20this.password%2C%20hobbies)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%20%40Accessors%0A%60%60%60java%0A*%20Using%20this%20annotation%20does%20nothing%20by%20itself%3B%20an%20annotation%20that%20makes%20lombok%20generate%20getters%20and%20setters%2C%0A*%20such%20as%20%7B%40link%20lombok.Setter%7D%20or%20%7B%40link%20lombok.Data%7D%20is%20also%20required.%0A%60%60%60%0A!%5B99be1719bdae2cab8984189de4c37366.png%5D(en-resource%3A%2F%2Fdatabase%2F1101%3A1)%0A%0A%0A%23%23%23%23%23%201%20%40Accessors(fluent%20%3D%20true)%0A%3E%20%E5%B0%86%E5%B1%9E%E6%80%A7%E7%9A%84getter%E5%92%8Csetter%E6%96%B9%E6%B3%95%E5%8E%BB%E6%8E%89%E5%89%8D%E7%BC%80get%E5%92%8Cset%EF%BC%8C%E4%BB%85%E4%BF%9D%E7%95%99%E5%B1%9E%E6%80%A7%E5%90%8D%E7%A7%B0%0A%3E%20%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E8%AE%BE%E7%BD%AEchain%EF%BC%8C%E5%88%99chain%E4%BC%9A%E8%AE%BE%E7%BD%AE%E4%B8%BAtrue%0A%0A%23%23%23%23%23%202%20%40Accessors(chain%20%3D%20true)%0A%3E%20%E5%A6%82%E6%9E%9C%E4%B8%BAtrue%2C%20setter%E5%B0%86%E8%BF%94%E5%9B%9E%20%60this%60%20%E8%80%8C%E4%B8%8D%E6%98%AF%60void%60%0A%3E%20%E7%BC%96%E8%AF%91%E5%90%8E%E7%9A%84%E4%BB%A3%E7%A0%81%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A!%5B264d1963e546e99b8667d8bb32053f72.png%5D(en-resource%3A%2F%2Fdatabase%2F1100%3A1)%0A%0A%0A%0A%0A%0A%23%23%23%23%203%20Setter-Getter%E6%96%B9%E6%B3%95%E7%9A%84%E5%9D%91%0A%0A%0ALombok%E5%AF%B9%E4%BA%8E%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AF%8D%E5%B0%8F%E5%86%99%EF%BC%8C%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%AD%97%E6%AF%8D%E5%A4%A7%E5%86%99%E7%9A%84%E5%B1%9E%E6%80%A7%E7%94%9F%E6%88%90%E7%9A%84get-set%E6%96%B9%E6%B3%95%E5%92%8CMybatis%E4%BB%A5%E5%8F%8Aidea%E6%88%96%E8%80%85%E8%AF%B4%E6%98%AFJava%E5%AE%98%E6%96%B9%E8%AE%A4%E5%8F%AF%E7%9A%84get-set%E6%96%B9%E6%B3%95%E7%94%9F%E6%88%90%E7%9A%84%E4%B8%8D%E4%B8%80%E6%A0%B7%3A%0A%0A%60%60%60java%0A%40Data%0Apublic%20class%20NMetaVerify%20%7B%0A%20%20%20%20private%20Long%20id%3B%0A%20%20%20%20private%20NMetaType%20nMetaType%3B%0A%7D%0A%60%60%60%0A%0A%3E%20Lombok%E7%94%9F%E6%88%90%E7%9A%84get-set%E6%96%B9%3A%0A%60%60%60java%0Apublic%20void%20lombokFound()%7B%0A%20%20%20%20%20%20%20%20NMetaVerify%20nMetaVerify%20%3D%20new%20NMetaVerify()%3B%0A%20%20%20%20%20%20%20%20nMetaVerify.setNMetaType(NMetaType.TWO)%3B%20%2F%2F%E6%B3%A8%E6%84%8F%EF%BC%9AnMetaType%E7%9A%84set%E6%96%B9%E6%B3%95%E4%B8%BAsetNMetaType%EF%BC%8C%E7%AC%AC%E4%B8%80%E4%B8%AAn%E5%AD%97%E6%AF%8D%E5%A4%A7%E5%86%99%E4%BA%86%EF%BC%8C%0A%20%20%20%20%20%20%20%20nMetaVerify.getNMetaType()%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fgetxxxx%E6%96%B9%E6%B3%95%E4%B9%9F%E6%98%AF%E5%A4%A7%E5%86%99%0A%7D%0A%60%60%60%0A%0A%3E%20Java%E5%AE%98%E6%96%B9%E8%AE%A4%E5%8F%AF%E7%9A%84get-set%E6%96%B9%E6%B3%95%E7%94%9F%E6%88%90%E7%9A%84%3A%0A%60%60%60java%0Apublic%20NMetaType%20getnMetaType()%20%7B%2F%2F%E6%B3%A8%E6%84%8F%EF%BC%9AnMetaType%E5%B1%9E%E6%80%A7%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AF%8D%E5%B0%8F%E5%86%99%0A%20%20%20%20%20%20%20%20return%20nMetaType%3B%0A%7D%0A%0Apublic%20void%20setnMetaType(NMetaType%20nMetaType)%20%7B%2F%2F%E6%B3%A8%E6%84%8F%EF%BC%9AnMetaType%E5%B1%9E%E6%80%A7%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AF%8D%E5%B0%8F%E5%86%99%0A%20%20%20%20this.nMetaType%20%3D%20nMetaType%3B%0A%7D%0A%60%60%60%0A%0A%0A%3E%20Mybatis%E8%A7%A3%E6%9E%90get-set%E6%96%B9%E6%B3%95%E4%B8%BA%E5%B1%9E%E6%80%A7%E5%90%8D%E5%AD%97%E6%B5%8B%E8%AF%95%0A%3E%20%60org.apache.ibatis.reflection.property.PropertyNamer%C2%A0%60%0A%0A%60%60%60java%0Apublic%20static%20String%20methodToProperty(String%20name)%20%7B%0A%20%20%20%20%20%20if%20(name.startsWith(%22is%22))%20%7B%2F%2Fis%E5%BC%80%E5%A4%B4%E7%9A%84%E4%B8%80%E8%88%AC%E6%98%AFbool%E7%B1%BB%E5%9E%8B%EF%BC%8C%E7%9B%B4%E6%8E%A5%E4%BB%8E%E7%AC%AC%E4%BA%8C%E4%B8%AA(%E7%B4%A2%E5%BC%95)%E5%BC%80%E5%A7%8B%E6%88%AA%E5%8F%96(%E7%AE%80%E5%8D%95%E7%B2%97%E6%9A%B4)%0A%20%20%20%20%20%20%20%20%20%20name%20%3D%20name.substring(2)%3B%0A%20%20%20%20%20%20%7D%20else%20if%20(name.startsWith(%22get%22)%20%7C%7C%20name.startsWith(%22set%22))%20%7B%2F%2Fset-get%E7%9A%84%E5%B0%B1%E4%BB%8E%E7%AC%AC%E4%B8%89%E4%B8%AA(%E7%B4%A2%E5%BC%95)%E5%BC%80%E5%A7%8B%E6%88%AA%E5%8F%96%0A%20%20%20%20%20%20%20%20%20%20name%20%3D%20name.substring(3)%3B%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20ReflectionException(%22Error%20parsing%20property%20name%20'%22%20%2B%20name%20%2B%20%22'.%20%20Didn't%20start%20with%20'is'%2C%20'get'%20or%20'set'.%22)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E4%B8%8B%E9%9D%A2%E8%BF%99%E4%B8%AA%E5%88%A4%E6%96%AD%E5%BE%88%E9%87%8D%E8%A6%81%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%88%86%E6%88%90%E4%B8%A4%E5%8F%A5%E8%AF%9D%E5%BC%80%E5%A7%8B%E8%A7%A3%E9%87%8A%EF%BC%8C%E8%A7%A3%E9%87%8A%E5%A6%82%E4%B8%8B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E7%AC%AC%E4%B8%80%E5%8F%A5%E8%AF%9D%EF%BC%9Aname.length()%3D%3D1%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%20%20%20%20%20%20%E5%AF%B9%E4%BA%8E%E5%B1%9E%E6%80%A7%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AF%8D%E7%9A%84%EF%BC%8C%E4%BE%8B%E5%A6%82private%20int%20x%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%20%20%20%20%20%20%20%20%20%E5%AF%B9%E5%BA%94%E7%9A%84get-set%E6%96%B9%E6%B3%95%E6%98%AFgetX()%3BsetX(int%20x)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E7%AC%AC%E4%BA%8C%E5%8F%A5%E8%AF%9D%EF%BC%9Aname.length()%20%3E%201%20%26%26%20!Character.isUpperCase(name.charAt(1)))%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%20%20%20%20%20%E5%B1%9E%E6%80%A7%E5%90%8D%E5%AD%97%E9%95%BF%E5%BA%A6%E5%A4%A7%E4%BA%8E1%EF%BC%8C%E5%B9%B6%E4%B8%94%E7%AC%AC%E4%BA%8C%E4%B8%AA(%E4%BB%A3%E7%A0%81%E4%B8%AD%E7%9A%84charAt(1)%EF%BC%8C%E8%BF%99%E4%B8%AA1%E6%98%AF%E6%95%B0%E7%BB%84%E4%B8%8B%E6%A0%87)%E5%AD%97%E6%AF%8D%E6%98%AF%E5%B0%8F%E5%86%99%E7%9A%84%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%20%20%20%20%20%E5%A6%82%E6%9E%9C%E7%AC%AC%E4%BA%8C%E4%B8%AAchar%E6%98%AF%E5%A4%A7%E5%86%99%E7%9A%84%EF%BC%8C%E9%82%A3%E5%B0%B1%E7%9B%B4%E6%8E%A5%E8%BF%94%E5%9B%9Ename%0A%20%20%20%20%20%20if%20(name.length()%20%3D%3D%201%20%7C%7C%20(name.length()%20%3E%201%20%26%26%20!Character.isUpperCase(name.charAt(1))))%20%7B%0A%20%20%20%20%20%20%20%20%20%20name%20%3D%20name.substring(0%2C%201).toLowerCase(Locale.ENGLISH)%20%2B%20name.substring(1)%3B%2F%2F%E8%AE%A9%E5%B1%9E%E6%80%A7%E5%90%8D%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AF%8D%E5%B0%8F%E5%86%99%EF%BC%8C%E7%84%B6%E5%90%8E%E5%8A%A0%E4%B8%8A%E5%90%8E%E9%9D%A2%E7%9A%84%E5%86%85%E5%AE%B9%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20return%20name%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20foundPropertyNamer()%20%7B%0A%20%20%20%20String%20isName%20%3D%20%22isName%22%3B%0A%20%20%20%20String%20getName%20%3D%20%22getName%22%3B%0A%20%20%20%20String%20getnMetaType%20%3D%20%22getnMetaType%22%3B%0A%20%20%20%20String%20getNMetaType%20%3D%20%22getNMetaType%22%3B%0A%0A%20%20%20%20Stream.of(isName%2CgetName%2CgetnMetaType%2CgetNMetaType)%0A%20%20%20%20%20%20%20%20%20%20%20%20.forEach(methodName-%3ESystem.out.println(%22%E6%96%B9%E6%B3%95%E5%90%8D%E5%AD%97%E6%98%AF%3A%22%2BmethodName%2B%22%20%E5%B1%9E%E6%80%A7%E5%90%8D%E5%AD%97%3A%22%2B%20PropertyNamer.methodToProperty(methodName)))%3B%0A%7D%0A%0A%E6%96%B9%E6%B3%95%E5%90%8D%E5%AD%97%E6%98%AF%3AisName%20%E5%B1%9E%E6%80%A7%E5%90%8D%E5%AD%97%3Aname%20%0A%E6%96%B9%E6%B3%95%E5%90%8D%E5%AD%97%E6%98%AF%3AgetName%20%E5%B1%9E%E6%80%A7%E5%90%8D%E5%AD%97%3Aname%20%0A%E6%96%B9%E6%B3%95%E5%90%8D%E5%AD%97%E6%98%AF%3AgetnMetaType%20%E5%B1%9E%E6%80%A7%E5%90%8D%E5%AD%97%3AnMetaType%20%2F%2F%E8%BF%99%E4%B8%AA%E4%BB%A5%E5%8F%8A%E4%B8%8B%E9%9D%A2%E7%9A%84%E5%B1%9E%E6%80%A7%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%AD%97%E6%AF%8D%E9%83%BD%E6%98%AF%E5%A4%A7%E5%86%99%EF%BC%8C%E6%89%80%E4%BB%A5%E7%9B%B4%E6%8E%A5%E8%BF%94%E5%9B%9Ename%0A%E6%96%B9%E6%B3%95%E5%90%8D%E5%AD%97%E6%98%AF%3AgetNMetaType%20%E5%B1%9E%E6%80%A7%E5%90%8D%E5%AD%97%3ANMetaType%0A%60%60%60%0A%0A%0A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%0A%3E%201.%20%E4%BF%AE%E6%94%B9%E5%B1%9E%E6%80%A7%E5%90%8D%E5%AD%97%EF%BC%8C%E8%AE%A9%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%AD%97%E6%AF%8D%E5%B0%8F%E5%86%99%EF%BC%8C%E6%88%96%E8%80%85%E8%AF%B4%E6%98%AF%E8%A7%84%E5%AE%9A%E6%89%80%E6%9C%89%E7%9A%84%E5%B1%9E%E6%80%A7%E7%9A%84%E5%89%8D%E4%B8%A4%E4%B8%AA%E5%AD%97%E6%AF%8D%E5%BF%85%E9%A1%BB%E5%B0%8F%E5%86%99%0A%3E%202.%20%E5%A6%82%E6%9E%9C%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B7%B2%E7%BB%8F%E8%AE%BE%E8%AE%A1%E5%A5%BD%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%89%8D%E5%90%8E%E7%AB%AF%E6%8E%A5%E5%8F%A3%E5%AF%B9%E6%8E%A5%E5%A5%BD%E4%BA%86%EF%BC%8C%E4%B8%8D%E6%83%B3%E4%BF%AE%E6%94%B9%EF%BC%8C%E9%82%A3%E5%B0%B1%E4%B8%93%E9%97%A8%E4%B8%BA%E8%BF%99%E7%A7%8D%E7%89%B9%E6%AE%8A%E7%9A%84%E5%B1%9E%E6%80%A7%E4%BD%BF%E7%94%A8idea%E7%94%9F%E6%88%90get-set%E6%96%B9%E6%B3%95%E5%A4%8D%E5%88%B6%E4%BB%A3%E7%A0%81%0A%0A%0A%23%23%23%23%204%20%40Accessor(chain%20%3D%20true)%E6%B3%A8%E8%A7%A3%E7%9A%84%E9%97%AE%E9%A2%98%0A%3E%20%E5%9C%A8%E4%BD%BF%E7%94%A8%20easyexcel%20%E5%AF%BC%E5%87%BA%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%8F%91%E7%8E%B0%E4%BB%A5%E5%89%8D%E7%9A%84%E5%AE%9E%E4%BD%93%E7%B1%BB%E5%AF%BC%E5%87%BA%E9%83%BD%E5%BE%88%E6%AD%A3%E5%B8%B8%EF%BC%8C%E4%BD%86%E6%98%AF%E7%8E%B0%E5%9C%A8%E6%96%B0%E5%8A%A0%E7%9A%84%E5%AE%9E%E4%BD%93%E7%B1%BB%E4%B8%8D%E6%AD%A3%E5%B8%B8%E4%BA%86%EF%BC%8C%E6%AF%94%E5%AF%B9%E4%BA%86%E5%8F%91%E7%8E%B0%EF%BC%8C%E6%96%B0%E5%8A%A0%E7%9A%84%E5%AE%9E%E4%BD%93%E7%B1%BB%E5%A2%9E%E5%8A%A0%E4%BA%86%40Accessor(chain%20%3D%20true)%E6%B3%A8%E8%A7%A3%0A%0A%0A%3E%20easyexcel%E5%BA%95%E5%B1%82%E4%BD%BF%E7%94%A8%E7%9A%84%E6%98%AFcglib%E6%9D%A5%E5%81%9A%E5%8F%8D%E5%B0%84%E5%B7%A5%E5%85%B7%E5%8C%85%E7%9A%84%EF%BC%9A%0A%60%60%60java%0Acom.alibaba.excel.read.listener.ModelBuildEventListener%20%E7%B1%BB%E7%9A%84%E7%AC%AC130%E8%A1%8C%0ABeanMap.create(resultModel).putAll(map)%3B%0A%0A%E6%9C%80%E5%BA%95%E5%B1%82%E7%9A%84%E6%98%AFcglib%E7%9A%84BeanMap%E7%9A%84%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%0Aabstract%20public%20Object%20put(Object%20bean%2C%20Object%20key%2C%20Object%20value)%3B%0A%60%60%60%0A%0A%0A%3E%20%E4%BD%86%E6%98%AFcglib%E4%BD%BF%E7%94%A8%E7%9A%84%E6%98%AFJava%E7%9A%84rt.jar%E9%87%8C%E9%9D%A2%E7%9A%84%E4%B8%80%E4%B8%AAIntrospector%E8%BF%99%E4%B8%AA%E7%B1%BB%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%9AIntrospector.java%20%E7%AC%AC520%E8%A1%8C%0A%60%60%60java%0Aif%20(int.class.equals(argTypes%5B0%5D)%20%26%26%20name.startsWith(GET_PREFIX))%20%7B%0A%20%20%20pd%20%3D%20new%20IndexedPropertyDescriptor(this.beanClass%2C%20name.substring(3)%2C%20null%2C%20null%2C%20method%2C%20null)%3B%0A%20%20%20%2F%2F%E4%B8%8B%E9%9D%A2%E8%BF%99%E8%A1%8C%E5%88%A4%E6%96%AD%EF%BC%8C%E5%8F%AA%E8%8E%B7%E5%8F%96%E8%BF%94%E5%9B%9E%E5%80%BC%E6%98%AFvoid%E7%B1%BB%E5%9E%8B%E7%9A%84setxxxx%E6%96%B9%E6%B3%95%0A%20%7D%20else%20if%20(void.class.equals(resultType)%20%26%26%20name.startsWith(SET_PREFIX))%20%7B%0A%20%20%20%20%2F%2F%20Simple%20setter%0A%20%20%20%20pd%20%3D%20new%20PropertyDescriptor(this.beanClass%2C%20name.substring(3)%2C%20null%2C%20method)%3B%0A%20%20%20%20if%20(throwsException(method%2C%20PropertyVetoException.class))%20%7B%0A%20%20%20%20%20%20%20pd.setConstrained(true)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%0A%3E%201.%20%E5%8E%BB%E6%8E%89Accessor%E6%B3%A8%E8%A7%A3%E3%80%82%E8%A6%81%E4%B9%88%E5%B0%B1%E7%AD%89%E5%BE%85easyexcel%E7%9A%84%E4%BD%9C%E8%80%85%E6%9B%BF%E6%8D%A2%E6%8E%89%E5%BA%95%E5%B1%82%E7%9A%84cglib%0A%3E%202.%20%E6%88%96%E8%80%85%E6%98%AF%E5%85%B6%E4%BB%96%EF%BC%8C%E5%8F%8D%E6%AD%A3%E6%98%AF%E6%94%AF%E6%8C%81%E8%8E%B7%E5%8F%96%E8%BF%94%E5%9B%9E%E5%80%BC%E4%B8%8D%E6%98%AFvoid%E7%9A%84setxxx%E6%96%B9%E6%B3%95%E5%B0%B1%E8%A1%8C%E5%A4%8D%E5%88%B6%E4%BB%A3%E7%A0%81%E3%80%82

comm issue

创建时间:2020/9/2 14:42
更新时间:2022/1/29 11:40
作者:Chris

1. 容器中粘贴宿主机中的文本

/usr/share/vim/vim80# vi defaults.vim
将set mouse=a 改为 set mouse-=a

2. 更新源后下载出差

Err:1 http://mirrors.aliyun.com/ubuntu xenial InRelease                                               
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 40976EAF437D05B5 NO_PUBKEY 3B4FE6ACC0B21F32
Err:2 http://mirrors.aliyun.com/ubuntu xenial-updates InRelease            
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 40976EAF437D05B5 NO_PUBKEY 3B4FE6ACC0B21F32
Err:3 http://mirrors.aliyun.com/ubuntu xenial-backports InRelease          
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 40976EAF437D05B5 NO_PUBKEY 3B4FE6ACC0B21F32
Err:4 http://mirrors.aliyun.com/ubuntu xenial-security InRelease           
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 40976EAF437D05B5 NO_PUBKEY 3B4FE6ACC0B21F32

https://chrisjean.com/fix-apt-get-update-the-following-signatures-couldnt-be-verified-because-the-public-key-is-not-available/

将需要的key增加到apt-key 中

apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32
%23%23%23%23%201.%20%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%B2%98%E8%B4%B4%E5%AE%BF%E4%B8%BB%E6%9C%BA%E4%B8%AD%E7%9A%84%E6%96%87%E6%9C%AC%0A%0A%60%60%60%0A%2Fusr%2Fshare%2Fvim%2Fvim80%23%20vi%20defaults.vim%0A%E5%B0%86set%20mouse%3Da%20%E6%94%B9%E4%B8%BA%20set%20mouse-%3Da%0A%60%60%60%0A!%5B32542eaa657dda49e83e967bdb1fab84.png%5D(en-resource%3A%2F%2Fdatabase%2F1075%3A0)%0A%0A%0A%0A%0A%23%23%23%23%202.%20%E6%9B%B4%E6%96%B0%E6%BA%90%E5%90%8E%E4%B8%8B%E8%BD%BD%E5%87%BA%E5%B7%AE%0A%0A%60%60%60%0AErr%3A1%20http%3A%2F%2Fmirrors.aliyun.com%2Fubuntu%20xenial%20InRelease%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20The%20following%20signatures%20couldn't%20be%20verified%20because%20the%20public%20key%20is%20not%20available%3A%20NO_PUBKEY%2040976EAF437D05B5%20NO_PUBKEY%203B4FE6ACC0B21F32%0AErr%3A2%20http%3A%2F%2Fmirrors.aliyun.com%2Fubuntu%20xenial-updates%20InRelease%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20The%20following%20signatures%20couldn't%20be%20verified%20because%20the%20public%20key%20is%20not%20available%3A%20NO_PUBKEY%2040976EAF437D05B5%20NO_PUBKEY%203B4FE6ACC0B21F32%0AErr%3A3%20http%3A%2F%2Fmirrors.aliyun.com%2Fubuntu%20xenial-backports%20InRelease%20%20%20%20%20%20%20%20%20%20%0A%20%20The%20following%20signatures%20couldn't%20be%20verified%20because%20the%20public%20key%20is%20not%20available%3A%20NO_PUBKEY%2040976EAF437D05B5%20NO_PUBKEY%203B4FE6ACC0B21F32%0AErr%3A4%20http%3A%2F%2Fmirrors.aliyun.com%2Fubuntu%20xenial-security%20InRelease%20%20%20%20%20%20%20%20%20%20%20%0A%20%20The%20following%20signatures%20couldn't%20be%20verified%20because%20the%20public%20key%20is%20not%20available%3A%20NO_PUBKEY%2040976EAF437D05B5%20NO_PUBKEY%203B4FE6ACC0B21F32%0A%60%60%60%0A%0A%0Ahttps%3A%2F%2Fchrisjean.com%2Ffix-apt-get-update-the-following-signatures-couldnt-be-verified-because-the-public-key-is-not-available%2F%0A%0A%E5%B0%86%E9%9C%80%E8%A6%81%E7%9A%84key%E5%A2%9E%E5%8A%A0%E5%88%B0apt-key%20%E4%B8%AD%0A%0A%60%60%60%0Aapt-key%20adv%20--keyserver%20keyserver.ubuntu.com%20--recv-keys%2040976EAF437D05B5%0Aapt-key%20adv%20--keyserver%20keyserver.ubuntu.com%20--recv-keys%203B4FE6ACC0B21F32%0A%60%60%60%0A%0A

yml配置文件: 定义list集合,数组

创建时间:2022/1/25 22:39
更新时间:2022/1/25 23:07
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzUyNDkzNzczNQ==&mid=2247516327&idx=2&sn=3caf679e415301b8e92d64666737fdbd&chksm=fa277fcfcd50f6d9457ec942a31139847d74798d271a8f59197ec70ae37164e02e1aa57e5385&mpshare=1&scene=24&srcid=01253AofqngVOzGSAEPl8jst&sharer_sharetime=1643083037349&sharer_shareid=5b3482cc84e779e76f71a8abd134e217&key=d7bf91b26fddbe84655cf1faadc00b002699b68139466f9a07a6b6155e5ba2116f5c76aa27005f4728eb3d04d3f0c61e809789aa01ae8c3f4da32944b7d73dd393f4ec2d3184631064c6edf327e567d1f27bee6a998d2cc09fb61b3d9919ee49c4ee402b239a40fa9eff6cdbefdfc15bcd526a63c9c73fe30536645b96d1ff2d&ascene=0&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=6304051b&lang=zh_CN&exportkey=AXPkwRN1AUXLrfbi9JlcWZY%3D&acctmode=0&pass_ticket=9tttJnB6TtFwVc4PLI%2FZbrAT6dNMvBh9zSErAM3ZA2kLlsYdascHczU5WXrH4fLD&wx_header=0&fontgear=2

1 字符串配置及获取

yml配置

# 配置日志输出级别
logging:
  # 指定logback配置文件的位置 
  config: classpath:logback-spring.xml
  # 文件日志要输出的路径
  path: E:/logs/springboot_server
  # 日志的输出级别
  level:
    root: info

java代码中通过@Value("${logging.path}")来获取配置值

@Value("${logging.path}")
private String path;

2 定义list集合

# 拦截器路径拦截或者不拦截配置
interceptorconfig:
  path:
    #该路径下任何类型请求均拦截
    include:
      - /api/v1/token/api_token
      - /api/v1/yibaotong/save

# 拦截器路径拦截或者不拦截配置
interceptorconfig:
  path:
    #或者可以写成:
    include: [/api/v1/token/api_token,/api/v1/yibaotong/save]      

定义list集合不能用@value 注解来获取list集合的所有值,
需要定义一个配置类bean,然后使用@ConfigurationProperties 注解来获取list集合值,
做法如下:

@Data
@Component
@ConfigurationProperties(prefix = "interceptorconfig.path") // 配置文件的前缀
public class InterceptorPathBean
{
    /*
     * 需要拦截的路径
     */
    private List<String> include;
}

3 定义对象list集合

首先创建一个user对象如下

@Data
public class User implements Serializable
{  
    private static final long serialVersionUID = 1L;

    private String appId;
    private String password;
}

然后yml配置文件的写法如下

jwt:
  userlist:
    - appId: YiBaoTong
      password: 123456
    - appId: ZhiKe
      password: 123456

定义配置bean

@Data
@Component
@ConfigurationProperties(prefix = "jwt") // 配置 文件的前缀
public class JwtConfigBean
{
    /**
     * 用户列表
     */
    private List<User> userlist;
}

4 定义数组

interceptorconfig:
  path:
    includes: /api/v1,/api/v2  #注意要用逗号分隔开

可以通过@value注解获取数组值

@Value("${interceptorconfig.path.includes}")
 private String[] includes;

也可以通过创建配置类bean, 获取数组

@Data
@Component
@ConfigurationProperties(prefix = "interceptorconfig.path") // 配置 文件的前缀
public class InterceptorPathBean
{  
    private String[] includes;
}

5 定义map集合

interceptorconfig:
  path:
    maps: {name: 小明,age: 24}

interceptorconfig:
  path:
    #或者可以写成:
    maps:
      name: 小明
      age: 24

通过创建配置类bean,获取map值

@Data
@Component
@ConfigurationProperties(prefix = "interceptorconfig.path") // 配置 文件的前缀
public class InterceptorPathBean
{
    private Map<String , String> maps;
}          
%5Btoc%5D%0A%0A%23%23%23%23%201%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%85%8D%E7%BD%AE%E5%8F%8A%E8%8E%B7%E5%8F%96%0A%3E%20yml%E9%85%8D%E7%BD%AE%0A%60%60%60yml%0A%23%20%E9%85%8D%E7%BD%AE%E6%97%A5%E5%BF%97%E8%BE%93%E5%87%BA%E7%BA%A7%E5%88%AB%0Alogging%3A%0A%20%20%23%20%E6%8C%87%E5%AE%9Alogback%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E4%BD%8D%E7%BD%AE%20%0A%20%20config%3A%20classpath%3Alogback-spring.xml%0A%20%20%23%20%E6%96%87%E4%BB%B6%E6%97%A5%E5%BF%97%E8%A6%81%E8%BE%93%E5%87%BA%E7%9A%84%E8%B7%AF%E5%BE%84%0A%20%20path%3A%20E%3A%2Flogs%2Fspringboot_server%0A%20%20%23%20%E6%97%A5%E5%BF%97%E7%9A%84%E8%BE%93%E5%87%BA%E7%BA%A7%E5%88%AB%0A%20%20level%3A%0A%20%20%20%20root%3A%20info%0A%60%60%60%0A%3E%20java%E4%BB%A3%E7%A0%81%E4%B8%AD%E9%80%9A%E8%BF%87%60%40Value(%22%24%7Blogging.path%7D%22)%60%E6%9D%A5%E8%8E%B7%E5%8F%96%E9%85%8D%E7%BD%AE%E5%80%BC%0A%60%60%60java%0A%40Value(%22%24%7Blogging.path%7D%22)%0Aprivate%C2%A0String%C2%A0path%3B%0A%60%60%60%0A%0A%0A%23%23%23%23%202%20%E5%AE%9A%E4%B9%89list%E9%9B%86%E5%90%88%0A%60%60%60yml%0A%23%20%E6%8B%A6%E6%88%AA%E5%99%A8%E8%B7%AF%E5%BE%84%E6%8B%A6%E6%88%AA%E6%88%96%E8%80%85%E4%B8%8D%E6%8B%A6%E6%88%AA%E9%85%8D%E7%BD%AE%0Ainterceptorconfig%3A%0A%20%20path%3A%0A%20%20%20%20%23%E8%AF%A5%E8%B7%AF%E5%BE%84%E4%B8%8B%E4%BB%BB%E4%BD%95%E7%B1%BB%E5%9E%8B%E8%AF%B7%E6%B1%82%E5%9D%87%E6%8B%A6%E6%88%AA%0A%20%20%20%20include%3A%0A%20%20%20%20%20%20-%20%2Fapi%2Fv1%2Ftoken%2Fapi_token%0A%20%20%20%20%20%20-%20%2Fapi%2Fv1%2Fyibaotong%2Fsave%0A%0A%23%20%E6%8B%A6%E6%88%AA%E5%99%A8%E8%B7%AF%E5%BE%84%E6%8B%A6%E6%88%AA%E6%88%96%E8%80%85%E4%B8%8D%E6%8B%A6%E6%88%AA%E9%85%8D%E7%BD%AE%0Ainterceptorconfig%3A%0A%20%20path%3A%0A%20%20%20%20%23%E6%88%96%E8%80%85%E5%8F%AF%E4%BB%A5%E5%86%99%E6%88%90%EF%BC%9A%0A%20%20%20%20include%3A%20%5B%2Fapi%2Fv1%2Ftoken%2Fapi_token%2C%2Fapi%2Fv1%2Fyibaotong%2Fsave%5D%20%20%20%20%20%20%0A%60%60%60%0A%3E%20%E5%AE%9A%E4%B9%89list%E9%9B%86%E5%90%88%E4%B8%8D%E8%83%BD%E7%94%A8%60%40value%60%20%E6%B3%A8%E8%A7%A3%E6%9D%A5%E8%8E%B7%E5%8F%96list%E9%9B%86%E5%90%88%E7%9A%84%E6%89%80%E6%9C%89%E5%80%BC%EF%BC%8C%0A%3E%20%E9%9C%80%E8%A6%81%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BBbean%EF%BC%8C%E7%84%B6%E5%90%8E%E4%BD%BF%E7%94%A8%60%40ConfigurationProperties%60%20%E6%B3%A8%E8%A7%A3%E6%9D%A5%E8%8E%B7%E5%8F%96list%E9%9B%86%E5%90%88%E5%80%BC%EF%BC%8C%0A%3E%20%E5%81%9A%E6%B3%95%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60java%0A%40Data%0A%40Component%0A%40ConfigurationProperties(prefix%20%3D%20%22interceptorconfig.path%22)%20%2F%2F%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%89%8D%E7%BC%80%0Apublic%20class%20InterceptorPathBean%0A%7B%0A%20%20%20%20%2F*%0A%20%20%20%20%20*%20%E9%9C%80%E8%A6%81%E6%8B%A6%E6%88%AA%E7%9A%84%E8%B7%AF%E5%BE%84%0A%20%20%20%20%20*%2F%0A%20%20%20%20private%20List%3CString%3E%20include%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%203%20%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1list%E9%9B%86%E5%90%88%0A%3E%20%E9%A6%96%E5%85%88%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAuser%E5%AF%B9%E8%B1%A1%E5%A6%82%E4%B8%8B%0A%60%60%60java%0A%40Data%0Apublic%20class%20User%20implements%20Serializable%0A%7B%20%20%0A%20%20%20%20private%20static%20final%20long%20serialVersionUID%20%3D%201L%3B%0A%0A%20%20%20%20private%20String%20appId%3B%0A%20%20%20%20private%20String%20password%3B%0A%7D%0A%60%60%60%0A%3E%20%E7%84%B6%E5%90%8Eyml%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%86%99%E6%B3%95%E5%A6%82%E4%B8%8B%0A%60%60%60yml%0Ajwt%3A%0A%20%20userlist%3A%0A%20%20%20%20-%20appId%3A%20YiBaoTong%0A%20%20%20%20%20%20password%3A%20123456%0A%20%20%20%20-%20appId%3A%20ZhiKe%0A%20%20%20%20%20%20password%3A%20123456%0A%60%60%60%0A%3E%20%E5%AE%9A%E4%B9%89%E9%85%8D%E7%BD%AEbean%0A%60%60%60java%0A%40Data%0A%40Component%0A%40ConfigurationProperties(prefix%20%3D%20%22jwt%22)%20%2F%2F%20%E9%85%8D%E7%BD%AE%20%E6%96%87%E4%BB%B6%E7%9A%84%E5%89%8D%E7%BC%80%0Apublic%20class%20JwtConfigBean%0A%7B%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20%E7%94%A8%E6%88%B7%E5%88%97%E8%A1%A8%0A%20%20%20%20%20*%2F%0A%20%20%20%20private%20List%3CUser%3E%20userlist%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%204%20%E5%AE%9A%E4%B9%89%E6%95%B0%E7%BB%84%0A%60%60%60yml%0Ainterceptorconfig%3A%0A%20%20path%3A%0A%20%20%20%20includes%3A%20%2Fapi%2Fv1%2C%2Fapi%2Fv2%20%20%23%E6%B3%A8%E6%84%8F%E8%A6%81%E7%94%A8%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E5%BC%80%0A%60%60%60%0A%3E%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%60%40value%60%E6%B3%A8%E8%A7%A3%E8%8E%B7%E5%8F%96%E6%95%B0%E7%BB%84%E5%80%BC%0A%60%60%60java%0A%40Value(%22%24%7Binterceptorconfig.path.includes%7D%22)%0A%20private%20String%5B%5D%20includes%3B%0A%60%60%60%0A%3E%20%E4%B9%9F%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%88%9B%E5%BB%BA%E9%85%8D%E7%BD%AE%E7%B1%BBbean%2C%20%E8%8E%B7%E5%8F%96%E6%95%B0%E7%BB%84%0A%60%60%60java%0A%40Data%0A%40Component%0A%40ConfigurationProperties(prefix%20%3D%20%22interceptorconfig.path%22)%20%2F%2F%20%E9%85%8D%E7%BD%AE%20%E6%96%87%E4%BB%B6%E7%9A%84%E5%89%8D%E7%BC%80%0Apublic%20class%20InterceptorPathBean%0A%7B%20%20%0A%20%20%20%20private%20String%5B%5D%20includes%3B%0A%7D%0A%60%60%60%0A%23%23%23%23%205%20%E5%AE%9A%E4%B9%89map%E9%9B%86%E5%90%88%0A%60%60%60yml%0Ainterceptorconfig%3A%0A%20%20path%3A%0A%20%20%20%20maps%3A%20%7Bname%3A%20%E5%B0%8F%E6%98%8E%2Cage%3A%2024%7D%0A%0Ainterceptorconfig%3A%0A%20%20path%3A%0A%20%20%20%20%23%E6%88%96%E8%80%85%E5%8F%AF%E4%BB%A5%E5%86%99%E6%88%90%EF%BC%9A%0A%20%20%20%20maps%3A%0A%20%20%20%20%20%20name%3A%20%E5%B0%8F%E6%98%8E%0A%20%20%20%20%20%20age%3A%2024%0A%60%60%60%0A%0A%3E%20%E9%80%9A%E8%BF%87%E5%88%9B%E5%BB%BA%E9%85%8D%E7%BD%AE%E7%B1%BBbean%EF%BC%8C%E8%8E%B7%E5%8F%96map%E5%80%BC%0A%60%60%60java%0A%40Data%0A%40Component%0A%40ConfigurationProperties(prefix%20%3D%20%22interceptorconfig.path%22)%20%2F%2F%20%E9%85%8D%E7%BD%AE%20%E6%96%87%E4%BB%B6%E7%9A%84%E5%89%8D%E7%BC%80%0Apublic%20class%20InterceptorPathBean%0A%7B%0A%20%20%20%20private%20Map%3CString%20%2C%20String%3E%20maps%3B%0A%7D%20%20%20%20%20%20%20%20%20%20%0A%60%60%60

JSON数据类型

创建时间:2022/1/13 22:31
更新时间:2022/1/21 18:48
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU2MDY0NDA1MQ==&mid=2247494251&idx=1&sn=d848cf0298595c480e7a6bba2adb967f&chksm=fc0640d7cb71c9c1c5d8c216b201555bae5b156a5a45331e37b368ebc5ee10e2dc7f0b4d7a6c&mpshare=1&scene=24&srcid=0113WSuslqBmwXMVWMdRhr7o&sharer_sharetime=1642082529529&sharer_shareid=5b3482cc84e779e76f71a8abd134e217&key=f6674797a48aa0ad8e9926ceee2c2f180f9a9fec40bd8f42015dc022d7fd5bcfaee95a4c3b656b5e6bbec8b7f0882a23a6f061f5bf9f07526c6b911b9fa6948554d3028f5940d7f492df424905fc02b6d57bb044b17f1de4f97a623a262dd73483693bae20c6cf7f0a4651f6a4d852b47b77c83d4d670ee81177adf375d06fad&ascene=0&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=6304051b&lang=zh_CN&exportkey=AfdKKI8I37q7mDixzQHgsuI%3D&acctmode=0&pass_ticket=U4WmL8erp00Neq23VmR9nnS5EycC4iAr3f12xqXUxg4rq8q3FMCLPItrDFhBtCn9&wx_header=0&fontgear=2

1 JSON 数据类型

MySQL 支持 RFC 7159 定义的JSON规范,
主要有 JSON 对象JSON 数组 两种类型

mysql :: mysql 8.0 reference manual :: 12.18.3 functions that search json values

1.1 JSON对象

{
 "Image": {
   "Width": 800,
   "Height": 600,
   "Title": "View from 15th Floor",
   "Thumbnail": {
     "Url": "http://www.example.com/image/xx9943",
     "Height": 125,
     "Width": 100
   },
 "IDs": [116, 943, 234, 38793]
 }
}

1.2 JSON数组

[
   {
     "precision": "zip",
     "Latitude": 37.7668,
     "Longitude": -122.3959,
     "Address": "",
     "City": "SAN FRANCISCO",
     "State": "CA",
     "Zip": "94107",
     "Country": "US"
   },
   {
     "precision": "zip",
     "Latitude": 37.371991,
     "Longitude": -122.026020,
     "Address": "",
     "City": "SUNNYVALE",
     "State": "CA",
     "Zip": "94085",
     "Country": "US"
   }
 ]

2 JSON 数据类型优点

  • 本质上,JSON 是一种新的类型,有自己的存储格式,还能在每个对应的字段上创建索引,做特定的优化,这是传统字段串无法实现的
  • 无须预定义字段,字段可以无限扩展。
    而传统关系型数据库的列都需预先定义,想要扩展需要执行 ALTER TABLE … ADD COLUMN … 这样比较重的操作
  • JSON 类型是从 MySQL 5.7 版本开始支持的功能,而 8.0 版本解决了更新 JSON 的日志性能瓶颈。如果要在生产环境中使用 JSON 数据类型,强烈推荐使用 MySQL 8.0 版本。

3 怎么玩

在数据库中,JSON 类型比较适合存储一些修改较少、相对静态的数据
比如用户登录信息的存储如下

3.1 写表

建表

DROP TABLE IF EXISTS UserLogin;

CREATE TABLE UserLogin (
    userId BIGINT NOT NULL,
    loginInfo JSON,
    PRIMARY KEY(userId)
);

写数据
用户1 登录有三种方式:手机验证码登录、微信登录、QQ 登录,而用户2 只有手机验证码登录

INSERT INTO UserLogin VALUES (1, '{ "cellphone" : "1", "wxchat" : "码农", "77" : 
"1" }');
INSERT INTO UserLogin VALUES (2, '{ "cellphone" : "1188" }');

查数据

SELECT
    userId,
    JSON_UNQUOTE(JSON_EXTRACT(loginInfo, "$.cellphone")) cellphone,
    JSON_UNQUOTE(JSON_EXTRACT(loginInfo, "$.wxchat")) wxchat
FROM UserLogin;

+--------+-------------+--------------+
| userId | cellphone   | wxchat       |
+--------+-------------+--------------+
|      1  | 11             | 码农          |
|      2  | 11             | NULL         |
+--------+-------------+--------------+
2 rows in set (0.01 sec)

3.2 建索引

当 JSON 数据量非常大,用户希望对 JSON 数据进行有效检索时,可以利用 MySQL 的 函数索引 功能对 JSON 中的某个字段进行索引。

ALTER TABLE UserLogin ADD COLUMN cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone");

ALTER TABLE UserLogin ADD UNIQUE INDEX idx_cellphone(cellphone);

上述 SQL 首先创建了一个虚拟列 cellphone,这个列是由函数 loginInfo->>"$.cellphone" 计算得到的。然后在这个虚拟列上创建一个唯一索引 idx_cellphone

这时再通过虚拟列 cellphone 进行查询,就可以看到优化器会使用到新创建的 idx_cellphone 索引:

EXPLAIN SELECT  *  FROM UserLogin 
WHERE cellphone = '1'\G
*************************** 1. row ***************************
                  id: 1
      select_type: SIMPLE
              table: UserLogin
       partitions: NULL
            type: const
possible_keys: idx_cellphone
             key: idx_cellphone
        key_len: 1023
              ref: const
            rows: 1
         filtered: 100.00
            Extra: NULL
1 row in set, 1 warning (0.00 sec)

可以在一开始创建表的时候,就完成虚拟列及函数索引的创建
如下表创建的列 cellphone 对应的就是 JSON 中的内容,是个虚拟列;
uk_idx_cellphone 就是在虚拟列 cellphone 上所创建的索引

CREATE TABLE UserLogin (
    userId BIGINT,
    loginInfo JSON,
    cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone"),
    PRIMARY KEY(userId),
    UNIQUE KEY uk_idx_cellphone(cellphone)
);

4 用户画像设计

4.1 画像定义表

CREATE TABLE Tags (
    tagId bigint auto_increment,
    tagName varchar(255) NOT NULL,
    primary key(tagId)
);

SELECT * FROM Tags;
+-------+--------------+
| tagId | tagName      |
+-------+--------------+
|     1 | 70后         |
|     2 | 80后         |
|     3 | 90后         |
|     4 | 00后         |
|     5 | 爱运动       |
|     6 | 高学历       |
|     7 | 小资         |
|     8 | 有房         |
|     9 | 有车         |
|    10 | 常看电影     |
|    11 | 爱网购       |
|    12 | 爱外卖       |

4.2 画像定义表

若不用 JSON 数据类型进行标签存储,通常会将用户标签通过字符串,加上分割符的方式,在一个字段中存取用户所有的标签:
这样做的缺点是:不好搜索特定画像的用户,另外分隔符也是一种自我约定,在数据库中其实可以任意存储其他数据,最终产生脏数据。

用 JSON 数据类型就能很好解决这个问题:

DROP TABLE IF EXISTS UserTag;
CREATE TABLE UserTag (
    userId bigint NOT NULL,
    userTags JSON,
    PRIMARY KEY (userId)
);

INSERT INTO UserTag VALUES (1,'[2,6,8,10]');
INSERT INTO UserTag VALUES (2,'[3,10,12]');

MySQL 8.0.17 版本开始支持 Multi-Valued Indexes,用于在 JSON 数组上创建索引,并通过函数 member of、json_contains、json_overlaps 来快速检索索引数据。所以你可以在表 UserTag 上创建 Multi-Valued Indexes:

ALTER TABLE UserTagADD INDEX idx_user_tags ((cast((userTags->"$"as unsigned array)));

如果想要查询用户画像为常看电影的用户,可以使用函数 MEMBER OF:

EXPLAIN SELECT * FROM UserTag 
WHERE 10 MEMBER OF(userTags->"$")\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: UserTag
   partitions: NULL
         type: ref
possible_keys: idx_user_tags
          key: idx_user_tags
      key_len: 9
            ref: const
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

SELECT * FROM UserTag 
WHERE 10 MEMBER OF(userTags->"$");
+--------+---------------+
| userId    | userTags      |
+--------+---------------+
|      1    | [2, 6, 8, 10] |
|      2    | [3, 10, 12]   |
+--------+---------------+
2 rows in set (0.00 sec)

如果想要查询画像为 80 后,且常看电影的用户,可以使用函数 JSON_CONTAINS:

EXPLAIN SELECT * FROM UserTag 
WHERE JSON_CONTAINS(userTags->"$", '[2,10]')\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: UserTag
   partitions: NULL
         type: range
possible_keys: idx_user_tags
          key: idx_user_tags
      key_len: 9
          ref: NULL
         rows: 3
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

SELECT * FROM UserTag 
WHERE JSON_CONTAINS(userTags->"$", '[2,10]');
+--------+---------------+
| userId | userTags      |
+--------+---------------+
|      1  | [2, 6, 8, 10] |
+--------+---------------+
1 row in set (0.00 sec)

如果想要查询画像为 80 后、90 后,且常看电影的用户,则可以使用函数 JSON_OVERLAP:

EXPLAIN SELECT * FROM UserTag 
WHERE JSON_OVERLAPS(userTags->"$", '[2,3,10]')\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: UserTag
   partitions: NULL
         type: range
possible_keys: idx_user_tags
          key: idx_user_tags
      key_len: 9
          ref: NULL
         rows: 4
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

SELECT * FROM UserTag 
WHERE JSON_OVERLAPS(userTags->"$", '[2,3,10]');
+--------+---------------+
| userId | userTags      |
+--------+---------------+
|      1  |   [2, 6, 8, 10] |
|      2  |   [3, 10, 12]   |
+--------+---------------+
2 rows in set (0.01 sec)

5 总结

JSON 类型是 MySQL 5.7 版本新增的数据类型,用好 JSON 数据类型可以有效解决很多业务中实际问题。

%5Btoc%5D%0A%23%23%201%20JSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%0A%0A%3E%20MySQL%20%E6%94%AF%E6%8C%81%20RFC%207159%20%E5%AE%9A%E4%B9%89%E7%9A%84JSON%E8%A7%84%E8%8C%83%EF%BC%8C%0A%3E%20%E4%B8%BB%E8%A6%81%E6%9C%89%20%60JSON%20%E5%AF%B9%E8%B1%A1%60%20%E5%92%8C%20%60JSON%20%E6%95%B0%E7%BB%84%60%20%E4%B8%A4%E7%A7%8D%E7%B1%BB%E5%9E%8B%0A%0A%5Bmysql%20%3A%3A%20mysql%208.0%20reference%20manual%20%3A%3A%2012.18.3%20functions%20that%20search%20json%20values%5D(https%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2F8.0%2Fen%2Fjson-search-functions.html%23operator_member-of)%0A%0A%23%23%23%23%201.1%20JSON%E5%AF%B9%E8%B1%A1%0A%60%60%60json%0A%7B%0A%20%22Image%22%3A%20%7B%0A%20%20%20%22Width%22%3A%20800%2C%0A%20%20%20%22Height%22%3A%20600%2C%0A%20%20%20%22Title%22%3A%20%22View%20from%2015th%20Floor%22%2C%0A%20%20%20%22Thumbnail%22%3A%20%7B%0A%20%20%20%20%20%22Url%22%3A%20%22http%3A%2F%2Fwww.example.com%2Fimage%2Fxx9943%22%2C%0A%20%20%20%20%20%22Height%22%3A%20125%2C%0A%20%20%20%20%20%22Width%22%3A%20100%0A%20%20%20%7D%2C%0A%20%22IDs%22%3A%20%5B116%2C%20943%2C%20234%2C%2038793%5D%0A%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%201.2%20JSON%E6%95%B0%E7%BB%84%0A%60%60%60json%0A%5B%0A%20%20%20%7B%0A%20%20%20%20%20%22precision%22%3A%20%22zip%22%2C%0A%20%20%20%20%20%22Latitude%22%3A%2037.7668%2C%0A%20%20%20%20%20%22Longitude%22%3A%20-122.3959%2C%0A%20%20%20%20%20%22Address%22%3A%20%22%22%2C%0A%20%20%20%20%20%22City%22%3A%20%22SAN%20FRANCISCO%22%2C%0A%20%20%20%20%20%22State%22%3A%20%22CA%22%2C%0A%20%20%20%20%20%22Zip%22%3A%20%2294107%22%2C%0A%20%20%20%20%20%22Country%22%3A%20%22US%22%0A%20%20%20%7D%2C%0A%20%20%20%7B%0A%20%20%20%20%20%22precision%22%3A%20%22zip%22%2C%0A%20%20%20%20%20%22Latitude%22%3A%2037.371991%2C%0A%20%20%20%20%20%22Longitude%22%3A%20-122.026020%2C%0A%20%20%20%20%20%22Address%22%3A%20%22%22%2C%0A%20%20%20%20%20%22City%22%3A%20%22SUNNYVALE%22%2C%0A%20%20%20%20%20%22State%22%3A%20%22CA%22%2C%0A%20%20%20%20%20%22Zip%22%3A%20%2294085%22%2C%0A%20%20%20%20%20%22Country%22%3A%20%22US%22%0A%20%20%20%7D%0A%20%5D%0A%60%60%60%0A%0A%23%23%202%20JSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E4%BC%98%E7%82%B9%0A%3E%20-%20%E6%9C%AC%E8%B4%A8%E4%B8%8A%EF%BC%8CJSON%20%E6%98%AF%E4%B8%80%E7%A7%8D%E6%96%B0%E7%9A%84%E7%B1%BB%E5%9E%8B%EF%BC%8C%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E5%AD%98%E5%82%A8%E6%A0%BC%E5%BC%8F%EF%BC%8C%E8%BF%98%E8%83%BD%E5%9C%A8%E6%AF%8F%E4%B8%AA%E5%AF%B9%E5%BA%94%E7%9A%84%E5%AD%97%E6%AE%B5%E4%B8%8A%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%EF%BC%8C%E5%81%9A%E7%89%B9%E5%AE%9A%E7%9A%84%E4%BC%98%E5%8C%96%EF%BC%8C%E8%BF%99%E6%98%AF%E4%BC%A0%E7%BB%9F%E5%AD%97%E6%AE%B5%E4%B8%B2%E6%97%A0%E6%B3%95%E5%AE%9E%E7%8E%B0%E7%9A%84%0A%3E%20-%20%E6%97%A0%E9%A1%BB%E9%A2%84%E5%AE%9A%E4%B9%89%E5%AD%97%E6%AE%B5%EF%BC%8C%E5%AD%97%E6%AE%B5%E5%8F%AF%E4%BB%A5%E6%97%A0%E9%99%90%E6%89%A9%E5%B1%95%E3%80%82%0A%3E%20%E8%80%8C%E4%BC%A0%E7%BB%9F%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E5%88%97%E9%83%BD%E9%9C%80%E9%A2%84%E5%85%88%E5%AE%9A%E4%B9%89%EF%BC%8C%E6%83%B3%E8%A6%81%E6%89%A9%E5%B1%95%E9%9C%80%E8%A6%81%E6%89%A7%E8%A1%8C%C2%A0%60ALTER%20TABLE%20%E2%80%A6%20ADD%20COLUMN%20%E2%80%A6%C2%A0%60%20%E8%BF%99%E6%A0%B7%E6%AF%94%E8%BE%83%E9%87%8D%E7%9A%84%E6%93%8D%E4%BD%9C%0A%3E%20-%20JSON%20%E7%B1%BB%E5%9E%8B%E6%98%AF%E4%BB%8E%20MySQL%205.7%20%E7%89%88%E6%9C%AC%E5%BC%80%E5%A7%8B%E6%94%AF%E6%8C%81%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E8%80%8C%208.0%20%E7%89%88%E6%9C%AC%E8%A7%A3%E5%86%B3%E4%BA%86%E6%9B%B4%E6%96%B0%20JSON%20%E7%9A%84%E6%97%A5%E5%BF%97%E6%80%A7%E8%83%BD%E7%93%B6%E9%A2%88%E3%80%82%E5%A6%82%E6%9E%9C%E8%A6%81%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8%20JSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%BC%BA%E7%83%88%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8%20MySQL%208.0%20%E7%89%88%E6%9C%AC%E3%80%82%0A%0A%0A%23%23%203%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%3E%E5%9C%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%EF%BC%8CJSON%20%E7%B1%BB%E5%9E%8B%E6%AF%94%E8%BE%83%E9%80%82%E5%90%88%E5%AD%98%E5%82%A8%E4%B8%80%E4%BA%9B%E4%BF%AE%E6%94%B9%E8%BE%83%E5%B0%91%E3%80%81%E7%9B%B8%E5%AF%B9%E9%9D%99%E6%80%81%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20%E6%AF%94%E5%A6%82%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95%E4%BF%A1%E6%81%AF%E7%9A%84%E5%AD%98%E5%82%A8%E5%A6%82%E4%B8%8B%0A%0A%23%23%23%23%203.1%20%E5%86%99%E8%A1%A8%0A%0A%0A%3E%E5%BB%BA%E8%A1%A8%20%0A%60%60%60sql%0ADROP%20TABLE%20IF%20EXISTS%20UserLogin%3B%0A%0ACREATE%20TABLE%20UserLogin%20(%0A%20%20%20%20userId%20BIGINT%20NOT%20NULL%2C%0A%20%20%20%20loginInfo%20JSON%2C%0A%20%20%20%20PRIMARY%20KEY(userId)%0A)%3B%0A%60%60%60%0A%0A%3E%20%E5%86%99%E6%95%B0%E6%8D%AE%0A%3E%20%E7%94%A8%E6%88%B71%20%E7%99%BB%E5%BD%95%E6%9C%89%E4%B8%89%E7%A7%8D%E6%96%B9%E5%BC%8F%EF%BC%9A%E6%89%8B%E6%9C%BA%E9%AA%8C%E8%AF%81%E7%A0%81%E7%99%BB%E5%BD%95%E3%80%81%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E3%80%81QQ%20%E7%99%BB%E5%BD%95%EF%BC%8C%E8%80%8C%E7%94%A8%E6%88%B72%20%E5%8F%AA%E6%9C%89%E6%89%8B%E6%9C%BA%E9%AA%8C%E8%AF%81%E7%A0%81%E7%99%BB%E5%BD%95%0A%60%60%60sql%0AINSERT%20INTO%20UserLogin%20VALUES%20(1%2C%20'%7B%20%22cellphone%22%20%3A%20%221%22%2C%20%22wxchat%22%20%3A%20%22%E7%A0%81%E5%86%9C%22%2C%20%2277%22%20%3A%20%0A%221%22%20%7D')%3B%0AINSERT%20INTO%20UserLogin%20VALUES%20(2%2C%20'%7B%20%22cellphone%22%20%3A%20%221188%22%20%7D')%3B%0A%60%60%60%0A%3E%20%E6%9F%A5%E6%95%B0%E6%8D%AE%0A%60%60%60sql%0ASELECT%0A%20%20%20%20userId%2C%0A%20%20%20%20JSON_UNQUOTE(JSON_EXTRACT(loginInfo%2C%20%22%24.cellphone%22))%20cellphone%2C%0A%20%20%20%20JSON_UNQUOTE(JSON_EXTRACT(loginInfo%2C%20%22%24.wxchat%22))%20wxchat%0AFROM%20UserLogin%3B%0A%0A%2B--------%2B-------------%2B--------------%2B%0A%7C%20userId%20%7C%20cellphone%20%20%20%7C%20wxchat%20%20%20%20%20%20%20%7C%0A%2B--------%2B-------------%2B--------------%2B%0A%7C%20%20%20%20%20%201%20%20%7C%2011%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E7%A0%81%E5%86%9C%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%20%202%20%20%7C%2011%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20NULL%20%20%20%20%20%20%20%20%20%7C%0A%2B--------%2B-------------%2B--------------%2B%0A2%20rows%20in%20set%20(0.01%20sec)%0A%60%60%60%0A%0A%23%23%23%23%203.2%20%E5%BB%BA%E7%B4%A2%E5%BC%95%0A%3E%20%E5%BD%93%20JSON%20%E6%95%B0%E6%8D%AE%E9%87%8F%E9%9D%9E%E5%B8%B8%E5%A4%A7%EF%BC%8C%E7%94%A8%E6%88%B7%E5%B8%8C%E6%9C%9B%E5%AF%B9%20JSON%20%E6%95%B0%E6%8D%AE%E8%BF%9B%E8%A1%8C%E6%9C%89%E6%95%88%E6%A3%80%E7%B4%A2%E6%97%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%88%A9%E7%94%A8%20MySQL%20%E7%9A%84%20%60%E5%87%BD%E6%95%B0%E7%B4%A2%E5%BC%95%60%20%E5%8A%9F%E8%83%BD%E5%AF%B9%20JSON%20%E4%B8%AD%E7%9A%84%E6%9F%90%E4%B8%AA%E5%AD%97%E6%AE%B5%E8%BF%9B%E8%A1%8C%E7%B4%A2%E5%BC%95%E3%80%82%0A%0A%60%60%60sql%0AALTER%20TABLE%20UserLogin%20ADD%20COLUMN%20cellphone%20VARCHAR(255)%20AS%20(loginInfo-%3E%3E%22%24.cellphone%22)%3B%0A%0AALTER%20TABLE%20UserLogin%20ADD%20UNIQUE%20INDEX%20idx_cellphone(cellphone)%3B%0A%60%60%60%0A%3E%20%E4%B8%8A%E8%BF%B0%20SQL%20%E9%A6%96%E5%85%88%E5%88%9B%E5%BB%BA%E4%BA%86%E4%B8%80%E4%B8%AA%E8%99%9A%E6%8B%9F%E5%88%97%20%60cellphone%60%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%88%97%E6%98%AF%E7%94%B1%E5%87%BD%E6%95%B0%20%60loginInfo-%3E%3E%22%24.cellphone%22%20%60%20%E8%AE%A1%E7%AE%97%E5%BE%97%E5%88%B0%E7%9A%84%E3%80%82%E7%84%B6%E5%90%8E%E5%9C%A8%E8%BF%99%E4%B8%AA%E8%99%9A%E6%8B%9F%E5%88%97%E4%B8%8A%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%20%60idx_cellphone%60%E3%80%82%0A%0A%3E%20%E8%BF%99%E6%97%B6%E5%86%8D%E9%80%9A%E8%BF%87%E8%99%9A%E6%8B%9F%E5%88%97%20%60cellphone%60%20%E8%BF%9B%E8%A1%8C%E6%9F%A5%E8%AF%A2%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E4%BC%98%E5%8C%96%E5%99%A8%E4%BC%9A%E4%BD%BF%E7%94%A8%E5%88%B0%E6%96%B0%E5%88%9B%E5%BB%BA%E7%9A%84%20%60idx_cellphone%60%20%E7%B4%A2%E5%BC%95%EF%BC%9A%0A%60%60%60sql%0AEXPLAIN%20SELECT%20%20*%20%20FROM%20UserLogin%20%0AWHERE%20cellphone%20%3D%20'1'%5CG%0A***************************%201.%20row%20***************************%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3A%201%0A%20%20%20%20%20%20select_type%3A%20SIMPLE%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20table%3A%20UserLogin%0A%20%20%20%20%20%20%20partitions%3A%20NULL%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20const%0Apossible_keys%3A%20idx_cellphone%0A%20%20%20%20%20%20%20%20%20%20%20%20%20key%3A%20idx_cellphone%0A%20%20%20%20%20%20%20%20key_len%3A%201023%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20ref%3A%20const%0A%20%20%20%20%20%20%20%20%20%20%20%20rows%3A%201%0A%20%20%20%20%20%20%20%20%20filtered%3A%20100.00%0A%20%20%20%20%20%20%20%20%20%20%20%20Extra%3A%20NULL%0A1%20row%20in%20set%2C%201%20warning%20(0.00%20sec)%0A%60%60%60%0A%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%B8%80%E5%BC%80%E5%A7%8B%E5%88%9B%E5%BB%BA%E8%A1%A8%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%B0%B1%E5%AE%8C%E6%88%90%E8%99%9A%E6%8B%9F%E5%88%97%E5%8F%8A%E5%87%BD%E6%95%B0%E7%B4%A2%E5%BC%95%E7%9A%84%E5%88%9B%E5%BB%BA%0A%3E%20%E5%A6%82%E4%B8%8B%E8%A1%A8%E5%88%9B%E5%BB%BA%E7%9A%84%E5%88%97%20%60cellphone%60%20%20%E5%AF%B9%E5%BA%94%E7%9A%84%E5%B0%B1%E6%98%AF%20JSON%20%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8C%E6%98%AF%E4%B8%AA%E8%99%9A%E6%8B%9F%E5%88%97%EF%BC%9B%0A%3E%20%60uk_idx_cellphone%60%C2%A0%E5%B0%B1%E6%98%AF%E5%9C%A8%E8%99%9A%E6%8B%9F%E5%88%97%20cellphone%20%E4%B8%8A%E6%89%80%E5%88%9B%E5%BB%BA%E7%9A%84%E7%B4%A2%E5%BC%95%0A%60%60%60sql%0ACREATE%20TABLE%20UserLogin%20(%0A%20%20%20%20userId%20BIGINT%2C%0A%20%20%20%20loginInfo%20JSON%2C%0A%20%20%20%20cellphone%20VARCHAR(255)%20AS%20(loginInfo-%3E%3E%22%24.cellphone%22)%2C%0A%20%20%20%20PRIMARY%20KEY(userId)%2C%0A%20%20%20%20UNIQUE%20KEY%20uk_idx_cellphone(cellphone)%0A)%3B%0A%60%60%60%0A%0A%23%23%204%20%E7%94%A8%E6%88%B7%E7%94%BB%E5%83%8F%E8%AE%BE%E8%AE%A1%0A%23%23%23%23%204.1%20%E7%94%BB%E5%83%8F%E5%AE%9A%E4%B9%89%E8%A1%A8%0A%0A%60%60%60sql%0ACREATE%20TABLE%20Tags%20(%0A%20%20%20%20tagId%20bigint%20auto_increment%2C%0A%20%20%20%20tagName%20varchar(255)%20NOT%20NULL%2C%0A%20%20%20%20primary%20key(tagId)%0A)%3B%0A%0ASELECT%20*%20FROM%20Tags%3B%0A%2B-------%2B--------------%2B%0A%7C%20tagId%20%7C%20tagName%20%20%20%20%20%20%7C%0A%2B-------%2B--------------%2B%0A%7C%20%20%20%20%201%20%7C%2070%E5%90%8E%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%202%20%7C%2080%E5%90%8E%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%203%20%7C%2090%E5%90%8E%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%204%20%7C%2000%E5%90%8E%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%205%20%7C%20%E7%88%B1%E8%BF%90%E5%8A%A8%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%206%20%7C%20%E9%AB%98%E5%AD%A6%E5%8E%86%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%207%20%7C%20%E5%B0%8F%E8%B5%84%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%208%20%7C%20%E6%9C%89%E6%88%BF%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%209%20%7C%20%E6%9C%89%E8%BD%A6%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%2010%20%7C%20%E5%B8%B8%E7%9C%8B%E7%94%B5%E5%BD%B1%20%20%20%20%20%7C%0A%7C%20%20%20%2011%20%7C%20%E7%88%B1%E7%BD%91%E8%B4%AD%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%2012%20%7C%20%E7%88%B1%E5%A4%96%E5%8D%96%20%20%20%20%20%20%20%7C%0A%60%60%60%0A%0A%0A%23%23%23%23%204.2%20%E7%94%BB%E5%83%8F%E5%AE%9A%E4%B9%89%E8%A1%A8%0A%0A%3E%20%E8%8B%A5%E4%B8%8D%E7%94%A8%20JSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BF%9B%E8%A1%8C%E6%A0%87%E7%AD%BE%E5%AD%98%E5%82%A8%EF%BC%8C%E9%80%9A%E5%B8%B8%E4%BC%9A%E5%B0%86%E7%94%A8%E6%88%B7%E6%A0%87%E7%AD%BE%E9%80%9A%E8%BF%87%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8C%E5%8A%A0%E4%B8%8A%E5%88%86%E5%89%B2%E7%AC%A6%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%9C%A8%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%E4%B8%AD%E5%AD%98%E5%8F%96%E7%94%A8%E6%88%B7%E6%89%80%E6%9C%89%E7%9A%84%E6%A0%87%E7%AD%BE%EF%BC%9A%0A%3E%E8%BF%99%E6%A0%B7%E5%81%9A%E7%9A%84%E7%BC%BA%E7%82%B9%E6%98%AF%EF%BC%9A%E4%B8%8D%E5%A5%BD%E6%90%9C%E7%B4%A2%E7%89%B9%E5%AE%9A%E7%94%BB%E5%83%8F%E7%9A%84%E7%94%A8%E6%88%B7%EF%BC%8C%E5%8F%A6%E5%A4%96%E5%88%86%E9%9A%94%E7%AC%A6%E4%B9%9F%E6%98%AF%E4%B8%80%E7%A7%8D%E8%87%AA%E6%88%91%E7%BA%A6%E5%AE%9A%EF%BC%8C%E5%9C%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E5%85%B6%E5%AE%9E%E5%8F%AF%E4%BB%A5%E4%BB%BB%E6%84%8F%E5%AD%98%E5%82%A8%E5%85%B6%E4%BB%96%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%9C%80%E7%BB%88%E4%BA%A7%E7%94%9F%E8%84%8F%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A!%5B2cc8f8222ca051afebeb31c394e5a499.png%5D(en-resource%3A%2F%2Fdatabase%2F1300%3A1)%0A%0A%3E%20%E7%94%A8%20JSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%B0%B1%E8%83%BD%E5%BE%88%E5%A5%BD%E8%A7%A3%E5%86%B3%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%9A%0A%60%60%60sql%0ADROP%20TABLE%20IF%20EXISTS%20UserTag%3B%0ACREATE%20TABLE%20UserTag%20(%0A%20%20%20%20userId%20bigint%20NOT%20NULL%2C%0A%20%20%20%20userTags%20JSON%2C%0A%20%20%20%20PRIMARY%20KEY%20(userId)%0A)%3B%0A%0AINSERT%20INTO%20UserTag%20VALUES%20(1%2C'%5B2%2C6%2C8%2C10%5D')%3B%0AINSERT%20INTO%20UserTag%20VALUES%20(2%2C'%5B3%2C10%2C12%5D')%3B%0A%60%60%60%0A%0A%3E%20MySQL%208.0.17%20%E7%89%88%E6%9C%AC%E5%BC%80%E5%A7%8B%E6%94%AF%E6%8C%81%C2%A0Multi-Valued%20Indexes%EF%BC%8C%E7%94%A8%E4%BA%8E%E5%9C%A8%20JSON%20%E6%95%B0%E7%BB%84%E4%B8%8A%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%EF%BC%8C%E5%B9%B6%E9%80%9A%E8%BF%87%E5%87%BD%E6%95%B0%C2%A0member%20of%E3%80%81json_contains%E3%80%81json_overlaps%C2%A0%E6%9D%A5%E5%BF%AB%E9%80%9F%E6%A3%80%E7%B4%A2%E7%B4%A2%E5%BC%95%E6%95%B0%E6%8D%AE%E3%80%82%E6%89%80%E4%BB%A5%E4%BD%A0%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%A1%A8%20UserTag%20%E4%B8%8A%E5%88%9B%E5%BB%BA%C2%A0Multi-Valued%20Indexes%EF%BC%9A%0A%0A%60%60%60sql%0AALTER%C2%A0TABLE%C2%A0UserTagADD%C2%A0INDEX%C2%A0idx_user_tags%C2%A0((cast((userTags-%3E%22%24%22)%C2%A0as%C2%A0unsigned%C2%A0array)))%3B%0A%60%60%60%0A%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E6%83%B3%E8%A6%81%E6%9F%A5%E8%AF%A2%E7%94%A8%E6%88%B7%E7%94%BB%E5%83%8F%E4%B8%BA%E5%B8%B8%E7%9C%8B%E7%94%B5%E5%BD%B1%E7%9A%84%E7%94%A8%E6%88%B7%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E5%87%BD%E6%95%B0%20MEMBER%20OF%EF%BC%9A%0A%0A%60%60%60sql%0AEXPLAIN%20SELECT%20*%20FROM%20UserTag%20%0AWHERE%2010%20MEMBER%20OF(userTags-%3E%22%24%22)%5CG%0A***************************%201.%20row%20***************************%0A%20%20%20%20%20%20%20%20%20%20%20id%3A%201%0A%20%20select_type%3A%20SIMPLE%0A%20%20%20%20%20%20%20%20table%3A%20UserTag%0A%20%20%20partitions%3A%20NULL%0A%20%20%20%20%20%20%20%20%20type%3A%20ref%0Apossible_keys%3A%20idx_user_tags%0A%20%20%20%20%20%20%20%20%20%20key%3A%20idx_user_tags%0A%20%20%20%20%20%20key_len%3A%209%0A%20%20%20%20%20%20%20%20%20%20%20%20ref%3A%20const%0A%20%20%20%20%20%20%20%20%20rows%3A%201%0A%20%20%20%20%20filtered%3A%20100.00%0A%20%20%20%20%20%20%20%20Extra%3A%20Using%20where%0A1%20row%20in%20set%2C%201%20warning%20(0.00%20sec)%0A%0ASELECT%20*%20FROM%20UserTag%20%0AWHERE%2010%20MEMBER%20OF(userTags-%3E%22%24%22)%3B%0A%2B--------%2B---------------%2B%0A%7C%20userId%20%20%20%20%7C%20userTags%20%20%20%20%20%20%7C%0A%2B--------%2B---------------%2B%0A%7C%20%20%20%20%20%201%20%20%20%20%7C%20%5B2%2C%206%2C%208%2C%2010%5D%20%7C%0A%7C%20%20%20%20%20%202%20%20%20%20%7C%20%5B3%2C%2010%2C%2012%5D%20%20%20%7C%0A%2B--------%2B---------------%2B%0A2%20rows%20in%20set%20(0.00%20sec)%0A%60%60%60%0A%3E%20%E5%A6%82%E6%9E%9C%E6%83%B3%E8%A6%81%E6%9F%A5%E8%AF%A2%E7%94%BB%E5%83%8F%E4%B8%BA%2080%20%E5%90%8E%EF%BC%8C%E4%B8%94%E5%B8%B8%E7%9C%8B%E7%94%B5%E5%BD%B1%E7%9A%84%E7%94%A8%E6%88%B7%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E5%87%BD%E6%95%B0%C2%A0JSON_CONTAINS%EF%BC%9A%0A%0A%60%60%60sql%0AEXPLAIN%20SELECT%20*%20FROM%20UserTag%20%0AWHERE%20JSON_CONTAINS(userTags-%3E%22%24%22%2C%20'%5B2%2C10%5D')%5CG%0A***************************%201.%20row%20***************************%0A%20%20%20%20%20%20%20%20%20%20%20id%3A%201%0A%20%20select_type%3A%20SIMPLE%0A%20%20%20%20%20%20%20%20table%3A%20UserTag%0A%20%20%20partitions%3A%20NULL%0A%20%20%20%20%20%20%20%20%20type%3A%20range%0Apossible_keys%3A%20idx_user_tags%0A%20%20%20%20%20%20%20%20%20%20key%3A%20idx_user_tags%0A%20%20%20%20%20%20key_len%3A%209%0A%20%20%20%20%20%20%20%20%20%20ref%3A%20NULL%0A%20%20%20%20%20%20%20%20%20rows%3A%203%0A%20%20%20%20%20filtered%3A%20100.00%0A%20%20%20%20%20%20%20%20Extra%3A%20Using%20where%0A1%20row%20in%20set%2C%201%20warning%20(0.00%20sec)%0A%0ASELECT%20*%20FROM%20UserTag%20%0AWHERE%20JSON_CONTAINS(userTags-%3E%22%24%22%2C%20'%5B2%2C10%5D')%3B%0A%2B--------%2B---------------%2B%0A%7C%20userId%20%7C%20userTags%20%20%20%20%20%20%7C%0A%2B--------%2B---------------%2B%0A%7C%20%20%20%20%20%201%20%20%7C%20%5B2%2C%206%2C%208%2C%2010%5D%20%7C%0A%2B--------%2B---------------%2B%0A1%20row%20in%20set%20(0.00%20sec)%0A%60%60%60%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E6%83%B3%E8%A6%81%E6%9F%A5%E8%AF%A2%E7%94%BB%E5%83%8F%E4%B8%BA%2080%20%E5%90%8E%E3%80%8190%20%E5%90%8E%EF%BC%8C%E4%B8%94%E5%B8%B8%E7%9C%8B%E7%94%B5%E5%BD%B1%E7%9A%84%E7%94%A8%E6%88%B7%EF%BC%8C%E5%88%99%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E5%87%BD%E6%95%B0%C2%A0JSON_OVERLAP%EF%BC%9A%0A%0A%60%60%60sql%0AEXPLAIN%20SELECT%20*%20FROM%20UserTag%20%0AWHERE%20JSON_OVERLAPS(userTags-%3E%22%24%22%2C%20'%5B2%2C3%2C10%5D')%5CG%0A***************************%201.%20row%20***************************%0A%20%20%20%20%20%20%20%20%20%20%20id%3A%201%0A%20%20select_type%3A%20SIMPLE%0A%20%20%20%20%20%20%20%20table%3A%20UserTag%0A%20%20%20partitions%3A%20NULL%0A%20%20%20%20%20%20%20%20%20type%3A%20range%0Apossible_keys%3A%20idx_user_tags%0A%20%20%20%20%20%20%20%20%20%20key%3A%20idx_user_tags%0A%20%20%20%20%20%20key_len%3A%209%0A%20%20%20%20%20%20%20%20%20%20ref%3A%20NULL%0A%20%20%20%20%20%20%20%20%20rows%3A%204%0A%20%20%20%20%20filtered%3A%20100.00%0A%20%20%20%20%20%20%20%20Extra%3A%20Using%20where%0A1%20row%20in%20set%2C%201%20warning%20(0.00%20sec)%0A%0ASELECT%20*%20FROM%20UserTag%20%0AWHERE%20JSON_OVERLAPS(userTags-%3E%22%24%22%2C%20'%5B2%2C3%2C10%5D')%3B%0A%2B--------%2B---------------%2B%0A%7C%20userId%20%7C%20userTags%20%20%20%20%20%20%7C%0A%2B--------%2B---------------%2B%0A%7C%20%20%20%20%20%201%20%20%7C%20%20%20%5B2%2C%206%2C%208%2C%2010%5D%20%7C%0A%7C%20%20%20%20%20%202%20%20%7C%20%20%20%5B3%2C%2010%2C%2012%5D%20%20%20%7C%0A%2B--------%2B---------------%2B%0A2%20rows%20in%20set%20(0.01%20sec)%0A%60%60%60%0A%0A%23%23%205%20%E6%80%BB%E7%BB%93%0A%0AJSON%20%E7%B1%BB%E5%9E%8B%E6%98%AF%20MySQL%205.7%20%E7%89%88%E6%9C%AC%E6%96%B0%E5%A2%9E%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%EF%BC%8C%E7%94%A8%E5%A5%BD%20JSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%8F%AF%E4%BB%A5%E6%9C%89%E6%95%88%E8%A7%A3%E5%86%B3%E5%BE%88%E5%A4%9A%E4%B8%9A%E5%8A%A1%E4%B8%AD%E5%AE%9E%E9%99%85%E9%97%AE%E9%A2%98%E3%80%82%0A-%20%E4%BD%BF%E7%94%A8%20JSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%EF%BC%8C%E6%8E%A8%E8%8D%90%E7%94%A8%20MySQL%208.0.17%20%E4%BB%A5%E4%B8%8A%E7%9A%84%E7%89%88%E6%9C%AC%EF%BC%8C%E6%80%A7%E8%83%BD%E6%9B%B4%E5%A5%BD%EF%BC%8C%E5%90%8C%E6%97%B6%E4%B9%9F%E6%94%AF%E6%8C%81%C2%A0Multi-Valued%20Indexes%EF%BC%9B%0A-%20JSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%A5%BD%E5%A4%84%E6%98%AF%E6%97%A0%E9%A1%BB%E9%A2%84%E5%85%88%E5%AE%9A%E4%B9%89%E5%88%97%EF%BC%8C%E6%95%B0%E6%8D%AE%E6%9C%AC%E8%BA%AB%E5%B0%B1%E5%85%B7%E6%9C%89%E5%BE%88%E5%A5%BD%E7%9A%84%E6%8F%8F%E8%BF%B0%E6%80%A7%EF%BC%9B%E4%B8%8D%E8%A6%81%E5%B0%86%E6%9C%89%E6%98%8E%E6%98%BE%E5%85%B3%E7%B3%BB%E5%9E%8B%E7%9A%84%E6%95%B0%E6%8D%AE%0A-%20%E7%94%A8%20JSON%20%E5%AD%98%E5%82%A8%EF%BC%8C%E5%A6%82%E7%94%A8%E6%88%B7%E4%BD%99%E9%A2%9D%E3%80%81%E7%94%A8%E6%88%B7%E5%A7%93%E5%90%8D%E3%80%81%E7%94%A8%E6%88%B7%E8%BA%AB%E4%BB%BD%E8%AF%81%E7%AD%89%EF%BC%8C%E8%BF%99%E4%BA%9B%E9%83%BD%E6%98%AF%E6%AF%8F%E4%B8%AA%E7%94%A8%E6%88%B7%E5%BF%85%E9%A1%BB%E5%8C%85%E5%90%AB%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%9BJSON%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8%E5%9C%A8%E4%B8%8D%E7%BB%8F%E5%B8%B8%E6%9B%B4%E6%96%B0%E7%9A%84%E9%9D%99%E6%80%81%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8%E3%80%82

Genericity

创建时间:2022/1/15 22:34
更新时间:2022/1/15 23:05
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=Mzg5NDM1ODk4Mw==&mid=2247529860&idx=2&sn=42a756e98696fab6a8b0f71eacc8787c&chksm=c022f12cf755783a2ae26666bdb3bdfee21291c0e8261bc25dad8c1ee4e146c946eecd36f3a5&mpshare=1&scene=24&srcid=0113KOdthig98klSKwQrTdNR&sharer_sharetime=1642082502266&sharer_shareid=5b3482cc84e779e76f71a8abd134e217&key=756768bae9c758c239b8528ed1a3bcfa9b03feb33a07feadfe1ba34bc4b78389e0d38c794f0ee20f765d0eaf8238a3a7721a011c2346e3effd4786fe06355ff4f21f62d632785af4fbba8295e993f7ef7e18838a884d44672a3295e707a6e0d0517494f45e622456ebbdc5a5407b7c150f07cb9015cf8986f066fdc31445b514&ascene=0&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=6304051b&lang=zh_CN&exportkey=Afhju8Ew8WWJtx8%2FDgXgc4I%3D&acctmode=0&pass_ticket=3465YyDJuv8a412ltyX5UCULUeBTXsjMDwU53AnqqYO%2FTOPJw0ZFvUjYfNHEAK5y&wx_header=0&fontgear=2

1 泛型概述

作用在类、方法上

1.1 定义泛型类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Genericity<T> {

    private T t1;
    private T t2;
}

这就是泛型类的定义,通过在类名后面添加<T> 符号即可定义泛型类,而类中的属性类型均为T,这将导致类中的属性类型会跟随 T 的变化而变化,用法如下:

public static void main(String[] args) {
    Genericity<Integer> genericity = new Genericity<>(1, 1);
    Integer t1 = genericity.getT1();
    Integer t2 = genericity.getT2();
    int result = t1 + t2;
    System.out.println(result);
}

实际上,泛型类可以定义多个泛型变量,比如:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Genericity<T,U> {

    private T t1;
    private U t2;
}


// 此时我们在创建对象时就可以传入两个类型:
public static void main(String[] args) {
    Genericity<Integer,String> genericity = new Genericity<>(1, "1");
    Integer t1 = genericity.getT1();
    String t2 = genericity.getT2();
}

1.2 定义泛型方法

public static <T> void method(T t) {
}

编译器能够自动推断出泛型类型T

public static void main(String[] args) {
    Genericity.method(1);
}

泛型方法的返回值也可以使用类型变量:

public static <T> T method(T t) {
    return t;
}

泛型方法也支持定义多个类型变量:

public static <T, U> T method(T t, U u) {
    return t;
}

1.3 泛型的限定符

public static <T> T min(T[] t) {
    T minimum = t[0];
    for (int i = 0; i < t.length; i++) {
        if (minimum.compareTo(t[i]) > 0) {
            minimum = t[i];
        }
    }
    return minimum;
}

它能够取出数组t中的最小值,然而这段程序是有问题的,因为T可以是任意类型的对象,但不是什么对象都能够调用compareTo方法进行比较的,所以,我们需要对类型变量T进行限定,限定为实现了Comparable接口的对象,如下:

public static <T extends Comparable> T min(T[] t) {
    T minimum = t[0];
    for (int i = 0; i < t.length; i++) {
        if (minimum.compareTo(t[i]) > 0) {
            minimum = t[i];
        }
    }
    return minimum;
}

一个泛型方法也可以对类型变量进行多个限定

 public static <T extends Comparable & Serializable> T min(T[] t) {
    ......
 }

1.4 泛型擦除

泛型仅仅是在编译期间起作用,目的是让程序员在编译期间就避免发生一些类型不对应的问题,而在运行阶段,泛型是根本不存在的,因为虚拟机会对泛型进行擦除。

可以通过反射进行验证,因为反射是作用在运行阶段的:

public static void main(String[] args) throws Exception {
    List<Integer> list = new ArrayList<>();
    list.add(1);
    Method addMethod = list.getClass().getDeclaredMethod("add",Object.class);
    addMethod.invoke(list,"2");
    addMethod.invoke(list,true);
    addMethod.invoke(list,3.2f);
    System.out.println(list);
}

若是通过反射能够将这些非Integer类型的值存入list,则说明在运行期间确实是不存在泛型检查的,运行结果如下:

[1, 2, true, 3.2]

泛型擦除也体现在泛型方法中

 public static <T extends Comparable> T min(T[] t) {
    ......
 }

当程序运行期间,泛型会被擦除,此时方法变为如下:

public static Comparable min(Comparable t) {
    ......
}

这也就是为什么类型限定能够生效的原因了,通过泛型擦除后,该方法就只能接收和返回Comparable接口的实现类。

1.5 泛型通配符

固定的泛型类型显然无法满足复杂多变的需求,为此,泛型设计者们还提供了泛型通配符,如:

//它表示类型变量必须是Person类型的子类
Genericity<? extends Person>
//此时类型变量就必须是Person类的超类
Genericity<? super Person>

还有一种情况是无限定通配符:

Genericity<?>

它和 Genericity<T> 非常相似,但又有不同,Genericity<?> 的setter方法不能被调用,getter方法只能返回Object类型,不过这种方式的用法较少,可能会被用来判断空引用:

public static boolean isNull(Genericity<?> genericity){
    return genericity.getContent();
}
%5Btoc%5D%0A%23%23%201%20%E6%B3%9B%E5%9E%8B%E6%A6%82%E8%BF%B0%0A%0A%3E%20%E4%BD%9C%E7%94%A8%E5%9C%A8%E7%B1%BB%E3%80%81%E6%96%B9%E6%B3%95%E4%B8%8A%0A%0A%23%23%23%23%201.1%20%E5%AE%9A%E4%B9%89%E6%B3%9B%E5%9E%8B%E7%B1%BB%0A%0A%60%60%60java%0A%40Data%0A%40AllArgsConstructor%0A%40NoArgsConstructor%0Apublic%20class%20Genericity%3CT%3E%20%7B%0A%0A%20%20%20%20private%20T%20t1%3B%0A%20%20%20%20private%20T%20t2%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E8%BF%99%E5%B0%B1%E6%98%AF%E6%B3%9B%E5%9E%8B%E7%B1%BB%E7%9A%84%E5%AE%9A%E4%B9%89%EF%BC%8C%E9%80%9A%E8%BF%87%E5%9C%A8%E7%B1%BB%E5%90%8D%E5%90%8E%E9%9D%A2%E6%B7%BB%E5%8A%A0%60%3CT%3E%60%20%E7%AC%A6%E5%8F%B7%E5%8D%B3%E5%8F%AF%E5%AE%9A%E4%B9%89%E6%B3%9B%E5%9E%8B%E7%B1%BB%EF%BC%8C%E8%80%8C%E7%B1%BB%E4%B8%AD%E7%9A%84%E5%B1%9E%E6%80%A7%E7%B1%BB%E5%9E%8B%E5%9D%87%E4%B8%BA%60T%60%EF%BC%8C%E8%BF%99%E5%B0%86%E5%AF%BC%E8%87%B4%E7%B1%BB%E4%B8%AD%E7%9A%84%E5%B1%9E%E6%80%A7%E7%B1%BB%E5%9E%8B%E4%BC%9A%E8%B7%9F%E9%9A%8F%20%60T%60%20%E7%9A%84%E5%8F%98%E5%8C%96%E8%80%8C%E5%8F%98%E5%8C%96%EF%BC%8C%E7%94%A8%E6%B3%95%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20Genericity%3CInteger%3E%20genericity%20%3D%20new%20Genericity%3C%3E(1%2C%201)%3B%0A%20%20%20%20Integer%20t1%20%3D%20genericity.getT1()%3B%0A%20%20%20%20Integer%20t2%20%3D%20genericity.getT2()%3B%0A%20%20%20%20int%20result%20%3D%20t1%20%2B%20t2%3B%0A%20%20%20%20System.out.println(result)%3B%0A%7D%0A%60%60%60%0A%3E%20%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8C%E6%B3%9B%E5%9E%8B%E7%B1%BB%E5%8F%AF%E4%BB%A5%E5%AE%9A%E4%B9%89%E5%A4%9A%E4%B8%AA%E6%B3%9B%E5%9E%8B%E5%8F%98%E9%87%8F%EF%BC%8C%E6%AF%94%E5%A6%82%EF%BC%9A%0A%60%60%60java%0A%40Data%0A%40AllArgsConstructor%0A%40NoArgsConstructor%0Apublic%20class%20Genericity%3CT%2CU%3E%20%7B%0A%0A%20%20%20%20private%20T%20t1%3B%0A%20%20%20%20private%20U%20t2%3B%0A%7D%0A%0A%0A%2F%2F%20%E6%AD%A4%E6%97%B6%E6%88%91%E4%BB%AC%E5%9C%A8%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E6%97%B6%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BC%A0%E5%85%A5%E4%B8%A4%E4%B8%AA%E7%B1%BB%E5%9E%8B%EF%BC%9A%0Apublic%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20Genericity%3CInteger%2CString%3E%20genericity%20%3D%20new%20Genericity%3C%3E(1%2C%20%221%22)%3B%0A%20%20%20%20Integer%20t1%20%3D%20genericity.getT1()%3B%0A%20%20%20%20String%20t2%20%3D%20genericity.getT2()%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%201.2%20%E5%AE%9A%E4%B9%89%E6%B3%9B%E5%9E%8B%E6%96%B9%E6%B3%95%0A%60%60%60java%0Apublic%20static%20%3CT%3E%20void%20method(T%20t)%20%7B%0A%7D%0A%60%60%60%0A%0A%3E%20%E7%BC%96%E8%AF%91%E5%99%A8%E8%83%BD%E5%A4%9F%E8%87%AA%E5%8A%A8%E6%8E%A8%E6%96%AD%E5%87%BA%E6%B3%9B%E5%9E%8B%E7%B1%BB%E5%9E%8BT%0A%0A%60%60%60java%0Apublic%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20Genericity.method(1)%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%B3%9B%E5%9E%8B%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E4%B9%9F%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20static%20%3CT%3E%20T%20method(T%20t)%20%7B%0A%20%20%20%20return%20t%3B%0A%7D%0A%60%60%60%0A%0A%3E%20%E6%B3%9B%E5%9E%8B%E6%96%B9%E6%B3%95%E4%B9%9F%E6%94%AF%E6%8C%81%E5%AE%9A%E4%B9%89%E5%A4%9A%E4%B8%AA%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20static%20%3CT%2C%20U%3E%20T%20method(T%20t%2C%20U%20u)%20%7B%0A%20%20%20%20return%20t%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%201.3%20%E6%B3%9B%E5%9E%8B%E7%9A%84%E9%99%90%E5%AE%9A%E7%AC%A6%0A%60%60%60java%0Apublic%20static%20%3CT%3E%20T%20min(T%5B%5D%20t)%20%7B%0A%20%20%20%20T%20minimum%20%3D%20t%5B0%5D%3B%0A%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20t.length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20if%20(minimum.compareTo(t%5Bi%5D)%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20minimum%20%3D%20t%5Bi%5D%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20return%20minimum%3B%0A%7D%0A%60%60%60%0A%3E%20%E5%AE%83%E8%83%BD%E5%A4%9F%E5%8F%96%E5%87%BA%E6%95%B0%E7%BB%84t%E4%B8%AD%E7%9A%84%E6%9C%80%E5%B0%8F%E5%80%BC%EF%BC%8C%E7%84%B6%E8%80%8C%E8%BF%99%E6%AE%B5%E7%A8%8B%E5%BA%8F%E6%98%AF%E6%9C%89%E9%97%AE%E9%A2%98%E7%9A%84%EF%BC%8C%E5%9B%A0%E4%B8%BAT%E5%8F%AF%E4%BB%A5%E6%98%AF%E4%BB%BB%E6%84%8F%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BD%86%E4%B8%8D%E6%98%AF%E4%BB%80%E4%B9%88%E5%AF%B9%E8%B1%A1%E9%83%BD%E8%83%BD%E5%A4%9F%E8%B0%83%E7%94%A8compareTo%E6%96%B9%E6%B3%95%E8%BF%9B%E8%A1%8C%E6%AF%94%E8%BE%83%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%EF%BC%8C%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E5%AF%B9%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8FT%E8%BF%9B%E8%A1%8C%E9%99%90%E5%AE%9A%EF%BC%8C%E9%99%90%E5%AE%9A%E4%B8%BA%E5%AE%9E%E7%8E%B0%E4%BA%86Comparable%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60java%0Apublic%20static%20%3CT%20extends%20Comparable%3E%20T%20min(T%5B%5D%20t)%20%7B%0A%20%20%20%20T%20minimum%20%3D%20t%5B0%5D%3B%0A%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20t.length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20if%20(minimum.compareTo(t%5Bi%5D)%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20minimum%20%3D%20t%5Bi%5D%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20return%20minimum%3B%0A%7D%0A%60%60%60%0A%3E%20%E4%B8%80%E4%B8%AA%E6%B3%9B%E5%9E%8B%E6%96%B9%E6%B3%95%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%AF%B9%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E8%BF%9B%E8%A1%8C%E5%A4%9A%E4%B8%AA%E9%99%90%E5%AE%9A%0A%60%60%60java%0A%20public%20static%20%3CT%20extends%20Comparable%20%26%20Serializable%3E%20T%20min(T%5B%5D%20t)%20%7B%0A%20%20%20%20......%0A%20%7D%0A%60%60%60%0A%0A%23%23%23%23%201.4%20%E6%B3%9B%E5%9E%8B%E6%93%A6%E9%99%A4%0A%3E%20%E6%B3%9B%E5%9E%8B%E4%BB%85%E4%BB%85%E6%98%AF%E5%9C%A8%E7%BC%96%E8%AF%91%E6%9C%9F%E9%97%B4%E8%B5%B7%E4%BD%9C%E7%94%A8%EF%BC%8C%E7%9B%AE%E7%9A%84%E6%98%AF%E8%AE%A9%E7%A8%8B%E5%BA%8F%E5%91%98%E5%9C%A8%E7%BC%96%E8%AF%91%E6%9C%9F%E9%97%B4%E5%B0%B1%E9%81%BF%E5%85%8D%E5%8F%91%E7%94%9F%E4%B8%80%E4%BA%9B%E7%B1%BB%E5%9E%8B%E4%B8%8D%E5%AF%B9%E5%BA%94%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E8%80%8C%E5%9C%A8%E8%BF%90%E8%A1%8C%E9%98%B6%E6%AE%B5%EF%BC%8C%E6%B3%9B%E5%9E%8B%E6%98%AF%E6%A0%B9%E6%9C%AC%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%9A%84%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%99%9A%E6%8B%9F%E6%9C%BA%E4%BC%9A%E5%AF%B9%E6%B3%9B%E5%9E%8B%E8%BF%9B%E8%A1%8C%E6%93%A6%E9%99%A4%E3%80%82%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%8F%8D%E5%B0%84%E8%BF%9B%E8%A1%8C%E9%AA%8C%E8%AF%81%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%8F%8D%E5%B0%84%E6%98%AF%E4%BD%9C%E7%94%A8%E5%9C%A8%E8%BF%90%E8%A1%8C%E9%98%B6%E6%AE%B5%E7%9A%84%EF%BC%9A%0A%60%60%60java%0Apublic%20static%20void%20main(String%5B%5D%20args)%20throws%20Exception%20%7B%0A%20%20%20%20List%3CInteger%3E%20list%20%3D%20new%20ArrayList%3C%3E()%3B%0A%20%20%20%20list.add(1)%3B%0A%20%20%20%20Method%20addMethod%20%3D%20list.getClass().getDeclaredMethod(%22add%22%2CObject.class)%3B%0A%20%20%20%20addMethod.invoke(list%2C%222%22)%3B%0A%20%20%20%20addMethod.invoke(list%2Ctrue)%3B%0A%20%20%20%20addMethod.invoke(list%2C3.2f)%3B%0A%20%20%20%20System.out.println(list)%3B%0A%7D%0A%60%60%60%0A%3E%20%E8%8B%A5%E6%98%AF%E9%80%9A%E8%BF%87%E5%8F%8D%E5%B0%84%E8%83%BD%E5%A4%9F%E5%B0%86%E8%BF%99%E4%BA%9B%E9%9D%9EInteger%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%80%BC%E5%AD%98%E5%85%A5list%EF%BC%8C%E5%88%99%E8%AF%B4%E6%98%8E%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%9C%9F%E9%97%B4%E7%A1%AE%E5%AE%9E%E6%98%AF%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%B3%9B%E5%9E%8B%E6%A3%80%E6%9F%A5%E7%9A%84%EF%BC%8C%E8%BF%90%E8%A1%8C%E7%BB%93%E6%9E%9C%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60%0A%5B1%2C%202%2C%20true%2C%203.2%5D%0A%60%60%60%0A%0A%3E%20%E6%B3%9B%E5%9E%8B%E6%93%A6%E9%99%A4%E4%B9%9F%E4%BD%93%E7%8E%B0%E5%9C%A8%E6%B3%9B%E5%9E%8B%E6%96%B9%E6%B3%95%E4%B8%AD%0A%0A%60%60%60java%0A%20public%20static%20%3CT%20extends%20Comparable%3E%20T%20min(T%5B%5D%20t)%20%7B%0A%20%20%20%20......%0A%20%7D%0A%60%60%60%0A%0A%3E%20%E5%BD%93%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E6%9C%9F%E9%97%B4%EF%BC%8C%E6%B3%9B%E5%9E%8B%E4%BC%9A%E8%A2%AB%E6%93%A6%E9%99%A4%EF%BC%8C%E6%AD%A4%E6%97%B6%E6%96%B9%E6%B3%95%E5%8F%98%E4%B8%BA%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60java%0Apublic%20static%20Comparable%20min(Comparable%20t)%20%7B%0A%20%20%20%20......%0A%7D%0A%60%60%60%0A%3E%20%E8%BF%99%E4%B9%9F%E5%B0%B1%E6%98%AF%E4%B8%BA%E4%BB%80%E4%B9%88%E7%B1%BB%E5%9E%8B%E9%99%90%E5%AE%9A%E8%83%BD%E5%A4%9F%E7%94%9F%E6%95%88%E7%9A%84%E5%8E%9F%E5%9B%A0%E4%BA%86%EF%BC%8C%E9%80%9A%E8%BF%87%E6%B3%9B%E5%9E%8B%E6%93%A6%E9%99%A4%E5%90%8E%EF%BC%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E5%B0%B1%E5%8F%AA%E8%83%BD%E6%8E%A5%E6%94%B6%E5%92%8C%E8%BF%94%E5%9B%9EComparable%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%AE%9E%E7%8E%B0%E7%B1%BB%E3%80%82%0A%0A%23%23%23%23%201.5%20%E6%B3%9B%E5%9E%8B%E9%80%9A%E9%85%8D%E7%AC%A6%0A%3E%20%E5%9B%BA%E5%AE%9A%E7%9A%84%E6%B3%9B%E5%9E%8B%E7%B1%BB%E5%9E%8B%E6%98%BE%E7%84%B6%E6%97%A0%E6%B3%95%E6%BB%A1%E8%B6%B3%E5%A4%8D%E6%9D%82%E5%A4%9A%E5%8F%98%E7%9A%84%E9%9C%80%E6%B1%82%EF%BC%8C%E4%B8%BA%E6%AD%A4%EF%BC%8C%E6%B3%9B%E5%9E%8B%E8%AE%BE%E8%AE%A1%E8%80%85%E4%BB%AC%E8%BF%98%E6%8F%90%E4%BE%9B%E4%BA%86%E6%B3%9B%E5%9E%8B%E9%80%9A%E9%85%8D%E7%AC%A6%EF%BC%8C%E5%A6%82%EF%BC%9A%0A%0A%60%60%60java%0A%2F%2F%E5%AE%83%E8%A1%A8%E7%A4%BA%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E5%BF%85%E9%A1%BB%E6%98%AFPerson%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%AD%90%E7%B1%BB%0AGenericity%3C%3F%20extends%20Person%3E%0A%60%60%60%0A%0A%60%60%60java%0A%2F%2F%E6%AD%A4%E6%97%B6%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E5%B0%B1%E5%BF%85%E9%A1%BB%E6%98%AFPerson%E7%B1%BB%E7%9A%84%E8%B6%85%E7%B1%BB%0AGenericity%3C%3F%20super%20Person%3E%0A%60%60%60%0A%0A%3E%20%E8%BF%98%E6%9C%89%E4%B8%80%E7%A7%8D%E6%83%85%E5%86%B5%E6%98%AF%E6%97%A0%E9%99%90%E5%AE%9A%E9%80%9A%E9%85%8D%E7%AC%A6%EF%BC%9A%0A%60%60%60java%0AGenericity%3C%3F%3E%0A%60%60%60%0A%3E%20%E5%AE%83%E5%92%8C%20%60Genericity%3CT%3E%60%20%E9%9D%9E%E5%B8%B8%E7%9B%B8%E4%BC%BC%EF%BC%8C%E4%BD%86%E5%8F%88%E6%9C%89%E4%B8%8D%E5%90%8C%EF%BC%8C%60Genericity%3C%3F%3E%60%20%E7%9A%84setter%E6%96%B9%E6%B3%95%E4%B8%8D%E8%83%BD%E8%A2%AB%E8%B0%83%E7%94%A8%EF%BC%8Cgetter%E6%96%B9%E6%B3%95%E5%8F%AA%E8%83%BD%E8%BF%94%E5%9B%9EObject%E7%B1%BB%E5%9E%8B%EF%BC%8C%E4%B8%8D%E8%BF%87%E8%BF%99%E7%A7%8D%E6%96%B9%E5%BC%8F%E7%9A%84%E7%94%A8%E6%B3%95%E8%BE%83%E5%B0%91%EF%BC%8C%E5%8F%AF%E8%83%BD%E4%BC%9A%E8%A2%AB%E7%94%A8%E6%9D%A5%E5%88%A4%E6%96%AD%E7%A9%BA%E5%BC%95%E7%94%A8%EF%BC%9A%0A%60%60%60java%0Apublic%20static%20boolean%20isNull(Genericity%3C%3F%3E%20genericity)%7B%0A%20%20%20%20return%20genericity.getContent()%3B%0A%7D%0A%60%60%60

Oberver设计模式

创建时间:2022/1/11 11:05
作者:Chris


Transient的作用及使用方法

创建时间:2022/1/7 17:31
更新时间:2022/1/11 10:48
作者:Chris
来源:https://www.cnblogs.com/lanxuezaipiao/p/3369962.html

1 是什么

transient使用小结

  • 一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。
  • 然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。
    换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

2 能干什么

实现了Serilizable接口,在不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

3 怎么玩

3.1 非静态类属性

@Test
public void testTransient() {
    User user = new User("Alexia", "123456");

    System.out.println("read before Serializable: ");
    System.out.println("username: " + user.getName());
    System.err.println("password: " + user.getPassword());

    try {
        ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("C:/user.txt"));
        os.writeObject(user); // 将User对象写进文件
        os.flush();
        os.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        ObjectInputStream is = new ObjectInputStream(new FileInputStream("C:/user.txt"));
        user = (User) is.readObject(); // 从流中读取User的数据
        is.close();

        System.out.println("\nread after Serializable: ");
        System.out.println("username: " + user.getName());
        System.err.println("password: " + user.getPassword());

    } catch (ClassNotFoundException | IOException e) {
        e.printStackTrace();
    }
}

3.2 静态变量

@Test
public void testTransient() {
    User user = new User("123456");

    User.name = "Alexia";

    System.out.println("read before Serializable: ");
    System.out.println("username: " + User.name);
    System.err.println("password: " + user.getPassword());

    try {
        ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("C:/user.txt"));
        os.writeObject(user); // 将User对象写进文件
        os.flush();
        os.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        // 在反序列化之前改变username的值
        User.name = "Chris";

        ObjectInputStream is = new ObjectInputStream(new FileInputStream("C:/user.txt"));
        user = (User) is.readObject(); // 从流中读取User的数据
        is.close();

        System.out.println("\nread after Serializable: ");
        System.out.println("username: " + User.name);
        System.err.println("password: " + user.getPassword());

    } catch (ClassNotFoundException | IOException e) {
        e.printStackTrace();
    }
}

@Data
@AllArgsConstructor
public class User implements Serializable {
    public static String name;
    private transient String password;
}

%5Btoc%5D%0A%0A%23%23%201%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%5Btransient%E4%BD%BF%E7%94%A8%E5%B0%8F%E7%BB%93%5D(https%3A%2F%2Fwww.cnblogs.com%2Flanxuezaipiao%2Fp%2F3369962.html)%0A%0A%3E-%20%20%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%8F%AA%E8%A6%81%E5%AE%9E%E7%8E%B0%E4%BA%86Serilizable%E6%8E%A5%E5%8F%A3%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%A2%AB%E5%BA%8F%E5%88%97%E5%8C%96%EF%BC%8Cjava%E7%9A%84%E8%BF%99%E7%A7%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%A8%A1%E5%BC%8F%E4%B8%BA%E5%BC%80%E5%8F%91%E8%80%85%E6%8F%90%E4%BE%9B%E4%BA%86%E5%BE%88%E5%A4%9A%E4%BE%BF%E5%88%A9%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E4%B8%8D%E5%BF%85%E5%85%B3%E7%B3%BB%E5%85%B7%E4%BD%93%E5%BA%8F%E5%88%97%E5%8C%96%E7%9A%84%E8%BF%87%E7%A8%8B%EF%BC%8C%E5%8F%AA%E8%A6%81%E8%BF%99%E4%B8%AA%E7%B1%BB%E5%AE%9E%E7%8E%B0%E4%BA%86Serilizable%E6%8E%A5%E5%8F%A3%EF%BC%8C%E8%BF%99%E4%B8%AA%E7%B1%BB%E7%9A%84%E6%89%80%E6%9C%89%E5%B1%9E%E6%80%A7%E5%92%8C%E6%96%B9%E6%B3%95%E9%83%BD%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%BA%8F%E5%88%97%E5%8C%96%E3%80%82%0A%0A%3E-%20%E7%84%B6%E8%80%8C%E5%9C%A8%E5%AE%9E%E9%99%85%E5%BC%80%E5%8F%91%E8%BF%87%E7%A8%8B%E4%B8%AD%EF%BC%8C%E6%88%91%E4%BB%AC%E5%B8%B8%E5%B8%B8%E4%BC%9A%E9%81%87%E5%88%B0%E8%BF%99%E6%A0%B7%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E8%BF%99%E4%B8%AA%E7%B1%BB%E7%9A%84%E6%9C%89%E4%BA%9B%E5%B1%9E%E6%80%A7%E9%9C%80%E8%A6%81%E5%BA%8F%E5%88%97%E5%8C%96%EF%BC%8C%E8%80%8C%E5%85%B6%E4%BB%96%E5%B1%9E%E6%80%A7%E4%B8%8D%E9%9C%80%E8%A6%81%E8%A2%AB%E5%BA%8F%E5%88%97%E5%8C%96%EF%BC%8C%E6%89%93%E4%B8%AA%E6%AF%94%E6%96%B9%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E7%94%A8%E6%88%B7%E6%9C%89%E4%B8%80%E4%BA%9B%E6%95%8F%E6%84%9F%E4%BF%A1%E6%81%AF%EF%BC%88%E5%A6%82%E5%AF%86%E7%A0%81%EF%BC%8C%E9%93%B6%E8%A1%8C%E5%8D%A1%E5%8F%B7%E7%AD%89%EF%BC%89%EF%BC%8C%E4%B8%BA%E4%BA%86%E5%AE%89%E5%85%A8%E8%B5%B7%E8%A7%81%EF%BC%8C%E4%B8%8D%E5%B8%8C%E6%9C%9B%E5%9C%A8%E7%BD%91%E7%BB%9C%E6%93%8D%E4%BD%9C%EF%BC%88%E4%B8%BB%E8%A6%81%E6%B6%89%E5%8F%8A%E5%88%B0%E5%BA%8F%E5%88%97%E5%8C%96%E6%93%8D%E4%BD%9C%EF%BC%8C%E6%9C%AC%E5%9C%B0%E5%BA%8F%E5%88%97%E5%8C%96%E7%BC%93%E5%AD%98%E4%B9%9F%E9%80%82%E7%94%A8%EF%BC%89%E4%B8%AD%E8%A2%AB%E4%BC%A0%E8%BE%93%EF%BC%8C%E8%BF%99%E4%BA%9B%E4%BF%A1%E6%81%AF%E5%AF%B9%E5%BA%94%E7%9A%84%E5%8F%98%E9%87%8F%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%8A%A0%E4%B8%8Atransient%E5%85%B3%E9%94%AE%E5%AD%97%E3%80%82%0A%E6%8D%A2%E5%8F%A5%E8%AF%9D%E8%AF%B4%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%AD%97%E6%AE%B5%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E4%BB%85%E5%AD%98%E4%BA%8E%E8%B0%83%E7%94%A8%E8%80%85%E7%9A%84%E5%86%85%E5%AD%98%E4%B8%AD%E8%80%8C%E4%B8%8D%E4%BC%9A%E5%86%99%E5%88%B0%E7%A3%81%E7%9B%98%E9%87%8C%E6%8C%81%E4%B9%85%E5%8C%96%E3%80%82%0A%0A%23%23%202%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%3E%20%E5%AE%9E%E7%8E%B0%E4%BA%86Serilizable%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%9C%A8%E4%B8%8D%E9%9C%80%E8%A6%81%E5%BA%8F%E5%88%97%E5%8C%96%E7%9A%84%E5%B1%9E%E6%80%A7%E5%89%8D%E6%B7%BB%E5%8A%A0%E5%85%B3%E9%94%AE%E5%AD%97transient%EF%BC%8C%E5%BA%8F%E5%88%97%E5%8C%96%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%B1%9E%E6%80%A7%E5%B0%B1%E4%B8%8D%E4%BC%9A%E5%BA%8F%E5%88%97%E5%8C%96%E5%88%B0%E6%8C%87%E5%AE%9A%E7%9A%84%E7%9B%AE%E7%9A%84%E5%9C%B0%E4%B8%AD%E3%80%82%0A%0A-%201.%20%20%E8%A2%ABtransient%E4%BF%AE%E9%A5%B0%E7%9A%84%E5%8F%98%E9%87%8F%EF%BC%8C%E5%B0%86%E4%B8%8D%E5%86%8D%E6%98%AF%E5%AF%B9%E8%B1%A1%E6%8C%81%E4%B9%85%E5%8C%96%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%EF%BC%8C%E8%AF%A5%E5%8F%98%E9%87%8F%E5%86%85%E5%AE%B9%E5%9C%A8%E5%BA%8F%E5%88%97%E5%8C%96%E5%90%8E%E6%97%A0%E6%B3%95%E8%8E%B7%E5%BE%97%E8%AE%BF%E9%97%AE%E3%80%82%0A-%202.%20%20transient%20%E5%85%B3%E9%94%AE%E5%AD%97%E5%8F%AA%E8%83%BD%E4%BF%AE%E9%A5%B0%E5%8F%98%E9%87%8F%EF%BC%8C%E8%80%8C%E4%B8%8D%E8%83%BD%E4%BF%AE%E9%A5%B0%E6%96%B9%E6%B3%95%E5%92%8C%E7%B1%BB%E3%80%82%0A%20%20%E6%B3%A8%E6%84%8F%EF%BC%8C%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E6%98%AF%E4%B8%8D%E8%83%BD%E8%A2%ABtransient%E5%85%B3%E9%94%AE%E5%AD%97%E4%BF%AE%E9%A5%B0%E7%9A%84%E3%80%82%0A%20%20%E5%8F%98%E9%87%8F%E5%A6%82%E6%9E%9C%E6%98%AF%E7%94%A8%E6%88%B7%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%8F%98%E9%87%8F%EF%BC%8C%E5%88%99%E8%AF%A5%E7%B1%BB%E9%9C%80%E8%A6%81%E5%AE%9E%E7%8E%B0Serializable%E6%8E%A5%E5%8F%A3%E3%80%82%0A-%203.%20%20%E4%B8%80%E4%B8%AA%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E4%B8%8D%E7%AE%A1%E6%98%AF%E5%90%A6%E8%A2%ABtransient%E4%BF%AE%E9%A5%B0%EF%BC%8C%E5%9D%87%E4%B8%8D%E8%83%BD%E8%A2%AB%E5%BA%8F%E5%88%97%E5%8C%96%E3%80%82%0A%20%20%3E%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%90%8E%E7%B1%BB%E4%B8%ADstatic%E5%9E%8B%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%E4%B8%BA%E5%BD%93%E5%89%8DJVM%E4%B8%AD%E5%AF%B9%E5%BA%94static%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%80%BC%E6%98%AFJVM%E4%B8%AD%E7%9A%84%E4%B8%8D%E6%98%AF%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%BE%97%E5%87%BA%E7%9A%84%0A%0A%0A%23%23%203%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%23%23%23%23%203.1%20%E9%9D%9E%E9%9D%99%E6%80%81%E7%B1%BB%E5%B1%9E%E6%80%A7%0A%60%60%60java%0A%40Test%0Apublic%20void%20testTransient()%20%7B%0A%20%20%20%20User%20user%20%3D%20new%20User(%22Alexia%22%2C%20%22123456%22)%3B%0A%0A%20%20%20%20System.out.println(%22read%20before%20Serializable%3A%20%22)%3B%0A%20%20%20%20System.out.println(%22username%3A%20%22%20%2B%20user.getName())%3B%0A%20%20%20%20System.err.println(%22password%3A%20%22%20%2B%20user.getPassword())%3B%0A%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20ObjectOutputStream%20os%20%3D%20new%20ObjectOutputStream(new%20FileOutputStream(%22C%3A%2Fuser.txt%22))%3B%0A%20%20%20%20%20%20%20%20os.writeObject(user)%3B%20%2F%2F%20%E5%B0%86User%E5%AF%B9%E8%B1%A1%E5%86%99%E8%BF%9B%E6%96%87%E4%BB%B6%0A%20%20%20%20%20%20%20%20os.flush()%3B%0A%20%20%20%20%20%20%20%20os.close()%3B%0A%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%7D%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20ObjectInputStream%20is%20%3D%20new%20ObjectInputStream(new%20FileInputStream(%22C%3A%2Fuser.txt%22))%3B%0A%20%20%20%20%20%20%20%20user%20%3D%20(User)%20is.readObject()%3B%20%2F%2F%20%E4%BB%8E%E6%B5%81%E4%B8%AD%E8%AF%BB%E5%8F%96User%E7%9A%84%E6%95%B0%E6%8D%AE%0A%20%20%20%20%20%20%20%20is.close()%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(%22%5Cnread%20after%20Serializable%3A%20%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22username%3A%20%22%20%2B%20user.getName())%3B%0A%20%20%20%20%20%20%20%20System.err.println(%22password%3A%20%22%20%2B%20user.getPassword())%3B%0A%0A%20%20%20%20%7D%20catch%20(ClassNotFoundException%20%7C%20IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A!%5B3bcf3424341395458ad0fbb1efafafbd.png%5D(en-resource%3A%2F%2Fdatabase%2F1286%3A1)%0A%0A%23%23%23%23%203.2%20%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%0A%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20testTransient()%20%7B%0A%20%20%20%20User%20user%20%3D%20new%20User(%22123456%22)%3B%0A%0A%20%20%20%20User.name%20%3D%20%22Alexia%22%3B%0A%0A%20%20%20%20System.out.println(%22read%20before%20Serializable%3A%20%22)%3B%0A%20%20%20%20System.out.println(%22username%3A%20%22%20%2B%20User.name)%3B%0A%20%20%20%20System.err.println(%22password%3A%20%22%20%2B%20user.getPassword())%3B%0A%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20ObjectOutputStream%20os%20%3D%20new%20ObjectOutputStream(new%20FileOutputStream(%22C%3A%2Fuser.txt%22))%3B%0A%20%20%20%20%20%20%20%20os.writeObject(user)%3B%20%2F%2F%20%E5%B0%86User%E5%AF%B9%E8%B1%A1%E5%86%99%E8%BF%9B%E6%96%87%E4%BB%B6%0A%20%20%20%20%20%20%20%20os.flush()%3B%0A%20%20%20%20%20%20%20%20os.close()%3B%0A%20%20%20%20%7D%20catch%20(IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%7D%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E5%9C%A8%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B9%8B%E5%89%8D%E6%94%B9%E5%8F%98username%E7%9A%84%E5%80%BC%0A%20%20%20%20%20%20%20%20User.name%20%3D%20%22Chris%22%3B%0A%0A%20%20%20%20%20%20%20%20ObjectInputStream%20is%20%3D%20new%20ObjectInputStream(new%20FileInputStream(%22C%3A%2Fuser.txt%22))%3B%0A%20%20%20%20%20%20%20%20user%20%3D%20(User)%20is.readObject()%3B%20%2F%2F%20%E4%BB%8E%E6%B5%81%E4%B8%AD%E8%AF%BB%E5%8F%96User%E7%9A%84%E6%95%B0%E6%8D%AE%0A%20%20%20%20%20%20%20%20is.close()%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(%22%5Cnread%20after%20Serializable%3A%20%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22username%3A%20%22%20%2B%20User.name)%3B%0A%20%20%20%20%20%20%20%20System.err.println(%22password%3A%20%22%20%2B%20user.getPassword())%3B%0A%0A%20%20%20%20%7D%20catch%20(ClassNotFoundException%20%7C%20IOException%20e)%20%7B%0A%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%40Data%0A%40AllArgsConstructor%0Apublic%20class%20User%20implements%20Serializable%20%7B%0A%20%20%20%20public%20static%20String%20name%3B%0A%20%20%20%20private%20transient%20String%20password%3B%0A%7D%0A%60%60%60%0A%0A!%5B462ad9c96571f2a81083b5275251e4e5.png%5D(en-resource%3A%2F%2Fdatabase%2F1288%3A1)%0A

command

创建时间:2020/12/29 19:57
更新时间:2023/3/26 14:08
作者:Chris
来源:https://blog.csdn.net/maxiaoyin111111/article/details/81908172

1. find

在abc.txt中查找字符串abc的行。

find "abc" d:\abc.txt

/I 搜索字符串时忽略大小写。

find /i "abc" d:\abc.txt

参数/i代表的是“Ignore”(忽略),也就是忽略大小写。通过/I 参数可以不区分要查找的字符串“abc”的大小写。

/N 显示行号

find /n "abc" d:\abc.txt

参数/n代表英语单词“Number”(号码).。通过/n参数我们可以查找到字符串"abc"所在的行号。

2. findstr

要搜索包含单词 Windows 的当前目录和所有子目录中的每个文件,不考虑字母大小写,请键入如下

findstr /s /i Windows  *.*

3. 进程和端口号

3.1 查看所有端口占用情况

 netstat -ano

3.1 查看指定端口占用情况

netstat -ano | findstr "端口号"

netstat -ano | findstr 6400

3.3 使用tasklist查看 PID 对应的进程名

tasklist | findstr "PID号"
tasklist | findstr "java"

3.3 结束进程

/PID processid 指定要终止的进程的 PID。 使用 TaskList 取得 PID。
/T 终止指定的进程和由它启用的子进程。
/F 指定强制终止进程

TASKKILL /T /PID 1230 /PID 1241 /PID 1253 
taskkill -t -f -pid 13500

%5Btoc%5D%0A%0A%23%23%201.%20find%0A%0A%0A%3E%20%E5%9C%A8abc.txt%E4%B8%AD%E6%9F%A5%E6%89%BE%E5%AD%97%E7%AC%A6%E4%B8%B2abc%E7%9A%84%E8%A1%8C%E3%80%82%0A%60%60%60%0Afind%20%22abc%22%20d%3A%5Cabc.txt%0A%60%60%60%0A%0A%3E%20%2FI%20%E6%90%9C%E7%B4%A2%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%97%B6%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99%E3%80%82%0A%60%60%60%0Afind%20%2Fi%20%22abc%22%20d%3A%5Cabc.txt%0A%60%60%60%0A%3E%20%E5%8F%82%E6%95%B0%2Fi%E4%BB%A3%E8%A1%A8%E7%9A%84%E6%98%AF%E2%80%9CIgnore%E2%80%9D(%E5%BF%BD%E7%95%A5)%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99%E3%80%82%E9%80%9A%E8%BF%87%2FI%20%E5%8F%82%E6%95%B0%E5%8F%AF%E4%BB%A5%E4%B8%8D%E5%8C%BA%E5%88%86%E8%A6%81%E6%9F%A5%E6%89%BE%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E2%80%9Cabc%E2%80%9D%E7%9A%84%E5%A4%A7%E5%B0%8F%E5%86%99%E3%80%82%0A%0A%3E%20%2FN%20%E6%98%BE%E7%A4%BA%E8%A1%8C%E5%8F%B7%0A%60%60%60%0Afind%20%2Fn%20%22abc%22%20d%3A%5Cabc.txt%0A%60%60%60%0A%3E%20%E5%8F%82%E6%95%B0%2Fn%E4%BB%A3%E8%A1%A8%E8%8B%B1%E8%AF%AD%E5%8D%95%E8%AF%8D%E2%80%9CNumber%E2%80%9D(%E5%8F%B7%E7%A0%81).%E3%80%82%E9%80%9A%E8%BF%87%2Fn%E5%8F%82%E6%95%B0%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E6%9F%A5%E6%89%BE%E5%88%B0%E5%AD%97%E7%AC%A6%E4%B8%B2%22abc%22%E6%89%80%E5%9C%A8%E7%9A%84%E8%A1%8C%E5%8F%B7%E3%80%82%0A%0A%23%23%202.%20findstr%0A%0A%3E%20%E8%A6%81%E6%90%9C%E7%B4%A2%E5%8C%85%E5%90%AB%E5%8D%95%E8%AF%8D%20Windows%20%E7%9A%84%E5%BD%93%E5%89%8D%E7%9B%AE%E5%BD%95%E5%92%8C%E6%89%80%E6%9C%89%E5%AD%90%E7%9B%AE%E5%BD%95%E4%B8%AD%E7%9A%84%E6%AF%8F%E4%B8%AA%E6%96%87%E4%BB%B6%EF%BC%8C%E4%B8%8D%E8%80%83%E8%99%91%E5%AD%97%E6%AF%8D%E5%A4%A7%E5%B0%8F%E5%86%99%EF%BC%8C%E8%AF%B7%E9%94%AE%E5%85%A5%E5%A6%82%E4%B8%8B%0A%60%60%60%0Afindstr%20%2Fs%20%2Fi%20Windows%20%20*.*%0A%60%60%60%0A%0A%0A%23%23%203.%20%E8%BF%9B%E7%A8%8B%E5%92%8C%E7%AB%AF%E5%8F%A3%E5%8F%B7%0A%0A%0A%23%23%23%23%203.1%20%E6%9F%A5%E7%9C%8B%E6%89%80%E6%9C%89%E7%AB%AF%E5%8F%A3%E5%8D%A0%E7%94%A8%E6%83%85%E5%86%B5%0A%60%60%60%0A%20netstat%20-ano%0A%60%60%60%0A%23%23%23%23%203.1%20%E6%9F%A5%E7%9C%8B%E6%8C%87%E5%AE%9A%E7%AB%AF%E5%8F%A3%E5%8D%A0%E7%94%A8%E6%83%85%E5%86%B5%0A%60%60%60%0Anetstat%20-ano%20%7C%20findstr%20%22%E7%AB%AF%E5%8F%A3%E5%8F%B7%22%0A%60%60%60%0A%3E%20netstat%20-ano%20%7C%20findstr%206400%0A%0A%0A%23%23%23%23%203.3%20%E4%BD%BF%E7%94%A8tasklist%E6%9F%A5%E7%9C%8B%20PID%20%E5%AF%B9%E5%BA%94%E7%9A%84%E8%BF%9B%E7%A8%8B%E5%90%8D%0A%0A!%5B643063464e55de6e9b18b0c752973cc3.png%5D(en-resource%3A%2F%2Fdatabase%2F1401%3A0)%0A%0A%60%60%60%0Atasklist%20%7C%20findstr%20%22PID%E5%8F%B7%22%0Atasklist%20%7C%20findstr%20%22java%22%0A%60%60%60%0A%0A%23%23%23%23%203.3%20%E7%BB%93%E6%9D%9F%E8%BF%9B%E7%A8%8B%0A%3E%20%2FPID%20processid%20%E6%8C%87%E5%AE%9A%E8%A6%81%E7%BB%88%E6%AD%A2%E7%9A%84%E8%BF%9B%E7%A8%8B%E7%9A%84%20PID%E3%80%82%20%E4%BD%BF%E7%94%A8%20TaskList%20%E5%8F%96%E5%BE%97%20PID%E3%80%82%0A%2FT%20%E7%BB%88%E6%AD%A2%E6%8C%87%E5%AE%9A%E7%9A%84%E8%BF%9B%E7%A8%8B%E5%92%8C%E7%94%B1%E5%AE%83%E5%90%AF%E7%94%A8%E7%9A%84%E5%AD%90%E8%BF%9B%E7%A8%8B%E3%80%82%0A%2FF%20%E6%8C%87%E5%AE%9A%E5%BC%BA%E5%88%B6%E7%BB%88%E6%AD%A2%E8%BF%9B%E7%A8%8B%0A%60%60%60%0ATASKKILL%20%2FT%20%2FPID%201230%20%2FPID%201241%20%2FPID%201253%20%0Ataskkill%20-t%20-f%20-pid%2013500%0A%60%60%60%0A!%5Be5ff8f6b84a16c053d16caa35cdf927c.png%5D(en-resource%3A%2F%2Fdatabase%2F1403%3A0)%0A

VMware NAT配置

创建时间:2020/9/18 16:38
更新时间:2020/12/28 10:12
作者:Chris

  1. 关闭宿主机和虚拟机的防火墙(宿主机防火墙可能不需要关闭)

    services.msc

  2. 确保宿主机中的NAT和DHCP服务是开启的

  1. 在虚拟机中的虚拟网络编辑器中找到NAT网络的关键信息

edit -> Visual NetWork Editor

  1. 编辑虚拟机网卡信息

cd /etc/sysconfig/network-scripts
cp ifcfg-ens33 ifcfg-ens33.bak
vi ifcfg-ens33

ens33是网卡的名字,这个在每台机器上可能是不同的。

修改内容如下:

ONBOOT="yes"
BOOTPROTO=static
IPADDR=192.168.174.127  #静态IP
GATEWAY=192.168.174.2  #默认网关, 与NAT设置中的网关一致
NETMASK=255.255.255.0  #子网掩码
DNS1=192.168.174.2        #DNS 配置与GATEWAY一致
DNS2=8.8.8.8                 #DNS 配置
  1. 在宿主机配置NAT网络,找到对应的以太网

  1. 重启虚拟机网络服务

执行service network restart

1.%20%E5%85%B3%E9%97%AD%E5%AE%BF%E4%B8%BB%E6%9C%BA%E5%92%8C%E8%99%9A%E6%8B%9F%E6%9C%BA%E7%9A%84%E9%98%B2%E7%81%AB%E5%A2%99%EF%BC%88%E5%AE%BF%E4%B8%BB%E6%9C%BA%E9%98%B2%E7%81%AB%E5%A2%99%E5%8F%AF%E8%83%BD%E4%B8%8D%E9%9C%80%E8%A6%81%E5%85%B3%E9%97%AD%EF%BC%89%0A%20%20%20%20%3E%20%20%20services.msc%0A2.%20%E7%A1%AE%E4%BF%9D%E5%AE%BF%E4%B8%BB%E6%9C%BA%E4%B8%AD%E7%9A%84NAT%E5%92%8CDHCP%E6%9C%8D%E5%8A%A1%E6%98%AF%E5%BC%80%E5%90%AF%E7%9A%84%0A%0A!%5Bc0af45ebe424fc3473e32d5b9857de22.png%5D(en-resource%3A%2F%2Fdatabase%2F744%3A1)%0A%0A3.%20%E5%9C%A8%E8%99%9A%E6%8B%9F%E6%9C%BA%E4%B8%AD%E7%9A%84%E8%99%9A%E6%8B%9F%E7%BD%91%E7%BB%9C%E7%BC%96%E8%BE%91%E5%99%A8%E4%B8%AD%E6%89%BE%E5%88%B0NAT%E7%BD%91%E7%BB%9C%E7%9A%84%E5%85%B3%E9%94%AE%E4%BF%A1%E6%81%AF%0A%3E%20edit%20-%3E%20Visual%20NetWork%20Editor%0A%0A!%5B3830455929ac6a632442b4dd485adc4a.png%5D(en-resource%3A%2F%2Fdatabase%2F740%3A1)%0A%0A!%5Bb5400c1fad9732dd2f34fe913a745f09.png%5D(en-resource%3A%2F%2Fdatabase%2F743%3A1)%0A%0A4.%20%E7%BC%96%E8%BE%91%E8%99%9A%E6%8B%9F%E6%9C%BA%E7%BD%91%E5%8D%A1%E4%BF%A1%E6%81%AF%0A%0A!%5Be394bf54d9faefa5991757d2cbf49b7b.png%5D(en-resource%3A%2F%2Fdatabase%2F745%3A1)%0A%0A%60%60%60%0Acd%20%2Fetc%2Fsysconfig%2Fnetwork-scripts%0Acp%20ifcfg-ens33%20ifcfg-ens33.bak%0Avi%20ifcfg-ens33%0A%60%60%60%0Aens33%E6%98%AF%E7%BD%91%E5%8D%A1%E7%9A%84%E5%90%8D%E5%AD%97%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%9C%A8%E6%AF%8F%E5%8F%B0%E6%9C%BA%E5%99%A8%E4%B8%8A%E5%8F%AF%E8%83%BD%E6%98%AF%E4%B8%8D%E5%90%8C%E7%9A%84%E3%80%82%0A%0A%E4%BF%AE%E6%94%B9%E5%86%85%E5%AE%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A!%5Bb2110495875ee972404db184399105bf.png%5D(en-resource%3A%2F%2Fdatabase%2F742%3A1)%0A%0A%60%60%60%0AONBOOT%3D%22yes%22%0ABOOTPROTO%3Dstatic%0AIPADDR%3D192.168.174.127%20%20%23%E9%9D%99%E6%80%81IP%0AGATEWAY%3D192.168.174.2%20%20%23%E9%BB%98%E8%AE%A4%E7%BD%91%E5%85%B3%2C%20%E4%B8%8ENAT%E8%AE%BE%E7%BD%AE%E4%B8%AD%E7%9A%84%E7%BD%91%E5%85%B3%E4%B8%80%E8%87%B4%0ANETMASK%3D255.255.255.0%20%20%23%E5%AD%90%E7%BD%91%E6%8E%A9%E7%A0%81%0ADNS1%3D192.168.174.2%20%20%20%20%20%20%20%20%23DNS%20%E9%85%8D%E7%BD%AE%E4%B8%8EGATEWAY%E4%B8%80%E8%87%B4%0ADNS2%3D8.8.8.8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23DNS%20%E9%85%8D%E7%BD%AE%0A%60%60%60%0A%0A5.%20%E5%9C%A8%E5%AE%BF%E4%B8%BB%E6%9C%BA%E9%85%8D%E7%BD%AENAT%E7%BD%91%E7%BB%9C%EF%BC%8C%E6%89%BE%E5%88%B0%E5%AF%B9%E5%BA%94%E7%9A%84%E4%BB%A5%E5%A4%AA%E7%BD%91%0A!%5B7a91e0e878b65a13f6443d58a27fcfc4.png%5D(en-resource%3A%2F%2Fdatabase%2F746%3A1)%0A%0A!%5Ba3a0380e9e62f734b2cf74c4bf819b09.png%5D(en-resource%3A%2F%2Fdatabase%2F741%3A1)%0A%0A6.%20%E9%87%8D%E5%90%AF%E8%99%9A%E6%8B%9F%E6%9C%BA%E7%BD%91%E7%BB%9C%E6%9C%8D%E5%8A%A1%0A%0A%E6%89%A7%E8%A1%8C%60service%20network%20restart%60

SpringBoot集成Redis

创建时间:2020/12/23 18:07
更新时间:2020/12/23 18:25
作者:Chris
来源:https://victor-huihui.gitee.io/2020/03/15/SpringBoot%E6%95%B4%E5%90%88redis/

SpringBoot集成Redis

SpringBoot集成Redis

实际上使用Spring Data Redis操作Redis

1. 建POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hhzhu</groupId>
    <artifactId>redis_practice</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.1.5.RELEASE</version>

    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
		<!--连接池-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>


</project>
2. 写YAM

创建配置文件appliacation.yml

spring:
  redis:
    database: 0
    host: localhost
    port: 6379
3. 启动类
package com.hhzhu;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}
4. 业务类
package com.hhzhu.pojo;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;

@Data
//实现序列化接口,否则无法存入redis
public class Student implements Serializable {
    private Integer id;
    private String name;
    private Double score;
    private Date birthday;
}
5. 创建控制器
package com.hhzhu.controller;

import com.hhzhu.pojo.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

@RestController
public class StudentHandler {

    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/set")
    //Request将json数据转换成java对象
    public void set(@RequestBody Student student){
        redisTemplate.opsForValue().set("student",student);

    }

    @GetMapping("/get/{key}")
    public Student get(@PathVariable("key") String key){
        return (Student) redisTemplate.opsForValue().get(key);
    }

    @DeleteMapping("/delete/{key}")
    public boolean delete(@PathVariable("key") String key){
        redisTemplate.delete(key);
        return redisTemplate.hasKey(key);
    }
}

Redis 5种数据类型

1.字符串
@GetMapping("/string")
public String stringTest(){
    redisTemplate.opsForValue().set("str","Hello world");
    String str = (String) redisTemplate.opsForValue().get("str");
    return str;
}
2.列表
@GetMapping("list")
public List<String> listTest(){
    ListOperations<String,String> listOperations = redisTemplate.opsForList();
    listOperations.leftPush("list","hello");
    listOperations.leftPush("list","world");
    listOperations.rightPush("list","java");
    //返回从左边开始前三个元素值  
    List<String> list = listOperations.range("list",0,2);
    return list;
}
3.集合(set)
@GetMapping("/set")
public Set<String> setTest(){
    SetOperations<String,String> setOperations = redisTemplate.opsForSet();
    setOperations.add("set","Hello");
    setOperations.add("set","Hello");
    setOperations.add("set","world");
    setOperations.add("set","world");
    setOperations.add("set","java");
    setOperations.add("set","java");
  
    Set<String> set = setOperations.members("set");
    return set;
}
4.有序集合
@GetMapping("/zset")
public Set<String> zsetTest(){
    ZSetOperations<String,String> zSetOperations = redisTemplate.opsForZSet();
    zSetOperations.add("zset","Hello",1);
    zSetOperations.add("zset","world",2);
    zSetOperations.add("zset","java",3);
  
    Set<String> set = zSetOperations.range("zset",0,2);
    return set;
}
5.哈希

Hash:key value

HashOperations:key hashkey value

key是每一组数据的ID,hashkey和value是一组完整的HashMap数据,通过key来区分不同的HashMap

HashMap hashMap = new HashMap();
hashMap.put(key1,value1);
HashMap hashMap = new HashMap();
hashMap.put(key2,value2);
HashMap hashMap = new HashMap();
hashMap.put(key3,value3);

HashOperations<String,String,String> hashOperation = redisTemplate.opsForHash();
hashOperation.put(hashMap1,key1,value1);
hashOperation.put(hashMap2,key2,value2);
hashOperation.put(hashMap3,key3,value3);


@GetMapping("/hash")
public void hashTest(){
    HashOperations<String,String,String> hashOperations = redisTemplate.opsForHash();
    hashOperations.put("key","hashKey","Hello");
    System.out.println(hashOperations.get("key","hashKey"));
    
}
SpringBoot%E9%9B%86%E6%88%90Redis%0A%0A%23%23%23%23%20SpringBoot%E9%9B%86%E6%88%90Redis%0A%0A%3E%20%E5%AE%9E%E9%99%85%E4%B8%8A%E4%BD%BF%E7%94%A8Spring%20Data%20Redis%E6%93%8D%E4%BD%9CRedis%0A%0A%23%23%23%23%23%201.%20%E5%BB%BAPOM%0A%0A%60%60%60xml%0A%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3Cproject%20xmlns%3D%22http%3A%2F%2Fmaven.apache.org%2FPOM%2F4.0.0%22%0A%20%20%20%20%20%20%20%20%20xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22%0A%20%20%20%20%20%20%20%20%20xsi%3AschemaLocation%3D%22http%3A%2F%2Fmaven.apache.org%2FPOM%2F4.0.0%20http%3A%2F%2Fmaven.apache.org%2Fxsd%2Fmaven-4.0.0.xsd%22%3E%0A%20%20%20%20%3CmodelVersion%3E4.0.0%3C%2FmodelVersion%3E%0A%0A%20%20%20%20%3CgroupId%3Ecom.hhzhu%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Eredis_practice%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E1.0-SNAPSHOT%3C%2Fversion%3E%0A%0A%20%20%20%20%3Cparent%3E%0A%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-parent%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%3Cversion%3E2.1.5.RELEASE%3C%2Fversion%3E%0A%0A%20%20%20%20%3C%2Fparent%3E%0A%0A%20%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-data-redis%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%09%09%3C!--%E8%BF%9E%E6%8E%A5%E6%B1%A0--%3E%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.commons%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ecommons-pool2%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.projectlombok%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Elombok%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%3C%2Fdependencies%3E%0A%0A%0A%3C%2Fproject%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%202.%20%E5%86%99YAM%0A%0A%3E%20%E5%88%9B%E5%BB%BA%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6appliacation.yml%0A%0A%60%60%60yml%0Aspring%3A%0A%20%20redis%3A%0A%20%20%20%20database%3A%200%0A%20%20%20%20host%3A%20localhost%0A%20%20%20%20port%3A%206379%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%203.%20%E5%90%AF%E5%8A%A8%E7%B1%BB%0A%0A%60%60%60java%0Apackage%20com.hhzhu%3B%0A%0Aimport%20org.springframework.boot.SpringApplication%3B%0Aimport%20org.springframework.boot.autoconfigure.SpringBootApplication%3B%0A%0A%40SpringBootApplication%0Apublic%20class%20Application%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20SpringApplication.run(Application.class%2Cargs)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%204.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%60%60%60java%0Apackage%20com.hhzhu.pojo%3B%0A%0Aimport%20lombok.Data%3B%0A%0Aimport%20java.io.Serializable%3B%0Aimport%20java.util.Date%3B%0A%0A%40Data%0A%2F%2F%E5%AE%9E%E7%8E%B0%E5%BA%8F%E5%88%97%E5%8C%96%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%90%A6%E5%88%99%E6%97%A0%E6%B3%95%E5%AD%98%E5%85%A5redis%0Apublic%20class%20Student%20implements%20Serializable%20%7B%0A%20%20%20%20private%20Integer%20id%3B%0A%20%20%20%20private%20String%20name%3B%0A%20%20%20%20private%20Double%20score%3B%0A%20%20%20%20private%20Date%20birthday%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%205.%20%E5%88%9B%E5%BB%BA%E6%8E%A7%E5%88%B6%E5%99%A8%0A%0A%60%60%60java%0Apackage%20com.hhzhu.controller%3B%0A%0Aimport%20com.hhzhu.pojo.Student%3B%0Aimport%20org.springframework.beans.factory.annotation.Autowired%3B%0Aimport%20org.springframework.data.redis.core.RedisTemplate%3B%0Aimport%20org.springframework.web.bind.annotation.*%3B%0A%0A%40RestController%0Apublic%20class%20StudentHandler%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20RedisTemplate%20redisTemplate%3B%0A%0A%20%20%20%20%40PostMapping(%22%2Fset%22)%0A%20%20%20%20%2F%2FRequest%E5%B0%86json%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2%E6%88%90java%E5%AF%B9%E8%B1%A1%0A%20%20%20%20public%20void%20set(%40RequestBody%20Student%20student)%7B%0A%20%20%20%20%20%20%20%20redisTemplate.opsForValue().set(%22student%22%2Cstudent)%3B%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40GetMapping(%22%2Fget%2F%7Bkey%7D%22)%0A%20%20%20%20public%20Student%20get(%40PathVariable(%22key%22)%20String%20key)%7B%0A%20%20%20%20%20%20%20%20return%20(Student)%20redisTemplate.opsForValue().get(key)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40DeleteMapping(%22%2Fdelete%2F%7Bkey%7D%22)%0A%20%20%20%20public%20boolean%20delete(%40PathVariable(%22key%22)%20String%20key)%7B%0A%20%20%20%20%20%20%20%20redisTemplate.delete(key)%3B%0A%20%20%20%20%20%20%20%20return%20redisTemplate.hasKey(key)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%20Redis%205%E7%A7%8D%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%0A%0A%23%23%23%23%23%201.%E5%AD%97%E7%AC%A6%E4%B8%B2%0A%0A%60%60%60java%0A%40GetMapping(%22%2Fstring%22)%0Apublic%20String%20stringTest()%7B%0A%20%20%20%20redisTemplate.opsForValue().set(%22str%22%2C%22Hello%20world%22)%3B%0A%20%20%20%20String%20str%20%3D%20(String)%20redisTemplate.opsForValue().get(%22str%22)%3B%0A%20%20%20%20return%20str%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%202.%E5%88%97%E8%A1%A8%0A%0A%60%60%60java%0A%40GetMapping(%22list%22)%0Apublic%20List%3CString%3E%20listTest()%7B%0A%20%20%20%20ListOperations%3CString%2CString%3E%20listOperations%20%3D%20redisTemplate.opsForList()%3B%0A%20%20%20%20listOperations.leftPush(%22list%22%2C%22hello%22)%3B%0A%20%20%20%20listOperations.leftPush(%22list%22%2C%22world%22)%3B%0A%20%20%20%20listOperations.rightPush(%22list%22%2C%22java%22)%3B%0A%20%20%20%20%2F%2F%E8%BF%94%E5%9B%9E%E4%BB%8E%E5%B7%A6%E8%BE%B9%E5%BC%80%E5%A7%8B%E5%89%8D%E4%B8%89%E4%B8%AA%E5%85%83%E7%B4%A0%E5%80%BC%20%20%0A%20%20%20%20List%3CString%3E%20list%20%3D%20listOperations.range(%22list%22%2C0%2C2)%3B%0A%20%20%20%20return%20list%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%203.%E9%9B%86%E5%90%88(set)%0A%0A%60%60%60java%0A%40GetMapping(%22%2Fset%22)%0Apublic%20Set%3CString%3E%20setTest()%7B%0A%20%20%20%20SetOperations%3CString%2CString%3E%20setOperations%20%3D%20redisTemplate.opsForSet()%3B%0A%20%20%20%20setOperations.add(%22set%22%2C%22Hello%22)%3B%0A%20%20%20%20setOperations.add(%22set%22%2C%22Hello%22)%3B%0A%20%20%20%20setOperations.add(%22set%22%2C%22world%22)%3B%0A%20%20%20%20setOperations.add(%22set%22%2C%22world%22)%3B%0A%20%20%20%20setOperations.add(%22set%22%2C%22java%22)%3B%0A%20%20%20%20setOperations.add(%22set%22%2C%22java%22)%3B%0A%20%20%0A%20%20%20%20Set%3CString%3E%20set%20%3D%20setOperations.members(%22set%22)%3B%0A%20%20%20%20return%20set%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%204.%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88%0A%0A%60%60%60java%0A%40GetMapping(%22%2Fzset%22)%0Apublic%20Set%3CString%3E%20zsetTest()%7B%0A%20%20%20%20ZSetOperations%3CString%2CString%3E%20zSetOperations%20%3D%20redisTemplate.opsForZSet()%3B%0A%20%20%20%20zSetOperations.add(%22zset%22%2C%22Hello%22%2C1)%3B%0A%20%20%20%20zSetOperations.add(%22zset%22%2C%22world%22%2C2)%3B%0A%20%20%20%20zSetOperations.add(%22zset%22%2C%22java%22%2C3)%3B%0A%20%20%0A%20%20%20%20Set%3CString%3E%20set%20%3D%20zSetOperations.range(%22zset%22%2C0%2C2)%3B%0A%20%20%20%20return%20set%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%205.%E5%93%88%E5%B8%8C%0A%0A%3E%20Hash%EF%BC%9Akey%20value%0A%3E%0A%3E%20HashOperations%EF%BC%9Akey%20hashkey%20value%0A%3E%0A%3E%20key%E6%98%AF%E6%AF%8F%E4%B8%80%E7%BB%84%E6%95%B0%E6%8D%AE%E7%9A%84ID%EF%BC%8Chashkey%E5%92%8Cvalue%E6%98%AF%E4%B8%80%E7%BB%84%E5%AE%8C%E6%95%B4%E7%9A%84HashMap%E6%95%B0%E6%8D%AE%EF%BC%8C%E9%80%9A%E8%BF%87key%E6%9D%A5%E5%8C%BA%E5%88%86%E4%B8%8D%E5%90%8C%E7%9A%84HashMap%0A%0A!%5Bc61e046118bc7719538b2b5f36e05d42.png%5D(en-resource%3A%2F%2Fdatabase%2F942%3A0)%0A%0A%0A%60%60%60java%0AHashMap%20hashMap%20%3D%20new%20HashMap()%3B%0AhashMap.put(key1%2Cvalue1)%3B%0AHashMap%20hashMap%20%3D%20new%20HashMap()%3B%0AhashMap.put(key2%2Cvalue2)%3B%0AHashMap%20hashMap%20%3D%20new%20HashMap()%3B%0AhashMap.put(key3%2Cvalue3)%3B%0A%0AHashOperations%3CString%2CString%2CString%3E%20hashOperation%20%3D%20redisTemplate.opsForHash()%3B%0AhashOperation.put(hashMap1%2Ckey1%2Cvalue1)%3B%0AhashOperation.put(hashMap2%2Ckey2%2Cvalue2)%3B%0AhashOperation.put(hashMap3%2Ckey3%2Cvalue3)%3B%0A%0A%0A%40GetMapping(%22%2Fhash%22)%0Apublic%20void%20hashTest()%7B%0A%20%20%20%20HashOperations%3CString%2CString%2CString%3E%20hashOperations%20%3D%20redisTemplate.opsForHash()%3B%0A%20%20%20%20hashOperations.put(%22key%22%2C%22hashKey%22%2C%22Hello%22)%3B%0A%20%20%20%20System.out.println(hashOperations.get(%22key%22%2C%22hashKey%22))%3B%0A%20%20%20%20%0A%7D%0A%60%60%60%0A%0A

powerdesigner

创建时间:2020/12/17 15:57
更新时间:2020/12/18 16:08
作者:Chris

1 是什么

是Sybase公司开发的用于数据库设计的强大软件,是开发人员常用的数据库建模工具

2 概念模型

3 物理模型

4 逆向工程

4.1 PowerDesigner连接MySQL
  1. 新建一个pdm,dbms选择mysql

  2. Database - Connect 选择数据库连接

  3. 配置连接信息

    数据库连接这里是通过一个配置文件来获取连接信息的,首次的话因为没有,所以我们需要选择Configure进行配置。

  4. 填写配置信息

  5. 安装问题

    cann't initialize javaVM

    需要下载32位jdk并配置如下配置项

    tools > General Options

    Java Exception : Fatal Error. Unable to initialize DatabaseMetaData

    Non SQL Error : Could not load class com.mysql.jdbc.Drive

    而指定的jar包没有问题,那么是因为PowerDesigner无法找到驱动所产生的。解决办法是配置系统的classpath路径,指定jar包路径就好了

4.2 逆向工程图
  1. 菜单选择,从数据库更新模型

  2. 选择数据库连接配置文件

  3. 选择对应的库和表

  4. 在表之间建立关联关系

5 物理模块转概念模型

5.1 物理模型如果只显示Name列

Tools -> Display Preferences -> Table -> Columns

这个栏目中就是显示的列,就是控制模型显示的列;你可以全部去掉就只显示Name的值

5.2 物理模型转换成概念模型
  1. 去掉"Check model"复选框,如果不去掉的话,可能有些模型不规范报错

  2. 生成概念模型中只显示Entity名称

%5BTOC%5D%0A%0A%0A%0A%23%23%23%23%201%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E6%98%AFSybase%E5%85%AC%E5%8F%B8%E5%BC%80%E5%8F%91%E7%9A%84%E7%94%A8%E4%BA%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AE%BE%E8%AE%A1%E7%9A%84%E5%BC%BA%E5%A4%A7%E8%BD%AF%E4%BB%B6%EF%BC%8C%E6%98%AF%E5%BC%80%E5%8F%91%E4%BA%BA%E5%91%98%E5%B8%B8%E7%94%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E5%BB%BA%E6%A8%A1%E5%B7%A5%E5%85%B7%0A%0A%23%23%23%23%202%20%E6%A6%82%E5%BF%B5%E6%A8%A1%E5%9E%8B%0A%0A%23%23%23%23%203%20%E7%89%A9%E7%90%86%E6%A8%A1%E5%9E%8B%0A%0A%0A%0A%0A%0A%23%23%23%23%204%20%E9%80%86%E5%90%91%E5%B7%A5%E7%A8%8B%0A%0A%23%23%23%23%23%204.1%20%5BPowerDesigner%E8%BF%9E%E6%8E%A5MySQL%5D(https%3A%2F%2Fwww.cnblogs.com%2Fdeng-cc%2Fp%2F6824946.html)%0A%0A1.%20%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AApdm%EF%BC%8Cdbms%E9%80%89%E6%8B%A9mysql%0A%20%20%20%20!%5B5e81c3730cddd4559e1ea1c478b98183.png%5D(en-resource%3A%2F%2Fdatabase%2F924%3A1)%0A%20%20%20%20%0A2.%20Database%20-%20Connect%20%20%E9%80%89%E6%8B%A9%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%0A%20%20%20%20%0A%20%20%20%20!%5B1819b278f402c370ee2a951804d2b523.png%5D(en-resource%3A%2F%2Fdatabase%2F922%3A0)%0A%20%20%20%20%0A3.%20%E9%85%8D%E7%BD%AE%E8%BF%9E%E6%8E%A5%E4%BF%A1%E6%81%AF%0A%0A%20%20%20%3E%20%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E8%BF%99%E9%87%8C%E6%98%AF%E9%80%9A%E8%BF%87%E4%B8%80%E4%B8%AA%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E6%9D%A5%E8%8E%B7%E5%8F%96%E8%BF%9E%E6%8E%A5%E4%BF%A1%E6%81%AF%E7%9A%84%EF%BC%8C%E9%A6%96%E6%AC%A1%E7%9A%84%E8%AF%9D%E5%9B%A0%E4%B8%BA%E6%B2%A1%E6%9C%89%EF%BC%8C%E6%89%80%E4%BB%A5%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E9%80%89%E6%8B%A9Configure%E8%BF%9B%E8%A1%8C%E9%85%8D%E7%BD%AE%E3%80%82%0A%20%20%20%0A%20%20%20%20!%5B8469d0437c6c6f2fee175fe50456c37f.png%5D(en-resource%3A%2F%2Fdatabase%2F920%3A0)%0A%0A%0A4.%20%E5%A1%AB%E5%86%99%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%0A%20%20%20%20!%5B561737067b3713225ecc275fe5af2594.png%5D(en-resource%3A%2F%2Fdatabase%2F918%3A0)%0A%20%20%20%20%0A%20%20%20%20!%5B35b94792d5a55ce17d1e5bcdea3e9ede.png%5D(en-resource%3A%2F%2Fdatabase%2F916%3A0)%0A%20%20%20%20%0A%0A5.%20%E5%AE%89%E8%A3%85%E9%97%AE%E9%A2%98%0A%0A%20%20%20%3E%20cann't%20initialize%20javaVM%0A%20%20%20%3E%0A%20%20%20%3E%20%E9%9C%80%E8%A6%81%E4%B8%8B%E8%BD%BD32%E4%BD%8Djdk%E5%B9%B6%E9%85%8D%E7%BD%AE%E5%A6%82%E4%B8%8B%E9%85%8D%E7%BD%AE%E9%A1%B9%0A%20%20%20%3E%0A%20%20%20%3E%20tools%20%20%3E%20General%20Options%0A%20%20%20%0A%20%20%20!%5B986d8e58e5715686342653fa06e86c67.png%5D(en-resource%3A%2F%2Fdatabase%2F914%3A0)%0A%0A%20%20%20%3E%20Java%20Exception%20%3A%20Fatal%20Error.%20Unable%20to%20initialize%20DatabaseMetaData%0A%20%20%20%3E%0A%20%20%20%3E%20Non%20SQL%20Error%20%3A%20Could%20not%20load%20class%20com.mysql.jdbc.Drive%20%0A%20%20%20%3E%0A%20%20%20%3E%20%E8%80%8C%E6%8C%87%E5%AE%9A%E7%9A%84jar%E5%8C%85%E6%B2%A1%E6%9C%89%E9%97%AE%E9%A2%98%EF%BC%8C%E9%82%A3%E4%B9%88%E6%98%AF%E5%9B%A0%E4%B8%BAPowerDesigner%E6%97%A0%E6%B3%95%E6%89%BE%E5%88%B0%E9%A9%B1%E5%8A%A8%E6%89%80%E4%BA%A7%E7%94%9F%E7%9A%84%E3%80%82%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%E6%98%AF%E9%85%8D%E7%BD%AE%E7%B3%BB%E7%BB%9F%E7%9A%84classpath%E8%B7%AF%E5%BE%84%EF%BC%8C%E6%8C%87%E5%AE%9Ajar%E5%8C%85%E8%B7%AF%E5%BE%84%E5%B0%B1%E5%A5%BD%E4%BA%86%0A%0A%20%20%20%20!%5Bee2d78ca234c074ab625e239645109f8.png%5D(en-resource%3A%2F%2Fdatabase%2F912%3A0)%0A%0A%0A%0A%0A%23%23%23%23%23%204.2%20%E9%80%86%E5%90%91%E5%B7%A5%E7%A8%8B%E5%9B%BE%0A%0A1.%20%E8%8F%9C%E5%8D%95%E9%80%89%E6%8B%A9%EF%BC%8C%E4%BB%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E6%9B%B4%E6%96%B0%E6%A8%A1%E5%9E%8B%0A!%5B204a1ad9b466fc3afe61446be4bf8ad0.png%5D(en-resource%3A%2F%2Fdatabase%2F910%3A0)%0A%0A2.%20%E9%80%89%E6%8B%A9%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%20%0A!%5B4aa80317d80df8c767279b2cb220590f.png%5D(en-resource%3A%2F%2Fdatabase%2F908%3A0)%0A%0A3.%20%E9%80%89%E6%8B%A9%E5%AF%B9%E5%BA%94%E7%9A%84%E5%BA%93%E5%92%8C%E8%A1%A8%0A!%5B5bbf48095655ef2547954d9d0065a257.png%5D(en-resource%3A%2F%2Fdatabase%2F906%3A0)%0A%0A4.%20%E5%9C%A8%E8%A1%A8%E4%B9%8B%E9%97%B4%E5%BB%BA%E7%AB%8B%E5%85%B3%E8%81%94%E5%85%B3%E7%B3%BB%0A!%5Bbcc45845d03a8be46e9657bc5924d474.png%5D(en-resource%3A%2F%2Fdatabase%2F904%3A0)%0A%0A%0A%0A%23%23%23%23%205%20%E7%89%A9%E7%90%86%E6%A8%A1%E5%9D%97%E8%BD%AC%E6%A6%82%E5%BF%B5%E6%A8%A1%E5%9E%8B%0A%0A%23%23%23%23%23%205.1%20%E7%89%A9%E7%90%86%E6%A8%A1%E5%9E%8B%E5%A6%82%E6%9E%9C%E5%8F%AA%E6%98%BE%E7%A4%BAName%E5%88%97%0A%0A%3E%20Tools%20-%3E%20Display%20Preferences%20-%3E%20%20Table%20-%3E%20Columns%20%0A%3E%0A%3E%20%E8%BF%99%E4%B8%AA%E6%A0%8F%E7%9B%AE%E4%B8%AD%E5%B0%B1%E6%98%AF%E6%98%BE%E7%A4%BA%E7%9A%84%E5%88%97%EF%BC%8C%E5%B0%B1%E6%98%AF%E6%8E%A7%E5%88%B6%E6%A8%A1%E5%9E%8B%E6%98%BE%E7%A4%BA%E7%9A%84%E5%88%97%EF%BC%9B%E4%BD%A0%E5%8F%AF%E4%BB%A5%E5%85%A8%E9%83%A8%E5%8E%BB%E6%8E%89%E5%B0%B1%E5%8F%AA%E6%98%BE%E7%A4%BAName%E7%9A%84%E5%80%BC%0A%0A!%5Bb3738f6cb4f5a712a8fbf34137e0e4a9.png%5D(en-resource%3A%2F%2Fdatabase%2F902%3A0)%0A%0A%0A%0A%0A%23%23%23%23%23%205.2%20%E7%89%A9%E7%90%86%E6%A8%A1%E5%9E%8B%E8%BD%AC%E6%8D%A2%E6%88%90%E6%A6%82%E5%BF%B5%E6%A8%A1%E5%9E%8B%0A%0A1.%20%E5%8E%BB%E6%8E%89%22Check%20model%22%E5%A4%8D%E9%80%89%E6%A1%86%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%8E%BB%E6%8E%89%E7%9A%84%E8%AF%9D%EF%BC%8C%E5%8F%AF%E8%83%BD%E6%9C%89%E4%BA%9B%E6%A8%A1%E5%9E%8B%E4%B8%8D%E8%A7%84%E8%8C%83%E6%8A%A5%E9%94%99%0A%20%20%20%20!%5B8113cffb98aee24244f627a363ebdb07.png%5D(en-resource%3A%2F%2Fdatabase%2F896%3A0)%0A%20%20%20%20%0A%0A2.%20%E7%94%9F%E6%88%90%E6%A6%82%E5%BF%B5%E6%A8%A1%E5%9E%8B%E4%B8%AD%E5%8F%AA%E6%98%BE%E7%A4%BAEntity%E5%90%8D%E7%A7%B0%0A%20%20%20%20!%5Bab5d4ed715d795d2ee2becf2a6590ca8.png%5D(en-resource%3A%2F%2Fdatabase%2F890%3A0)%0A%0A%20%20%20%20!%5B0ca1d9724cea3041027938e0bb5a5028.png%5D(en-resource%3A%2F%2Fdatabase%2F900%3A0)%0A%20%20%20%20%0A%0A

git stash

创建时间:2020/9/2 15:23
更新时间:2020/12/16 15:37
作者:Chris
来源:https://www.cnblogs.com/zndxall/archive/2018/09/04/9586088.html

1.应用场景

  1. 当正在dev分支上开发某个项目,这时项目中出现一个bug,需要紧急修复,但是正在开发的内容只是完成一半,还不想提交,这时可以用git stash命令将修改的内容保存至堆栈区,然后顺利切换到hotfix分支进行bug修复,修复完成后,再次切回到dev分支,从堆栈中恢复刚刚保存的内容。
  1. 由于疏忽,本应该在dev分支开发的内容,却在master上进行了开发,需要重新切回到dev分支上进行开发,可以用git stash将内容保存至堆栈中,切回到dev分支后,再次恢复内容即可。

2.总结

总的来说,git stash命令的作用就是将目前还不想提交的但是已经修改的内容进行保存至堆栈中,后续可以在某个分支上恢复出堆栈中的内容。

这也就是说,stash中的内容不仅仅可以恢复到原先开发的分支,也可以恢复到其他任意指定的分支上。git stash作用的范围包括工作区和暂存区中的内容,也就是说没有提交的内容都会保存至堆栈中。

git stash save作用等同于git stash,
区别是执行存储时,添加备注,方便查找

git stash save “test1”

查看stash了哪些存储

git stash list

显示做了哪些改动,默认show第一个存储,如果要显示其他存贮,后面加stash@{$num},比如第二个 git stash show stash@{1}

git stash show
git stash show stash@{1}

显示第一个存储的改动详细内容,如果想显示其他存储,命令:git stash show  stash@{$num}  -p ,比如第二个:git stash show  stash@{1}  -p

git stash show -p
git stash show  stash@{1}  -p

应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0},如果要使用其他个,git stash apply stash@{$num} , 比如第二个:git stash apply stash@{1}

git stash apply
git stash apply stash@{1} 

恢复之前缓存的工作目录,将缓存堆栈中的对应stash删除,并将对应修改应用到当前的工作目录下, 默认为第一个stash,即stash@{0},如果要应用并删除其他stash,命令:git stash pop stash@{$num} ,比如应用并删除第二个:git stash pop stash@{1}

git stash pop
git stash pop stash@{1}

丢弃stash@{$num}存储,从列表中删除这个存储

git stash drop stash@{$num} 

删除所有缓存的stash

git stash clear
%23%23%23%23%201.%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%0A%0A%3E%201.%20%E5%BD%93%E6%AD%A3%E5%9C%A8dev%E5%88%86%E6%94%AF%E4%B8%8A%E5%BC%80%E5%8F%91%E6%9F%90%E4%B8%AA%E9%A1%B9%E7%9B%AE%EF%BC%8C%E8%BF%99%E6%97%B6%E9%A1%B9%E7%9B%AE%E4%B8%AD%E5%87%BA%E7%8E%B0%E4%B8%80%E4%B8%AAbug%EF%BC%8C%E9%9C%80%E8%A6%81%E7%B4%A7%E6%80%A5%E4%BF%AE%E5%A4%8D%EF%BC%8C%E4%BD%86%E6%98%AF%E6%AD%A3%E5%9C%A8%E5%BC%80%E5%8F%91%E7%9A%84%E5%86%85%E5%AE%B9%E5%8F%AA%E6%98%AF%E5%AE%8C%E6%88%90%E4%B8%80%E5%8D%8A%EF%BC%8C%E8%BF%98%E4%B8%8D%E6%83%B3%E6%8F%90%E4%BA%A4%EF%BC%8C%E8%BF%99%E6%97%B6%E5%8F%AF%E4%BB%A5%E7%94%A8git%20stash%E5%91%BD%E4%BB%A4%E5%B0%86%E4%BF%AE%E6%94%B9%E7%9A%84%E5%86%85%E5%AE%B9%E4%BF%9D%E5%AD%98%E8%87%B3%E5%A0%86%E6%A0%88%E5%8C%BA%EF%BC%8C%E7%84%B6%E5%90%8E%E9%A1%BA%E5%88%A9%E5%88%87%E6%8D%A2%E5%88%B0hotfix%E5%88%86%E6%94%AF%E8%BF%9B%E8%A1%8Cbug%E4%BF%AE%E5%A4%8D%EF%BC%8C%E4%BF%AE%E5%A4%8D%E5%AE%8C%E6%88%90%E5%90%8E%EF%BC%8C%E5%86%8D%E6%AC%A1%E5%88%87%E5%9B%9E%E5%88%B0dev%E5%88%86%E6%94%AF%EF%BC%8C%E4%BB%8E%E5%A0%86%E6%A0%88%E4%B8%AD%E6%81%A2%E5%A4%8D%E5%88%9A%E5%88%9A%E4%BF%9D%E5%AD%98%E7%9A%84%E5%86%85%E5%AE%B9%E3%80%82%0A%0A%3E%202.%20%E7%94%B1%E4%BA%8E%E7%96%8F%E5%BF%BD%EF%BC%8C%E6%9C%AC%E5%BA%94%E8%AF%A5%E5%9C%A8dev%E5%88%86%E6%94%AF%E5%BC%80%E5%8F%91%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8C%E5%8D%B4%E5%9C%A8master%E4%B8%8A%E8%BF%9B%E8%A1%8C%E4%BA%86%E5%BC%80%E5%8F%91%EF%BC%8C%E9%9C%80%E8%A6%81%E9%87%8D%E6%96%B0%E5%88%87%E5%9B%9E%E5%88%B0dev%E5%88%86%E6%94%AF%E4%B8%8A%E8%BF%9B%E8%A1%8C%E5%BC%80%E5%8F%91%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8git%20stash%E5%B0%86%E5%86%85%E5%AE%B9%E4%BF%9D%E5%AD%98%E8%87%B3%E5%A0%86%E6%A0%88%E4%B8%AD%EF%BC%8C%E5%88%87%E5%9B%9E%E5%88%B0dev%E5%88%86%E6%94%AF%E5%90%8E%EF%BC%8C%E5%86%8D%E6%AC%A1%E6%81%A2%E5%A4%8D%E5%86%85%E5%AE%B9%E5%8D%B3%E5%8F%AF%E3%80%82%0A%0A%23%23%23%23%202.%E6%80%BB%E7%BB%93%0A%3E%20%E6%80%BB%E7%9A%84%E6%9D%A5%E8%AF%B4%EF%BC%8Cgit%20stash%E5%91%BD%E4%BB%A4%E7%9A%84%E4%BD%9C%E7%94%A8%E5%B0%B1%E6%98%AF%E5%B0%86%E7%9B%AE%E5%89%8D%E8%BF%98%E4%B8%8D%E6%83%B3%E6%8F%90%E4%BA%A4%E7%9A%84%E4%BD%86%E6%98%AF%E5%B7%B2%E7%BB%8F%E4%BF%AE%E6%94%B9%E7%9A%84%E5%86%85%E5%AE%B9%E8%BF%9B%E8%A1%8C%E4%BF%9D%E5%AD%98%E8%87%B3%E5%A0%86%E6%A0%88%E4%B8%AD%EF%BC%8C%E5%90%8E%E7%BB%AD%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%9F%90%E4%B8%AA%E5%88%86%E6%94%AF%E4%B8%8A%E6%81%A2%E5%A4%8D%E5%87%BA%E5%A0%86%E6%A0%88%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%E3%80%82%0A%3E%0A%3E%20%E8%BF%99%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8Cstash%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%E4%B8%8D%E4%BB%85%E4%BB%85%E5%8F%AF%E4%BB%A5%E6%81%A2%E5%A4%8D%E5%88%B0%E5%8E%9F%E5%85%88%E5%BC%80%E5%8F%91%E7%9A%84%E5%88%86%E6%94%AF%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%81%A2%E5%A4%8D%E5%88%B0%E5%85%B6%E4%BB%96%E4%BB%BB%E6%84%8F%E6%8C%87%E5%AE%9A%E7%9A%84%E5%88%86%E6%94%AF%E4%B8%8A%E3%80%82git%20stash%E4%BD%9C%E7%94%A8%E7%9A%84%E8%8C%83%E5%9B%B4%E5%8C%85%E6%8B%AC%E5%B7%A5%E4%BD%9C%E5%8C%BA%E5%92%8C%E6%9A%82%E5%AD%98%E5%8C%BA%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%E6%B2%A1%E6%9C%89%E6%8F%90%E4%BA%A4%E7%9A%84%E5%86%85%E5%AE%B9%E9%83%BD%E4%BC%9A%E4%BF%9D%E5%AD%98%E8%87%B3%E5%A0%86%E6%A0%88%E4%B8%AD%E3%80%82%0A%0A%0A%0A%3E%20git%20stash%20save%E4%BD%9C%E7%94%A8%E7%AD%89%E5%90%8C%E4%BA%8Egit%20stash%EF%BC%8C%0A%3E%20%E5%8C%BA%E5%88%AB%E6%98%AF%E6%89%A7%E8%A1%8C%E5%AD%98%E5%82%A8%E6%97%B6%EF%BC%8C%E6%B7%BB%E5%8A%A0%E5%A4%87%E6%B3%A8%EF%BC%8C%E6%96%B9%E4%BE%BF%E6%9F%A5%E6%89%BE%0A%0A%60%60%60%0Agit%20stash%20save%20%E2%80%9Ctest1%E2%80%9D%0A%60%60%60%0A%3E%20%E6%9F%A5%E7%9C%8Bstash%E4%BA%86%E5%93%AA%E4%BA%9B%E5%AD%98%E5%82%A8%0A%60%60%60%0Agit%20stash%20list%0A%60%60%60%0A%0A%3E%20%E6%98%BE%E7%A4%BA%E5%81%9A%E4%BA%86%E5%93%AA%E4%BA%9B%E6%94%B9%E5%8A%A8%EF%BC%8C%E9%BB%98%E8%AE%A4show%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%98%E5%82%A8%2C%E5%A6%82%E6%9E%9C%E8%A6%81%E6%98%BE%E7%A4%BA%E5%85%B6%E4%BB%96%E5%AD%98%E8%B4%AE%EF%BC%8C%E5%90%8E%E9%9D%A2%E5%8A%A0stash%40%7B%24num%7D%EF%BC%8C%E6%AF%94%E5%A6%82%E7%AC%AC%E4%BA%8C%E4%B8%AA%20git%20stash%20show%20stash%40%7B1%7D%0A%60%60%60%0Agit%20stash%20show%0Agit%20stash%20show%20stash%40%7B1%7D%0A%60%60%60%0A!%5B7a30c98e67907c07d5ae38e4d7d3eacc.png%5D(en-resource%3A%2F%2Fdatabase%2F884%3A0)%0A%0A%3E%20%E6%98%BE%E7%A4%BA%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%98%E5%82%A8%E7%9A%84%E6%94%B9%E5%8A%A8%E8%AF%A6%E7%BB%86%E5%86%85%E5%AE%B9%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%83%B3%E6%98%BE%E7%A4%BA%E5%85%B6%E4%BB%96%E5%AD%98%E5%82%A8%EF%BC%8C%E5%91%BD%E4%BB%A4%EF%BC%9Agit%20stash%20show%C2%A0%20stash%40%7B%24num%7D%C2%A0%C2%A0-p%20%EF%BC%8C%E6%AF%94%E5%A6%82%E7%AC%AC%E4%BA%8C%E4%B8%AA%EF%BC%9Agit%20stash%20show%C2%A0%C2%A0stash%40%7B1%7D%C2%A0%C2%A0-p%0A%60%60%60%0Agit%20stash%20show%20-p%0Agit%20stash%20show%C2%A0%C2%A0stash%40%7B1%7D%C2%A0%C2%A0-p%0A%60%60%60%0A%0A%3E%20%E5%BA%94%E7%94%A8%E6%9F%90%E4%B8%AA%E5%AD%98%E5%82%A8%2C%E4%BD%86%E4%B8%8D%E4%BC%9A%E6%8A%8A%E5%AD%98%E5%82%A8%E4%BB%8E%E5%AD%98%E5%82%A8%E5%88%97%E8%A1%A8%E4%B8%AD%E5%88%A0%E9%99%A4%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%98%E5%82%A8%2C%E5%8D%B3stash%40%7B0%7D%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BD%BF%E7%94%A8%E5%85%B6%E4%BB%96%E4%B8%AA%EF%BC%8Cgit%20stash%20apply%C2%A0stash%40%7B%24num%7D%20%EF%BC%8C%C2%A0%E6%AF%94%E5%A6%82%E7%AC%AC%E4%BA%8C%E4%B8%AA%EF%BC%9Agit%20stash%20apply%C2%A0stash%40%7B1%7D%C2%A0%0A%0A%60%60%60%0Agit%20stash%20apply%0Agit%20stash%20apply%C2%A0stash%40%7B1%7D%C2%A0%0A%60%60%60%0A%0A%0A%3E%20%E6%81%A2%E5%A4%8D%E4%B9%8B%E5%89%8D%E7%BC%93%E5%AD%98%E7%9A%84%E5%B7%A5%E4%BD%9C%E7%9B%AE%E5%BD%95%EF%BC%8C%E5%B0%86%E7%BC%93%E5%AD%98%E5%A0%86%E6%A0%88%E4%B8%AD%E7%9A%84%E5%AF%B9%E5%BA%94stash%E5%88%A0%E9%99%A4%EF%BC%8C%E5%B9%B6%E5%B0%86%E5%AF%B9%E5%BA%94%E4%BF%AE%E6%94%B9%E5%BA%94%E7%94%A8%E5%88%B0%E5%BD%93%E5%89%8D%E7%9A%84%E5%B7%A5%E4%BD%9C%E7%9B%AE%E5%BD%95%E4%B8%8B%2C%20%E9%BB%98%E8%AE%A4%E4%B8%BA%E7%AC%AC%E4%B8%80%E4%B8%AAstash%2C%E5%8D%B3stash%40%7B0%7D%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%A6%81%E5%BA%94%E7%94%A8%E5%B9%B6%E5%88%A0%E9%99%A4%E5%85%B6%E4%BB%96stash%EF%BC%8C%E5%91%BD%E4%BB%A4%EF%BC%9Agit%20stash%20pop%C2%A0stash%40%7B%24num%7D%20%EF%BC%8C%E6%AF%94%E5%A6%82%E5%BA%94%E7%94%A8%E5%B9%B6%E5%88%A0%E9%99%A4%E7%AC%AC%E4%BA%8C%E4%B8%AA%EF%BC%9Agit%20stash%20pop%C2%A0stash%40%7B1%7D%0A%0A%60%60%60%0Agit%20stash%20pop%0Agit%20stash%20pop%C2%A0stash%40%7B1%7D%0A%60%60%60%0A%0A%3E%20%E4%B8%A2%E5%BC%83stash%40%7B%24num%7D%E5%AD%98%E5%82%A8%EF%BC%8C%E4%BB%8E%E5%88%97%E8%A1%A8%E4%B8%AD%E5%88%A0%E9%99%A4%E8%BF%99%E4%B8%AA%E5%AD%98%E5%82%A8%0A%0A%60%60%60%0Agit%20stash%20drop%C2%A0stash%40%7B%24num%7D%20%0A%60%60%60%0A%0A%0A%3E%20%E5%88%A0%E9%99%A4%E6%89%80%E6%9C%89%E7%BC%93%E5%AD%98%E7%9A%84stash%0A%60%60%60%0Agit%20stash%20clear%0A%60%60%60

1. Redis是什么?

创建时间:2020/10/14 21:48
更新时间:2024/9/21 14:39
作者:Chris

1. Redis是什么?

Remote Dicionary Server 远程字典服务器,是完全开源的C语言编写的高性能的KV分布式内存数据库。

Redis与其他KV产品有一下特点

  1. Redis支持数据的持久化,可以将内存中的数据保存到磁盘上
  2. Redis不仅仅支持简单的KV类型的数据,同时还支持list,set,zset,hash等数据结构的存储
  3. Redis支持Master-Slave模式的数据备份

2. Redis能干什么?

  1. 内存存储和持久化
  2. 取最新N的数据在的操作
  3. 发布,订阅消息系统
  4. 定时器和计数器

3. Redis去哪下 ?

http://redis.io/

http://www.redis.cn//

4. Redis怎么玩

  1. 数据类型,基本操作和配置
  2. 持久化和事务
  3. 事务的控制
  4. 主从复制
4.1 安装Redis

Linux 安装gcc

yum install gcc-c++
gcc -v

Ubuntu install gcc

apt install gcc

安装Redis

wget https://download.redis.io/releases/redis-5.0.5.tar.gz
tar -zxvf  redis-5.0.5.tar.gz
cd  redis-5.0.5
make
make install

默认安装目录:/usr/local/bin

4.2 配置Redis
mkdir /myredis
cp /usr/local/redis/redis-5.0.5/redis.conf /myredis
vi /myredis/redis.conf
daemonize yes

redis 默认安装了16个DB

# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
databases 16
4.3 启停redis
redis-server /myredis/redis.conf
ps aux | grep redis
redis-cli -p 6379
ping
shundown
4.4 查询命令
# 使用第三个库
127.0.0.1:6379> select 2
dbsize -->查看当前数据库的key的数量

keys *
keys k?
keys k*


exists k1 -> 判断k1是否存在,存在返回1,不存在返回0
move k1 2 -> 将k1移到3号库
expire k1 seconds ->  给指定的key设置过期时间, 到期后全将key移除
ttl k1 -> 查看还有多少秒过期,-1表示永不过期,-2表示已经过期,过期的key被移除。
type k1 -> 查看key的数据类型
del k1 -> 删除key

flushdb -->清空当前库中的key
flushall -->清空所有库中的key
4.5 常见问题

(error) MISCONF Redis is configured to save RDB snapshots

vi /etc/sysctl.conf
vm.overcommit_memory = 1

5. Redis的五大数据类型

5.1 String

二进制安全的,可以包含任何数据,比如图片和二进制的数据,一个redis字符串的value最多可以是512M.

append k1 12345
strlen k1
incr k1 -> 加1
decr k1 -> 减1
incrby k1 2 -> 加2
decrby k1 2 -> 减2
getrange k1 0 -1 / getrange k1 0 3
setrange k1 0 xxx
setex k1 10 v1 -> 新建k1并设置过期时间为10秒
setnx k1 v1 -> 不存在则set
mset k1 v1 k2 v2-> 一次性设置多个KV
mget k1 k2 -> 一次性获取多个K
msetnx k2 v2 k3 v3 -> 当KV不存在时,一次性设置多个KV, 如果有存在的K,则整体设置失败
5.2 Hash

是一个键值对集合,适合用于存储对象。
KV模式不变但V是一个键值对

hset user id 11
hget user id
hmset customer id 11 name li age 30
hmget customer id name age
hgetall customer
hdel user name -> 删除user 中的name
hlen customer
hexists customer id -> 判断customer中的key id是否存在,不存在返回0,存在返回1
hkeys customer
hvals  customer
hincrby customer age 2
hincrbyfloat customer score 0.5
hsetnx customer email abc@163.com -> email不存在时才新增
5.3 List

是一个字符串链表,左右都可以插入数据,如果键不存在则新增链表,如果键存在则新增内容。

如果键全部移除则对应的链表则消失

lpush list01 1 2 3 4 5
lrange list01 0 -1
rpush list01 1 2 3 4 5
lpop list01
rpop list01
lindex list01 3  -> 获取值是3的元素的索引


llen list01
lrem list01 2 3-> 从list01里面删除2个3
del list01
ltrim list01 2 3  -> 截取指定索引范围2-3的值再赋给list01
rpoplpush source destination -> 将source的最后一个元素取出并压到dest的头元素
lset list01 index value -> 设置list01中index位置的value
linsert list01 before/after v x -> 在list01中的value前/后插入x
5.4 Set

无序无重复

sadd set01 1 2 2 3 3
smembers set01 -> 打印整个集合
sismember set01 1 -> 判断1是否在set01中,在返回1,否则返回0
scard set01 -> 获取set中的元素个数
srem set01 3 -> 删除集合set01中的元素3
srandmember set01 3 ->在集合中随机抽取3个元素
spop set01 -> 随机弹出一个元素并移除
smove set01 set02 5 -> 把set01中的元素5移动到set02
sdiff set01 set02 -> 取set01有但set02中没有的元素
sunion set01 set02 -> 取两个集合的并集
5.5 Zset

sorted set, 不同的是每个元素关联一个double类型的score,通过score来为集合中的元素排序。

zadd zset01 60 v1 70 v2 80 v3 90 v4 100 v5
zrange zset01 0 -1 -> 获取集合中的元素值
zrange zset01 0 -1 withscores -> 获取集合中的元素值及其score
zrangebyscore zset01 60 90 ->  获取60<=score<=90的value
zrangebyscore zset01 60 (90 ->  获取60<=score<90的value,  ( 表示不包含
zrangebyscore zset01 60 90 limit 2 3  -> 获取60<=score<=90的value并从index2截取3个
zrem zset01 v5
zcard zset01 -> 获取集合中元素的个数
zcount zset01 60 80 ->统计 60<=score<=80的value的个数
zrank zset01 v4 ->获取v4在集合中的位置的索引位
zscore zset01 v4 ->获取v4的score值
zrevrank zset01 v4 -> 逆序获取v4在集合中的位置的索引位
zrevrange zset01 0 -1 -> 逆序获取集合中的元素
zrevrangebyscore zset01 90 60 ->逆序获取60<=score>=90的value
zrevrangebyscore zset01 90 (60 limit 1 2

6 Redis配置

# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
units are case insensitive so 1GB 1Gb 1gB are all the same.
6.1 通用设置
tcp-backlog
timeout 0
tcp-keepalive 300
loglevel debug|verbose|notice|warning
logfile "/usr/local/redis/log/redis.log"
database 16
dir ./ -> 指定本地数据库的存放目录
6.2 SECURITY安全
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""
127.0.0.1:6379>
config set requirepass '123456' -> 设置密码
auth 123456 -> 使用密码认证
config set requirepass '' -> 取消密码设置
config get dir -> 从那个目录下启动redis
6.3 LIMITS限制
maxclients 默认10000
maxmemory <bytes>

maxmemory-policy
volatile-lru     -> Evict using approximated LRU among the keys with an expire set.
allkeys-lru      -> Evict any key using approximated LRU.
volatile-lfu     -> Evict using approximated LFU among the keys with an expire set.
allkeys-lfu      -> Evict any key using approximated LFU.
volatile-random  -> Remove a random key among the ones with an expire set.
allkeys-random   -> Remove a random key, any key.
volatile-ttl     -> Remove the key with the nearest expire time (minor TTL)
noeviction       -> Don't evict anything, just return an error on write operations, set as default.
6.3.1 LRU 和 LFU
LRU 最近最久未访问的。如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。
LFU 最近最少使用算法。如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小”的思路。
注意LFU和LRU算法的不同之处,LRU的淘汰规则是基于访问时间,而LFU是基于访问次数的。
举个简单的例子:
    假设缓存大小为3,数据访问序列为
    set(2,2),set(1,1)
    get(2),get(1),get(2)
    set(3,3),set(4,4),
    则在set(4,4)时对于LFU算法应该淘汰(3,3),而LRU应该淘汰(1,1)。

7. 持久化

7.1 RDB [Redis DataBase]
7.1.1 原理

在指定时间间隔内将数据集快照写入磁盘,恢复时直接将snapshot快照读入内存。

单独创建一个fork一个子进程进行持久化,会先将数据写入到一个临时文件中,待持久化过程结束会,再用这个临时文件代替上次持久化好的文件,整个过程中主进程不进行任何IO操作,这就确保了极高的性能。

如果要进行大规模的数据恢复,且对数据恢复的完整性要求不是很高,那RDB比AOF的方式更为高效。

Fork的作用是复制一个与当前进程一样的进程,新进程的所有数据(变量,环境变量,程序计数器)与原进程一致,但是它是一个全新的进程并作为原进程的子进程。

7.1.2 缺点
1. RDB的缺点是最后一次持久化后的数据可能丢失
2. 当主程序数据量很大时,fork一个子进得非常消耗资源,相当于将原进程double一份。
7.1.3 触发时机

RDB保存是的dump.rdb文件

save <seconds> <changes>
save 900 1    -> after 900 sec (15 min) if at least 1 key changed
save 300 10   -> after 300 sec (5 min) if at least 10 keys changed
save 60 10000 ->  after 60 sec if at least 10000 keys changed
7.1.4 save 和 bgsave

使用save或bgsave命令手动即刻备份

  1. save 只管保存,在保存时其它线程阻塞,在生产环境很少执行 SAVE 操作

  2. bgsave fock一个子进程异步进行快照操作,同时父进程还可以响应当前客户端请求.可以通过 lastsave 获了最后一次成功执行快照的时间来判断bgsave是否成功。

7.1.5 相关配置项

stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes -> 使用CRC64算法校验数据完整性
dbfilename dump.rdb
7.2 AOF [Append Only File]
7.2.1 原理

以日志的形式记录每个写操作,只许追加文件但不能改写文件,redis启动时将日志文件内容从头到尾执行一次完成数据恢复。

7.2.2 缺点

aof文件不断增长变大,文件远大于rdb,恢复速度慢于rdb,运行效率慢于rdb。

每次load aof文件时带来持续的IO。

7.2.3 AOF配置
appendonly no -> 要用aof,需要改为yes
appendfilename
appendfsync : aof备份
	always   -> 同步持久化,每一个数据变更都会被立刻记录到磁盘
	everysec -> 默认设置,异步操作每秒记录一,如果一秒内宕机会有数据丢失
    no
7.2.4 Rewrite机制
  1. 是什么

    appendonly.aof文件采用文件追加的方式,文件会变得越来越大,当文件大小超过设置的阈值时,Redis会启动AOF内容的压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof。

  2. 重写原理

    AOF文件持续增长变大,会fork出一条新进程将文件重写,先写临时文件再rename,重写aof文件时并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件。

  3. 触发机制

    redis会记录上次重写时的aof文件的大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且大于64M时触发.

    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 	64mb
    
7.2.5 修复AOF文件
./redis-check-aof --fix appendonly.aof
yes
7.3 总结

8. Redis的事务

8.1 是什么

一次性执行多个命令,本质是一组命令的集合,一个事务中的所有命令都会被序列化,按顺序串行化执行而不允许其它命令加塞

8.2 怎么玩

multi 标记一个事务开启,并返回ok.

exec 被redis调用,来执行一个事务中入队的多个命令

discard 放弃本次事务

unwatch 取消对所有key的监视

watch k1 k2... 监视一个或者多个key,如果在事务执行exec之前这些被监控的key被其它命令改动,那么事务将被打断,一但执行了exec之后,之前加的监控锁都会被清理掉。

watch监控:

行级锁:
表级锁:迸发时极差,但一致性是好
悲观锁:
乐观锁
CAS check-and-set
8.3 redis部分支行事务
8.3.1 集体连坐

在编译过程中出错时,整个事务中的所有命令集体失败。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 11
QUEUED
127.0.0.1:6379> set k2 22
QUEUED
127.0.0.1:6379> setget k3 33
(error) ERR unknown command `setget`, with args beginning with: `k3`, `33`,
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys *
(empty list or set)
8.3.2 冤头债主

在执行的过程中出错时,只有出错的命令失败,其它命令正常执行

127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> exec
1) (error) ERR value is not an integer or out of range
2) "v1"
3) "v2"
4) OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby balance 20
QUEUED
127.0.0.1:6379> incrby debt 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20

9. Redis的主从复制[Master/Slave]

9.1 是什么

也就是我们所说的主从复制,主机数据更新后根据配置和策略自动同步到备机的机制, Master以写为主,Slave以读为主

9.2 复制原理

salve启动成功连接到master后会发关一个sync命令,master将整个数据文件全量发送到slave,此后master新增的数据会增量复制到slaver, 但是只要重新连接一次master就会首先做一次全量复制。
复制最大的缺点就是延时,因为所的有写操作都在master上,然后同步更新到slaver上,所以master同步到slaver会有一定的延时。

9.3 能干什么

读写分离,容灾恢复

9.4 怎么玩
9.4.1 配置步骤
  1. 配从不配主

  2. 备机配置

    slaveof master-ip master-portnumber
    

    每次与master断开之后,都需要重新连接,除非你配置到redis.conf文件

  3. 修改配置文件

    拷贝多个redis.conf文件
    开启daemonize yes 
    Pid文件名称
    指定端口
    Log 文件名称
    Dump.rdb 名称
    
9.4.2 常用3招
  1. 一主二仆

    127.0.0.1:6379> info replication
    master:
    ./redis-server /myredis/redis_6379.conf
    ./redis-cli  -p 6379
    
    slave01:
    ./redis-server /myredis/redis_6380.conf
    ./redis-cli  -p 6380
    slaveof 127.0.0.1 6379
    
    slave02:
    ./redis-server /myredis/redis_6381.conf
    ./redis-cli  -p 6381
    slaveof 127.0.0.1 6379
    
    只有master节点可以写,salve节点不能写只能读取
    如果主机宕机,备机原地待命
    

  2. 薪火相传(去中心化)

    上一个slave可以是下一个slave的master 来接收其它连接和请求,这样可以有效的减轻链条中master的写压力。

    127.0.0.1:6379> info replication
    master:
    ./redis-server /myredis/redis_6379.conf
    ./redis-cli  -p 6379
    
    slave01:
    ./redis-server /myredis/redis_6380.conf
    ./redis-cli  -p 6380
    slaveof 127.0.0.1 6379
    
    slave02:
    ./redis-server /myredis/redis_6381.conf
    ./redis-cli  -p 6381
    slaveof 127.0.0.1 6380
    

  3. 反客为主(当master挂掉之后,从新分配)

    127.0.0.1:6379> info replication
    master:
    ./redis-server /myredis/redis_6379.conf
    ./redis-cli  -p 6379
    shundown
    exit
    
    slave01:
    ./redis-server /myredis/redis_6380.conf
    ./redis-cli  -p 6380
    slaveof no one
    
    slave02:
    ./redis-server /myredis/redis_6381.conf
    ./redis-cli  -p 6381
    slaveof 127.0.0.1 6380
    

10. 哨兵模式sentinel

10.1 是什么

是反客为主的自动版本,从后台自动监控主机是否故障,主要发生故障后自动将从机转为主机。

10.2 怎么玩
cd /myredis
vi sentinel.conf
sentinel monitor masterhost 本机ip master端口号 1
-- 当主机宕机之后,让slaver投票,谁的票数多,谁就成主机
cd /usr/local/bin
./redis-sentinel /myredis/sentinel.conf

当6379shutdown后,sentinal会启动leader选举机制,之后6379重启后会作用新的master的salve

2956:X 22 May 2019 22:54:25.383 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
2956:X 22 May 2019 22:54:25.393 # Sentinel ID is f0a3e6562c5bd63b41f9445fa7b9cfef4c34c2f3
2956:X 22 May 2019 22:54:25.393 # +monitor master host6379 127.0.0.1 6379 quorum 1
2956:X 22 May 2019 22:54:25.394 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:54:25.396 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.279 # +sdown master host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.279 # +odown master host6379 127.0.0.1 6379 #quorum 1/1
2956:X 22 May 2019 22:56:01.279 # +new-epoch 1
2956:X 22 May 2019 22:56:01.279 # +try-failover master host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.281 # +vote-for-leader f0a3e6562c5bd63b41f9445fa7b9cfef4c34c2f3 1
2956:X 22 May 2019 22:56:01.281 # +elected-leader master host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.281 # +failover-state-select-slave master host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.343 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.343 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.399 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.626 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.626 # +failover-state-reconf-slaves master host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.708 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:01.780 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:02.819 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:02.897 # +failover-end master host6379 127.0.0.1 6379
2956:X 22 May 2019 22:56:02.897 # +switch-master host6379 127.0.0.1 6379 127.0.0.1 6380
2956:X 22 May 2019 22:56:02.898 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6380
2956:X 22 May 2019 22:56:02.898 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
2956:X 22 May 2019 22:56:02.898 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
2956:X 22 May 2019 22:56:32.906 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
2956:X 22 May 2019 23:03:17.541 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
2956:X 22 May 2019 23:03:27.455 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380

11 Redis Lua

make[3]: Entering directory `/usr/local/redis-5.0.5/deps/hiredis'
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  net.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  hiredis.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  sds.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  async.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  read.c
ar rcs libhiredis.a net.o hiredis.o sds.o async.o read.o
make[3]: Leaving directory `/usr/local/redis-5.0.5/deps/hiredis'
MAKE linenoise
cd linenoise && make
make[3]: Entering directory `/usr/local/redis-5.0.5/deps/linenoise'
cc  -Wall -Os -g  -c linenoise.c
make[3]: Leaving directory `/usr/local/redis-5.0.5/deps/linenoise'
MAKE lua
cd lua/src && make all CFLAGS="-O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC='' " MYLDFLAGS="" AR="ar rcu"
make[3]: Entering directory `/usr/local/redis-5.0.5/deps/lua/src'
cc -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC=''    -c -o lapi.o lapi.c
cc -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC=''    -c -o lcode.o lcode.c
cc -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC=''    -c -o ldebug.o ldebug.c
cc -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC=''    -c -o ldo.o ldo.c
ldo.c: In function ‘f_parser’:
ldo.c:496:7: warning: unused variable ‘c’ [-Wunused-variable]
   int c = luaZ_lookahead(p->z);
```

![a0b2f38ef60748e132d49c28d7627b92.png](en-resource://database/1585:0)
%5Btoc%5D%0A%0A%23%23%23%23%201.%20Redis%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F%0A%0ARemote%20Dicionary%20Server%20%E8%BF%9C%E7%A8%8B%E5%AD%97%E5%85%B8%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E6%98%AF%E5%AE%8C%E5%85%A8%E5%BC%80%E6%BA%90%E7%9A%84C%E8%AF%AD%E8%A8%80%E7%BC%96%E5%86%99%E7%9A%84%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84KV%E5%88%86%E5%B8%83%E5%BC%8F%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE%E5%BA%93%E3%80%82%0A%0ARedis%E4%B8%8E%E5%85%B6%E4%BB%96KV%E4%BA%A7%E5%93%81%E6%9C%89%E4%B8%80%E4%B8%8B%E7%89%B9%E7%82%B9%0A%0A1.%20Redis%E6%94%AF%E6%8C%81%E6%95%B0%E6%8D%AE%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%B0%86%E5%86%85%E5%AD%98%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E4%BF%9D%E5%AD%98%E5%88%B0%E7%A3%81%E7%9B%98%E4%B8%8A%0A2.%20Redis%E4%B8%8D%E4%BB%85%E4%BB%85%E6%94%AF%E6%8C%81%E7%AE%80%E5%8D%95%E7%9A%84KV%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%90%8C%E6%97%B6%E8%BF%98%E6%94%AF%E6%8C%81list%2Cset%2Czset%2Chash%E7%AD%89%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%9A%84%E5%AD%98%E5%82%A8%0A3.%20Redis%E6%94%AF%E6%8C%81Master-Slave%E6%A8%A1%E5%BC%8F%E7%9A%84%E6%95%B0%E6%8D%AE%E5%A4%87%E4%BB%BD%0A%0A%0A%0A%23%23%23%23%202.%20Redis%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%EF%BC%9F%0A%0A1.%20%E5%86%85%E5%AD%98%E5%AD%98%E5%82%A8%E5%92%8C%E6%8C%81%E4%B9%85%E5%8C%96%0A2.%20%E5%8F%96%E6%9C%80%E6%96%B0N%E7%9A%84%E6%95%B0%E6%8D%AE%E5%9C%A8%E7%9A%84%E6%93%8D%E4%BD%9C%0A3.%20%E5%8F%91%E5%B8%83%EF%BC%8C%E8%AE%A2%E9%98%85%E6%B6%88%E6%81%AF%E7%B3%BB%E7%BB%9F%0A4.%20%E5%AE%9A%E6%97%B6%E5%99%A8%E5%92%8C%E8%AE%A1%E6%95%B0%E5%99%A8%0A%0A%0A%0A%23%23%23%23%203.%20Redis%E5%8E%BB%E5%93%AA%E4%B8%8B%20%3F%0A%0Ahttp%3A%2F%2Fredis.io%2F%0A%0Ahttp%3A%2F%2Fwww.redis.cn%2F%2F%0A%0A%23%23%23%23%204.%20Redis%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A1.%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C%E5%92%8C%E9%85%8D%E7%BD%AE%0A2.%20%E6%8C%81%E4%B9%85%E5%8C%96%E5%92%8C%E4%BA%8B%E5%8A%A1%0A3.%20%E4%BA%8B%E5%8A%A1%E7%9A%84%E6%8E%A7%E5%88%B6%0A4.%20%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%0A%0A%23%23%23%23%23%204.1%20%E5%AE%89%E8%A3%85Redis%0A%0ALinux%20%E5%AE%89%E8%A3%85gcc%0A%0A%60%60%60%0Ayum%20install%20gcc-c%2B%2B%0Agcc%20-v%0A%60%60%60%0A%0AUbuntu%20install%20gcc%0A%0A%60%60%60%0Aapt%20install%20gcc%0A%60%60%60%0A%0A%E5%AE%89%E8%A3%85Redis%0A%0A%60%60%60%0Awget%20https%3A%2F%2Fdownload.redis.io%2Freleases%2Fredis-5.0.5.tar.gz%0Atar%20-zxvf%20%20redis-5.0.5.tar.gz%0Acd%20%20redis-5.0.5%0Amake%0Amake%20install%0A%60%60%60%0A%0A%E9%BB%98%E8%AE%A4%E5%AE%89%E8%A3%85%E7%9B%AE%E5%BD%95%EF%BC%9A%2Fusr%2Flocal%2Fbin%0A%0A%23%23%23%23%23%204.2%20%E9%85%8D%E7%BD%AERedis%0A%0A%60%60%60%0Amkdir%20%2Fmyredis%0Acp%20%2Fusr%2Flocal%2Fredis%2Fredis-5.0.5%2Fredis.conf%20%2Fmyredis%0Avi%20%2Fmyredis%2Fredis.conf%0Adaemonize%20yes%0A%60%60%60%0A%0Aredis%20%E9%BB%98%E8%AE%A4%E5%AE%89%E8%A3%85%E4%BA%8616%E4%B8%AADB%0A%0A%60%60%60%0A%23%20Set%20the%20number%20of%20databases.%20The%20default%20database%20is%20DB%200%2C%20you%20can%20select%0A%23%20a%20different%20one%20on%20a%20per-connection%20basis%20using%20SELECT%20%3Cdbid%3E%20where%0A%23%20dbid%20is%20a%20number%20between%200%20and%20'databases'-1%0Adatabases%2016%0A%60%60%60%0A%0A%23%23%23%23%23%204.3%20%E5%90%AF%E5%81%9Credis%0A%0A%60%60%60%0Aredis-server%20%2Fmyredis%2Fredis.conf%0Aps%20aux%20%7C%20grep%20redis%0Aredis-cli%20-p%206379%0Aping%0Ashundown%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%204.4%20%E6%9F%A5%E8%AF%A2%E5%91%BD%E4%BB%A4%0A%0A%60%60%60%0A%23%20%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%BA%93%0A127.0.0.1%3A6379%3E%20select%202%0Adbsize%20--%3E%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8D%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84key%E7%9A%84%E6%95%B0%E9%87%8F%0A%0Akeys%20*%0Akeys%20k%3F%0Akeys%20k*%0A%0A%0Aexists%20k1%20-%3E%20%E5%88%A4%E6%96%ADk1%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%2C%E5%AD%98%E5%9C%A8%E8%BF%94%E5%9B%9E1%EF%BC%8C%E4%B8%8D%E5%AD%98%E5%9C%A8%E8%BF%94%E5%9B%9E0%0Amove%20k1%202%20-%3E%20%E5%B0%86k1%E7%A7%BB%E5%88%B03%E5%8F%B7%E5%BA%93%0Aexpire%20k1%20seconds%20-%3E%20%20%E7%BB%99%E6%8C%87%E5%AE%9A%E7%9A%84key%E8%AE%BE%E7%BD%AE%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%2C%20%E5%88%B0%E6%9C%9F%E5%90%8E%E5%85%A8%E5%B0%86key%E7%A7%BB%E9%99%A4%0Attl%20k1%20-%3E%20%E6%9F%A5%E7%9C%8B%E8%BF%98%E6%9C%89%E5%A4%9A%E5%B0%91%E7%A7%92%E8%BF%87%E6%9C%9F%EF%BC%8C-1%E8%A1%A8%E7%A4%BA%E6%B0%B8%E4%B8%8D%E8%BF%87%E6%9C%9F%EF%BC%8C-2%E8%A1%A8%E7%A4%BA%E5%B7%B2%E7%BB%8F%E8%BF%87%E6%9C%9F%EF%BC%8C%E8%BF%87%E6%9C%9F%E7%9A%84key%E8%A2%AB%E7%A7%BB%E9%99%A4%E3%80%82%0Atype%20k1%20-%3E%20%E6%9F%A5%E7%9C%8Bkey%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%0Adel%20k1%20-%3E%20%E5%88%A0%E9%99%A4key%0A%0Aflushdb%20--%3E%E6%B8%85%E7%A9%BA%E5%BD%93%E5%89%8D%E5%BA%93%E4%B8%AD%E7%9A%84key%0Aflushall%20--%3E%E6%B8%85%E7%A9%BA%E6%89%80%E6%9C%89%E5%BA%93%E4%B8%AD%E7%9A%84key%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%204.5%20%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%0A%0A%3E%20(error)%20MISCONF%20Redis%20is%20configured%20to%20save%20RDB%20snapshots%0A%0A%60%60%60%0Avi%20%2Fetc%2Fsysctl.conf%0Avm.overcommit_memory%20%3D%201%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%205.%20Redis%E7%9A%84%E4%BA%94%E5%A4%A7%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%0A%0A%23%23%23%23%23%205.1%20String%0A%0A%3E%20%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%AE%89%E5%85%A8%E7%9A%84%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%8C%85%E5%90%AB%E4%BB%BB%E4%BD%95%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%AF%94%E5%A6%82%E5%9B%BE%E7%89%87%E5%92%8C%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%B8%80%E4%B8%AAredis%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84value%E6%9C%80%E5%A4%9A%E5%8F%AF%E4%BB%A5%E6%98%AF512M.%0A%0A%60%60%60%0Aappend%20k1%2012345%0Astrlen%20k1%0Aincr%20k1%20-%3E%20%E5%8A%A01%0Adecr%20k1%20-%3E%20%E5%87%8F1%0Aincrby%20k1%202%20-%3E%20%E5%8A%A02%0Adecrby%20k1%202%20-%3E%20%E5%87%8F2%0Agetrange%20k1%200%20-1%20%2F%20getrange%20k1%200%203%0Asetrange%20k1%200%20xxx%0Asetex%20k1%2010%20v1%20-%3E%20%E6%96%B0%E5%BB%BAk1%E5%B9%B6%E8%AE%BE%E7%BD%AE%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%E4%B8%BA10%E7%A7%92%0Asetnx%20k1%20v1%20-%3E%20%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%88%99set%0Amset%20k1%20v1%20k2%20v2-%3E%20%E4%B8%80%E6%AC%A1%E6%80%A7%E8%AE%BE%E7%BD%AE%E5%A4%9A%E4%B8%AAKV%0Amget%20k1%20k2%20-%3E%20%E4%B8%80%E6%AC%A1%E6%80%A7%E8%8E%B7%E5%8F%96%E5%A4%9A%E4%B8%AAK%0Amsetnx%20k2%20v2%20k3%20v3%20-%3E%20%E5%BD%93KV%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%97%B6%EF%BC%8C%E4%B8%80%E6%AC%A1%E6%80%A7%E8%AE%BE%E7%BD%AE%E5%A4%9A%E4%B8%AAKV%2C%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%AD%98%E5%9C%A8%E7%9A%84K%EF%BC%8C%E5%88%99%E6%95%B4%E4%BD%93%E8%AE%BE%E7%BD%AE%E5%A4%B1%E8%B4%A5%0A%60%60%60%0A%0A%23%23%23%23%23%205.2%20Hash%0A%0A%3E%20%E6%98%AF%E4%B8%80%E4%B8%AA%E9%94%AE%E5%80%BC%E5%AF%B9%E9%9B%86%E5%90%88%EF%BC%8C%E9%80%82%E5%90%88%E7%94%A8%E4%BA%8E%E5%AD%98%E5%82%A8%E5%AF%B9%E8%B1%A1%E3%80%82%0A%3E%20KV%E6%A8%A1%E5%BC%8F%E4%B8%8D%E5%8F%98%E4%BD%86V%E6%98%AF%E4%B8%80%E4%B8%AA%E9%94%AE%E5%80%BC%E5%AF%B9%0A%0A%60%60%60%0Ahset%20user%20id%2011%0Ahget%20user%20id%0Ahmset%20customer%20id%2011%20name%20li%20age%2030%0Ahmget%20customer%20id%20name%20age%0Ahgetall%20customer%0Ahdel%20user%20name%20-%3E%20%E5%88%A0%E9%99%A4user%20%E4%B8%AD%E7%9A%84name%0Ahlen%20customer%0Ahexists%20customer%20id%20-%3E%20%E5%88%A4%E6%96%ADcustomer%E4%B8%AD%E7%9A%84key%20id%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%2C%E4%B8%8D%E5%AD%98%E5%9C%A8%E8%BF%94%E5%9B%9E0%EF%BC%8C%E5%AD%98%E5%9C%A8%E8%BF%94%E5%9B%9E1%0Ahkeys%20customer%0Ahvals%20%20customer%0Ahincrby%20customer%20age%202%0Ahincrbyfloat%20customer%20score%200.5%0Ahsetnx%20customer%20email%20abc%40163.com%20-%3E%20email%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%97%B6%E6%89%8D%E6%96%B0%E5%A2%9E%0A%60%60%60%0A%0A%23%23%23%23%23%205.3%20List%0A%0A%3E%20%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%93%BE%E8%A1%A8%EF%BC%8C%E5%B7%A6%E5%8F%B3%E9%83%BD%E5%8F%AF%E4%BB%A5%E6%8F%92%E5%85%A5%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%94%AE%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%88%99%E6%96%B0%E5%A2%9E%E9%93%BE%E8%A1%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%94%AE%E5%AD%98%E5%9C%A8%E5%88%99%E6%96%B0%E5%A2%9E%E5%86%85%E5%AE%B9%E3%80%82%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E9%94%AE%E5%85%A8%E9%83%A8%E7%A7%BB%E9%99%A4%E5%88%99%E5%AF%B9%E5%BA%94%E7%9A%84%E9%93%BE%E8%A1%A8%E5%88%99%E6%B6%88%E5%A4%B1%0A%0A%60%60%60%0Alpush%20list01%201%202%203%204%205%0Alrange%20list01%200%20-1%0Arpush%20list01%201%202%203%204%205%0Alpop%20list01%0Arpop%20list01%0Alindex%20list01%203%20%20-%3E%20%E8%8E%B7%E5%8F%96%E5%80%BC%E6%98%AF3%E7%9A%84%E5%85%83%E7%B4%A0%E7%9A%84%E7%B4%A2%E5%BC%95%0Allen%20list01%0Alrem%20list01%202%203-%3E%20%E4%BB%8Elist01%E9%87%8C%E9%9D%A2%E5%88%A0%E9%99%A42%E4%B8%AA3%0Adel%20list01%0Altrim%20list01%202%203%20%20-%3E%20%E6%88%AA%E5%8F%96%E6%8C%87%E5%AE%9A%E7%B4%A2%E5%BC%95%E8%8C%83%E5%9B%B42-3%E7%9A%84%E5%80%BC%E5%86%8D%E8%B5%8B%E7%BB%99list01%0Arpoplpush%20source%20destination%20-%3E%20%E5%B0%86source%E7%9A%84%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E5%8F%96%E5%87%BA%E5%B9%B6%E5%8E%8B%E5%88%B0dest%E7%9A%84%E5%A4%B4%E5%85%83%E7%B4%A0%0Alset%20list01%20index%20value%20-%3E%20%E8%AE%BE%E7%BD%AElist01%E4%B8%ADindex%E4%BD%8D%E7%BD%AE%E7%9A%84value%0Alinsert%20list01%20before%2Fafter%20v%20x%20-%3E%20%E5%9C%A8list01%E4%B8%AD%E7%9A%84value%E5%89%8D%2F%E5%90%8E%E6%8F%92%E5%85%A5x%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%205.4%20Set%20%0A%0A%3E%20%E6%97%A0%E5%BA%8F%E6%97%A0%E9%87%8D%E5%A4%8D%0A%0A%60%60%60%0Asadd%20set01%201%202%202%203%203%0Asmembers%20set01%20-%3E%20%E6%89%93%E5%8D%B0%E6%95%B4%E4%B8%AA%E9%9B%86%E5%90%88%0Asismember%20set01%201%20-%3E%20%E5%88%A4%E6%96%AD1%E6%98%AF%E5%90%A6%E5%9C%A8set01%E4%B8%AD%2C%E5%9C%A8%E8%BF%94%E5%9B%9E1%EF%BC%8C%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9E0%0Ascard%20set01%20-%3E%20%E8%8E%B7%E5%8F%96set%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%E4%B8%AA%E6%95%B0%0Asrem%20set01%203%20-%3E%20%E5%88%A0%E9%99%A4%E9%9B%86%E5%90%88set01%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A03%0Asrandmember%20set01%203%20-%3E%E5%9C%A8%E9%9B%86%E5%90%88%E4%B8%AD%E9%9A%8F%E6%9C%BA%E6%8A%BD%E5%8F%963%E4%B8%AA%E5%85%83%E7%B4%A0%0Aspop%20set01%20-%3E%20%E9%9A%8F%E6%9C%BA%E5%BC%B9%E5%87%BA%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E5%B9%B6%E7%A7%BB%E9%99%A4%0Asmove%20set01%20set02%205%20-%3E%20%E6%8A%8Aset01%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A05%E7%A7%BB%E5%8A%A8%E5%88%B0set02%0Asdiff%20set01%20set02%20-%3E%20%E5%8F%96set01%E6%9C%89%E4%BD%86set02%E4%B8%AD%E6%B2%A1%E6%9C%89%E7%9A%84%E5%85%83%E7%B4%A0%0Asunion%20set01%20set02%20-%3E%20%E5%8F%96%E4%B8%A4%E4%B8%AA%E9%9B%86%E5%90%88%E7%9A%84%E5%B9%B6%E9%9B%86%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%205.5%20Zset%20%0A%0A%3E%20sorted%20set%2C%20%E4%B8%8D%E5%90%8C%E7%9A%84%E6%98%AF%E6%AF%8F%E4%B8%AA%E5%85%83%E7%B4%A0%E5%85%B3%E8%81%94%E4%B8%80%E4%B8%AAdouble%E7%B1%BB%E5%9E%8B%E7%9A%84score%EF%BC%8C%E9%80%9A%E8%BF%87score%E6%9D%A5%E4%B8%BA%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%E6%8E%92%E5%BA%8F%E3%80%82%0A%0A%60%60%60%0Azadd%20zset01%2060%20v1%2070%20v2%2080%20v3%2090%20v4%20100%20v5%0Azrange%20zset01%200%20-1%20-%3E%20%E8%8E%B7%E5%8F%96%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%E5%80%BC%0Azrange%20zset01%200%20-1%20withscores%20-%3E%20%E8%8E%B7%E5%8F%96%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%E5%80%BC%E5%8F%8A%E5%85%B6score%0Azrangebyscore%20zset01%2060%2090%20-%3E%20%20%E8%8E%B7%E5%8F%9660%3C%3Dscore%3C%3D90%E7%9A%84value%0Azrangebyscore%20zset01%2060%20(90%20-%3E%20%20%E8%8E%B7%E5%8F%9660%3C%3Dscore%3C90%E7%9A%84value%2C%20%20(%20%E8%A1%A8%E7%A4%BA%E4%B8%8D%E5%8C%85%E5%90%AB%0Azrangebyscore%20zset01%2060%2090%20limit%202%203%20%20-%3E%20%E8%8E%B7%E5%8F%9660%3C%3Dscore%3C%3D90%E7%9A%84value%E5%B9%B6%E4%BB%8Eindex2%E6%88%AA%E5%8F%963%E4%B8%AA%0Azrem%20zset01%20v5%0Azcard%20zset01%20-%3E%20%E8%8E%B7%E5%8F%96%E9%9B%86%E5%90%88%E4%B8%AD%E5%85%83%E7%B4%A0%E7%9A%84%E4%B8%AA%E6%95%B0%0Azcount%20zset01%2060%2080%20-%3E%E7%BB%9F%E8%AE%A1%2060%3C%3Dscore%3C%3D80%E7%9A%84value%E7%9A%84%E4%B8%AA%E6%95%B0%0Azrank%20zset01%20v4%20-%3E%E8%8E%B7%E5%8F%96v4%E5%9C%A8%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E4%BD%8D%E7%BD%AE%E7%9A%84%E7%B4%A2%E5%BC%95%E4%BD%8D%0Azscore%20zset01%20v4%20-%3E%E8%8E%B7%E5%8F%96v4%E7%9A%84score%E5%80%BC%0Azrevrank%20zset01%20v4%20-%3E%20%E9%80%86%E5%BA%8F%E8%8E%B7%E5%8F%96v4%E5%9C%A8%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E4%BD%8D%E7%BD%AE%E7%9A%84%E7%B4%A2%E5%BC%95%E4%BD%8D%0Azrevrange%20zset01%200%20-1%20-%3E%20%E9%80%86%E5%BA%8F%E8%8E%B7%E5%8F%96%E9%9B%86%E5%90%88%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%0Azrevrangebyscore%20zset01%2090%2060%20-%3E%E9%80%86%E5%BA%8F%E8%8E%B7%E5%8F%9660%3C%3Dscore%3E%3D90%E7%9A%84value%0Azrevrangebyscore%20zset01%2090%20(60%20limit%201%202%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%206%20Redis%E9%85%8D%E7%BD%AE%0A%0A%60%60%60%0A%23%201k%20%3D%3E%201000%20bytes%0A%23%201kb%20%3D%3E%201024%20bytes%0A%23%201m%20%3D%3E%201000000%20bytes%0A%23%201mb%20%3D%3E%201024*1024%20bytes%0A%23%201g%20%3D%3E%201000000000%20bytes%0A%23%201gb%20%3D%3E%201024*1024*1024%20bytes%0Aunits%20are%20case%20insensitive%20so%201GB%201Gb%201gB%20are%20all%20the%20same.%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%206.1%20%E9%80%9A%E7%94%A8%E8%AE%BE%E7%BD%AE%0A%0A%60%60%60%0Atcp-backlog%0Atimeout%200%0Atcp-keepalive%20300%0Aloglevel%20debug%7Cverbose%7Cnotice%7Cwarning%0Alogfile%20%22%2Fusr%2Flocal%2Fredis%2Flog%2Fredis.log%22%0Adatabase%2016%0Adir%20.%2F%20-%3E%20%E6%8C%87%E5%AE%9A%E6%9C%AC%E5%9C%B0%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E5%AD%98%E6%94%BE%E7%9B%AE%E5%BD%95%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%206.2%20SECURITY%E5%AE%89%E5%85%A8%0A%0A%60%60%60%0A127.0.0.1%3A6379%3E%20config%20get%20requirepass%0A1)%20%22requirepass%22%0A2)%20%22%22%0A127.0.0.1%3A6379%3E%0Aconfig%20set%20requirepass%20'123456'%20-%3E%20%E8%AE%BE%E7%BD%AE%E5%AF%86%E7%A0%81%0Aauth%20123456%20-%3E%20%E4%BD%BF%E7%94%A8%E5%AF%86%E7%A0%81%E8%AE%A4%E8%AF%81%0Aconfig%20set%20requirepass%20''%20-%3E%20%E5%8F%96%E6%B6%88%E5%AF%86%E7%A0%81%E8%AE%BE%E7%BD%AE%0Aconfig%20get%20dir%20-%3E%20%E4%BB%8E%E9%82%A3%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%8B%E5%90%AF%E5%8A%A8redis%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%206.3%20LIMITS%E9%99%90%E5%88%B6%0A%0A%60%60%60%0Amaxclients%20%E9%BB%98%E8%AE%A410000%0Amaxmemory%20%3Cbytes%3E%0A%0Amaxmemory-policy%0Avolatile-lru%20%20%20%20%20-%3E%20Evict%20using%20approximated%20LRU%20among%20the%20keys%20with%20an%20expire%20set.%0Aallkeys-lru%20%20%20%20%20%20-%3E%20Evict%20any%20key%20using%20approximated%20LRU.%0Avolatile-lfu%20%20%20%20%20-%3E%20Evict%20using%20approximated%20LFU%20among%20the%20keys%20with%20an%20expire%20set.%0Aallkeys-lfu%20%20%20%20%20%20-%3E%20Evict%20any%20key%20using%20approximated%20LFU.%0Avolatile-random%20%20-%3E%20Remove%20a%20random%20key%20among%20the%20ones%20with%20an%20expire%20set.%0Aallkeys-random%20%20%20-%3E%20Remove%20a%20random%20key%2C%20any%20key.%0Avolatile-ttl%20%20%20%20%20-%3E%20Remove%20the%20key%20with%20the%20nearest%20expire%20time%20(minor%20TTL)%0Anoeviction%20%20%20%20%20%20%20-%3E%20Don't%20evict%20anything%2C%20just%20return%20an%20error%20on%20write%20operations%2C%20set%20as%20default.%0A%60%60%60%0A%0A%23%23%23%23%23%23%20%206.3.1%20LRU%20%E5%92%8C%20LFU%0A%0A%60%60%60%0ALRU%20%E6%9C%80%E8%BF%91%E6%9C%80%E4%B9%85%E6%9C%AA%E8%AE%BF%E9%97%AE%E7%9A%84%E3%80%82%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%9C%A8%E6%9C%80%E8%BF%91%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%E6%B2%A1%E6%9C%89%E8%A2%AB%E8%AE%BF%E9%97%AE%E5%88%B0%EF%BC%8C%E9%82%A3%E4%B9%88%E5%9C%A8%E5%B0%86%E6%9D%A5%E5%AE%83%E8%A2%AB%E8%AE%BF%E9%97%AE%E7%9A%84%E5%8F%AF%E8%83%BD%E6%80%A7%E4%B9%9F%E5%BE%88%E5%B0%8F%E3%80%82%0ALFU%20%E6%9C%80%E8%BF%91%E6%9C%80%E5%B0%91%E4%BD%BF%E7%94%A8%E7%AE%97%E6%B3%95%E3%80%82%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%9C%A8%E6%9C%80%E8%BF%91%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%E5%86%85%E4%BD%BF%E7%94%A8%E6%AC%A1%E6%95%B0%E5%BE%88%E5%B0%91%EF%BC%8C%E9%82%A3%E4%B9%88%E5%9C%A8%E5%B0%86%E6%9D%A5%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%E5%86%85%E8%A2%AB%E4%BD%BF%E7%94%A8%E7%9A%84%E5%8F%AF%E8%83%BD%E6%80%A7%E4%B9%9F%E5%BE%88%E5%B0%8F%E2%80%9D%E7%9A%84%E6%80%9D%E8%B7%AF%E3%80%82%0A%E6%B3%A8%E6%84%8FLFU%E5%92%8CLRU%E7%AE%97%E6%B3%95%E7%9A%84%E4%B8%8D%E5%90%8C%E4%B9%8B%E5%A4%84%EF%BC%8CLRU%E7%9A%84%E6%B7%98%E6%B1%B0%E8%A7%84%E5%88%99%E6%98%AF%E5%9F%BA%E4%BA%8E%E8%AE%BF%E9%97%AE%E6%97%B6%E9%97%B4%EF%BC%8C%E8%80%8CLFU%E6%98%AF%E5%9F%BA%E4%BA%8E%E8%AE%BF%E9%97%AE%E6%AC%A1%E6%95%B0%E7%9A%84%E3%80%82%0A%E4%B8%BE%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E4%BE%8B%E5%AD%90%EF%BC%9A%0A%20%20%20%20%E5%81%87%E8%AE%BE%E7%BC%93%E5%AD%98%E5%A4%A7%E5%B0%8F%E4%B8%BA3%EF%BC%8C%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%E5%BA%8F%E5%88%97%E4%B8%BA%0A%20%20%20%20set(2%2C2)%2Cset(1%2C1)%0A%20%20%20%20get(2)%2Cget(1)%2Cget(2)%0A%20%20%20%20set(3%2C3)%2Cset(4%2C4)%EF%BC%8C%0A%20%20%20%20%E5%88%99%E5%9C%A8set(4%2C4)%E6%97%B6%E5%AF%B9%E4%BA%8ELFU%E7%AE%97%E6%B3%95%E5%BA%94%E8%AF%A5%E6%B7%98%E6%B1%B0(3%2C3)%EF%BC%8C%E8%80%8CLRU%E5%BA%94%E8%AF%A5%E6%B7%98%E6%B1%B0(1%2C1)%E3%80%82%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%207.%20%E6%8C%81%E4%B9%85%E5%8C%96%0A%0A%23%23%23%23%23%207.1%20RDB%20%5BRedis%20DataBase%5D%0A%0A%23%23%23%23%23%23%207.1.1%20%E5%8E%9F%E7%90%86%0A%0A%3E%20%E5%9C%A8%E6%8C%87%E5%AE%9A%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%E5%86%85%E5%B0%86%E6%95%B0%E6%8D%AE%E9%9B%86%E5%BF%AB%E7%85%A7%E5%86%99%E5%85%A5%E7%A3%81%E7%9B%98%EF%BC%8C%E6%81%A2%E5%A4%8D%E6%97%B6%E7%9B%B4%E6%8E%A5%E5%B0%86snapshot%E5%BF%AB%E7%85%A7%E8%AF%BB%E5%85%A5%E5%86%85%E5%AD%98%E3%80%82%0A%3E%0A%3E%20%E5%8D%95%E7%8B%AC%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAfork%E4%B8%80%E4%B8%AA%E5%AD%90%E8%BF%9B%E7%A8%8B%E8%BF%9B%E8%A1%8C%E6%8C%81%E4%B9%85%E5%8C%96%EF%BC%8C%E4%BC%9A%E5%85%88%E5%B0%86%E6%95%B0%E6%8D%AE%E5%86%99%E5%85%A5%E5%88%B0%E4%B8%80%E4%B8%AA%E4%B8%B4%E6%97%B6%E6%96%87%E4%BB%B6%E4%B8%AD%EF%BC%8C%E5%BE%85%E6%8C%81%E4%B9%85%E5%8C%96%E8%BF%87%E7%A8%8B%E7%BB%93%E6%9D%9F%E4%BC%9A%EF%BC%8C%E5%86%8D%E7%94%A8%E8%BF%99%E4%B8%AA%E4%B8%B4%E6%97%B6%E6%96%87%E4%BB%B6%E4%BB%A3%E6%9B%BF%E4%B8%8A%E6%AC%A1%E6%8C%81%E4%B9%85%E5%8C%96%E5%A5%BD%E7%9A%84%E6%96%87%E4%BB%B6%EF%BC%8C%E6%95%B4%E4%B8%AA%E8%BF%87%E7%A8%8B%E4%B8%AD%E4%B8%BB%E8%BF%9B%E7%A8%8B%E4%B8%8D%E8%BF%9B%E8%A1%8C%E4%BB%BB%E4%BD%95IO%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%BF%99%E5%B0%B1%E7%A1%AE%E4%BF%9D%E4%BA%86%E6%9E%81%E9%AB%98%E7%9A%84%E6%80%A7%E8%83%BD%E3%80%82%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E8%A6%81%E8%BF%9B%E8%A1%8C%E5%A4%A7%E8%A7%84%E6%A8%A1%E7%9A%84%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D%EF%BC%8C%E4%B8%94%E5%AF%B9%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D%E7%9A%84%E5%AE%8C%E6%95%B4%E6%80%A7%E8%A6%81%E6%B1%82%E4%B8%8D%E6%98%AF%E5%BE%88%E9%AB%98%EF%BC%8C%E9%82%A3RDB%E6%AF%94AOF%E7%9A%84%E6%96%B9%E5%BC%8F%E6%9B%B4%E4%B8%BA%E9%AB%98%E6%95%88%E3%80%82%0A%3E%0A%3E%20Fork%E7%9A%84%E4%BD%9C%E7%94%A8%E6%98%AF%E5%A4%8D%E5%88%B6%E4%B8%80%E4%B8%AA%E4%B8%8E%E5%BD%93%E5%89%8D%E8%BF%9B%E7%A8%8B%E4%B8%80%E6%A0%B7%E7%9A%84%E8%BF%9B%E7%A8%8B%EF%BC%8C%E6%96%B0%E8%BF%9B%E7%A8%8B%E7%9A%84%E6%89%80%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%88%E5%8F%98%E9%87%8F%EF%BC%8C%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%EF%BC%8C%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%EF%BC%89%E4%B8%8E%E5%8E%9F%E8%BF%9B%E7%A8%8B%E4%B8%80%E8%87%B4%EF%BC%8C%E4%BD%86%E6%98%AF%E5%AE%83%E6%98%AF%E4%B8%80%E4%B8%AA%E5%85%A8%E6%96%B0%E7%9A%84%E8%BF%9B%E7%A8%8B%E5%B9%B6%E4%BD%9C%E4%B8%BA%E5%8E%9F%E8%BF%9B%E7%A8%8B%E7%9A%84%E5%AD%90%E8%BF%9B%E7%A8%8B%E3%80%82%0A%0A%23%23%23%23%23%23%207.1.2%20%E7%BC%BA%E7%82%B9%0A%0A%60%60%60%0A1.%20RDB%E7%9A%84%E7%BC%BA%E7%82%B9%E6%98%AF%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E6%8C%81%E4%B9%85%E5%8C%96%E5%90%8E%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%83%BD%E4%B8%A2%E5%A4%B1%0A2.%20%E5%BD%93%E4%B8%BB%E7%A8%8B%E5%BA%8F%E6%95%B0%E6%8D%AE%E9%87%8F%E5%BE%88%E5%A4%A7%E6%97%B6%EF%BC%8Cfork%E4%B8%80%E4%B8%AA%E5%AD%90%E8%BF%9B%E5%BE%97%E9%9D%9E%E5%B8%B8%E6%B6%88%E8%80%97%E8%B5%84%E6%BA%90%EF%BC%8C%E7%9B%B8%E5%BD%93%E4%BA%8E%E5%B0%86%E5%8E%9F%E8%BF%9B%E7%A8%8Bdouble%E4%B8%80%E4%BB%BD%E3%80%82%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%207.1.3%20%E8%A7%A6%E5%8F%91%E6%97%B6%E6%9C%BA%0A%0ARDB%E4%BF%9D%E5%AD%98%E6%98%AF%E7%9A%84dump.rdb%E6%96%87%E4%BB%B6%0A%0A%60%60%60%0Asave%20%3Cseconds%3E%20%3Cchanges%3E%0Asave%20900%201%20%20%20%20-%3E%20after%20900%20sec%20(15%20min)%20if%20at%20least%201%20key%20changed%0Asave%20300%2010%20%20%20-%3E%20after%20300%20sec%20(5%20min)%20if%20at%20least%2010%20keys%20changed%0Asave%2060%2010000%20-%3E%20%20after%2060%20sec%20if%20at%20least%2010000%20keys%20changed%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%207.1.4%20save%20%E5%92%8C%20bgsave%0A%0A%E4%BD%BF%E7%94%A8save%E6%88%96bgsave%E5%91%BD%E4%BB%A4%E6%89%8B%E5%8A%A8%E5%8D%B3%E5%88%BB%E5%A4%87%E4%BB%BD%0A%0A1.%20save%20%E5%8F%AA%E7%AE%A1%E4%BF%9D%E5%AD%98%EF%BC%8C%E5%9C%A8%E4%BF%9D%E5%AD%98%E6%97%B6%E5%85%B6%E5%AE%83%E7%BA%BF%E7%A8%8B%E9%98%BB%E5%A1%9E%EF%BC%8C%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E5%BE%88%E5%B0%91%E6%89%A7%E8%A1%8C%20%5BSAVE%5D(http%3A%2F%2Fredisdoc.com%2Fpersistence%2Fsave.html%23save)%20%E6%93%8D%E4%BD%9C%0A%0A2.%20bgsave%20fock%E4%B8%80%E4%B8%AA%E5%AD%90%E8%BF%9B%E7%A8%8B%E5%BC%82%E6%AD%A5%E8%BF%9B%E8%A1%8C%E5%BF%AB%E7%85%A7%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%90%8C%E6%97%B6%E7%88%B6%E8%BF%9B%E7%A8%8B%E8%BF%98%E5%8F%AF%E4%BB%A5%E5%93%8D%E5%BA%94%E5%BD%93%E5%89%8D%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AF%B7%E6%B1%82.%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%20lastsave%20%E8%8E%B7%E4%BA%86%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E6%88%90%E5%8A%9F%E6%89%A7%E8%A1%8C%E5%BF%AB%E7%85%A7%E7%9A%84%E6%97%B6%E9%97%B4%E6%9D%A5%E5%88%A4%E6%96%ADbgsave%E6%98%AF%E5%90%A6%E6%88%90%E5%8A%9F%E3%80%82%0A%0A%0A%0A7.1.5%20%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%E9%A1%B9%0A%0A%60%60%60%0Astop-writes-on-bgsave-error%20yes%0Ardbcompression%20yes%0Ardbchecksum%20yes%20-%3E%20%E4%BD%BF%E7%94%A8CRC64%E7%AE%97%E6%B3%95%E6%A0%A1%E9%AA%8C%E6%95%B0%E6%8D%AE%E5%AE%8C%E6%95%B4%E6%80%A7%0Adbfilename%20dump.rdb%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%207.2%20AOF%20%5BAppend%20Only%20File%5D%0A%0A%23%23%23%23%23%23%207.2.1%20%E5%8E%9F%E7%90%86%0A%0A%3E%20%E4%BB%A5%E6%97%A5%E5%BF%97%E7%9A%84%E5%BD%A2%E5%BC%8F%E8%AE%B0%E5%BD%95%E6%AF%8F%E4%B8%AA%E5%86%99%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%8F%AA%E8%AE%B8%E8%BF%BD%E5%8A%A0%E6%96%87%E4%BB%B6%E4%BD%86%E4%B8%8D%E8%83%BD%E6%94%B9%E5%86%99%E6%96%87%E4%BB%B6%EF%BC%8Credis%E5%90%AF%E5%8A%A8%E6%97%B6%E5%B0%86%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E4%BB%8E%E5%A4%B4%E5%88%B0%E5%B0%BE%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%E5%AE%8C%E6%88%90%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D%E3%80%82%0A%0A%0A%0A%23%23%23%23%23%23%207.2.2%20%E7%BC%BA%E7%82%B9%0A%0A%3E%20aof%E6%96%87%E4%BB%B6%E4%B8%8D%E6%96%AD%E5%A2%9E%E9%95%BF%E5%8F%98%E5%A4%A7%EF%BC%8C%E6%96%87%E4%BB%B6%E8%BF%9C%E5%A4%A7%E4%BA%8Erdb%EF%BC%8C%E6%81%A2%E5%A4%8D%E9%80%9F%E5%BA%A6%E6%85%A2%E4%BA%8Erdb%EF%BC%8C%E8%BF%90%E8%A1%8C%E6%95%88%E7%8E%87%E6%85%A2%E4%BA%8Erdb%E3%80%82%0A%3E%0A%3E%20%E6%AF%8F%E6%AC%A1load%20aof%E6%96%87%E4%BB%B6%E6%97%B6%E5%B8%A6%E6%9D%A5%E6%8C%81%E7%BB%AD%E7%9A%84IO%E3%80%82%0A%0A%0A%0A%23%23%23%23%23%23%207.2.3%20AOF%E9%85%8D%E7%BD%AE%0A%0A%60%60%60%0Aappendonly%20no%20-%3E%20%E8%A6%81%E7%94%A8aof%EF%BC%8C%E9%9C%80%E8%A6%81%E6%94%B9%E4%B8%BAyes%0Aappendfilename%0Aappendfsync%20%3A%20aof%E5%A4%87%E4%BB%BD%0A%09always%20%20%20-%3E%20%E5%90%8C%E6%AD%A5%E6%8C%81%E4%B9%85%E5%8C%96%EF%BC%8C%E6%AF%8F%E4%B8%80%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E9%83%BD%E4%BC%9A%E8%A2%AB%E7%AB%8B%E5%88%BB%E8%AE%B0%E5%BD%95%E5%88%B0%E7%A3%81%E7%9B%98%0A%09everysec%20-%3E%20%E9%BB%98%E8%AE%A4%E8%AE%BE%E7%BD%AE%EF%BC%8C%E5%BC%82%E6%AD%A5%E6%93%8D%E4%BD%9C%E6%AF%8F%E7%A7%92%E8%AE%B0%E5%BD%95%E4%B8%80%2C%E5%A6%82%E6%9E%9C%E4%B8%80%E7%A7%92%E5%86%85%E5%AE%95%E6%9C%BA%E4%BC%9A%E6%9C%89%E6%95%B0%E6%8D%AE%E4%B8%A2%E5%A4%B1%0A%20%20%20%20no%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%207.2.4%20Rewrite%E6%9C%BA%E5%88%B6%0A%0A1.%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%20%20%20%3E%20appendonly.aof%E6%96%87%E4%BB%B6%E9%87%87%E7%94%A8%E6%96%87%E4%BB%B6%E8%BF%BD%E5%8A%A0%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E6%96%87%E4%BB%B6%E4%BC%9A%E5%8F%98%E5%BE%97%E8%B6%8A%E6%9D%A5%E8%B6%8A%E5%A4%A7%EF%BC%8C%E5%BD%93%E6%96%87%E4%BB%B6%E5%A4%A7%E5%B0%8F%E8%B6%85%E8%BF%87%E8%AE%BE%E7%BD%AE%E7%9A%84%E9%98%88%E5%80%BC%E6%97%B6%EF%BC%8CRedis%E4%BC%9A%E5%90%AF%E5%8A%A8AOF%E5%86%85%E5%AE%B9%E7%9A%84%E5%8E%8B%E7%BC%A9%2C%E5%8F%AA%E4%BF%9D%E7%95%99%E5%8F%AF%E4%BB%A5%E6%81%A2%E5%A4%8D%E6%95%B0%E6%8D%AE%E7%9A%84%E6%9C%80%E5%B0%8F%E6%8C%87%E4%BB%A4%E9%9B%86%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E5%91%BD%E4%BB%A4bgrewriteaof%E3%80%82%0A%0A2.%20%E9%87%8D%E5%86%99%E5%8E%9F%E7%90%86%0A%0A%20%20%20%3E%20AOF%E6%96%87%E4%BB%B6%E6%8C%81%E7%BB%AD%E5%A2%9E%E9%95%BF%E5%8F%98%E5%A4%A7%EF%BC%8C%E4%BC%9Afork%E5%87%BA%E4%B8%80%E6%9D%A1%E6%96%B0%E8%BF%9B%E7%A8%8B%E5%B0%86%E6%96%87%E4%BB%B6%E9%87%8D%E5%86%99%EF%BC%8C%E5%85%88%E5%86%99%E4%B8%B4%E6%97%B6%E6%96%87%E4%BB%B6%E5%86%8Drename%EF%BC%8C%E9%87%8D%E5%86%99aof%E6%96%87%E4%BB%B6%E6%97%B6%E5%B9%B6%E6%B2%A1%E6%9C%89%E8%AF%BB%E5%8F%96%E6%97%A7%E7%9A%84aof%E6%96%87%E4%BB%B6%EF%BC%8C%E8%80%8C%E6%98%AF%E5%B0%86%E6%95%B4%E4%B8%AA%E5%86%85%E5%AD%98%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E5%86%85%E5%AE%B9%E7%94%A8%E5%91%BD%E4%BB%A4%E7%9A%84%E6%96%B9%E5%BC%8F%E9%87%8D%E5%86%99%E4%BA%86%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84aof%E6%96%87%E4%BB%B6%E3%80%82%0A%0A3.%20%E8%A7%A6%E5%8F%91%E6%9C%BA%E5%88%B6%0A%0A%20%20%20%3E%20redis%E4%BC%9A%E8%AE%B0%E5%BD%95%E4%B8%8A%E6%AC%A1%E9%87%8D%E5%86%99%E6%97%B6%E7%9A%84aof%E6%96%87%E4%BB%B6%E7%9A%84%E5%A4%A7%E5%B0%8F%EF%BC%8C%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E6%98%AF%E5%BD%93AOF%E6%96%87%E4%BB%B6%E5%A4%A7%E5%B0%8F%E6%98%AF%E4%B8%8A%E6%AC%A1rewrite%E5%90%8E%E5%A4%A7%E5%B0%8F%E7%9A%84%E4%B8%80%E5%80%8D%E4%B8%94%E5%A4%A7%E4%BA%8E64M%E6%97%B6%E8%A7%A6%E5%8F%91.%0A%0A%20%20%20%60%60%60%0A%20%20%20auto-aof-rewrite-percentage%20100%0A%20%20%20auto-aof-rewrite-min-size%20%0964mb%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%207.2.5%20%E4%BF%AE%E5%A4%8DAOF%E6%96%87%E4%BB%B6%0A%0A%60%60%60%0A.%2Fredis-check-aof%20--fix%20appendonly.aof%0Ayes%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%207.3%20%E6%80%BB%E7%BB%93%0A%0A!%5B6fa75a7f4bd608452f777d26058508d0.png%5D(en-resource%3A%2F%2Fdatabase%2F1143%3A1)%0A%0A%0A%0A%23%23%23%23%208.%20Redis%E7%9A%84%E4%BA%8B%E5%8A%A1%0A%0A%23%23%23%23%23%208.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E4%B8%80%E6%AC%A1%E6%80%A7%E6%89%A7%E8%A1%8C%E5%A4%9A%E4%B8%AA%E5%91%BD%E4%BB%A4%EF%BC%8C%E6%9C%AC%E8%B4%A8%E6%98%AF%E4%B8%80%E7%BB%84%E5%91%BD%E4%BB%A4%E7%9A%84%E9%9B%86%E5%90%88%EF%BC%8C%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E5%91%BD%E4%BB%A4%E9%83%BD%E4%BC%9A%E8%A2%AB%E5%BA%8F%E5%88%97%E5%8C%96%EF%BC%8C%E6%8C%89%E9%A1%BA%E5%BA%8F%E4%B8%B2%E8%A1%8C%E5%8C%96%E6%89%A7%E8%A1%8C%E8%80%8C%E4%B8%8D%E5%85%81%E8%AE%B8%E5%85%B6%E5%AE%83%E5%91%BD%E4%BB%A4%E5%8A%A0%E5%A1%9E%0A%0A%0A%0A%23%23%23%23%23%208.2%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%3E%20multi%20%E6%A0%87%E8%AE%B0%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%BC%80%E5%90%AF%EF%BC%8C%E5%B9%B6%E8%BF%94%E5%9B%9Eok.%0A%3E%0A%3E%20exec%20%E8%A2%ABredis%E8%B0%83%E7%94%A8%EF%BC%8C%E6%9D%A5%E6%89%A7%E8%A1%8C%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E4%B8%AD%E5%85%A5%E9%98%9F%E7%9A%84%E5%A4%9A%E4%B8%AA%E5%91%BD%E4%BB%A4%0A%3E%0A%3E%20discard%20%E6%94%BE%E5%BC%83%E6%9C%AC%E6%AC%A1%E4%BA%8B%E5%8A%A1%0A%3E%0A%3E%20unwatch%20%E5%8F%96%E6%B6%88%E5%AF%B9%E6%89%80%E6%9C%89key%E7%9A%84%E7%9B%91%E8%A7%86%0A%3E%0A%3E%20watch%20k1%20k2...%20%E7%9B%91%E8%A7%86%E4%B8%80%E4%B8%AA%E6%88%96%E8%80%85%E5%A4%9A%E4%B8%AAkey%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%9C%A8%E4%BA%8B%E5%8A%A1%E6%89%A7%E8%A1%8Cexec%E4%B9%8B%E5%89%8D%E8%BF%99%E4%BA%9B%E8%A2%AB%E7%9B%91%E6%8E%A7%E7%9A%84key%E8%A2%AB%E5%85%B6%E5%AE%83%E5%91%BD%E4%BB%A4%E6%94%B9%E5%8A%A8%EF%BC%8C%E9%82%A3%E4%B9%88%E4%BA%8B%E5%8A%A1%E5%B0%86%E8%A2%AB%E6%89%93%E6%96%AD%EF%BC%8C%E4%B8%80%E4%BD%86%E6%89%A7%E8%A1%8C%E4%BA%86exec%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%B9%8B%E5%89%8D%E5%8A%A0%E7%9A%84%E7%9B%91%E6%8E%A7%E9%94%81%E9%83%BD%E4%BC%9A%E8%A2%AB%E6%B8%85%E7%90%86%E6%8E%89%E3%80%82%0A%0A%0A%0Awatch%E7%9B%91%E6%8E%A7%EF%BC%9A%0A%0A%60%60%60%0A%E8%A1%8C%E7%BA%A7%E9%94%81%EF%BC%9A%0A%E8%A1%A8%E7%BA%A7%E9%94%81%EF%BC%9A%E8%BF%B8%E5%8F%91%E6%97%B6%E6%9E%81%E5%B7%AE%EF%BC%8C%E4%BD%86%E4%B8%80%E8%87%B4%E6%80%A7%E6%98%AF%E5%A5%BD%0A%E6%82%B2%E8%A7%82%E9%94%81%3A%0A%E4%B9%90%E8%A7%82%E9%94%81%0ACAS%20check-and-set%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%208.3%20%20redis%E9%83%A8%E5%88%86%E6%94%AF%E8%A1%8C%E4%BA%8B%E5%8A%A1%0A%0A%23%23%23%23%23%23%208.3.1%20%E9%9B%86%E4%BD%93%E8%BF%9E%E5%9D%90%0A%0A%3E%20%E5%9C%A8%E7%BC%96%E8%AF%91%E8%BF%87%E7%A8%8B%E4%B8%AD%E5%87%BA%E9%94%99%E6%97%B6%EF%BC%8C%E6%95%B4%E4%B8%AA%E4%BA%8B%E5%8A%A1%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E5%91%BD%E4%BB%A4%E9%9B%86%E4%BD%93%E5%A4%B1%E8%B4%A5%E3%80%82%0A%0A%60%60%60%0A127.0.0.1%3A6379%3E%20multi%0AOK%0A127.0.0.1%3A6379%3E%20set%20k1%2011%0AQUEUED%0A127.0.0.1%3A6379%3E%20set%20k2%2022%0AQUEUED%0A127.0.0.1%3A6379%3E%20setget%20k3%2033%0A(error)%20ERR%20unknown%20command%20%60setget%60%2C%20with%20args%20beginning%20with%3A%20%60k3%60%2C%20%6033%60%2C%0A127.0.0.1%3A6379%3E%20get%20k2%0AQUEUED%0A127.0.0.1%3A6379%3E%20exec%0A(error)%20EXECABORT%20Transaction%20discarded%20because%20of%20previous%20errors.%0A127.0.0.1%3A6379%3E%20keys%20*%0A(empty%20list%20or%20set)%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%208.3.2%20%E5%86%A4%E5%A4%B4%E5%80%BA%E4%B8%BB%0A%0A%3E%20%E5%9C%A8%E6%89%A7%E8%A1%8C%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%E5%87%BA%E9%94%99%E6%97%B6%EF%BC%8C%E5%8F%AA%E6%9C%89%E5%87%BA%E9%94%99%E7%9A%84%E5%91%BD%E4%BB%A4%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%85%B6%E5%AE%83%E5%91%BD%E4%BB%A4%E6%AD%A3%E5%B8%B8%E6%89%A7%E8%A1%8C%0A%0A%60%60%60%0A127.0.0.1%3A6379%3E%20multi%0AOK%0A127.0.0.1%3A6379%3E%20incr%20k1%0AQUEUED%0A127.0.0.1%3A6379%3E%20get%20k1%0AQUEUED%0A127.0.0.1%3A6379%3E%20get%20k2%0AQUEUED%0A127.0.0.1%3A6379%3E%20set%20k4%20v4%0AQUEUED%0A127.0.0.1%3A6379%3E%20exec%0A1)%20(error)%20ERR%20value%20is%20not%20an%20integer%20or%20out%20of%20range%0A2)%20%22v1%22%0A3)%20%22v2%22%0A4)%20OK%0A%60%60%60%0A%0A%60%60%60%0A127.0.0.1%3A6379%3E%20multi%0AOK%0A127.0.0.1%3A6379%3E%20decrby%20balance%2020%0AQUEUED%0A127.0.0.1%3A6379%3E%20incrby%20debt%2020%0AQUEUED%0A127.0.0.1%3A6379%3E%20exec%0A1)%20(integer)%2080%0A2)%20(integer)%2020%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%209.%20Redis%E7%9A%84%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%5BMaster%2FSlave%5D%0A%0A%23%23%23%23%23%209.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%88%91%E4%BB%AC%E6%89%80%E8%AF%B4%E7%9A%84%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%EF%BC%8C%E4%B8%BB%E6%9C%BA%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E5%90%8E%E6%A0%B9%E6%8D%AE%E9%85%8D%E7%BD%AE%E5%92%8C%E7%AD%96%E7%95%A5%E8%87%AA%E5%8A%A8%E5%90%8C%E6%AD%A5%E5%88%B0%E5%A4%87%E6%9C%BA%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%09Master%E4%BB%A5%E5%86%99%E4%B8%BA%E4%B8%BB%EF%BC%8CSlave%E4%BB%A5%E8%AF%BB%E4%B8%BA%E4%B8%BB%0A%0A%23%23%23%23%23%23%209.2%20%E5%A4%8D%E5%88%B6%E5%8E%9F%E7%90%86%0A%0A%3E%20salve%E5%90%AF%E5%8A%A8%E6%88%90%E5%8A%9F%E8%BF%9E%E6%8E%A5%E5%88%B0master%E5%90%8E%E4%BC%9A%E5%8F%91%E5%85%B3%E4%B8%80%E4%B8%AAsync%E5%91%BD%E4%BB%A4%EF%BC%8Cmaster%E5%B0%86%E6%95%B4%E4%B8%AA%E6%95%B0%E6%8D%AE%E6%96%87%E4%BB%B6%E5%85%A8%E9%87%8F%E5%8F%91%E9%80%81%E5%88%B0slave%EF%BC%8C%E6%AD%A4%E5%90%8Emaster%E6%96%B0%E5%A2%9E%E7%9A%84%E6%95%B0%E6%8D%AE%E4%BC%9A%E5%A2%9E%E9%87%8F%E5%A4%8D%E5%88%B6%E5%88%B0slaver%2C%20%E4%BD%86%E6%98%AF%E5%8F%AA%E8%A6%81%E9%87%8D%E6%96%B0%E8%BF%9E%E6%8E%A5%E4%B8%80%E6%AC%A1master%E5%B0%B1%E4%BC%9A%E9%A6%96%E5%85%88%E5%81%9A%E4%B8%80%E6%AC%A1%E5%85%A8%E9%87%8F%E5%A4%8D%E5%88%B6%E3%80%82%0A%3E%20%E5%A4%8D%E5%88%B6%E6%9C%80%E5%A4%A7%E7%9A%84%E7%BC%BA%E7%82%B9%E5%B0%B1%E6%98%AF%E5%BB%B6%E6%97%B6%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%89%80%E7%9A%84%E6%9C%89%E5%86%99%E6%93%8D%E4%BD%9C%E9%83%BD%E5%9C%A8master%E4%B8%8A%EF%BC%8C%E7%84%B6%E5%90%8E%E5%90%8C%E6%AD%A5%E6%9B%B4%E6%96%B0%E5%88%B0slaver%E4%B8%8A%EF%BC%8C%E6%89%80%E4%BB%A5master%E5%90%8C%E6%AD%A5%E5%88%B0slaver%E4%BC%9A%E6%9C%89%E4%B8%80%E5%AE%9A%E7%9A%84%E5%BB%B6%E6%97%B6%E3%80%82%0A%0A%23%23%23%23%23%209.3%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%20%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB%EF%BC%8C%E5%AE%B9%E7%81%BE%E6%81%A2%E5%A4%8D%0A%0A%23%23%23%23%23%209.4%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%23%23%209.4.1%20%E9%85%8D%E7%BD%AE%E6%AD%A5%E9%AA%A4%0A%0A1.%20%E9%85%8D%E4%BB%8E%E4%B8%8D%E9%85%8D%E4%B8%BB%0A%0A2.%20%E5%A4%87%E6%9C%BA%E9%85%8D%E7%BD%AE%0A%0A%20%20%20%60%60%60%0A%20%20%20slaveof%20master-ip%20master-portnumber%0A%20%20%20%60%60%60%0A%0A%20%20%20%E6%AF%8F%E6%AC%A1%E4%B8%8Emaster%E6%96%AD%E5%BC%80%E4%B9%8B%E5%90%8E%EF%BC%8C%E9%83%BD%E9%9C%80%E8%A6%81%E9%87%8D%E6%96%B0%E8%BF%9E%E6%8E%A5%EF%BC%8C%E9%99%A4%E9%9D%9E%E4%BD%A0%E9%85%8D%E7%BD%AE%E5%88%B0redis.conf%E6%96%87%E4%BB%B6%0A%0A3.%20%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60%0A%20%20%20%E6%8B%B7%E8%B4%9D%E5%A4%9A%E4%B8%AAredis.conf%E6%96%87%E4%BB%B6%0A%20%20%20%E5%BC%80%E5%90%AFdaemonize%20yes%20%0A%20%20%20Pid%E6%96%87%E4%BB%B6%E5%90%8D%E7%A7%B0%0A%20%20%20%E6%8C%87%E5%AE%9A%E7%AB%AF%E5%8F%A3%0A%20%20%20Log%20%E6%96%87%E4%BB%B6%E5%90%8D%E7%A7%B0%0A%20%20%20Dump.rdb%20%E5%90%8D%E7%A7%B0%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%209.4.2%20%E5%B8%B8%E7%94%A83%E6%8B%9B%0A%0A1.%20%E4%B8%80%E4%B8%BB%E4%BA%8C%E4%BB%86%0A%0A%20%20%20%60%60%60%0A%20%20%20127.0.0.1%3A6379%3E%20info%20replication%0A%20%20%20master%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6379.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206379%0A%20%20%20%0A%20%20%20slave01%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6380.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206380%0A%20%20%20slaveof%20127.0.0.1%206379%0A%20%20%20%0A%20%20%20slave02%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6381.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206381%0A%20%20%20slaveof%20127.0.0.1%206379%0A%20%20%20%0A%20%20%20%E5%8F%AA%E6%9C%89master%E8%8A%82%E7%82%B9%E5%8F%AF%E4%BB%A5%E5%86%99%EF%BC%8Csalve%E8%8A%82%E7%82%B9%E4%B8%8D%E8%83%BD%E5%86%99%E5%8F%AA%E8%83%BD%E8%AF%BB%E5%8F%96%0A%20%20%20%E5%A6%82%E6%9E%9C%E4%B8%BB%E6%9C%BA%E5%AE%95%E6%9C%BA%EF%BC%8C%E5%A4%87%E6%9C%BA%E5%8E%9F%E5%9C%B0%E5%BE%85%E5%91%BD%0A%20%20%20%60%60%60%0A%20%20%20!%5Be92ddfd22e28047bef0e25e3e4a91c3b.png%5D(en-resource%3A%2F%2Fdatabase%2F1144%3A1)%0A%20%20%20%0A%0A%0A2.%20%E8%96%AA%E7%81%AB%E7%9B%B8%E4%BC%A0(%E5%8E%BB%E4%B8%AD%E5%BF%83%E5%8C%96)%0A%0A%20%20%20%E4%B8%8A%E4%B8%80%E4%B8%AAslave%E5%8F%AF%E4%BB%A5%E6%98%AF%E4%B8%8B%E4%B8%80%E4%B8%AAslave%E7%9A%84master%20%E6%9D%A5%E6%8E%A5%E6%94%B6%E5%85%B6%E5%AE%83%E8%BF%9E%E6%8E%A5%E5%92%8C%E8%AF%B7%E6%B1%82%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%8F%AF%E4%BB%A5%E6%9C%89%E6%95%88%E7%9A%84%E5%87%8F%E8%BD%BB%E9%93%BE%E6%9D%A1%E4%B8%ADmaster%E7%9A%84%E5%86%99%E5%8E%8B%E5%8A%9B%E3%80%82%0A%0A%20%20%20%60%60%60%0A%20%20%20127.0.0.1%3A6379%3E%20info%20replication%0A%20%20%20master%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6379.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206379%0A%20%20%20%0A%20%20%20slave01%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6380.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206380%0A%20%20%20slaveof%20127.0.0.1%206379%0A%20%20%20%0A%20%20%20slave02%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6381.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206381%0A%20%20%20slaveof%20127.0.0.1%206380%0A%20%20%20%60%60%60%0A%20%20%20%20!%5B1bad00ac07d858804b82fe9e32a386c7.png%5D(en-resource%3A%2F%2Fdatabase%2F1145%3A1)%0A%20%20%20%20%0A%0A%0A%0A3.%20%E5%8F%8D%E5%AE%A2%E4%B8%BA%E4%B8%BB(%E5%BD%93master%E6%8C%82%E6%8E%89%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%BB%8E%E6%96%B0%E5%88%86%E9%85%8D)%0A%0A%20%20%20%60%60%60%0A%20%20%20127.0.0.1%3A6379%3E%20info%20replication%0A%20%20%20master%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6379.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206379%0A%20%20%20shundown%0A%20%20%20exit%0A%20%20%20%0A%20%20%20slave01%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6380.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206380%0A%20%20%20slaveof%20no%20one%0A%20%20%20%0A%20%20%20slave02%3A%0A%20%20%20.%2Fredis-server%20%2Fmyredis%2Fredis_6381.conf%0A%20%20%20.%2Fredis-cli%20%20-p%206381%0A%20%20%20slaveof%20127.0.0.1%206380%0A%20%20%20%60%60%60%0A%0A%0A%23%23%23%23%2010.%20%E5%93%A8%E5%85%B5%E6%A8%A1%E5%BC%8Fsentinel%0A%0A%23%23%23%23%23%2010.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E6%98%AF%E5%8F%8D%E5%AE%A2%E4%B8%BA%E4%B8%BB%E7%9A%84%E8%87%AA%E5%8A%A8%E7%89%88%E6%9C%AC%EF%BC%8C%E4%BB%8E%E5%90%8E%E5%8F%B0%E8%87%AA%E5%8A%A8%E7%9B%91%E6%8E%A7%E4%B8%BB%E6%9C%BA%E6%98%AF%E5%90%A6%E6%95%85%E9%9A%9C%EF%BC%8C%E4%B8%BB%E8%A6%81%E5%8F%91%E7%94%9F%E6%95%85%E9%9A%9C%E5%90%8E%E8%87%AA%E5%8A%A8%E5%B0%86%E4%BB%8E%E6%9C%BA%E8%BD%AC%E4%B8%BA%E4%B8%BB%E6%9C%BA%E3%80%82%0A%0A%23%23%23%23%23%2010.2%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%60%60%60%0Acd%20%2Fmyredis%0Avi%20sentinel.conf%0Asentinel%20monitor%20masterhost%20%E6%9C%AC%E6%9C%BAip%20master%E7%AB%AF%E5%8F%A3%E5%8F%B7%201%0A--%20%E5%BD%93%E4%B8%BB%E6%9C%BA%E5%AE%95%E6%9C%BA%E4%B9%8B%E5%90%8E%EF%BC%8C%E8%AE%A9slaver%E6%8A%95%E7%A5%A8%EF%BC%8C%E8%B0%81%E7%9A%84%E7%A5%A8%E6%95%B0%E5%A4%9A%EF%BC%8C%E8%B0%81%E5%B0%B1%E6%88%90%E4%B8%BB%E6%9C%BA%0Acd%20%2Fusr%2Flocal%2Fbin%0A.%2Fredis-sentinel%20%2Fmyredis%2Fsentinel.conf%0A%60%60%60%0A%0A%0A%0A%3E%20%E5%BD%936379shutdown%E5%90%8E%EF%BC%8Csentinal%E4%BC%9A%E5%90%AF%E5%8A%A8leader%E9%80%89%E4%B8%BE%E6%9C%BA%E5%88%B6%EF%BC%8C%E4%B9%8B%E5%90%8E6379%E9%87%8D%E5%90%AF%E5%90%8E%E4%BC%9A%E4%BD%9C%E7%94%A8%E6%96%B0%E7%9A%84master%E7%9A%84salve%0A%0A%60%60%60%0A2956%3AX%2022%20May%202019%2022%3A54%3A25.383%20%23%20WARNING%3A%20The%20TCP%20backlog%20setting%20of%20511%20cannot%20be%20enforced%20because%20%2Fproc%2Fsys%2Fnet%2Fcore%2Fsomaxconn%20is%20set%20to%20the%20lower%20value%20of%20128.%0A2956%3AX%2022%20May%202019%2022%3A54%3A25.393%20%23%20Sentinel%20ID%20is%20f0a3e6562c5bd63b41f9445fa7b9cfef4c34c2f3%0A2956%3AX%2022%20May%202019%2022%3A54%3A25.393%20%23%20%2Bmonitor%20master%20host6379%20127.0.0.1%206379%20quorum%201%0A2956%3AX%2022%20May%202019%2022%3A54%3A25.394%20*%20%2Bslave%20slave%20127.0.0.1%3A6380%20127.0.0.1%206380%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A54%3A25.396%20*%20%2Bslave%20slave%20127.0.0.1%3A6381%20127.0.0.1%206381%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.279%20%23%20%2Bsdown%20master%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.279%20%23%20%2Bodown%20master%20host6379%20127.0.0.1%206379%20%23quorum%201%2F1%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.279%20%23%20%2Bnew-epoch%201%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.279%20%23%20%2Btry-failover%20master%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.281%20%23%20%2Bvote-for-leader%20f0a3e6562c5bd63b41f9445fa7b9cfef4c34c2f3%201%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.281%20%23%20%2Belected-leader%20master%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.281%20%23%20%2Bfailover-state-select-slave%20master%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.343%20%23%20%2Bselected-slave%20slave%20127.0.0.1%3A6380%20127.0.0.1%206380%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.343%20*%20%2Bfailover-state-send-slaveof-noone%20slave%20127.0.0.1%3A6380%20127.0.0.1%206380%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.399%20*%20%2Bfailover-state-wait-promotion%20slave%20127.0.0.1%3A6380%20127.0.0.1%206380%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.626%20%23%20%2Bpromoted-slave%20slave%20127.0.0.1%3A6380%20127.0.0.1%206380%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.626%20%23%20%2Bfailover-state-reconf-slaves%20master%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.708%20*%20%2Bslave-reconf-sent%20slave%20127.0.0.1%3A6381%20127.0.0.1%206381%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A01.780%20*%20%2Bslave-reconf-inprog%20slave%20127.0.0.1%3A6381%20127.0.0.1%206381%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A02.819%20*%20%2Bslave-reconf-done%20slave%20127.0.0.1%3A6381%20127.0.0.1%206381%20%40%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A02.897%20%23%20%2Bfailover-end%20master%20host6379%20127.0.0.1%206379%0A2956%3AX%2022%20May%202019%2022%3A56%3A02.897%20%23%20%2Bswitch-master%20host6379%20127.0.0.1%206379%20127.0.0.1%206380%0A2956%3AX%2022%20May%202019%2022%3A56%3A02.898%20*%20%2Bslave%20slave%20127.0.0.1%3A6381%20127.0.0.1%206381%20%40%20host6379%20127.0.0.1%206380%0A2956%3AX%2022%20May%202019%2022%3A56%3A02.898%20*%20%2Bslave%20slave%20127.0.0.1%3A6379%20127.0.0.1%206379%20%40%20host6379%20127.0.0.1%206380%0A2956%3AX%2022%20May%202019%2022%3A56%3A02.898%20*%20%2Bslave%20slave%20127.0.0.1%3A6379%20127.0.0.1%206379%20%40%20host6379%20127.0.0.1%206380%0A2956%3AX%2022%20May%202019%2022%3A56%3A32.906%20%23%20%2Bsdown%20slave%20127.0.0.1%3A6379%20127.0.0.1%206379%20%40%20host6379%20127.0.0.1%206380%0A2956%3AX%2022%20May%202019%2023%3A03%3A17.541%20%23%20-sdown%20slave%20127.0.0.1%3A6379%20127.0.0.1%206379%20%40%20host6379%20127.0.0.1%206380%0A2956%3AX%2022%20May%202019%2023%3A03%3A27.455%20*%20%2Bconvert-to-slave%20slave%20127.0.0.1%3A6379%20127.0.0.1%206379%20%40%20host6379%20127.0.0.1%206380%0A%60%60%60%0A%0A%23%23%23%23%2011%20Redis%20Lua%0A%60%60%60%60%0Amake%5B3%5D%3A%20Entering%20directory%20%60%2Fusr%2Flocal%2Fredis-5.0.5%2Fdeps%2Fhiredis'%0Acc%20-std%3Dc99%20-pedantic%20-c%20-O3%20-fPIC%20%20-Wall%20-W%20-Wstrict-prototypes%20-Wwrite-strings%20-g%20-ggdb%20%20net.c%0Acc%20-std%3Dc99%20-pedantic%20-c%20-O3%20-fPIC%20%20-Wall%20-W%20-Wstrict-prototypes%20-Wwrite-strings%20-g%20-ggdb%20%20hiredis.c%0Acc%20-std%3Dc99%20-pedantic%20-c%20-O3%20-fPIC%20%20-Wall%20-W%20-Wstrict-prototypes%20-Wwrite-strings%20-g%20-ggdb%20%20sds.c%0Acc%20-std%3Dc99%20-pedantic%20-c%20-O3%20-fPIC%20%20-Wall%20-W%20-Wstrict-prototypes%20-Wwrite-strings%20-g%20-ggdb%20%20async.c%0Acc%20-std%3Dc99%20-pedantic%20-c%20-O3%20-fPIC%20%20-Wall%20-W%20-Wstrict-prototypes%20-Wwrite-strings%20-g%20-ggdb%20%20read.c%0Aar%20rcs%20libhiredis.a%20net.o%20hiredis.o%20sds.o%20async.o%20read.o%0Amake%5B3%5D%3A%20Leaving%20directory%20%60%2Fusr%2Flocal%2Fredis-5.0.5%2Fdeps%2Fhiredis'%0AMAKE%20linenoise%0Acd%20linenoise%20%26%26%20make%0Amake%5B3%5D%3A%20Entering%20directory%20%60%2Fusr%2Flocal%2Fredis-5.0.5%2Fdeps%2Flinenoise'%0Acc%20%20-Wall%20-Os%20-g%20%20-c%20linenoise.c%0Amake%5B3%5D%3A%20Leaving%20directory%20%60%2Fusr%2Flocal%2Fredis-5.0.5%2Fdeps%2Flinenoise'%0AMAKE%20lua%0Acd%20lua%2Fsrc%20%26%26%20make%20all%20CFLAGS%3D%22-O2%20-Wall%20-DLUA_ANSI%20-DENABLE_CJSON_GLOBAL%20-DREDIS_STATIC%3D''%20%22%20MYLDFLAGS%3D%22%22%20AR%3D%22ar%20rcu%22%0Amake%5B3%5D%3A%20Entering%20directory%20%60%2Fusr%2Flocal%2Fredis-5.0.5%2Fdeps%2Flua%2Fsrc'%0Acc%20-O2%20-Wall%20-DLUA_ANSI%20-DENABLE_CJSON_GLOBAL%20-DREDIS_STATIC%3D''%20%20%20%20-c%20-o%20lapi.o%20lapi.c%0Acc%20-O2%20-Wall%20-DLUA_ANSI%20-DENABLE_CJSON_GLOBAL%20-DREDIS_STATIC%3D''%20%20%20%20-c%20-o%20lcode.o%20lcode.c%0Acc%20-O2%20-Wall%20-DLUA_ANSI%20-DENABLE_CJSON_GLOBAL%20-DREDIS_STATIC%3D''%20%20%20%20-c%20-o%20ldebug.o%20ldebug.c%0Acc%20-O2%20-Wall%20-DLUA_ANSI%20-DENABLE_CJSON_GLOBAL%20-DREDIS_STATIC%3D''%20%20%20%20-c%20-o%20ldo.o%20ldo.c%0Aldo.c%3A%20In%20function%20%E2%80%98f_parser%E2%80%99%3A%0Aldo.c%3A496%3A7%3A%20warning%3A%20unused%20variable%20%E2%80%98c%E2%80%99%20%5B-Wunused-variable%5D%0A%20%20%20int%20c%20%3D%20luaZ_lookahead(p-%3Ez)%3B%0A%60%60%60%0A%0A!%5Ba0b2f38ef60748e132d49c28d7627b92.png%5D(en-resource%3A%2F%2Fdatabase%2F1585%3A0)%0A

links

创建时间:2020/11/13 17:08
更新时间:2020/11/13 17:08
作者:Chris

https://www.cnblogs.com/jpfss/p/11075458.html

https%3A%2F%2Fwww.cnblogs.com%2Fjpfss%2Fp%2F11075458.html

Dubbo

创建时间:2020/10/28 14:24
更新时间:2020/11/7 22:46
作者:Chris

Dubbo

https://blog.csdn.net/qq_41157588/article/details/106737191

<<分布式系统原理与范型>>

对系统应用进行垂直拆分

2. RPC

分布式服务架构下主要解决的是如何很好的进行RPC

2.1 基本原理

2.2 RPC两个核心模块
2.2.1 通讯

看一个RPC构架能否快速在两个服务器间建立连接。

2.2.2 序列化与反序列化

传的是xml,json 还是二进制流

2.3 主流的RPC框架

Dubbo, gRPC, Thrift, HSF(High Speed Service Framework)

基于访问压力,实时管理集群容量,提高集群利用率、

流动计算架构

3. Dubbo

3.1 是什么

一款高性能的 Java RPC框架

3.2 能干什么?
  1. 面向接口代理的高性能RPC调用

  2. 智能负载均衡

  3. 服务注册与发现

  4. 高度可扩展能力

    基于微内核+插件的设计原则

  5. 运行期流量调度

    可以在运行时配置Dubbo,以便可以根据不同的规则对流量进行路由,这使得轻松支持诸如蓝绿部署,数据中心感知路由等功能成为可能。

  6. 可视化的服务治理与运维

3.3 原理

  1. 首先部署和启动dubbo容器
  2. 第一步将服务提供者注册到dubbo服务注册中心
  3. 第二步服务消费者从务注册中心获取服务的注册信息
  4. 第三步当服务提供者更新或停用服务后同步服务注册中心,服务注册中心会以异步的方式通知服务消费者。
  5. 第四步服务消费者通过RPC方式调用服务提供者
  6. 第五步服务调用的信息会被监控收集并以图形化的方式展示
3.4 ZK服务注册中心

dubbo推荐使用zk作为服务注册中心

安装参见 zk installment

3.5 Dubbo监控中心

https://github.com/apache/dubbo

3.5.1 管理控制台

dubbo admin是dubbo的控制台,具有服务查询、服务治理的功能。

最新版的dubbo admin做了前后端的分离,前端使用Vue、Vuetify分别作为Javascript框架和UI框架,后端采用Spring Boot框架。

https://github.com/apache/dubbo-admin

  1. 下载zip包

  2. 配置dubbo-admin-server

    配置文件修改zookeeper地址,dubbo控制台端口默认8080,可以自定义端口

  3. 打包

    在主目录dubbo-admin-develop目录下,执行 mvn clean package

  4. 运行jar包

    cd dubbo-admin-distribution/target
    java -jar dubbo-admin-0.2.0-SNAPSHOT.jar
    


  5. 测试

    http://localhost:9898

4. 怎么玩

4.1 创建服务提供者
  1. 建module

    user-service-provider

  2. 改pom

    <dependencies>
        <dependency>
            <groupId>com.chris.dubbo</groupId>
            <artifactId>dubbo-api-common</artifactId>
        </dependency>
        <!--引入dubbo-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <!-- 由于我们使用zookeeper作为注册中心,所以需要操作zookeeper
            dubbo 2.6以前的版本引入zkclient操作zookeeper
            dubbo 2.6及以后的版本引入curator操作zookeeper
            下面两个zk客户端根据dubbo版本2选1即可
        -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
        </dependency>
    
    </dependencies>
    
  3. 接口类

    public class UserServiceImpl implements UserService {
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
            UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
            return Arrays.asList(address1, address2);
        }
    }
    
  4. 建spring configation file : provider.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://dubbo.apache.org/schema/dubbo
           http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
        <!--指定当前服务名称,不要和别的服务名称重复 -->
        <dubbo:application name="user-service-consumer"/>
    
        <!--指定注册中心位置 -->
        <dubbo:registry address="zookeeper://master:2181"/>
        <!--<dubbo:registry protocol="zookeeper" address="master:2181"/>-->
    
        <!--指定dubbo协议在20080端口暴露服务-->
        <dubbo:protocol name="dubbo" port="20080"/>
    
        <!--声明要暴露的服务
            interface : 需要暴露的服务的接口全名,从dubbo-api-common中的com.chris.dubbo.service获取
            ref : 指向服务的实现实例对象
    
        -->
        <dubbo:service interface="com.chris.dubbo.service.UserService" ref="userServiceImpl"/>
    
        <bean id="userServiceImpl" class="com.chris.user.service.impl.UserServiceImpl"/>
    </beans>
    
  5. 测试类

    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.io.IOException;
    
    public class MainTest {
        public static void main(String[] args) throws IOException {
            ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
            ioc.start();
            System.in.read();
        }
    }
    
4.2 创建服务消费者
  1. 建module

    order-service-consumer

  2. 改pom

    <dependencies>
        <dependency>
            <groupId>com.chris.dubbo</groupId>
            <artifactId>dubbo-api-common</artifactId>
        </dependency>
        <!--引入dubbo-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <!-- 由于我们使用zookeeper作为注册中心,所以需要操作zookeeper
            dubbo 2.6以前的版本引入zkclient操作zookeeper
            dubbo 2.6及以后的版本引入curator操作zookeeper
            下面两个zk客户端根据dubbo版本2选1即可
        -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
        </dependency>
    
    </dependencies>
    
  3. 接口类

    @Service
    public class OrderServiceImpl implements OrderService {
    
        @Resource
        private UserService userService;
    
        @Override
        public List<UserAddress> initOrder(String userId) {
            System.out.println("用户id:" + userId);
            //1、查询用户的收货地址
            List<UserAddress> addressList = userService.getUserAddressList(userId);
            for (UserAddress userAddress : addressList) {
                System.out.println(userAddress.getUserAddress());
            }
            return addressList;
        }
    }
    
  4. 建spring configation file : consumer.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://dubbo.apache.org/schema/dubbo
           http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.chris.order.service.impl"/>
    
        <!--指定当前服务名称,不要和别的服务名称重复 -->
        <dubbo:application name="order-service-consumer"/>
    
        <!--指定注册中心位置 -->
        <dubbo:registry address="zookeeper://master:2181"/>
        <!--<dubbo:registry protocol="zookeeper" address="master:2181"/>-->
    
        <!--指定dubbo协议在20080端口暴露服务-->
        <dubbo:protocol name="dubbo" port="10080"/>
    
        <!-- 声明要调用的远程服务的接口:生成远程服务代理 -->
        <dubbo:reference id="userService" interface="com.chris.dubbo.service.UserService"/>
    
    </beans>
    
  5. 测试类

    package com.chris.order;
    
    import com.chris.dubbo.service.OrderService;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.io.IOException;
    
    public class MainTest {
        public static void main(String[] args) throws IOException {
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
            OrderService orderService = applicationContext.getBean(OrderService.class);
            orderService.initOrder("1");
            System.in.read();
        }
    }
    
4.3 重构公共类

建议将服务接口、服务模型、服务异常等均放在 API 包中,因为服务模型和异常也是 API 的一部分,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。

  1. 建module

    dubbo-api-common

  2. 对象类

    com.chris.dubbo.bean

    com.chris.dubbo.bean.UserAddress
    
  3. 接口类

    com.chris.dubbo.service

    com.chris.dubbo.service.OrderService
    com.chris.dubbo.service.UserService
    
4.4 集成SpringBoot

https://github.com/apache/dubbo-spring-boot-project

https://github.com/apache/dubbo-spring-boot-project/tree/0.2.x

4.4.1 服务提供者
  1. 建module

    boot-user-service-provider

  2. 改pom

    <!--引入spring-boot dubbo-->
    <dependency>
        <groupId>com.alibaba.boot</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
    </dependency>
    <!--引入dubbo-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
    </dependency>
    
    <!-- 由于我们使用zookeeper作为注册中心,所以需要操作zookeeper
        dubbo 2.6以前的版本引入zkclient操作zookeeper
        dubbo 2.6及以后的版本引入curator操作zookeeper
        下面两个zk客户端根据dubbo版本2选1即可
    -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
    </dependency>
    
  3. 写yml

    dubbo:
      application:
        name: boot-user-service-provider
      registry:
        protocol: zookeeper
        address: master:2181
      protocol:
        name: dubbo
        port: 20081
    
  4. 主启动

    @SpringBootApplication
    @EnableDubbo //开启基于注解的dubbo功能
    public class OrderMain {
        public static void main(String[] args) {
            SpringApplication.run(OrderMain.class, args);
        }
    }
    
  5. 业务类

    package com.chris.user.service.impl;
    
    import com.alibaba.dubbo.config.annotation.Service;
    import com.chris.dubbo.bean.UserAddress;
    import com.chris.dubbo.service.UserService;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    import java.util.List;
    
    @Service //暴露服务
    @Component
    public class UserServiceImpl implements UserService {
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
            UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
            return Arrays.asList(address1, address2);
        }
    }
    
4.4.2 服务消费者
  1. 建module

    boot-order-service-consumer

  2. 改pom

    <!--引入spring-boot dubbo-->
    <dependency>
        <groupId>com.alibaba.boot</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
    </dependency>
    <!--引入dubbo-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
    </dependency>
    
    <!-- 由于我们使用zookeeper作为注册中心,所以需要操作zookeeper
        dubbo 2.6以前的版本引入zkclient操作zookeeper
        dubbo 2.6及以后的版本引入curator操作zookeeper
        下面两个zk客户端根据dubbo版本2选1即可
    -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
    </dependency>
    
  3. 写yml

    server:
      port: 8081
    
    dubbo:
      application:
        name: boot-order-service-consumer
      registry:
        protocol: zookeeper
        address: master:2181
        check: false  #停用启动时检查服务注册中心是否存在
    
  4. 业务类

    @RestController
    @RequestMapping("/order")
    @Slf4j
    public class OrderController {
    
        @Resource
        private OrderService orderService;
    
        @ResponseBody
        @RequestMapping("/initOrder/{userId}")
        public List<UserAddress> initOrder(@PathVariable("userId") String userId) {
            return orderService.initOrder(userId);
        }
    }
    
  5. 接口类

    package com.chris.order.service.impl;
    
    import com.alibaba.dubbo.config.annotation.Reference;
    import com.chris.dubbo.bean.UserAddress;
    import com.chris.dubbo.service.OrderService;
    import com.chris.dubbo.service.UserService;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class OrderServiceImpl implements OrderService {
    
        @Reference(check = false)
        private UserService userService;
    
        @Override
        public List<UserAddress> initOrder(String userId) {
            System.out.println("用户id:" + userId);
            //1、查询用户的收货地址
            List<UserAddress> addressList = userService.getUserAddressList(userId);
            for (UserAddress userAddress : addressList) {
                System.out.println(userAddress.getUserAddress());
            }
            return addressList;
        }
    }
    

4.4.3 测试

http://localhost:8081/order/initOrder/1

[
  {
    "id": 1,
    "userAddress": "北京市昌平区宏福科技园综合楼3层",
    "userId": "1",
    "consignee": "李老师",
    "phoneNum": "010-56253825",
    "isDefault": "Y"
  },
  {
    "id": 2,
    "userAddress": "深圳市宝安区西部硅谷大厦B座3层(深圳分校)",
    "userId": "1",
    "consignee": "王老师",
    "phoneNum": "010-56253825",
    "isDefault": "N"
  }
]


4.5 dubbo配置
4.5.1 官方文档

http://dubbo.apache.org/en-us/docs/user/configuration/xml.html

http://dubbo.apache.org/en-us/docs/user/references/xml/introduction.html

4.5.2 覆盖策略
  1. 配置文件覆盖策略

    先是JVM中配置的参数

    再是application.yml或application.properties中配置的参数

    最后是dubbo.properties中配置的dubbo公共参数

    http://dubbo.apache.org/en-us/docs/user/configuration/properties.html

  2. 配置参数覆盖策略

    局部优先(方法级优先,接口级次之,全局配置再次之)

    消费者优先(如果级别一样,则消费方优先,提供方次之)

    注:如果级别不一样,局部优先

    例如:在消费端配置的超时为接口上的5秒,而在服务提供端配置方法级的超时时间为2秒,则服务提供端配置方法级的超时时间为2秒会被优先选择

4.5.3 启动时检查
  1. 消费者启动时检查

    http://dubbo.apache.org/en-us/docs/user/demos/preflight-check.html

    消息者启动时默认检查是否存在服务提供者, 如果没有服务提供者,启动消息者时会报错是

    public class MainTest {
        public static void main(String[] args) throws IOException {
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
            /*OrderService orderService = applicationContext.getBean(OrderService.class);
            orderService.initOrder("1");*/
            System.in.read();
        }
    }
    

    consumer.xml

    配置某个服务启动时是否检查

        <!-- 声明要调用的远程服务的接口:生成远程服务代理
             check: 检查消费者依赖的服务提供者是否存在,默认为true,即检查,等同于<dubbo:consumer check="false"/>
         -->
        <dubbo:reference id="userService" interface="com.chris.dubbo.service.UserService" check="false"/>
    
    

    consumer.xml

    配置所有服务启动时是否检查

    http://dubbo.apache.org/en-us/docs/user/references/xml/dubbo-consumer.html

    	<!--配置当前消费者的统一规则,当前所有的服务都不作启动时检查-->
        <dubbo:consumer check="false"/>
    

    与springboot集成后可以在注解中指定

    @Reference(check = false)
    private UserService userService;
    
  2. 注册中心启动时检查

    consumer.xml

    <!--指定注册中心位置 
        check: 检查注册中心是否存在,默认为true,即检查/>
    -->
    <dubbo:registry address="zookeeper://master:2181" check="false"/>
    

    与springboot集成后可以在application.yml中配置

    dubbo:
      application:
        name: boot-order-service-provider
      registry:
        protocol: zookeeper
        address: master:2181
        check: false
    
4.5.4 超时控制
  1. 消费者默认超时时间

    在没有给消费者设置超时时间的情况下,消费者启动时已超时

    因为dubbo:reference 的timeout 用的是消费者统一配置dubbo:consumer的timeout 默认为1秒超时


  2. 消费端超时配置

    消费端consumer.xml

    <!-- 声明要调用的远程服务的接口:生成远程服务代理
            check: 检查消费者依赖的服务提供者是否存在,默认为true,即检查,check="false"等同于<dubbo:consumer check="false"/>
            timeout:用的是消费者统一配置dubbo:consumer的timeout 默认为1秒超时
            dubbo:method: 指向服务提供方暴露的某个方法,timeout对此方法设置在消费端的等待时间
        -->
       <dubbo:reference id="userService" interface="com.chris.dubbo.service.UserService" check="false" timeout="7000">
           <dubbo:method name="getUserAddressList" timeout="5000"/>
       </dubbo:reference>
    
       <!--配置当前消费者的全局统一规则,
           check:设置当前消费端所有的服务是否启动时检查
           timeout:设置当前消费端所有服务的超时时间
        -->
       <dubbo:consumer check="false" timeout="2000"/>
    
  3. 服务端超时配置

    服务端provicer.xml

    <!--声明要暴露的服务
           interface : 需要暴露的服务的接口全名,从dubbo-api-common中的com.chris.dubbo.service获取
           ref : 指向服务的实现实例对象
           timeout:设置服务提供者的超时时间,默认为1秒超时
           dubbo:method: 指向服务提供者暴露的某个方法,timeout对此方法设置在服务提供端的等待时间
       -->
       <dubbo:service interface="com.chris.dubbo.service.UserService" ref="userServiceImpl" timeout="1000">
               <dubbo:method name="getUserAddressList" timeout="2000"/>
       </dubbo:service>
    
       <bean id="userServiceImpl" class="com.chris.user.service.impl.UserServiceImpl"/>
    
4.5.5 重试次数
  1. 配置消费端

    comsumer.xml

    retries: 服务重试次数,不包括第一次调用, 如果 retries="3"表示第一次调用失败后会再调用三次

    <!-- 声明要调用的远程服务的接口:生成远程服务代理
         check: 检查消费者依赖的服务提供者是否存在,默认为true,即检查,check="false"等同于<dubbo:consumer check="false"/>
         timeout:用的是消费者统一配置dubbo:consumer的timeout 默认为1秒超时
         dubbo:method: 指向服务提供方暴露的某个方法,timeout对此方法设置在消费端的等待时间
         retries: 服务重试次数,不包括第一次调用, 如果 retries="3"表示第一次调用失败后会再调用三次
     -->
    <dubbo:reference id="userService" interface="com.chris.dubbo.service.UserService" check="false" timeout="7000"
                     retries="3">
        <!--<dubbo:method name="getUserAddressList" timeout="5000"/>-->
    </dubbo:reference>
    
  2. 配置服务端

    public class UserServiceImpl implements UserService {
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            System.out.println("retry signal.....1....");
            UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
            UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return Arrays.asList(address1, address2);
        }
    }
    
  3. 测试

    在服务端的后台会打印如下信息

    如果有多个服务端节点,消费者在重试时会使用带有负载均衡的重试机制,即每个服务端节点轮询调用

  4. 幂等性和非幂等性下的重试

    修改,删除,修改的操作一般为幂等操作,执行多次后最终结果一致,可以允许重试

    新增为非幂等操作,多次执行同一操作可能会产生多条数据,不能允许重试

4.5.6 多版本

http://dubbo.apache.org/zh-cn/docs/user/demos/multi-versions.html

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

可以按照以下的步骤进行版本迁移:

  1. 在低压力时间段,先升级一半提供者为新版本
  2. 再将所有消费者升级为新版本
  3. 然后将剩下的一半提供者升级为新版本
  1. 服务端

    provider.xml

    version: 指定接口的版本号来支持灰度发布

    <!--声明要暴露的服务
        interface : 需要暴露的服务的接口全名,从dubbo-api-common中的com.chris.dubbo.service获取
        ref : 指向服务的实现实例对象
        timeout:设置服务提供者的超时时间,默认为1秒超时
        dubbo:method: 指向服务提供者暴露的某个方法,timeout对此方法设置在服务提供端的等待时间
        version: 指定接口的版本号来支持灰度发布
    -->
    <dubbo:service interface="com.chris.dubbo.service.UserService" ref="userServiceImpl" timeout="1000" version="0.0.1">
        <dubbo:method name="getUserAddressList" timeout="3000"/>
    </dubbo:service>
    
    <bean id="userServiceImpl" class="com.chris.user.service.impl.UserServiceImpl"/>
    
    
    <dubbo:service interface="com.chris.dubbo.service.UserService" ref="userServiceImpl2" timeout="1000"
                   version="0.0.2">
        <dubbo:method name="getUserAddressList" timeout="3000"/>
    </dubbo:service>
    

    UserServiceImpl

    public class UserServiceImpl implements UserService {
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            System.out.println("retry signal.....old....");
            UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
            UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return Arrays.asList(address1, address2);
        }
    }
    

    复制UserServiceImpl为UserServiceImpl2

    public class UserServiceImpl implements UserService {
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            System.out.println("retry signal.....new....");
            UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
            UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return Arrays.asList(address1, address2);
        }
    }
    

  1. 消费端

    consumer.xml

    version:声名使用服务提供者的哪个版本的接口, version=“*” 表示随机调用接口的不同版本

    <!-- 声明要调用的远程服务的接口:生成远程服务代理
         check: 检查消费者依赖的服务提供者是否存在,默认为true,即检查,check="false"等同于<dubbo:consumer check="false"/>
         timeout:用的是消费者统一配置dubbo:consumer的timeout 默认为1秒超时
         dubbo:method: 指向服务提供方暴露的某个方法,timeout对此方法设置在消费端的等待时间
         retries: 服务重试次数,不包括第一次调用, 如果 retries="3"表示第一次调用失败后会再调用三次
         version:声名使用服务提供者的哪个版本的接口,version=“*” 表示随机调用接口的不同版本
     -->
    <dubbo:reference id="userService" interface="com.chris.dubbo.service.UserService" check="false" timeout="7000" retries="3" version="0.0.1">
        <!--<dubbo:method name="getUserAddressList" timeout="5000"/>-->
    </dubbo:reference>
    
  2. 测试

    当消费端version="0.0.1"

    <dubbo:reference interface="com.chris.dubbo.service.UserService" check="false" timeout="7000" retries="3" version="0.0.1">

    在服务端的后台会打印如下信息

    当消费端version="0.0.2"

    <dubbo:reference interface="com.chris.dubbo.service.UserService" check="false" timeout="7000" retries="3" version="0.0.2">

    在服务端的后台会打印如下信息

4.5.7 本地存根

可以用来在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后伪造容错数据等等,此时就需要在 API 中带上 Stub,客户端生成 Proxy 实例,会把 Proxy 通过构造函数传给 Stub,然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。

  1. 实现UserServiceStub

    @RequiredArgsConstructor
    public class UserServiceStub implements UserService {
    
        private final UserService userService;
    
    
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            System.out.println("invoke UserServiceStub");
            if (StrUtil.isNotEmpty(userId)) {
                return userService.getUserAddressList(userId);
            }
            return null;
        }
    }
    

  2. 配置consumer.xml

    !-- interface:声明要调用的远程服务的接口:生成远程服务代理
         check: 检查消费者依赖的服务提供者是否存在,默认为true,即检查,check="false"等同于<dubbo:consumer check="false"/>
         timeout:用的是消费者统一配置dubbo:consumer的timeout 默认为1秒超时
         dubbo:method: 指向服务提供方暴露的某个方法,timeout对此方法设置在消费端的等待时间
         retries: 服务重试次数,不包括第一次调用, 如果 retries="3"表示第一次调用失败后会再调用三次
         version:声名使用服务提供者的哪个版本的接口
         stub :指向引用接口UserService的本地存根接口UserServiceStub
     -->
    <dubbo:reference id="userService" interface="com.chris.dubbo.service.UserService" check="false" timeout="7000"
                     retries="3" version="0.0.2" stub="com.chris.dubbo.service.stub.UserServiceStub">
        <!--<dubbo:method name="getUserAddressList" timeout="5000"/>-->
    </dubbo:reference>
    
  3. 测试

    在order-servicer-consumer中可以看到如下消息,表示在调用UserService接口方法前先调用存根接口UserServiceStub

4.5.8 与Springboot集成的三种方式
  1. 直接集成

    建module

    改pom

    <!--引入spring-boot dubbo-->
    <dependency>
        <groupId>com.alibaba.boot</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
    </dependency>
    <!--引入dubbo-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
    </dependency>
    
    <!-- 由于我们使用zookeeper作为注册中心,所以需要操作zookeeper
        dubbo 2.6以前的版本引入zkclient操作zookeeper
        dubbo 2.6及以后的版本引入curator操作zookeeper
        下面两个zk客户端根据dubbo版本2选1即可
    -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
    </dependency>
    

    写yml

    server:
      port: 8081
    
    dubbo:
      application:
        name: boot-order-service-provider
      registry:
        protocol: zookeeper
        address: master:2181
        check: false  #停用启动时检查服务注册中心是否存在
    

    主启动加@EnableDubbo //开启基于注解的dubbo功能

    消费端引用服务@Reference

    @Reference(check = false)
    private UserService userService;
    

    服务端服务使用dubbo 注解@Service 暴露服务

    import com.chris.dubbo.service.UserService;
    import org.springframework.stereotype.Component;
    
    @Service //暴露服务
    @Component
    public class UserServiceImpl implements UserService {
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
            UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
            return Arrays.asList(address1, address2);
        }
    }
    
  2. 使用xml配置信息

    将provider.xml或consumer.xml 放在 resources目前下

    主启动类使用 @ImportResource(locations = "classpath:provider.xml")

    @SpringBootApplication
    @ImportResource(locations = "classpath:provider.xml")
    public class UserMain {
    
        public static void main(String[] args) {
            SpringApplication.run(UserMain.class, args);
        }
    }
    

  1. 使用配置类来配置dubbo信息

    DubboConfig

    package com.chris.user.config;
    
    import com.alibaba.dubbo.config.*;
    import com.chris.dubbo.service.UserService;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.Collections;
    
    @Configuration
    public class DubboConfig {
    
        @Bean
        public ApplicationConfig applicationConfig() {
            ApplicationConfig applicationConfig = new ApplicationConfig();
            applicationConfig.setName("boot-user-service-provider");
            return applicationConfig;
        }
    
        @Bean
        public RegistryConfig registryConfig() {
            RegistryConfig registryConfig = new RegistryConfig();
            registryConfig.setProtocol("zookeeper");
            registryConfig.setAddress("master:2181");
            return registryConfig;
        }
    
        @Bean
        public ProtocolConfig protocolConfig() {
            ProtocolConfig protocolConfig = new ProtocolConfig();
            protocolConfig.setName("dubbo");
            protocolConfig.setPort(20081);
            return protocolConfig;
        }
    
        /*
        <dubbo:service interface="com.chris.dubbo.service.UserService" ref="userServiceImpl" timeout="1000" version="0.0.1">
           <dubbo:method name="getUserAddressList" timeout="3000"/>
        </dubbo:service>
        */
        @Bean
        public ServiceConfig<UserService> userServiceConfig(UserService userService) {
            ServiceConfig<UserService> serviceConfig = new ServiceConfig<>();
            serviceConfig.setInterface(UserService.class);
            serviceConfig.setRef(userService);
            serviceConfig.setTimeout(5000);
            serviceConfig.setVersion("0.0.1");
    
            MethodConfig methodConfig = new MethodConfig();
            methodConfig.setName("getUserAddressList");
            methodConfig.setTimeout(3000);
    
            serviceConfig.setMethods(Collections.singletonList(methodConfig));
            return serviceConfig;
        }
    
    
        /*
        <dubbo:provider timeout="3000"/>
        */
        @Bean
        public ProviderConfig providerConfig() {
            ProviderConfig providerConfig = new ProviderConfig();
            providerConfig.setTimeout(3000);
            return providerConfig;
        }
    
    }
    

    服务端接口类使用dubbo 注解@Service 暴露服务

    import com.alibaba.dubbo.config.annotation.Service;
    import com.chris.dubbo.bean.UserAddress;
    import com.chris.dubbo.service.UserService;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    import java.util.List;
    
    @Service //暴露服务
    @Component
    public class UserServiceImpl implements UserService {
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
            UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
            return Arrays.asList(address1, address2);
        }
    }
    
    

4.6 高可用
4.6.1 zk宕机

现象:zookeeper注册中心宕机,还可以消费dubbo暴露的服务。

健壮性

l 监控中心宕掉不影响使用,只是丢失部分采样数据

l 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务

l 注册中心对等集群,任意一台宕掉后,将自动切换到另一台

l 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯

l 服务提供者无状态,任意一台宕掉后,不影响使用

l 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

4.6.2 dubbo直连

不借助注册中心,实现消费者直接访问服务提供者

@Reference(check = false, url = "127.0.0.1:20081")

package com.chris.order.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.chris.dubbo.bean.UserAddress;
import com.chris.dubbo.service.OrderService;
import com.chris.dubbo.service.UserService;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

    @Reference(check = false, url = "127.0.0.1:20081")
    private UserService userService;

    @Override
    public List<UserAddress> initOrder(String userId) {
        System.out.println("用户id:" + userId);
        //1、查询用户的收货地址
        List<UserAddress> addressList = userService.getUserAddressList(userId);
        for (UserAddress userAddress : addressList) {
            System.out.println(userAddress.getUserAddress());
        }
        return addressList;
    }
}
4.7 集群下dubbo负载均衡配置

http://dubbo.apache.org/zh-cn/docs/user/demos/loadbalance.html

4.7.1 负载均衡策略

在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用。

@SPI(RandomLoadBalance.NAME)
public interface LoadBalance {
/**
 * random load balance.
 *
 */
public class RandomLoadBalance extends AbstractLoadBalance {

    public static final String NAME = "random";

Ctrl+H 打开继承树

  1. Random LoadBalance

    基于权重的随机负载均衡策略。

    下一次调用无法确定请求会落在哪个服务节点上,但是总概率是按权重来分布的。

  2. RoundRobin LoadBalance

    基于权重的轮询负载均衡策略。

    下一次调用请求会落在有序的服务节点上,但是需要考虑到权重分布。

  3. LeastActive LoadBalance

    最少活跃数负载均衡,活跃数指调用前后的响应时间, 下次在调用服务之前会比对上次调用所花费的时间,优先调用上次响应时间最少的服务节点。

    使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

  4. ConsistentHash LoadBalance

    一致性 Hash负载均衡策略

    相同参数的请求总是发到同一提供者。

    当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。算法参见:http://en.wikipedia.org/wiki/Consistent_hashing

    缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key="hash.arguments" value="0,1" />

    缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key="hash.nodes" value="320" />

4.7.2 修改负载均衡策略
  1. 服务端服务级别
<dubbo:service interface="..." loadbalance="roundrobin" />
  1. 客户端服务级别
<dubbo:reference interface="..." loadbalance="roundrobin" />
  1. 服务端方法级别
<dubbo:service interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>
  1. 客户端方法级别
<dubbo:reference interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:reference>
4.7.3 修改负载均衡权重
  1. 在暴露服务时直接hardcode在@Service里面

    @Service(weight = 100) //暴露服务
    @Component
    public class UserServiceImpl implements UserService {
        @Override
        public List<UserAddress> getUserAddressList(String userId) {
            UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
            UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
            return Arrays.asList(address1, address2);
        }
    }
    
  2. 在控制台动态增减权重

Dubbo%0A%5Btoc%5D%0A%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2Fqq_41157588%2Farticle%2Fdetails%2F106737191%0A%0A%3C%3C%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E5%8E%9F%E7%90%86%E4%B8%8E%E8%8C%83%E5%9E%8B%3E%3E%0A%0A%E5%AF%B9%E7%B3%BB%E7%BB%9F%E5%BA%94%E7%94%A8%E8%BF%9B%E8%A1%8C%E5%9E%82%E7%9B%B4%E6%8B%86%E5%88%86%0A%0A%0A%0A%23%23%23%23%202.%20RPC%0A%0A%3E%20%E5%88%86%E5%B8%83%E5%BC%8F%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84%E4%B8%8B%E4%B8%BB%E8%A6%81%E8%A7%A3%E5%86%B3%E7%9A%84%E6%98%AF%E5%A6%82%E4%BD%95%E5%BE%88%E5%A5%BD%E7%9A%84%E8%BF%9B%E8%A1%8CRPC%0A%0A%23%23%23%23%23%202.1%20%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86%0A%0A!%5Bda369c4ba8721713f8b7b6ffbd67a7cd.png%5D(en-resource%3A%2F%2Fdatabase%2F992%3A1)%0A%0A%23%23%23%23%23%202.2%20RPC%E4%B8%A4%E4%B8%AA%E6%A0%B8%E5%BF%83%E6%A8%A1%E5%9D%97%0A%0A%23%23%23%23%23%23%202.2.1%20%E9%80%9A%E8%AE%AF%0A%0A%3E%20%E7%9C%8B%E4%B8%80%E4%B8%AARPC%E6%9E%84%E6%9E%B6%E8%83%BD%E5%90%A6%E5%BF%AB%E9%80%9F%E5%9C%A8%E4%B8%A4%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%97%B4%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5%E3%80%82%0A%0A%23%23%23%23%23%23%202.2.2%20%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%8E%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%0A%0A%3E%20%E4%BC%A0%E7%9A%84%E6%98%AFxml%EF%BC%8Cjson%20%E8%BF%98%E6%98%AF%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%B5%81%0A%0A!%5B034b738a0d40982ec008614e74eb7add.png%5D(en-resource%3A%2F%2Fdatabase%2F1003%3A0)%0A%0A%0A%23%23%23%23%23%202.3%20%E4%B8%BB%E6%B5%81%E7%9A%84RPC%E6%A1%86%E6%9E%B6%0A%0A%3E%20Dubbo%2C%20gRPC%2C%20Thrift%2C%20HSF(High%20Speed%20Service%20Framework)%0A%0A%0A%E5%9F%BA%E4%BA%8E%E8%AE%BF%E9%97%AE%E5%8E%8B%E5%8A%9B%EF%BC%8C%E5%AE%9E%E6%97%B6%E7%AE%A1%E7%90%86%E9%9B%86%E7%BE%A4%E5%AE%B9%E9%87%8F%EF%BC%8C%E6%8F%90%E9%AB%98%E9%9B%86%E7%BE%A4%E5%88%A9%E7%94%A8%E7%8E%87%E3%80%81%0A%0A%E6%B5%81%E5%8A%A8%E8%AE%A1%E7%AE%97%E6%9E%B6%E6%9E%84%0A%0A!%5B531b663fe474166769b2f47ef23e06a5.png%5D(en-resource%3A%2F%2Fdatabase%2F1005%3A0)%0A%0A%0A%23%23%23%23%203.%20Dubbo%0A%0A%23%23%23%23%23%203.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E4%B8%80%E6%AC%BE%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84%20Java%20RPC%E6%A1%86%E6%9E%B6%0A%0A%0A%0A%23%23%23%23%23%203.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%EF%BC%9F%0A%0A1.%20%E9%9D%A2%E5%90%91%E6%8E%A5%E5%8F%A3%E4%BB%A3%E7%90%86%E7%9A%84%E9%AB%98%E6%80%A7%E8%83%BDRPC%E8%B0%83%E7%94%A8%0A%0A2.%20%E6%99%BA%E8%83%BD%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%0A3.%20%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0%0A%0A4.%20%E9%AB%98%E5%BA%A6%E5%8F%AF%E6%89%A9%E5%B1%95%E8%83%BD%E5%8A%9B%0A%0A%20%20%20%3E%20%E5%9F%BA%E4%BA%8E%E5%BE%AE%E5%86%85%E6%A0%B8%2B%E6%8F%92%E4%BB%B6%E7%9A%84%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%0A%0A5.%20%E8%BF%90%E8%A1%8C%E6%9C%9F%E6%B5%81%E9%87%8F%E8%B0%83%E5%BA%A6%0A%0A%20%20%20%3E%20%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E9%85%8D%E7%BD%AEDubbo%EF%BC%8C%E4%BB%A5%E4%BE%BF%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E4%B8%8D%E5%90%8C%E7%9A%84%E8%A7%84%E5%88%99%E5%AF%B9%E6%B5%81%E9%87%8F%E8%BF%9B%E8%A1%8C%E8%B7%AF%E7%94%B1%EF%BC%8C%E8%BF%99%E4%BD%BF%E5%BE%97%E8%BD%BB%E6%9D%BE%E6%94%AF%E6%8C%81%E8%AF%B8%E5%A6%82%E8%93%9D%E7%BB%BF%E9%83%A8%E7%BD%B2%EF%BC%8C%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83%E6%84%9F%E7%9F%A5%E8%B7%AF%E7%94%B1%E7%AD%89%E5%8A%9F%E8%83%BD%E6%88%90%E4%B8%BA%E5%8F%AF%E8%83%BD%E3%80%82%0A%0A6.%20%E5%8F%AF%E8%A7%86%E5%8C%96%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%B2%BB%E7%90%86%E4%B8%8E%E8%BF%90%E7%BB%B4%0A%0A%0A%0A%23%23%23%23%23%203.3%20%E5%8E%9F%E7%90%86%20%09%0A%0A!%5Bed1c11fa350451218b9b52dcd9e6ba85.png%5D(en-resource%3A%2F%2Fdatabase%2F1007%3A2)%0A%0A%0A1.%20%E9%A6%96%E5%85%88%E9%83%A8%E7%BD%B2%E5%92%8C%E5%90%AF%E5%8A%A8dubbo%E5%AE%B9%E5%99%A8%0A2.%20%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%B0%86%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%B3%A8%E5%86%8C%E5%88%B0dubbo%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A3.%20%E7%AC%AC%E4%BA%8C%E6%AD%A5%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E4%BB%8E%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E8%8E%B7%E5%8F%96%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF%0A4.%20%E7%AC%AC%E4%B8%89%E6%AD%A5%E5%BD%93%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%9B%B4%E6%96%B0%E6%88%96%E5%81%9C%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%90%8E%E5%90%8C%E6%AD%A5%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E4%BC%9A%E4%BB%A5%E5%BC%82%E6%AD%A5%E7%9A%84%E6%96%B9%E5%BC%8F%E9%80%9A%E7%9F%A5%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E3%80%82%0A5.%20%E7%AC%AC%E5%9B%9B%E6%AD%A5%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E9%80%9A%E8%BF%87RPC%E6%96%B9%E5%BC%8F%E8%B0%83%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%0A6.%20%E7%AC%AC%E4%BA%94%E6%AD%A5%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E7%9A%84%E4%BF%A1%E6%81%AF%E4%BC%9A%E8%A2%AB%E7%9B%91%E6%8E%A7%E6%94%B6%E9%9B%86%E5%B9%B6%E4%BB%A5%E5%9B%BE%E5%BD%A2%E5%8C%96%E7%9A%84%E6%96%B9%E5%BC%8F%E5%B1%95%E7%A4%BA%0A%0A%0A%0A%23%23%23%23%23%203.4%20ZK%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A%0A%3E%20dubbo%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8zk%E4%BD%9C%E4%B8%BA%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%0A%0A%E5%AE%89%E8%A3%85%E5%8F%82%E8%A7%81%20zk%20installment%0A%0A%0A%0A%23%23%23%23%23%203.5%20Dubbo%E7%9B%91%E6%8E%A7%E4%B8%AD%E5%BF%83%0A%0Ahttps%3A%2F%2Fgithub.com%2Fapache%2Fdubbo%0A%0A%23%23%23%23%23%23%203.5.1%20%E7%AE%A1%E7%90%86%E6%8E%A7%E5%88%B6%E5%8F%B0%0A%0A%3E%20dubbo%20admin%E6%98%AFdubbo%E7%9A%84%E6%8E%A7%E5%88%B6%E5%8F%B0%EF%BC%8C%E5%85%B7%E6%9C%89%E6%9C%8D%E5%8A%A1%E6%9F%A5%E8%AF%A2%E3%80%81%E6%9C%8D%E5%8A%A1%E6%B2%BB%E7%90%86%E7%9A%84%E5%8A%9F%E8%83%BD%E3%80%82%0A%3E%0A%3E%20%E6%9C%80%E6%96%B0%E7%89%88%E7%9A%84dubbo%20admin%E5%81%9A%E4%BA%86%E5%89%8D%E5%90%8E%E7%AB%AF%E7%9A%84%E5%88%86%E7%A6%BB%EF%BC%8C%E5%89%8D%E7%AB%AF%E4%BD%BF%E7%94%A8Vue%E3%80%81Vuetify%E5%88%86%E5%88%AB%E4%BD%9C%E4%B8%BAJavascript%E6%A1%86%E6%9E%B6%E5%92%8CUI%E6%A1%86%E6%9E%B6%EF%BC%8C%E5%90%8E%E7%AB%AF%E9%87%87%E7%94%A8Spring%20Boot%E6%A1%86%E6%9E%B6%E3%80%82%0A%3E%0A%3E%20https%3A%2F%2Fgithub.com%2Fapache%2Fdubbo-admin%0A%0A1.%20%E4%B8%8B%E8%BD%BDzip%E5%8C%85%0A%0A%20%20%20%20!%5Bf411fa69168a40e6f7c8ebfbe323fbc2.png%5D(en-resource%3A%2F%2Fdatabase%2F1011%3A0)%0A%20%20%0A%20%20%0A2.%20%E9%85%8D%E7%BD%AEdubbo-admin-server%0A%0A%20%20%20%3E%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%BF%AE%E6%94%B9zookeeper%E5%9C%B0%E5%9D%80%EF%BC%8Cdubbo%E6%8E%A7%E5%88%B6%E5%8F%B0%E7%AB%AF%E5%8F%A3%E9%BB%98%E8%AE%A48080%2C%E5%8F%AF%E4%BB%A5%E8%87%AA%E5%AE%9A%E4%B9%89%E7%AB%AF%E5%8F%A3%0A%0A%20%20%20%20%20%20!%5Bd75a27ef8532edec1fa6e9481d437fe8.png%5D(en-resource%3A%2F%2Fdatabase%2F1013%3A0)%0A%20%20%20%20%20%20%0A%20%20%0A3.%20%E6%89%93%E5%8C%85%0A%0A%20%20%20%3E%20%E5%9C%A8%E4%B8%BB%E7%9B%AE%E5%BD%95dubbo-admin-develop%E7%9B%AE%E5%BD%95%E4%B8%8B%EF%BC%8C%E6%89%A7%E8%A1%8C%20mvn%20clean%20package%0A%0A4.%20%E8%BF%90%E8%A1%8Cjar%E5%8C%85%0A%0A%20%20%20%60%60%60%0A%20%20%20cd%20dubbo-admin-distribution%2Ftarget%0A%20%20%20java%20-jar%20dubbo-admin-0.2.0-SNAPSHOT.jar%0A%20%20%20%60%60%60%0A%20%20%20%0A%20%20%20%20!%5Bcd4ae223983c6370d079975ad834e09a.png%5D(en-resource%3A%2F%2Fdatabase%2F1015%3A0)%0A%20%20%20%20%20!%5Ba07957f4c65ab562e2209712b8a486d9.png%5D(en-resource%3A%2F%2Fdatabase%2F1017%3A0)%0A%20%20%20%0A%0A%20%0A%0A%0A5.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%5Bhttp%3A%2F%2Flocalhost%3A9898%5D(http%3A%2F%2Flocalhost%3A9898%2F)%0A%0A%20%20%20!%5Bd7c42988b9f146b891c54f6a4ace0555.png%5D(en-resource%3A%2F%2Fdatabase%2F1019%3A0)%0A%20%20%20%0A%20%20%0A%20%20%20%0A%0A%0A%0A%23%23%23%23%204.%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%23%23%204.1%20%E5%88%9B%E5%BB%BA%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20user-service-provider%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecom.chris.dubbo%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Edubbo-api-common%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--%E5%BC%95%E5%85%A5dubbo--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Edubbo%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--%20%E7%94%B1%E4%BA%8E%E6%88%91%E4%BB%AC%E4%BD%BF%E7%94%A8zookeeper%E4%BD%9C%E4%B8%BA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%20%20%20%20dubbo%202.6%E4%BB%A5%E5%89%8D%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5zkclient%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%20%20%20%20dubbo%202.6%E5%8F%8A%E4%BB%A5%E5%90%8E%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5curator%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%20%20%20%20%E4%B8%8B%E9%9D%A2%E4%B8%A4%E4%B8%AAzk%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%A0%B9%E6%8D%AEdubbo%E7%89%88%E6%9C%AC2%E9%80%891%E5%8D%B3%E5%8F%AF%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.curator%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ecurator-framework%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%3C%2Fdependencies%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E6%8E%A5%E5%8F%A3%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address1%20%3D%20new%20UserAddress(1%2C%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%20%221%22%2C%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22Y%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address2%20%3D%20new%20UserAddress(2%2C%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%20%221%22%2C%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22N%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20Arrays.asList(address1%2C%20address2)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A4.%20%E5%BB%BAspring%20configation%20file%20%3A%20%20provider.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%20%20%20%3Cbeans%20xmlns%3D%22http%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%22%0A%20%20%20%20%20%20%20%20%20%20xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22%0A%20%20%20%20%20%20%20%20%20%20xmlns%3Adubbo%3D%22http%3A%2F%2Fdubbo.apache.org%2Fschema%2Fdubbo%22%0A%20%20%20%20%20%20%20%20%20%20xsi%3AschemaLocation%3D%22http%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%0A%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%2Fspring-beans.xsd%0A%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fdubbo.apache.org%2Fschema%2Fdubbo%0A%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fdubbo.apache.org%2Fschema%2Fdubbo%2Fdubbo.xsd%22%3E%0A%20%20%20%20%20%20%20%3C!--%E6%8C%87%E5%AE%9A%E5%BD%93%E5%89%8D%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%8C%E4%B8%8D%E8%A6%81%E5%92%8C%E5%88%AB%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%E9%87%8D%E5%A4%8D%20--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Aapplication%20name%3D%22user-service-consumer%22%2F%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%E6%8C%87%E5%AE%9A%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E4%BD%8D%E7%BD%AE%20--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Aregistry%20address%3D%22zookeeper%3A%2F%2Fmaster%3A2181%22%2F%3E%0A%20%20%20%20%20%20%20%3C!--%3Cdubbo%3Aregistry%20protocol%3D%22zookeeper%22%20address%3D%22master%3A2181%22%2F%3E--%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%E6%8C%87%E5%AE%9Adubbo%E5%8D%8F%E8%AE%AE%E5%9C%A820080%E7%AB%AF%E5%8F%A3%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Aprotocol%20name%3D%22dubbo%22%20port%3D%2220080%22%2F%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%E5%A3%B0%E6%98%8E%E8%A6%81%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9C%8D%E5%8A%A1%0A%20%20%20%20%20%20%20%20%20%20%20interface%20%3A%20%E9%9C%80%E8%A6%81%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%E5%85%A8%E5%90%8D%EF%BC%8C%E4%BB%8Edubbo-api-common%E4%B8%AD%E7%9A%84com.chris.dubbo.service%E8%8E%B7%E5%8F%96%0A%20%20%20%20%20%20%20%20%20%20%20ref%20%EF%BC%9A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%AE%9E%E4%BE%8B%E5%AF%B9%E8%B1%A1%0A%20%20%20%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Aservice%20interface%3D%22com.chris.dubbo.service.UserService%22%20ref%3D%22userServiceImpl%22%2F%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Cbean%20id%3D%22userServiceImpl%22%20class%3D%22com.chris.user.service.impl.UserServiceImpl%22%2F%3E%0A%20%20%20%3C%2Fbeans%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A%0A5.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20import%20org.springframework.context.support.ClassPathXmlApplicationContext%3B%0A%20%20%20%0A%20%20%20import%20java.io.IOException%3B%0A%20%20%20%0A%20%20%20public%20class%20MainTest%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20ClassPathXmlApplicationContext%20ioc%20%3D%20new%20ClassPathXmlApplicationContext(%22provider.xml%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20ioc.start()%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.in.read()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%23%204.2%20%E5%88%9B%E5%BB%BA%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20order-service-consumer%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Cdependencies%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecom.chris.dubbo%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Edubbo-api-common%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--%E5%BC%95%E5%85%A5dubbo--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Edubbo%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%3C!--%20%E7%94%B1%E4%BA%8E%E6%88%91%E4%BB%AC%E4%BD%BF%E7%94%A8zookeeper%E4%BD%9C%E4%B8%BA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%20%20%20%20dubbo%202.6%E4%BB%A5%E5%89%8D%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5zkclient%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%20%20%20%20dubbo%202.6%E5%8F%8A%E4%BB%A5%E5%90%8E%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5curator%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%20%20%20%20%E4%B8%8B%E9%9D%A2%E4%B8%A4%E4%B8%AAzk%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%A0%B9%E6%8D%AEdubbo%E7%89%88%E6%9C%AC2%E9%80%891%E5%8D%B3%E5%8F%AF%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.curator%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Ecurator-framework%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%3C%2Fdependencies%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E6%8E%A5%E5%8F%A3%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Service%0A%20%20%20public%20class%20OrderServiceImpl%20implements%20OrderService%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20UserService%20userService%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20initOrder(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%A8%E6%88%B7id%EF%BC%9A%22%20%2B%20userId)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F1%E3%80%81%E6%9F%A5%E8%AF%A2%E7%94%A8%E6%88%B7%E7%9A%84%E6%94%B6%E8%B4%A7%E5%9C%B0%E5%9D%80%0A%20%20%20%20%20%20%20%20%20%20%20List%3CUserAddress%3E%20addressList%20%3D%20userService.getUserAddressList(userId)%3B%0A%20%20%20%20%20%20%20%20%20%20%20for%20(UserAddress%20userAddress%20%3A%20addressList)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(userAddress.getUserAddress())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20return%20addressList%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A4.%20%E5%BB%BAspring%20configation%20file%20%3A%20%20consumer.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%20%20%20%3Cbeans%20xmlns%3D%22http%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%22%0A%20%20%20%20%20%20%20%20%20%20xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22%0A%20%20%20%20%20%20%20%20%20%20xmlns%3Adubbo%3D%22http%3A%2F%2Fdubbo.apache.org%2Fschema%2Fdubbo%22%20xmlns%3Acontext%3D%22http%3A%2F%2Fwww.springframework.org%2Fschema%2Fcontext%22%0A%20%20%20%20%20%20%20%20%20%20xsi%3AschemaLocation%3D%22http%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%0A%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%2Fspring-beans.xsd%0A%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fdubbo.apache.org%2Fschema%2Fdubbo%0A%20%20%20%20%20%20%20%20%20%20http%3A%2F%2Fdubbo.apache.org%2Fschema%2Fdubbo%2Fdubbo.xsd%20http%3A%2F%2Fwww.springframework.org%2Fschema%2Fcontext%20http%3A%2F%2Fwww.springframework.org%2Fschema%2Fcontext%2Fspring-context.xsd%22%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3Ccontext%3Acomponent-scan%20base-package%3D%22com.chris.order.service.impl%22%2F%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%E6%8C%87%E5%AE%9A%E5%BD%93%E5%89%8D%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%EF%BC%8C%E4%B8%8D%E8%A6%81%E5%92%8C%E5%88%AB%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%90%8D%E7%A7%B0%E9%87%8D%E5%A4%8D%20--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Aapplication%20name%3D%22order-service-consumer%22%2F%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%E6%8C%87%E5%AE%9A%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E4%BD%8D%E7%BD%AE%20--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Aregistry%20address%3D%22zookeeper%3A%2F%2Fmaster%3A2181%22%2F%3E%0A%20%20%20%20%20%20%20%3C!--%3Cdubbo%3Aregistry%20protocol%3D%22zookeeper%22%20address%3D%22master%3A2181%22%2F%3E--%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%E6%8C%87%E5%AE%9Adubbo%E5%8D%8F%E8%AE%AE%E5%9C%A820080%E7%AB%AF%E5%8F%A3%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Aprotocol%20name%3D%22dubbo%22%20port%3D%2210080%22%2F%3E%0A%20%20%20%0A%20%20%20%20%20%20%20%3C!--%20%E5%A3%B0%E6%98%8E%E8%A6%81%E8%B0%83%E7%94%A8%E7%9A%84%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%3A%E7%94%9F%E6%88%90%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E4%BB%A3%E7%90%86%20--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Areference%20id%3D%22userService%22%20interface%3D%22com.chris.dubbo.service.UserService%22%2F%3E%0A%20%20%20%0A%20%20%20%3C%2Fbeans%3E%0A%20%20%20%60%60%60%0A%0A5.%20%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.order%3B%0A%20%20%20%0A%20%20%20import%20com.chris.dubbo.service.OrderService%3B%0A%20%20%20import%20org.springframework.context.support.ClassPathXmlApplicationContext%3B%0A%20%20%20%0A%20%20%20import%20java.io.IOException%3B%0A%20%20%20%0A%20%20%20public%20class%20MainTest%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20ClassPathXmlApplicationContext%20applicationContext%20%3D%20new%20ClassPathXmlApplicationContext(%22consumer.xml%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20OrderService%20orderService%20%3D%20applicationContext.getBean(OrderService.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20orderService.initOrder(%221%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20System.in.read()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%204.3%20%E9%87%8D%E6%9E%84%E5%85%AC%E5%85%B1%E7%B1%BB%0A%3E%E5%BB%BA%E8%AE%AE%E5%B0%86%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3%E3%80%81%E6%9C%8D%E5%8A%A1%E6%A8%A1%E5%9E%8B%E3%80%81%E6%9C%8D%E5%8A%A1%E5%BC%82%E5%B8%B8%E7%AD%89%E5%9D%87%E6%94%BE%E5%9C%A8%20API%20%E5%8C%85%E4%B8%AD%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%9C%8D%E5%8A%A1%E6%A8%A1%E5%9E%8B%E5%92%8C%E5%BC%82%E5%B8%B8%E4%B9%9F%E6%98%AF%20API%20%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%81%9A%E4%B9%9F%E7%AC%A6%E5%90%88%E5%88%86%E5%8C%85%E5%8E%9F%E5%88%99%EF%BC%9A%E9%87%8D%E7%94%A8%E5%8F%91%E5%B8%83%E7%AD%89%E4%BB%B7%E5%8E%9F%E5%88%99(REP)%EF%BC%8C%E5%85%B1%E5%90%8C%E9%87%8D%E7%94%A8%E5%8E%9F%E5%88%99(CRP)%E3%80%82%0A%0A!%5B7c3964adba5db5d5f4a375939a1765c8.png%5D(en-resource%3A%2F%2Fdatabase%2F1021%3A0)%0A%0A%0A%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20dubbo-api-common%0A%0A2.%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%0A%0A%20%20%20%3E%20com.chris.dubbo.bean%0A%0A%20%20%20%60%60%60%0A%20%20%20com.chris.dubbo.bean.UserAddress%0A%20%20%20%60%60%60%0A%0A3.%20%E6%8E%A5%E5%8F%A3%E7%B1%BB%0A%0A%20%20%20%3E%20com.chris.dubbo.service%0A%0A%20%20%20%60%60%60%0A%20%20%20com.chris.dubbo.service.OrderService%0A%20%20%20com.chris.dubbo.service.UserService%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%204.4%20%E9%9B%86%E6%88%90SpringBoot%0A%0Ahttps%3A%2F%2Fgithub.com%2Fapache%2Fdubbo-spring-boot-project%0A%0Ahttps%3A%2F%2Fgithub.com%2Fapache%2Fdubbo-spring-boot-project%2Ftree%2F0.2.x%0A%0A%0A%0A%23%23%23%23%23%23%204.4.1%20%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20boot-user-service-provider%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5spring-boot%20dubbo--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Edubbo-spring-boot-starter%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5dubbo--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Edubbo%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%3C!--%20%E7%94%B1%E4%BA%8E%E6%88%91%E4%BB%AC%E4%BD%BF%E7%94%A8zookeeper%E4%BD%9C%E4%B8%BA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20dubbo%202.6%E4%BB%A5%E5%89%8D%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5zkclient%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20dubbo%202.6%E5%8F%8A%E4%BB%A5%E5%90%8E%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5curator%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%E4%B8%8B%E9%9D%A2%E4%B8%A4%E4%B8%AAzk%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%A0%B9%E6%8D%AEdubbo%E7%89%88%E6%9C%AC2%E9%80%891%E5%8D%B3%E5%8F%AF%0A%20%20%20--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.curator%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Ecurator-framework%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%86%99yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20dubbo%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20boot-user-service-provider%0A%20%20%20%20%20registry%3A%0A%20%20%20%20%20%20%20protocol%3A%20zookeeper%0A%20%20%20%20%20%20%20address%3A%20master%3A2181%0A%20%20%20%20%20protocol%3A%0A%20%20%20%20%20%20%20name%3A%20dubbo%0A%20%20%20%20%20%20%20port%3A%2020081%0A%20%20%20%60%60%60%0A%0A%0A%0A4.%20%E4%B8%BB%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40SpringBootApplication%0A%20%20%20%40EnableDubbo%20%2F%2F%E5%BC%80%E5%90%AF%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E7%9A%84dubbo%E5%8A%9F%E8%83%BD%0A%20%20%20public%20class%20OrderMain%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20SpringApplication.run(OrderMain.class%2C%20args)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A5.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.user.service.impl%3B%0A%20%20%20%0A%20%20%20import%20com.alibaba.dubbo.config.annotation.Service%3B%0A%20%20%20import%20com.chris.dubbo.bean.UserAddress%3B%0A%20%20%20import%20com.chris.dubbo.service.UserService%3B%0A%20%20%20import%20org.springframework.stereotype.Component%3B%0A%20%20%20%0A%20%20%20import%20java.util.Arrays%3B%0A%20%20%20import%20java.util.List%3B%0A%20%20%20%0A%20%20%20%40Service%20%2F%2F%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%0A%20%20%20%40Component%0A%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address1%20%3D%20new%20UserAddress(1%2C%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%20%221%22%2C%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22Y%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address2%20%3D%20new%20UserAddress(2%2C%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%20%221%22%2C%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22N%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20Arrays.asList(address1%2C%20address2)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%204.4.2%20%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A1.%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20boot-order-service-consumer%0A%0A2.%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5spring-boot%20dubbo--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Edubbo-spring-boot-starter%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5dubbo--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Edubbo%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%3C!--%20%E7%94%B1%E4%BA%8E%E6%88%91%E4%BB%AC%E4%BD%BF%E7%94%A8zookeeper%E4%BD%9C%E4%B8%BA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20dubbo%202.6%E4%BB%A5%E5%89%8D%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5zkclient%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20dubbo%202.6%E5%8F%8A%E4%BB%A5%E5%90%8E%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5curator%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%E4%B8%8B%E9%9D%A2%E4%B8%A4%E4%B8%AAzk%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%A0%B9%E6%8D%AEdubbo%E7%89%88%E6%9C%AC2%E9%80%891%E5%8D%B3%E5%8F%AF%0A%20%20%20--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.curator%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Ecurator-framework%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E5%86%99yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%208081%0A%20%20%20%0A%20%20%20dubbo%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20boot-order-service-consumer%0A%20%20%20%20%20registry%3A%0A%20%20%20%20%20%20%20protocol%3A%20zookeeper%0A%20%20%20%20%20%20%20address%3A%20master%3A2181%0A%20%20%20%20%20%20%20check%3A%20false%20%20%23%E5%81%9C%E7%94%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%0A%20%20%20%60%60%60%0A%0A4.%20%E4%B8%9A%E5%8A%A1%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RestController%0A%20%20%20%40RequestMapping(%22%2Forder%22)%0A%20%20%20%40Slf4j%0A%20%20%20public%20class%20OrderController%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Resource%0A%20%20%20%20%20%20%20private%20OrderService%20orderService%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40ResponseBody%0A%20%20%20%20%20%20%20%40RequestMapping(%22%2FinitOrder%2F%7BuserId%7D%22)%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20initOrder(%40PathVariable(%22userId%22)%20String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20return%20orderService.initOrder(userId)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A5.%20%E6%8E%A5%E5%8F%A3%E7%B1%BB%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.order.service.impl%3B%0A%20%20%20%0A%20%20%20import%20com.alibaba.dubbo.config.annotation.Reference%3B%0A%20%20%20import%20com.chris.dubbo.bean.UserAddress%3B%0A%20%20%20import%20com.chris.dubbo.service.OrderService%3B%0A%20%20%20import%20com.chris.dubbo.service.UserService%3B%0A%20%20%20import%20org.springframework.stereotype.Service%3B%0A%20%20%20%0A%20%20%20import%20java.util.List%3B%0A%20%20%20%0A%20%20%20%40Service%0A%20%20%20public%20class%20OrderServiceImpl%20implements%20OrderService%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Reference(check%20%3D%20false)%0A%20%20%20%20%20%20%20private%20UserService%20userService%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20initOrder(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%A8%E6%88%B7id%EF%BC%9A%22%20%2B%20userId)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%2F%2F1%E3%80%81%E6%9F%A5%E8%AF%A2%E7%94%A8%E6%88%B7%E7%9A%84%E6%94%B6%E8%B4%A7%E5%9C%B0%E5%9D%80%0A%20%20%20%20%20%20%20%20%20%20%20List%3CUserAddress%3E%20addressList%20%3D%20userService.getUserAddressList(userId)%3B%0A%20%20%20%20%20%20%20%20%20%20%20for%20(UserAddress%20userAddress%20%3A%20addressList)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(userAddress.getUserAddress())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20return%20addressList%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A%0A%0A4.4.3%20%E6%B5%8B%E8%AF%95%0A%0Ahttp%3A%2F%2Flocalhost%3A8081%2Forder%2FinitOrder%2F1%0A%0A%60%60%60json%0A%5B%0A%20%20%7B%0A%20%20%20%20%22id%22%3A%201%2C%0A%20%20%20%20%22userAddress%22%3A%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%0A%20%20%20%20%22userId%22%3A%20%221%22%2C%0A%20%20%20%20%22consignee%22%3A%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%0A%20%20%20%20%22phoneNum%22%3A%20%22010-56253825%22%2C%0A%20%20%20%20%22isDefault%22%3A%20%22Y%22%0A%20%20%7D%2C%0A%20%20%7B%0A%20%20%20%20%22id%22%3A%202%2C%0A%20%20%20%20%22userAddress%22%3A%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%0A%20%20%20%20%22userId%22%3A%20%221%22%2C%0A%20%20%20%20%22consignee%22%3A%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%0A%20%20%20%20%22phoneNum%22%3A%20%22010-56253825%22%2C%0A%20%20%20%20%22isDefault%22%3A%20%22N%22%0A%20%20%7D%0A%5D%0A%0A%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%23%204.5%20dubbo%E9%85%8D%E7%BD%AE%0A%0A%23%23%23%23%23%23%204.5.1%20%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%0A%0Ahttp%3A%2F%2Fdubbo.apache.org%2Fen-us%2Fdocs%2Fuser%2Fconfiguration%2Fxml.html%0A%0Ahttp%3A%2F%2Fdubbo.apache.org%2Fen-us%2Fdocs%2Fuser%2Freferences%2Fxml%2Fintroduction.html%0A%0A%0A%0A%23%23%23%23%23%23%204.5.2%20%E8%A6%86%E7%9B%96%E7%AD%96%E7%95%A5%0A%0A1.%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%A6%86%E7%9B%96%E7%AD%96%E7%95%A5%0A%0A%20%20%20%3E%20%E5%85%88%E6%98%AFJVM%E4%B8%AD%E9%85%8D%E7%BD%AE%E7%9A%84%E5%8F%82%E6%95%B0%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%86%8D%E6%98%AFapplication.yml%E6%88%96application.properties%E4%B8%AD%E9%85%8D%E7%BD%AE%E7%9A%84%E5%8F%82%E6%95%B0%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%9C%80%E5%90%8E%E6%98%AFdubbo.properties%E4%B8%AD%E9%85%8D%E7%BD%AE%E7%9A%84dubbo%E5%85%AC%E5%85%B1%E5%8F%82%E6%95%B0%0A%0A%20%20%20http%3A%2F%2Fdubbo.apache.org%2Fen-us%2Fdocs%2Fuser%2Fconfiguration%2Fproperties.html%0A%0A%20%20%20%20!%5Be2d42e3fbe319346fb0ffa07a869c02f.png%5D(en-resource%3A%2F%2Fdatabase%2F1023%3A0)%0A%20%20%0A%0A%0A2.%20%E9%85%8D%E7%BD%AE%E5%8F%82%E6%95%B0%E8%A6%86%E7%9B%96%E7%AD%96%E7%95%A5%0A%0A%20%20%20%3E%20%E5%B1%80%E9%83%A8%E4%BC%98%E5%85%88%EF%BC%88%E6%96%B9%E6%B3%95%E7%BA%A7%E4%BC%98%E5%85%88%EF%BC%8C%E6%8E%A5%E5%8F%A3%E7%BA%A7%E6%AC%A1%E4%B9%8B%EF%BC%8C%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE%E5%86%8D%E6%AC%A1%E4%B9%8B%EF%BC%89%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%B6%88%E8%B4%B9%E8%80%85%E4%BC%98%E5%85%88%EF%BC%88%E5%A6%82%E6%9E%9C%E7%BA%A7%E5%88%AB%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%88%99%E6%B6%88%E8%B4%B9%E6%96%B9%E4%BC%98%E5%85%88%EF%BC%8C%E6%8F%90%E4%BE%9B%E6%96%B9%E6%AC%A1%E4%B9%8B%EF%BC%89%0A%20%20%20%0A%20%20%20%3E%20%E6%B3%A8%EF%BC%9A%E5%A6%82%E6%9E%9C%E7%BA%A7%E5%88%AB%E4%B8%8D%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%B1%80%E9%83%A8%E4%BC%98%E5%85%88%0A%20%20%20%3E%0A%20%20%20%3E%20%E4%BE%8B%E5%A6%82%EF%BC%9A%E5%9C%A8%E6%B6%88%E8%B4%B9%E7%AB%AF%E9%85%8D%E7%BD%AE%E7%9A%84%E8%B6%85%E6%97%B6%E4%B8%BA%E6%8E%A5%E5%8F%A3%E4%B8%8A%E7%9A%845%E7%A7%92%EF%BC%8C%E8%80%8C%E5%9C%A8%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E7%AB%AF%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95%E7%BA%A7%E7%9A%84%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E4%B8%BA2%E7%A7%92%EF%BC%8C%E5%88%99%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E7%AB%AF%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95%E7%BA%A7%E7%9A%84%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E4%B8%BA2%E7%A7%92%E4%BC%9A%E8%A2%AB%E4%BC%98%E5%85%88%E9%80%89%E6%8B%A9%0A%0A%20%20%20%0A%20%20%20%20!%5Bd7812c454854187eb512359e532f4cb9.png%5D(en-resource%3A%2F%2Fdatabase%2F1025%3A1)%0A%20%20%20%20%0A%0A%23%23%23%23%23%23%204.5.3%20%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5%0A%0A1.%20%E6%B6%88%E8%B4%B9%E8%80%85%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5%0A%0A%20%20%20%3E%20http%3A%2F%2Fdubbo.apache.org%2Fen-us%2Fdocs%2Fuser%2Fdemos%2Fpreflight-check.html%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%B6%88%E6%81%AF%E8%80%85%E5%90%AF%E5%8A%A8%E6%97%B6%E9%BB%98%E8%AE%A4%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%2C%20%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%EF%BC%8C%E5%90%AF%E5%8A%A8%E6%B6%88%E6%81%AF%E8%80%85%E6%97%B6%E4%BC%9A%E6%8A%A5%E9%94%99%E6%98%AF%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20class%20MainTest%20%7B%0A%20%20%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20ClassPathXmlApplicationContext%20applicationContext%20%3D%20new%20ClassPathXmlApplicationContext(%22consumer.xml%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%2F*OrderService%20orderService%20%3D%20applicationContext.getBean(OrderService.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20orderService.initOrder(%221%22)%3B*%2F%0A%20%20%20%20%20%20%20%20%20%20%20System.in.read()%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20consumer.xml%0A%20%20%20%3E%0A%20%20%20%3E%20%E9%85%8D%E7%BD%AE%E6%9F%90%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E6%97%B6%E6%98%AF%E5%90%A6%E6%A3%80%E6%9F%A5%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%20%20%20%20%3C!--%20%E5%A3%B0%E6%98%8E%E8%A6%81%E8%B0%83%E7%94%A8%E7%9A%84%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%3A%E7%94%9F%E6%88%90%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E4%BB%A3%E7%90%86%0A%20%20%20%20%20%20%20%20%20%20%20%20check%3A%20%E6%A3%80%E6%9F%A5%E6%B6%88%E8%B4%B9%E8%80%85%E4%BE%9D%E8%B5%96%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%2C%E5%8D%B3%E6%A3%80%E6%9F%A5%EF%BC%8C%E7%AD%89%E5%90%8C%E4%BA%8E%3Cdubbo%3Aconsumer%20check%3D%22false%22%2F%3E%0A%20%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Areference%20id%3D%22userService%22%20interface%3D%22com.chris.dubbo.service.UserService%22%20check%3D%22false%22%2F%3E%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20consumer.xml%0A%20%20%20%3E%0A%20%20%20%3E%20%E9%85%8D%E7%BD%AE%E6%89%80%E6%9C%89%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E6%97%B6%E6%98%AF%E5%90%A6%E6%A3%80%E6%9F%A5%0A%20%20%20%3E%0A%20%20%20%3E%20http%3A%2F%2Fdubbo.apache.org%2Fen-us%2Fdocs%2Fuser%2Freferences%2Fxml%2Fdubbo-consumer.html%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%09%3C!--%E9%85%8D%E7%BD%AE%E5%BD%93%E5%89%8D%E6%B6%88%E8%B4%B9%E8%80%85%E7%9A%84%E7%BB%9F%E4%B8%80%E8%A7%84%E5%88%99%EF%BC%8C%E5%BD%93%E5%89%8D%E6%89%80%E6%9C%89%E7%9A%84%E6%9C%8D%E5%8A%A1%E9%83%BD%E4%B8%8D%E4%BD%9C%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5--%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Aconsumer%20check%3D%22false%22%2F%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E4%B8%8Espringboot%E9%9B%86%E6%88%90%E5%90%8E%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%B3%A8%E8%A7%A3%E4%B8%AD%E6%8C%87%E5%AE%9A%09%0A%0A%20%20%20%20%60%60%60java%0A%20%20%20%20%40Reference(check%20%3D%20false)%0A%20%20%20%20private%20UserService%20userService%3B%0A%20%20%20%20%60%60%60%0A%0A%0A2.%20%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5%0A%0A%20%20%20%3E%20consumer.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E6%8C%87%E5%AE%9A%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E4%BD%8D%E7%BD%AE%20%0A%20%20%20%20%20%20%20check%3A%20%E6%A3%80%E6%9F%A5%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%2C%E5%8D%B3%E6%A3%80%E6%9F%A5%2F%3E%0A%20%20%20--%3E%0A%20%20%20%3Cdubbo%3Aregistry%20address%3D%22zookeeper%3A%2F%2Fmaster%3A2181%22%20check%3D%22false%22%2F%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E4%B8%8Espringboot%E9%9B%86%E6%88%90%E5%90%8E%E5%8F%AF%E4%BB%A5%E5%9C%A8application.yml%E4%B8%AD%E9%85%8D%E7%BD%AE%0A%0A%20%20%20%60%60%60yml%0A%20%20%20dubbo%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20boot-order-service-provider%0A%20%20%20%20%20registry%3A%0A%20%20%20%20%20%20%20protocol%3A%20zookeeper%0A%20%20%20%20%20%20%20address%3A%20master%3A2181%0A%20%20%20%20%20%20%20check%3A%20false%0A%20%20%20%60%60%60%0A%0A%0A%0A%0A%23%23%23%23%23%23%204.5.4%20%E8%B6%85%E6%97%B6%E6%8E%A7%E5%88%B6%0A%0A1.%20%E6%B6%88%E8%B4%B9%E8%80%85%E9%BB%98%E8%AE%A4%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%0A%0A%20%20%20%E5%9C%A8%E6%B2%A1%E6%9C%89%E7%BB%99%E6%B6%88%E8%B4%B9%E8%80%85%E8%AE%BE%E7%BD%AE%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E6%B6%88%E8%B4%B9%E8%80%85%E5%90%AF%E5%8A%A8%E6%97%B6%E5%B7%B2%E8%B6%85%E6%97%B6%0A%0A%20%20%20!%5B7f56afae09509729a0935ef85865eea2.png%5D(en-resource%3A%2F%2Fdatabase%2F1027%3A0)%0A%20%20%20%0A%0A%20%20%20%3E%20%E5%9B%A0%E4%B8%BAdubbo%3Areference%20%E7%9A%84timeout%20%E7%94%A8%E7%9A%84%E6%98%AF%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AEdubbo%3Aconsumer%E7%9A%84timeout%20%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%E8%B6%85%E6%97%B6%0A%0A%20%20%20%20!%5B03a2b22d40d35d4e956870759dcc18b0.png%5D(en-resource%3A%2F%2Fdatabase%2F1029%3A1)%0A%20%20%20%20!%5B92f8319ff30d555034ec85addb0aa30e.png%5D(en-resource%3A%2F%2Fdatabase%2F1031%3A0)%0A%20%20%20%20%0A%0A2.%20%E6%B6%88%E8%B4%B9%E7%AB%AF%E8%B6%85%E6%97%B6%E9%85%8D%E7%BD%AE%0A%0A%20%20%20%3E%20%E6%B6%88%E8%B4%B9%E7%AB%AFconsumer.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%20%E5%A3%B0%E6%98%8E%E8%A6%81%E8%B0%83%E7%94%A8%E7%9A%84%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%3A%E7%94%9F%E6%88%90%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E4%BB%A3%E7%90%86%0A%20%20%20%20%20%20%20%20%20%20%20check%3A%20%E6%A3%80%E6%9F%A5%E6%B6%88%E8%B4%B9%E8%80%85%E4%BE%9D%E8%B5%96%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%2C%E5%8D%B3%E6%A3%80%E6%9F%A5%EF%BC%8Ccheck%3D%22false%22%E7%AD%89%E5%90%8C%E4%BA%8E%3Cdubbo%3Aconsumer%20check%3D%22false%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20timeout%EF%BC%9A%E7%94%A8%E7%9A%84%E6%98%AF%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AEdubbo%3Aconsumer%E7%9A%84timeout%20%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%E8%B6%85%E6%97%B6%0A%20%20%20%20%20%20%20%20%20%20%20dubbo%3Amethod%3A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9F%90%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8Ctimeout%E5%AF%B9%E6%AD%A4%E6%96%B9%E6%B3%95%E8%AE%BE%E7%BD%AE%E5%9C%A8%E6%B6%88%E8%B4%B9%E7%AB%AF%E7%9A%84%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%3Cdubbo%3Areference%20id%3D%22userService%22%20interface%3D%22com.chris.dubbo.service.UserService%22%20check%3D%22false%22%20timeout%3D%227000%22%3E%0A%20%20%20%20%20%20%20%20%20%20%3Cdubbo%3Amethod%20name%3D%22getUserAddressList%22%20timeout%3D%225000%22%2F%3E%0A%20%20%20%20%20%20%3C%2Fdubbo%3Areference%3E%0A%20%20%20%0A%20%20%20%20%20%20%3C!--%E9%85%8D%E7%BD%AE%E5%BD%93%E5%89%8D%E6%B6%88%E8%B4%B9%E8%80%85%E7%9A%84%E5%85%A8%E5%B1%80%E7%BB%9F%E4%B8%80%E8%A7%84%E5%88%99%EF%BC%8C%0A%20%20%20%20%20%20%20%20%20%20check%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%BD%93%E5%89%8D%E6%B6%88%E8%B4%B9%E7%AB%AF%E6%89%80%E6%9C%89%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%98%AF%E5%90%A6%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5%0A%20%20%20%20%20%20%20%20%20%20timeout%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%BD%93%E5%89%8D%E6%B6%88%E8%B4%B9%E7%AB%AF%E6%89%80%E6%9C%89%E6%9C%8D%E5%8A%A1%E7%9A%84%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%3Cdubbo%3Aconsumer%20check%3D%22false%22%20timeout%3D%222000%22%2F%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A3.%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%E8%B6%85%E6%97%B6%E9%85%8D%E7%BD%AE%0A%0A%20%20%20%3E%20%E6%9C%8D%E5%8A%A1%E7%AB%AFprovicer.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E5%A3%B0%E6%98%8E%E8%A6%81%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9C%8D%E5%8A%A1%0A%20%20%20%20%20%20%20%20%20%20interface%20%3A%20%E9%9C%80%E8%A6%81%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%E5%85%A8%E5%90%8D%EF%BC%8C%E4%BB%8Edubbo-api-common%E4%B8%AD%E7%9A%84com.chris.dubbo.service%E8%8E%B7%E5%8F%96%0A%20%20%20%20%20%20%20%20%20%20ref%20%EF%BC%9A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%AE%9E%E4%BE%8B%E5%AF%B9%E8%B1%A1%0A%20%20%20%20%20%20%20%20%20%20timeout%EF%BC%9A%E8%AE%BE%E7%BD%AE%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%E8%B6%85%E6%97%B6%0A%20%20%20%20%20%20%20%20%20%20dubbo%3Amethod%3A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9F%90%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8Ctimeout%E5%AF%B9%E6%AD%A4%E6%96%B9%E6%B3%95%E8%AE%BE%E7%BD%AE%E5%9C%A8%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E7%AB%AF%E7%9A%84%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20--%3E%0A%20%20%20%20%20%20%3Cdubbo%3Aservice%20interface%3D%22com.chris.dubbo.service.UserService%22%20ref%3D%22userServiceImpl%22%20timeout%3D%221000%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdubbo%3Amethod%20name%3D%22getUserAddressList%22%20timeout%3D%222000%22%2F%3E%0A%20%20%20%20%20%20%3C%2Fdubbo%3Aservice%3E%0A%20%20%20%0A%20%20%20%20%20%20%3Cbean%20id%3D%22userServiceImpl%22%20class%3D%22com.chris.user.service.impl.UserServiceImpl%22%2F%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%0A%0A%0A%0A%23%23%23%23%23%23%204.5.5%20%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%0A%0A1.%20%E9%85%8D%E7%BD%AE%E6%B6%88%E8%B4%B9%E7%AB%AF%0A%0A%20%20%20%3E%20comsumer.xml%0A%20%20%20%3E%0A%20%20%20%3E%20retries%3A%20%E6%9C%8D%E5%8A%A1%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%EF%BC%8C%E4%B8%8D%E5%8C%85%E6%8B%AC%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%EF%BC%8C%20%E5%A6%82%E6%9E%9C%20retries%3D%223%22%E8%A1%A8%E7%A4%BA%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%E5%A4%B1%E8%B4%A5%E5%90%8E%E4%BC%9A%E5%86%8D%E8%B0%83%E7%94%A8%E4%B8%89%E6%AC%A1%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%20%E5%A3%B0%E6%98%8E%E8%A6%81%E8%B0%83%E7%94%A8%E7%9A%84%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%3A%E7%94%9F%E6%88%90%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E4%BB%A3%E7%90%86%0A%20%20%20%20%20%20%20%20check%3A%20%E6%A3%80%E6%9F%A5%E6%B6%88%E8%B4%B9%E8%80%85%E4%BE%9D%E8%B5%96%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%2C%E5%8D%B3%E6%A3%80%E6%9F%A5%EF%BC%8Ccheck%3D%22false%22%E7%AD%89%E5%90%8C%E4%BA%8E%3Cdubbo%3Aconsumer%20check%3D%22false%22%2F%3E%0A%20%20%20%20%20%20%20%20timeout%EF%BC%9A%E7%94%A8%E7%9A%84%E6%98%AF%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AEdubbo%3Aconsumer%E7%9A%84timeout%20%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%E8%B6%85%E6%97%B6%0A%20%20%20%20%20%20%20%20dubbo%3Amethod%3A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9F%90%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8Ctimeout%E5%AF%B9%E6%AD%A4%E6%96%B9%E6%B3%95%E8%AE%BE%E7%BD%AE%E5%9C%A8%E6%B6%88%E8%B4%B9%E7%AB%AF%E7%9A%84%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20%20%20retries%3A%20%E6%9C%8D%E5%8A%A1%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%EF%BC%8C%E4%B8%8D%E5%8C%85%E6%8B%AC%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%EF%BC%8C%20%E5%A6%82%E6%9E%9C%20retries%3D%223%22%E8%A1%A8%E7%A4%BA%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%E5%A4%B1%E8%B4%A5%E5%90%8E%E4%BC%9A%E5%86%8D%E8%B0%83%E7%94%A8%E4%B8%89%E6%AC%A1%0A%20%20%20%20--%3E%0A%20%20%20%3Cdubbo%3Areference%20id%3D%22userService%22%20interface%3D%22com.chris.dubbo.service.UserService%22%20check%3D%22false%22%20timeout%3D%227000%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20retries%3D%223%22%3E%0A%20%20%20%20%20%20%20%3C!--%3Cdubbo%3Amethod%20name%3D%22getUserAddressList%22%20timeout%3D%225000%22%2F%3E--%3E%0A%20%20%20%3C%2Fdubbo%3Areference%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A2.%20%E9%85%8D%E7%BD%AE%E6%9C%8D%E5%8A%A1%E7%AB%AF%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22retry%20signal.....1....%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address1%20%3D%20new%20UserAddress(1%2C%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%20%221%22%2C%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22Y%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address2%20%3D%20new%20UserAddress(2%2C%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%20%221%22%2C%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22N%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(4)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20return%20Arrays.asList(address1%2C%20address2)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%3E%20%E5%9C%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84%E5%90%8E%E5%8F%B0%E4%BC%9A%E6%89%93%E5%8D%B0%E5%A6%82%E4%B8%8B%E4%BF%A1%E6%81%AF%0A%0A%20%20%20%20!%5Bda0fd496bc24bff3290d986ed4e02ad3.png%5D(en-resource%3A%2F%2Fdatabase%2F1033%3A0)%0A%20%20%20%20%0A%20%20%0A%20%20%20%3E%20%E5%A6%82%E6%9E%9C%E6%9C%89%E5%A4%9A%E4%B8%AA%E6%9C%8D%E5%8A%A1%E7%AB%AF%E8%8A%82%E7%82%B9%EF%BC%8C%E6%B6%88%E8%B4%B9%E8%80%85%E5%9C%A8%E9%87%8D%E8%AF%95%E6%97%B6%E4%BC%9A%E4%BD%BF%E7%94%A8%E5%B8%A6%E6%9C%89%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%9A%84%E9%87%8D%E8%AF%95%E6%9C%BA%E5%88%B6%EF%BC%8C%E5%8D%B3%E6%AF%8F%E4%B8%AA%E6%9C%8D%E5%8A%A1%E7%AB%AF%E8%8A%82%E7%82%B9%E8%BD%AE%E8%AF%A2%E8%B0%83%E7%94%A8%0A%0A%0A%0A4.%20%E5%B9%82%E7%AD%89%E6%80%A7%E5%92%8C%E9%9D%9E%E5%B9%82%E7%AD%89%E6%80%A7%E4%B8%8B%E7%9A%84%E9%87%8D%E8%AF%95%0A%0A%20%20%20%3E%20%E4%BF%AE%E6%94%B9%EF%BC%8C%E5%88%A0%E9%99%A4%EF%BC%8C%E4%BF%AE%E6%94%B9%E7%9A%84%E6%93%8D%E4%BD%9C%E4%B8%80%E8%88%AC%E4%B8%BA%E5%B9%82%E7%AD%89%E6%93%8D%E4%BD%9C%EF%BC%8C%E6%89%A7%E8%A1%8C%E5%A4%9A%E6%AC%A1%E5%90%8E%E6%9C%80%E7%BB%88%E7%BB%93%E6%9E%9C%E4%B8%80%E8%87%B4%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%85%81%E8%AE%B8%E9%87%8D%E8%AF%95%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%96%B0%E5%A2%9E%E4%B8%BA%E9%9D%9E%E5%B9%82%E7%AD%89%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%A4%9A%E6%AC%A1%E6%89%A7%E8%A1%8C%E5%90%8C%E4%B8%80%E6%93%8D%E4%BD%9C%E5%8F%AF%E8%83%BD%E4%BC%9A%E4%BA%A7%E7%94%9F%E5%A4%9A%E6%9D%A1%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%B8%8D%E8%83%BD%E5%85%81%E8%AE%B8%E9%87%8D%E8%AF%95%0A%0A%0A%23%23%23%23%23%23%204.5.6%20%20%E5%A4%9A%E7%89%88%E6%9C%AC%0A%0Ahttp%3A%2F%2Fdubbo.apache.org%2Fzh-cn%2Fdocs%2Fuser%2Fdemos%2Fmulti-versions.html%0A%0A%3E%20%E5%BD%93%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%E5%AE%9E%E7%8E%B0%EF%BC%8C%E5%87%BA%E7%8E%B0%E4%B8%8D%E5%85%BC%E5%AE%B9%E5%8D%87%E7%BA%A7%E6%97%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8%E7%89%88%E6%9C%AC%E5%8F%B7%E8%BF%87%E6%B8%A1%EF%BC%8C%E7%89%88%E6%9C%AC%E5%8F%B7%E4%B8%8D%E5%90%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E7%9B%B8%E4%BA%92%E9%97%B4%E4%B8%8D%E5%BC%95%E7%94%A8%E3%80%82%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E6%8C%89%E7%85%A7%E4%BB%A5%E4%B8%8B%E7%9A%84%E6%AD%A5%E9%AA%A4%E8%BF%9B%E8%A1%8C%E7%89%88%E6%9C%AC%E8%BF%81%E7%A7%BB%EF%BC%9A%0A%3E%0A%3E%201.%20%E5%9C%A8%E4%BD%8E%E5%8E%8B%E5%8A%9B%E6%97%B6%E9%97%B4%E6%AE%B5%EF%BC%8C%E5%85%88%E5%8D%87%E7%BA%A7%E4%B8%80%E5%8D%8A%E6%8F%90%E4%BE%9B%E8%80%85%E4%B8%BA%E6%96%B0%E7%89%88%E6%9C%AC%0A%3E%202.%20%E5%86%8D%E5%B0%86%E6%89%80%E6%9C%89%E6%B6%88%E8%B4%B9%E8%80%85%E5%8D%87%E7%BA%A7%E4%B8%BA%E6%96%B0%E7%89%88%E6%9C%AC%0A%3E%203.%20%E7%84%B6%E5%90%8E%E5%B0%86%E5%89%A9%E4%B8%8B%E7%9A%84%E4%B8%80%E5%8D%8A%E6%8F%90%E4%BE%9B%E8%80%85%E5%8D%87%E7%BA%A7%E4%B8%BA%E6%96%B0%E7%89%88%E6%9C%AC%0A%0A1.%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%0A%0A%20%20%20%3E%20provider.xml%0A%20%20%20%3E%0A%20%20%20%3E%20version%3A%20%E6%8C%87%E5%AE%9A%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%E6%9D%A5%E6%94%AF%E6%8C%81%E7%81%B0%E5%BA%A6%E5%8F%91%E5%B8%83%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%E5%A3%B0%E6%98%8E%E8%A6%81%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9C%8D%E5%8A%A1%0A%20%20%20%20%20%20%20interface%20%3A%20%E9%9C%80%E8%A6%81%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%E5%85%A8%E5%90%8D%EF%BC%8C%E4%BB%8Edubbo-api-common%E4%B8%AD%E7%9A%84com.chris.dubbo.service%E8%8E%B7%E5%8F%96%0A%20%20%20%20%20%20%20ref%20%EF%BC%9A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%AE%9E%E4%BE%8B%E5%AF%B9%E8%B1%A1%0A%20%20%20%20%20%20%20timeout%EF%BC%9A%E8%AE%BE%E7%BD%AE%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%E8%B6%85%E6%97%B6%0A%20%20%20%20%20%20%20dubbo%3Amethod%3A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9F%90%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8Ctimeout%E5%AF%B9%E6%AD%A4%E6%96%B9%E6%B3%95%E8%AE%BE%E7%BD%AE%E5%9C%A8%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E7%AB%AF%E7%9A%84%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20%20version%3A%20%E6%8C%87%E5%AE%9A%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%E6%9D%A5%E6%94%AF%E6%8C%81%E7%81%B0%E5%BA%A6%E5%8F%91%E5%B8%83%0A%20%20%20--%3E%0A%20%20%20%3Cdubbo%3Aservice%20interface%3D%22com.chris.dubbo.service.UserService%22%20ref%3D%22userServiceImpl%22%20timeout%3D%221000%22%20version%3D%220.0.1%22%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Amethod%20name%3D%22getUserAddressList%22%20timeout%3D%223000%22%2F%3E%0A%20%20%20%3C%2Fdubbo%3Aservice%3E%0A%20%20%20%0A%20%20%20%3Cbean%20id%3D%22userServiceImpl%22%20class%3D%22com.chris.user.service.impl.UserServiceImpl%22%2F%3E%0A%20%20%20%0A%20%20%20%0A%20%20%20%3Cdubbo%3Aservice%20interface%3D%22com.chris.dubbo.service.UserService%22%20ref%3D%22userServiceImpl2%22%20timeout%3D%221000%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20version%3D%220.0.2%22%3E%0A%20%20%20%20%20%20%20%3Cdubbo%3Amethod%20name%3D%22getUserAddressList%22%20timeout%3D%223000%22%2F%3E%0A%20%20%20%3C%2Fdubbo%3Aservice%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20UserServiceImpl%0A%0A%20%20%20%60%60%60java%0A%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22retry%20signal.....old....%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address1%20%3D%20new%20UserAddress(1%2C%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%20%221%22%2C%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22Y%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address2%20%3D%20new%20UserAddress(2%2C%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%20%221%22%2C%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22N%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(4)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20return%20Arrays.asList(address1%2C%20address2)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E5%A4%8D%E5%88%B6UserServiceImpl%E4%B8%BAUserServiceImpl2%0A%0A%20%20%20%20%60%60%60java%0A%20%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22retry%20signal.....new....%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address1%20%3D%20new%20UserAddress(1%2C%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%20%221%22%2C%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22Y%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address2%20%3D%20new%20UserAddress(2%2C%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%20%221%22%2C%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22N%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(4)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20Arrays.asList(address1%2C%20address2)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20%60%60%60%0A%0A%0A%E2%80%8B%09%0A%0A2.%20%E6%B6%88%E8%B4%B9%E7%AB%AF%0A%0A%20%20%20%3E%20consumer.xml%0A%20%20%20%3E%0A%20%20%20%3E%20version%EF%BC%9A%E5%A3%B0%E5%90%8D%E4%BD%BF%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E5%93%AA%E4%B8%AA%E7%89%88%E6%9C%AC%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%20version%3D%E2%80%9C*%E2%80%9D%20%E8%A1%A8%E7%A4%BA%E9%9A%8F%E6%9C%BA%E8%B0%83%E7%94%A8%E6%8E%A5%E5%8F%A3%E7%9A%84%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%0A%0A%20%20%20%60%60%60xml%0A%20%20%20%3C!--%20%E5%A3%B0%E6%98%8E%E8%A6%81%E8%B0%83%E7%94%A8%E7%9A%84%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%3A%E7%94%9F%E6%88%90%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E4%BB%A3%E7%90%86%0A%20%20%20%20%20%20%20%20check%3A%20%E6%A3%80%E6%9F%A5%E6%B6%88%E8%B4%B9%E8%80%85%E4%BE%9D%E8%B5%96%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%2C%E5%8D%B3%E6%A3%80%E6%9F%A5%EF%BC%8Ccheck%3D%22false%22%E7%AD%89%E5%90%8C%E4%BA%8E%3Cdubbo%3Aconsumer%20check%3D%22false%22%2F%3E%0A%20%20%20%20%20%20%20%20timeout%EF%BC%9A%E7%94%A8%E7%9A%84%E6%98%AF%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AEdubbo%3Aconsumer%E7%9A%84timeout%20%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%E8%B6%85%E6%97%B6%0A%20%20%20%20%20%20%20%20dubbo%3Amethod%3A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9F%90%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8Ctimeout%E5%AF%B9%E6%AD%A4%E6%96%B9%E6%B3%95%E8%AE%BE%E7%BD%AE%E5%9C%A8%E6%B6%88%E8%B4%B9%E7%AB%AF%E7%9A%84%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20%20%20retries%3A%20%E6%9C%8D%E5%8A%A1%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%EF%BC%8C%E4%B8%8D%E5%8C%85%E6%8B%AC%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%EF%BC%8C%20%E5%A6%82%E6%9E%9C%20retries%3D%223%22%E8%A1%A8%E7%A4%BA%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%E5%A4%B1%E8%B4%A5%E5%90%8E%E4%BC%9A%E5%86%8D%E8%B0%83%E7%94%A8%E4%B8%89%E6%AC%A1%0A%20%20%20%20%20%20%20%20version%EF%BC%9A%E5%A3%B0%E5%90%8D%E4%BD%BF%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E5%93%AA%E4%B8%AA%E7%89%88%E6%9C%AC%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8Cversion%3D%E2%80%9C*%E2%80%9D%20%E8%A1%A8%E7%A4%BA%E9%9A%8F%E6%9C%BA%E8%B0%83%E7%94%A8%E6%8E%A5%E5%8F%A3%E7%9A%84%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%0A%20%20%20%20--%3E%0A%20%20%20%3Cdubbo%3Areference%20id%3D%22userService%22%20interface%3D%22com.chris.dubbo.service.UserService%22%20check%3D%22false%22%20timeout%3D%227000%22%20retries%3D%223%22%20version%3D%220.0.1%22%3E%0A%20%20%20%20%20%20%20%3C!--%3Cdubbo%3Amethod%20name%3D%22getUserAddressList%22%20timeout%3D%225000%22%2F%3E--%3E%0A%20%20%20%3C%2Fdubbo%3Areference%3E%0A%20%20%20%60%60%60%0A%0A%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%3E%20%E5%BD%93%E6%B6%88%E8%B4%B9%E7%AB%AFversion%3D%220.0.1%22%0A%20%20%20%3E%0A%20%20%20%3E%20%3Cdubbo%3Areference%20id%3D%22userService%22%20interface%3D%22com.chris.dubbo.service.UserService%22%20check%3D%22false%22%20timeout%3D%227000%22%20retries%3D%223%22%20version%3D%220.0.1%22%3E%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%9C%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84%E5%90%8E%E5%8F%B0%E4%BC%9A%E6%89%93%E5%8D%B0%E5%A6%82%E4%B8%8B%E4%BF%A1%E6%81%AF%0A%0A%20%20%20!%5Badc7270bf39d39f7a8843571692cf195.png%5D(en-resource%3A%2F%2Fdatabase%2F1035%3A0)%0A%20%20%20%0A%0A%20%20%20%3E%20%E5%BD%93%E6%B6%88%E8%B4%B9%E7%AB%AFversion%3D%220.0.2%22%0A%20%20%20%3E%0A%20%20%20%3E%20%3Cdubbo%3Areference%20id%3D%22userService%22%20interface%3D%22com.chris.dubbo.service.UserService%22%20check%3D%22false%22%20timeout%3D%227000%22%20retries%3D%223%22%20version%3D%220.0.2%22%3E%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%9C%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84%E5%90%8E%E5%8F%B0%E4%BC%9A%E6%89%93%E5%8D%B0%E5%A6%82%E4%B8%8B%E4%BF%A1%E6%81%AF%0A%0A%20%20%20!%5Bd881eb00c45b14eb45ab75960841f225.png%5D(en-resource%3A%2F%2Fdatabase%2F1037%3A0)%0A%20%20%20%0A%0A%0A%0A%0A%23%23%23%23%23%23%204.5.7%20%E6%9C%AC%E5%9C%B0%E5%AD%98%E6%A0%B9%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E5%9C%A8%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%B9%9F%E6%89%A7%E8%A1%8C%E9%83%A8%E5%88%86%E9%80%BB%E8%BE%91%EF%BC%8C%E6%AF%94%E5%A6%82%EF%BC%9A%E5%81%9A%20ThreadLocal%20%E7%BC%93%E5%AD%98%EF%BC%8C%E6%8F%90%E5%89%8D%E9%AA%8C%E8%AF%81%E5%8F%82%E6%95%B0%EF%BC%8C%E8%B0%83%E7%94%A8%E5%A4%B1%E8%B4%A5%E5%90%8E%E4%BC%AA%E9%80%A0%E5%AE%B9%E9%94%99%E6%95%B0%E6%8D%AE%E7%AD%89%E7%AD%89%EF%BC%8C%E6%AD%A4%E6%97%B6%E5%B0%B1%E9%9C%80%E8%A6%81%E5%9C%A8%20API%20%E4%B8%AD%E5%B8%A6%E4%B8%8A%20Stub%EF%BC%8C%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%94%9F%E6%88%90%20Proxy%20%E5%AE%9E%E4%BE%8B%EF%BC%8C%E4%BC%9A%E6%8A%8A%20Proxy%20%E9%80%9A%E8%BF%87%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E4%BC%A0%E7%BB%99%20Stub%EF%BC%8C%E7%84%B6%E5%90%8E%E6%8A%8A%20Stub%20%E6%9A%B4%E9%9C%B2%E7%BB%99%E7%94%A8%E6%88%B7%EF%BC%8CStub%20%E5%8F%AF%E4%BB%A5%E5%86%B3%E5%AE%9A%E8%A6%81%E4%B8%8D%E8%A6%81%E5%8E%BB%E8%B0%83%20Proxy%E3%80%82%0A%0A%0A%0A1.%20%E5%AE%9E%E7%8E%B0UserServiceStub%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40RequiredArgsConstructor%0A%20%20%20public%20class%20UserServiceStub%20implements%20UserService%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20private%20final%20UserService%20userService%3B%0A%20%20%20%0A%20%20%20%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22invoke%20UserServiceStub%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20if%20(StrUtil.isNotEmpty(userId))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20userService.getUserAddressList(userId)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20return%20null%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%20!%5Bf4748d77de39a49e48f55720357353ac.png%5D(en-resource%3A%2F%2Fdatabase%2F1039%3A0)%0A%20%20%20%20%0A%0A2.%20%E9%85%8D%E7%BD%AEconsumer.xml%0A%0A%20%20%20%60%60%60xml%0A%20%20%20!--%20interface%EF%BC%9A%E5%A3%B0%E6%98%8E%E8%A6%81%E8%B0%83%E7%94%A8%E7%9A%84%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3%3A%E7%94%9F%E6%88%90%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E4%BB%A3%E7%90%86%0A%20%20%20%20%20%20%20%20check%3A%20%E6%A3%80%E6%9F%A5%E6%B6%88%E8%B4%B9%E8%80%85%E4%BE%9D%E8%B5%96%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAtrue%2C%E5%8D%B3%E6%A3%80%E6%9F%A5%EF%BC%8Ccheck%3D%22false%22%E7%AD%89%E5%90%8C%E4%BA%8E%3Cdubbo%3Aconsumer%20check%3D%22false%22%2F%3E%0A%20%20%20%20%20%20%20%20timeout%EF%BC%9A%E7%94%A8%E7%9A%84%E6%98%AF%E6%B6%88%E8%B4%B9%E8%80%85%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AEdubbo%3Aconsumer%E7%9A%84timeout%20%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%E8%B6%85%E6%97%B6%0A%20%20%20%20%20%20%20%20dubbo%3Amethod%3A%20%E6%8C%87%E5%90%91%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9F%90%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8Ctimeout%E5%AF%B9%E6%AD%A4%E6%96%B9%E6%B3%95%E8%AE%BE%E7%BD%AE%E5%9C%A8%E6%B6%88%E8%B4%B9%E7%AB%AF%E7%9A%84%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%0A%20%20%20%20%20%20%20%20retries%3A%20%E6%9C%8D%E5%8A%A1%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%EF%BC%8C%E4%B8%8D%E5%8C%85%E6%8B%AC%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%EF%BC%8C%20%E5%A6%82%E6%9E%9C%20retries%3D%223%22%E8%A1%A8%E7%A4%BA%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%E5%A4%B1%E8%B4%A5%E5%90%8E%E4%BC%9A%E5%86%8D%E8%B0%83%E7%94%A8%E4%B8%89%E6%AC%A1%0A%20%20%20%20%20%20%20%20version%EF%BC%9A%E5%A3%B0%E5%90%8D%E4%BD%BF%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E5%93%AA%E4%B8%AA%E7%89%88%E6%9C%AC%E7%9A%84%E6%8E%A5%E5%8F%A3%0A%20%20%20%20%20%20%20%20stub%20%EF%BC%9A%E6%8C%87%E5%90%91%E5%BC%95%E7%94%A8%E6%8E%A5%E5%8F%A3UserService%E7%9A%84%E6%9C%AC%E5%9C%B0%E5%AD%98%E6%A0%B9%E6%8E%A5%E5%8F%A3UserServiceStub%0A%20%20%20%20--%3E%0A%20%20%20%3Cdubbo%3Areference%20id%3D%22userService%22%20interface%3D%22com.chris.dubbo.service.UserService%22%20check%3D%22false%22%20timeout%3D%227000%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20retries%3D%223%22%20version%3D%220.0.2%22%20stub%3D%22com.chris.dubbo.service.stub.UserServiceStub%22%3E%0A%20%20%20%20%20%20%20%3C!--%3Cdubbo%3Amethod%20name%3D%22getUserAddressList%22%20timeout%3D%225000%22%2F%3E--%3E%0A%20%20%20%3C%2Fdubbo%3Areference%3E%0A%20%20%20%60%60%60%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%3E%20%E5%9C%A8order-servicer-consumer%E4%B8%AD%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E5%A6%82%E4%B8%8B%E6%B6%88%E6%81%AF%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%9C%A8%E8%B0%83%E7%94%A8UserService%E6%8E%A5%E5%8F%A3%E6%96%B9%E6%B3%95%E5%89%8D%E5%85%88%E8%B0%83%E7%94%A8%E5%AD%98%E6%A0%B9%E6%8E%A5%E5%8F%A3UserServiceStub%0A%20%20%20%0A%20%20%20%20!%5Bbfed4de2f9425a6e0f9326da4bb6820a.png%5D(en-resource%3A%2F%2Fdatabase%2F1041%3A0)%0A%20%20%20%20%0A%0A%0A%0A%0A%0A%23%23%23%23%23%23%204.5.8%20%E4%B8%8ESpringboot%E9%9B%86%E6%88%90%E7%9A%84%E4%B8%89%E7%A7%8D%E6%96%B9%E5%BC%8F%0A%0A1.%20%E7%9B%B4%E6%8E%A5%E9%9B%86%E6%88%90%0A%0A%20%20%20%3E%20%E5%BB%BAmodule%0A%0A%20%20%20%3E%20%E6%94%B9pom%0A%0A%20%20%20%60%60%60%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5spring-boot%20dubbo--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Edubbo-spring-boot-starter%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%3C!--%E5%BC%95%E5%85%A5dubbo--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Ecom.alibaba%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Edubbo%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%0A%20%20%20%3C!--%20%E7%94%B1%E4%BA%8E%E6%88%91%E4%BB%AC%E4%BD%BF%E7%94%A8zookeeper%E4%BD%9C%E4%B8%BA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20dubbo%202.6%E4%BB%A5%E5%89%8D%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5zkclient%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20dubbo%202.6%E5%8F%8A%E4%BB%A5%E5%90%8E%E7%9A%84%E7%89%88%E6%9C%AC%E5%BC%95%E5%85%A5curator%E6%93%8D%E4%BD%9Czookeeper%0A%20%20%20%20%20%20%20%E4%B8%8B%E9%9D%A2%E4%B8%A4%E4%B8%AAzk%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%A0%B9%E6%8D%AEdubbo%E7%89%88%E6%9C%AC2%E9%80%891%E5%8D%B3%E5%8F%AF%0A%20%20%20--%3E%0A%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%3CgroupId%3Eorg.apache.curator%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%3CartifactId%3Ecurator-framework%3C%2FartifactId%3E%0A%20%20%20%3C%2Fdependency%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E5%86%99yml%0A%0A%20%20%20%60%60%60yml%0A%20%20%20server%3A%0A%20%20%20%20%20port%3A%208081%0A%20%20%20%0A%20%20%20dubbo%3A%0A%20%20%20%20%20application%3A%0A%20%20%20%20%20%20%20name%3A%20boot-order-service-provider%0A%20%20%20%20%20registry%3A%0A%20%20%20%20%20%20%20protocol%3A%20zookeeper%0A%20%20%20%20%20%20%20address%3A%20master%3A2181%0A%20%20%20%20%20%20%20check%3A%20false%20%20%23%E5%81%9C%E7%94%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E4%B8%BB%E5%90%AF%E5%8A%A8%E5%8A%A0%40EnableDubbo%20%2F%2F%E5%BC%80%E5%90%AF%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E7%9A%84dubbo%E5%8A%9F%E8%83%BD%0A%0A%20%20%20%3E%20%E6%B6%88%E8%B4%B9%E7%AB%AF%E5%BC%95%E7%94%A8%E6%9C%8D%E5%8A%A1%40Reference%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Reference(check%20%3D%20false)%0A%20%20%20private%20UserService%20userService%3B%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%9C%8D%E5%8A%A1%E4%BD%BF%E7%94%A8dubbo%20%E6%B3%A8%E8%A7%A3%40Service%20%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%0A%0A%20%20%20%60%60%60java%0A%20%20%20import%20com.chris.dubbo.service.UserService%3B%0A%20%20%20import%20org.springframework.stereotype.Component%3B%0A%20%20%20%0A%20%20%20%40Service%20%2F%2F%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%0A%20%20%20%40Component%0A%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address1%20%3D%20new%20UserAddress(1%2C%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%20%221%22%2C%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22Y%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address2%20%3D%20new%20UserAddress(2%2C%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%20%221%22%2C%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22N%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20Arrays.asList(address1%2C%20address2)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%0A%0A2.%20%E4%BD%BF%E7%94%A8xml%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%0A%0A%20%20%20%3E%20%E5%B0%86provider.xml%E6%88%96consumer.xml%20%E6%94%BE%E5%9C%A8%20resources%E7%9B%AE%E5%89%8D%E4%B8%8B%0A%0A%20%20%20%3E%20%E4%B8%BB%E5%90%AF%E5%8A%A8%E7%B1%BB%E4%BD%BF%E7%94%A8%20%40ImportResource(locations%20%3D%20%22classpath%3Aprovider.xml%22)%0A%20%20%20%3E%0A%20%20%20%3E%20%60%60%60%0A%20%20%20%3E%20%40SpringBootApplication%0A%20%20%20%3E%20%40ImportResource(locations%20%3D%20%22classpath%3Aprovider.xml%22)%0A%20%20%20%3E%20public%20class%20UserMain%20%7B%0A%20%20%20%3E%20%0A%20%20%20%3E%20%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%3E%20%20%20%20%20%20%20%20%20SpringApplication.run(UserMain.class%2C%20args)%3B%0A%20%20%20%3E%20%20%20%20%20%7D%0A%20%20%20%3E%20%7D%0A%20%20%20%3E%20%60%60%60%0A%0A%E2%80%8B%09%09%0A%0A%0A%0A3.%20%E4%BD%BF%E7%94%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%E6%9D%A5%E9%85%8D%E7%BD%AEdubbo%E4%BF%A1%E6%81%AF%0A%0A%20%20%20%3E%20DubboConfig%0A%0A%20%20%20%60%60%60java%0A%20%20%20package%20com.chris.user.config%3B%0A%20%20%20%0A%20%20%20import%20com.alibaba.dubbo.config.*%3B%0A%20%20%20import%20com.chris.dubbo.service.UserService%3B%0A%20%20%20import%20org.springframework.context.annotation.Bean%3B%0A%20%20%20import%20org.springframework.context.annotation.Configuration%3B%0A%20%20%20%0A%20%20%20import%20java.util.Collections%3B%0A%20%20%20%0A%20%20%20%40Configuration%0A%20%20%20public%20class%20DubboConfig%20%7B%0A%20%20%20%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20public%20ApplicationConfig%20applicationConfig()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20ApplicationConfig%20applicationConfig%20%3D%20new%20ApplicationConfig()%3B%0A%20%20%20%20%20%20%20%20%20%20%20applicationConfig.setName(%22boot-user-service-provider%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20applicationConfig%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20public%20RegistryConfig%20registryConfig()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20RegistryConfig%20registryConfig%20%3D%20new%20RegistryConfig()%3B%0A%20%20%20%20%20%20%20%20%20%20%20registryConfig.setProtocol(%22zookeeper%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20registryConfig.setAddress(%22master%3A2181%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20registryConfig%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20public%20ProtocolConfig%20protocolConfig()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20ProtocolConfig%20protocolConfig%20%3D%20new%20ProtocolConfig()%3B%0A%20%20%20%20%20%20%20%20%20%20%20protocolConfig.setName(%22dubbo%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20protocolConfig.setPort(20081)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20protocolConfig%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20%2F*%0A%20%20%20%20%20%20%20%3Cdubbo%3Aservice%20interface%3D%22com.chris.dubbo.service.UserService%22%20ref%3D%22userServiceImpl%22%20timeout%3D%221000%22%20version%3D%220.0.1%22%3E%0A%20%20%20%20%20%20%20%20%20%20%3Cdubbo%3Amethod%20name%3D%22getUserAddressList%22%20timeout%3D%223000%22%2F%3E%0A%20%20%20%20%20%20%20%3C%2Fdubbo%3Aservice%3E%0A%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20public%20ServiceConfig%3CUserService%3E%20userServiceConfig(UserService%20userService)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20ServiceConfig%3CUserService%3E%20serviceConfig%20%3D%20new%20ServiceConfig%3C%3E()%3B%0A%20%20%20%20%20%20%20%20%20%20%20serviceConfig.setInterface(UserService.class)%3B%0A%20%20%20%20%20%20%20%20%20%20%20serviceConfig.setRef(userService)%3B%0A%20%20%20%20%20%20%20%20%20%20%20serviceConfig.setTimeout(5000)%3B%0A%20%20%20%20%20%20%20%20%20%20%20serviceConfig.setVersion(%220.0.1%22)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20MethodConfig%20methodConfig%20%3D%20new%20MethodConfig()%3B%0A%20%20%20%20%20%20%20%20%20%20%20methodConfig.setName(%22getUserAddressList%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20methodConfig.setTimeout(3000)%3B%0A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20serviceConfig.setMethods(Collections.singletonList(methodConfig))%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20serviceConfig%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%0A%20%20%20%20%20%20%20%2F*%0A%20%20%20%20%20%20%20%3Cdubbo%3Aprovider%20timeout%3D%223000%22%2F%3E%0A%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%40Bean%0A%20%20%20%20%20%20%20public%20ProviderConfig%20providerConfig()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20ProviderConfig%20providerConfig%20%3D%20new%20ProviderConfig()%3B%0A%20%20%20%20%20%20%20%20%20%20%20providerConfig.setTimeout(3000)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20providerConfig%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%8E%A5%E5%8F%A3%E7%B1%BB%E4%BD%BF%E7%94%A8dubbo%20%E6%B3%A8%E8%A7%A3%40Service%20%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%0A%0A%20%20%20%60%60%60java%0A%20%20%20import%20com.alibaba.dubbo.config.annotation.Service%3B%0A%20%20%20import%20com.chris.dubbo.bean.UserAddress%3B%0A%20%20%20import%20com.chris.dubbo.service.UserService%3B%0A%20%20%20import%20org.springframework.stereotype.Component%3B%0A%20%20%20%0A%20%20%20import%20java.util.Arrays%3B%0A%20%20%20import%20java.util.List%3B%0A%20%20%20%0A%20%20%20%40Service%20%2F%2F%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%0A%20%20%20%40Component%0A%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address1%20%3D%20new%20UserAddress(1%2C%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%20%221%22%2C%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22Y%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address2%20%3D%20new%20UserAddress(2%2C%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%20%221%22%2C%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22N%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20Arrays.asList(address1%2C%20address2)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%0A%20%20%20%60%60%60%0A%0A%E2%80%8B%09%0A%0A%0A%0A%0A%0A%23%23%23%23%23%204.6%20%E9%AB%98%E5%8F%AF%E7%94%A8%0A%0A%23%23%23%23%23%23%204.6.1%20zk%E5%AE%95%E6%9C%BA%0A%0A%3E%20%E7%8E%B0%E8%B1%A1%EF%BC%9Azookeeper%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%AE%95%E6%9C%BA%EF%BC%8C%E8%BF%98%E5%8F%AF%E4%BB%A5%E6%B6%88%E8%B4%B9dubbo%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%9C%8D%E5%8A%A1%E3%80%82%0A%0A%3E%20%E5%81%A5%E5%A3%AE%E6%80%A7%0A%3E%0A%3E%20l%20%E7%9B%91%E6%8E%A7%E4%B8%AD%E5%BF%83%E5%AE%95%E6%8E%89%E4%B8%8D%E5%BD%B1%E5%93%8D%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%8F%AA%E6%98%AF%E4%B8%A2%E5%A4%B1%E9%83%A8%E5%88%86%E9%87%87%E6%A0%B7%E6%95%B0%E6%8D%AE%0A%3E%0A%3E%20l%20%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%95%E6%8E%89%E5%90%8E%EF%BC%8C%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E4%BB%8D%E8%83%BD%E9%80%9A%E8%BF%87%E7%BC%93%E5%AD%98%E6%8F%90%E4%BE%9B%E6%9C%8D%E5%8A%A1%E5%88%97%E8%A1%A8%E6%9F%A5%E8%AF%A2%EF%BC%8C%E4%BD%86%E4%B8%8D%E8%83%BD%E6%B3%A8%E5%86%8C%E6%96%B0%E6%9C%8D%E5%8A%A1%0A%3E%0A%3E%20l%20%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%AF%B9%E7%AD%89%E9%9B%86%E7%BE%A4%EF%BC%8C%E4%BB%BB%E6%84%8F%E4%B8%80%E5%8F%B0%E5%AE%95%E6%8E%89%E5%90%8E%EF%BC%8C%E5%B0%86%E8%87%AA%E5%8A%A8%E5%88%87%E6%8D%A2%E5%88%B0%E5%8F%A6%E4%B8%80%E5%8F%B0%0A%3E%0A%3E%20l%20**%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%85%A8%E9%83%A8%E5%AE%95%E6%8E%89%E5%90%8E%EF%BC%8C%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E5%92%8C%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E4%BB%8D%E8%83%BD%E9%80%9A%E8%BF%87%E6%9C%AC%E5%9C%B0%E7%BC%93%E5%AD%98%E9%80%9A%E8%AE%AF**%0A%3E%0A%3E%20l%20%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%97%A0%E7%8A%B6%E6%80%81%EF%BC%8C%E4%BB%BB%E6%84%8F%E4%B8%80%E5%8F%B0%E5%AE%95%E6%8E%89%E5%90%8E%EF%BC%8C%E4%B8%8D%E5%BD%B1%E5%93%8D%E4%BD%BF%E7%94%A8%0A%3E%0A%3E%20l%20%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E5%85%A8%E9%83%A8%E5%AE%95%E6%8E%89%E5%90%8E%EF%BC%8C%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E5%BA%94%E7%94%A8%E5%B0%86%E6%97%A0%E6%B3%95%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%B9%B6%E6%97%A0%E9%99%90%E6%AC%A1%E9%87%8D%E8%BF%9E%E7%AD%89%E5%BE%85%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%81%A2%E5%A4%8D%0A%0A%0A%0A%23%23%23%23%23%23%204.6.2%20dubbo%E7%9B%B4%E8%BF%9E%0A%0A%3E%20%E4%B8%8D%E5%80%9F%E5%8A%A9%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%EF%BC%8C%E5%AE%9E%E7%8E%B0%E6%B6%88%E8%B4%B9%E8%80%85%E7%9B%B4%E6%8E%A5%E8%AE%BF%E9%97%AE%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%0A%3E%0A%3E%20%20%40Reference(check%20%3D%20false%2C%20url%20%3D%20%22127.0.0.1%3A20081%22)%0A%0A%60%60%60java%0Apackage%20com.chris.order.service.impl%3B%0A%0Aimport%20com.alibaba.dubbo.config.annotation.Reference%3B%0Aimport%20com.chris.dubbo.bean.UserAddress%3B%0Aimport%20com.chris.dubbo.service.OrderService%3B%0Aimport%20com.chris.dubbo.service.UserService%3B%0Aimport%20org.springframework.stereotype.Service%3B%0A%0Aimport%20java.util.List%3B%0A%0A%40Service%0Apublic%20class%20OrderServiceImpl%20implements%20OrderService%20%7B%0A%0A%20%20%20%20%40Reference(check%20%3D%20false%2C%20url%20%3D%20%22127.0.0.1%3A20081%22)%0A%20%20%20%20private%20UserService%20userService%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20List%3CUserAddress%3E%20initOrder(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%A8%E6%88%B7id%EF%BC%9A%22%20%2B%20userId)%3B%0A%20%20%20%20%20%20%20%20%2F%2F1%E3%80%81%E6%9F%A5%E8%AF%A2%E7%94%A8%E6%88%B7%E7%9A%84%E6%94%B6%E8%B4%A7%E5%9C%B0%E5%9D%80%0A%20%20%20%20%20%20%20%20List%3CUserAddress%3E%20addressList%20%3D%20userService.getUserAddressList(userId)%3B%0A%20%20%20%20%20%20%20%20for%20(UserAddress%20userAddress%20%3A%20addressList)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(userAddress.getUserAddress())%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20addressList%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%204.7%20%E9%9B%86%E7%BE%A4%E4%B8%8Bdubbo%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E9%85%8D%E7%BD%AE%0A%0Ahttp%3A%2F%2Fdubbo.apache.org%2Fzh-cn%2Fdocs%2Fuser%2Fdemos%2Floadbalance.html%0A%0A%23%23%23%23%23%23%204.7.1%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%0A%0A%3E%20%E5%9C%A8%E9%9B%86%E7%BE%A4%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%97%B6%EF%BC%8CDubbo%20%E6%8F%90%E4%BE%9B%E4%BA%86%E5%A4%9A%E7%A7%8D%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%EF%BC%8C%E7%BC%BA%E7%9C%81%E4%B8%BA%20random%20%E9%9A%8F%E6%9C%BA%E8%B0%83%E7%94%A8%E3%80%82%0A%0A%0A%0A%60%60%60java%0A%40SPI(RandomLoadBalance.NAME)%0Apublic%20interface%20LoadBalance%20%7B%0A%60%60%60%0A%0A%60%60%60java%0A%2F**%0A%20*%20random%20load%20balance.%0A%20*%0A%20*%2F%0Apublic%20class%20RandomLoadBalance%20extends%20AbstractLoadBalance%20%7B%0A%0A%20%20%20%20public%20static%20final%20String%20NAME%20%3D%20%22random%22%3B%0A%60%60%60%0A%0A%3E%20Ctrl%2BH%20%E6%89%93%E5%BC%80%E7%BB%A7%E6%89%BF%E6%A0%91%0A%0A!%5B34b4d72cfd529395811500d7fcb98529.png%5D(en-resource%3A%2F%2Fdatabase%2F1043%3A1)%0A%0A%0A%0A%0A1.%20**Random%20LoadBalance**%0A%0A%20%20%20!%5Ba8106b9e4278a92d5b6c9b195149ebf6.png%5D(en-resource%3A%2F%2Fdatabase%2F1047%3A0)%0A%20%20%20%0A%20%20%20%0A%0A%20%20%20%3E%20%E5%9F%BA%E4%BA%8E%E6%9D%83%E9%87%8D%E7%9A%84%E9%9A%8F%E6%9C%BA%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%E3%80%82%0A%20%20%20%3E%0A%20%20%20%3E%20%E4%B8%8B%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%E6%97%A0%E6%B3%95%E7%A1%AE%E5%AE%9A%E8%AF%B7%E6%B1%82%E4%BC%9A%E8%90%BD%E5%9C%A8%E5%93%AA%E4%B8%AA%E6%9C%8D%E5%8A%A1%E8%8A%82%E7%82%B9%E4%B8%8A%EF%BC%8C%E4%BD%86%E6%98%AF%E6%80%BB%E6%A6%82%E7%8E%87%E6%98%AF%E6%8C%89%E6%9D%83%E9%87%8D%E6%9D%A5%E5%88%86%E5%B8%83%E7%9A%84%E3%80%82%0A%0A2.%20**RoundRobin%20LoadBalance**%0A%0A%20%20%20!%5Becee73e4b58ac753954796cc2e6777ce.png%5D(en-resource%3A%2F%2Fdatabase%2F1051%3A0)%0A%20%20%20%0A%0A%20%20%20%3E%20%E5%9F%BA%E4%BA%8E%E6%9D%83%E9%87%8D%E7%9A%84%E8%BD%AE%E8%AF%A2%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%E3%80%82%0A%20%20%20%3E%0A%20%20%20%3E%20%E4%B8%8B%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%E8%AF%B7%E6%B1%82%E4%BC%9A%E8%90%BD%E5%9C%A8%E6%9C%89%E5%BA%8F%E7%9A%84%E6%9C%8D%E5%8A%A1%E8%8A%82%E7%82%B9%E4%B8%8A%EF%BC%8C%E4%BD%86%E6%98%AF%E9%9C%80%E8%A6%81%E8%80%83%E8%99%91%E5%88%B0%E6%9D%83%E9%87%8D%E5%88%86%E5%B8%83%E3%80%82%0A%0A3.%20**LeastActive%20LoadBalance**%0A%0A%20%20%20!%5B58b355b078b8917e3078b350062bfb91.png%5D(en-resource%3A%2F%2Fdatabase%2F1049%3A0)%0A%20%20%20%0A%0A%20%20%20%3E%20%E6%9C%80%E5%B0%91%E6%B4%BB%E8%B7%83%E6%95%B0%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%EF%BC%8C%E6%B4%BB%E8%B7%83%E6%95%B0%E6%8C%87%E8%B0%83%E7%94%A8%E5%89%8D%E5%90%8E%E7%9A%84%E5%93%8D%E5%BA%94%E6%97%B6%E9%97%B4%EF%BC%8C%20%E4%B8%8B%E6%AC%A1%E5%9C%A8%E8%B0%83%E7%94%A8%E6%9C%8D%E5%8A%A1%E4%B9%8B%E5%89%8D%E4%BC%9A%E6%AF%94%E5%AF%B9%E4%B8%8A%E6%AC%A1%E8%B0%83%E7%94%A8%E6%89%80%E8%8A%B1%E8%B4%B9%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%8C%E4%BC%98%E5%85%88%E8%B0%83%E7%94%A8%E4%B8%8A%E6%AC%A1%E5%93%8D%E5%BA%94%E6%97%B6%E9%97%B4%E6%9C%80%E5%B0%91%E7%9A%84%E6%9C%8D%E5%8A%A1%E8%8A%82%E7%82%B9%E3%80%82%0A%20%20%20%3E%0A%20%20%20%3E%20%E4%BD%BF%E6%85%A2%E7%9A%84%E6%8F%90%E4%BE%9B%E8%80%85%E6%94%B6%E5%88%B0%E6%9B%B4%E5%B0%91%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%B6%8A%E6%85%A2%E7%9A%84%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E8%B0%83%E7%94%A8%E5%89%8D%E5%90%8E%E8%AE%A1%E6%95%B0%E5%B7%AE%E4%BC%9A%E8%B6%8A%E5%A4%A7%E3%80%82%0A%0A4.%20**ConsistentHash%20LoadBalance**%0A%0A%20%20%20%3E%20%E4%B8%80%E8%87%B4%E6%80%A7%20Hash%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%0A%20%20%20%3E%0A%20%20%20%3E%20%E7%9B%B8%E5%90%8C%E5%8F%82%E6%95%B0%E7%9A%84%E8%AF%B7%E6%B1%82%E6%80%BB%E6%98%AF%E5%8F%91%E5%88%B0%E5%90%8C%E4%B8%80%E6%8F%90%E4%BE%9B%E8%80%85%E3%80%82%0A%20%20%20%3E%0A%20%20%20%3E%20%E5%BD%93%E6%9F%90%E4%B8%80%E5%8F%B0%E6%8F%90%E4%BE%9B%E8%80%85%E6%8C%82%E6%97%B6%EF%BC%8C%E5%8E%9F%E6%9C%AC%E5%8F%91%E5%BE%80%E8%AF%A5%E6%8F%90%E4%BE%9B%E8%80%85%E7%9A%84%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%9F%BA%E4%BA%8E%E8%99%9A%E6%8B%9F%E8%8A%82%E7%82%B9%EF%BC%8C%E5%B9%B3%E6%91%8A%E5%88%B0%E5%85%B6%E5%AE%83%E6%8F%90%E4%BE%9B%E8%80%85%EF%BC%8C%E4%B8%8D%E4%BC%9A%E5%BC%95%E8%B5%B7%E5%89%A7%E7%83%88%E5%8F%98%E5%8A%A8%E3%80%82%E7%AE%97%E6%B3%95%E5%8F%82%E8%A7%81%EF%BC%9Ahttp%3A%2F%2Fen.wikipedia.org%2Fwiki%2FConsistent_hashing%0A%20%20%20%3E%0A%20%20%20%3E%20%E7%BC%BA%E7%9C%81%E5%8F%AA%E5%AF%B9%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%20Hash%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BF%AE%E6%94%B9%EF%BC%8C%E8%AF%B7%E9%85%8D%E7%BD%AE%20%3Cdubbo%3Aparameter%20key%3D%22hash.arguments%22%20value%3D%220%2C1%22%20%2F%3E%0A%20%20%20%3E%0A%20%20%20%3E%20%E7%BC%BA%E7%9C%81%E7%94%A8%20160%20%E4%BB%BD%E8%99%9A%E6%8B%9F%E8%8A%82%E7%82%B9%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BF%AE%E6%94%B9%EF%BC%8C%E8%AF%B7%E9%85%8D%E7%BD%AE%20%3Cdubbo%3Aparameter%20key%3D%22hash.nodes%22%20value%3D%22320%22%20%2F%3E%0A%0A%0A%0A%23%23%23%23%23%23%204.7.2%20%E4%BF%AE%E6%94%B9%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%0A%0A1.%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%9C%8D%E5%8A%A1%E7%BA%A7%E5%88%AB%0A%0A%60%60%60xml%0A%3Cdubbo%3Aservice%20interface%3D%22...%22%20loadbalance%3D%22roundrobin%22%20%2F%3E%0A%60%60%60%0A%0A2.%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%8D%E5%8A%A1%E7%BA%A7%E5%88%AB%0A%0A%60%60%60xml%0A%3Cdubbo%3Areference%20interface%3D%22...%22%20loadbalance%3D%22roundrobin%22%20%2F%3E%0A%60%60%60%0A%0A3.%20%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%96%B9%E6%B3%95%E7%BA%A7%E5%88%AB%0A%0A%60%60%60xml%0A%3Cdubbo%3Aservice%20interface%3D%22...%22%3E%0A%20%20%20%20%3Cdubbo%3Amethod%20name%3D%22...%22%20loadbalance%3D%22roundrobin%22%2F%3E%0A%3C%2Fdubbo%3Aservice%3E%0A%60%60%60%0A%0A4.%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%96%B9%E6%B3%95%E7%BA%A7%E5%88%AB%0A%0A%60%60%60xml%0A%3Cdubbo%3Areference%20interface%3D%22...%22%3E%0A%20%20%20%20%3Cdubbo%3Amethod%20name%3D%22...%22%20loadbalance%3D%22roundrobin%22%2F%3E%0A%3C%2Fdubbo%3Areference%3E%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%204.7.3%20%E4%BF%AE%E6%94%B9%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%9D%83%E9%87%8D%0A%0A1.%20%E5%9C%A8%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%E6%97%B6%E7%9B%B4%E6%8E%A5hardcode%E5%9C%A8%40Service%E9%87%8C%E9%9D%A2%0A%0A%20%20%20%60%60%60java%0A%20%20%20%40Service(weight%20%3D%20100)%20%2F%2F%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%0A%20%20%20%40Component%0A%20%20%20public%20class%20UserServiceImpl%20implements%20UserService%20%7B%0A%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20public%20List%3CUserAddress%3E%20getUserAddressList(String%20userId)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address1%20%3D%20new%20UserAddress(1%2C%20%22%E5%8C%97%E4%BA%AC%E5%B8%82%E6%98%8C%E5%B9%B3%E5%8C%BA%E5%AE%8F%E7%A6%8F%E7%A7%91%E6%8A%80%E5%9B%AD%E7%BB%BC%E5%90%88%E6%A5%BC3%E5%B1%82%22%2C%20%221%22%2C%20%22%E6%9D%8E%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22Y%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20UserAddress%20address2%20%3D%20new%20UserAddress(2%2C%20%22%E6%B7%B1%E5%9C%B3%E5%B8%82%E5%AE%9D%E5%AE%89%E5%8C%BA%E8%A5%BF%E9%83%A8%E7%A1%85%E8%B0%B7%E5%A4%A7%E5%8E%A6B%E5%BA%A73%E5%B1%82%EF%BC%88%E6%B7%B1%E5%9C%B3%E5%88%86%E6%A0%A1%EF%BC%89%22%2C%20%221%22%2C%20%22%E7%8E%8B%E8%80%81%E5%B8%88%22%2C%20%22010-56253825%22%2C%20%22N%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20return%20Arrays.asList(address1%2C%20address2)%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A2.%20%E5%9C%A8%E6%8E%A7%E5%88%B6%E5%8F%B0%E5%8A%A8%E6%80%81%E5%A2%9E%E5%87%8F%E6%9D%83%E9%87%8D%0A%0A%20%20%20!%5B9db2ef9a0f973a2ab5f96171699ad299.png%5D(en-resource%3A%2F%2Fdatabase%2F1053%3A0)%0A%20%20%20%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A

OPPO-PDM项目组场地管理规范_v2.0

创建时间:2022/1/5 10:50
更新时间:2022/1/5 11:40
作者:Chris
来源:file:///C:/Program%20Files%20(x86)/TeamTalk2.0/resources/app.asar/build/renderer/windows/dashboard.html?isSingleLogin=false#/chat?groupId=4648197

1 上下班时间

  1. 上午时间9:00-12:00
  2. 就餐时间12:00-14:00
  3. 下午时间14:00-18:30
  • *注: 一般情况下每天都需要加班到8点之后,不要出现晚上开会找不到人的情况!

2 考勤打卡

  1. 要求每天【不包括周末,节假日】在OMS上打卡,每天两次,上下班各一次。
  2. 如果忘记打卡或迟到,OMS打卡会标红即异常打卡。
  3. 因特殊原因无法在OMS正常打卡,需要在客户TT打卡群中发送 现场上班打卡【已iknow健康打卡】

3 调休请假

  1. 请假或调休需提交一天向客户报备并提交相关书面申请
  2. 不许在手头工作没有完成或没有交待清楚的情况下请假或调休。
  3. 在上线前一天尽量不要请假或调休,如果事件紧急需向客户方负责人说明原因, 在得到明确许可情况下方可请假或调休。
  1. 邮件发送格式

    发送:wangshun@oppo.com;yangyuxiang@oppo.com
    抄送:zhengcan1@oppo.com;lilun@e-lead.cn; 和对应项目的对应项目BA、SE邮箱
    
  2. OMS提交申请

    在OMS管理系统发起请假/补签/加班申请等流程时,注意读者添加:王顺、闫伟、对应项目BA、SE

  3. PLM微信打卡群发送申请告知

    每次调休或请假都需要在PLM微信打卡群里面@王顺,郑灿和对应项目BA、SE

  4. 在公司OA上提交调休或请假申请电子流

4. 加班

  1. 提前发送加班邮件,写明加班处理事项及开发任务。
    邮件发送格式
    发送:对应项目BA、SE邮箱
    抄送:wangshun@oppo.com;zhengcan1@oppo.com;lilun@e-lead.cn; 
    
  2. 在公司OA上提交加班电子流

5. 信息安全

  1. 严禁将用户信息,数据, 通知等...在未得到用户明确授权时通过任何渠道【微信,QQ,邮件,微博...】转发或外发.
  2. 严禁将移动设备【U盘,手机,移动硬盘等...】接入用户提供的办公设备.
  3. 严禁通过第三方仓库【GitHub,DockHub, GitLab...】等上传用户代码.

【未完待续】

%23%23%23%23%201%20%E4%B8%8A%E4%B8%8B%E7%8F%AD%E6%97%B6%E9%97%B4%0A%0A%3E%201.%20%E4%B8%8A%E5%8D%88%E6%97%B6%E9%97%B49%3A00-12%3A00%0A%3E%202.%20%E5%B0%B1%E9%A4%90%E6%97%B6%E9%97%B412%3A00-14%3A00%0A%3E%203.%20%E4%B8%8B%E5%8D%88%E6%97%B6%E9%97%B414%3A00-18%3A30%0A%0A-%20*%E6%B3%A8%3A%20%E4%B8%80%E8%88%AC%E6%83%85%E5%86%B5%E4%B8%8B%E6%AF%8F%E5%A4%A9%E9%83%BD%E9%9C%80%E8%A6%81%E5%8A%A0%E7%8F%AD%E5%88%B08%E7%82%B9%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%B8%8D%E8%A6%81%E5%87%BA%E7%8E%B0%E6%99%9A%E4%B8%8A%E5%BC%80%E4%BC%9A%E6%89%BE%E4%B8%8D%E5%88%B0%E4%BA%BA%E7%9A%84%E6%83%85%E5%86%B5!%0A%0A%23%23%23%23%202%20%E8%80%83%E5%8B%A4%E6%89%93%E5%8D%A1%0A%3E%201.%20%E8%A6%81%E6%B1%82%E6%AF%8F%E5%A4%A9%E3%80%90%E4%B8%8D%E5%8C%85%E6%8B%AC%E5%91%A8%E6%9C%AB%EF%BC%8C%E8%8A%82%E5%81%87%E6%97%A5%E3%80%91%E5%9C%A8OMS%E4%B8%8A%E6%89%93%E5%8D%A1%EF%BC%8C%E6%AF%8F%E5%A4%A9%E4%B8%A4%E6%AC%A1%EF%BC%8C%E4%B8%8A%E4%B8%8B%E7%8F%AD%E5%90%84%E4%B8%80%E6%AC%A1%E3%80%82%0A%3E%202.%20%E5%A6%82%E6%9E%9C%E5%BF%98%E8%AE%B0%E6%89%93%E5%8D%A1%E6%88%96%E8%BF%9F%E5%88%B0%EF%BC%8COMS%E6%89%93%E5%8D%A1%E4%BC%9A%E6%A0%87%E7%BA%A2%E5%8D%B3%E5%BC%82%E5%B8%B8%E6%89%93%E5%8D%A1%E3%80%82%0A%3E%203.%20%E5%9B%A0%E7%89%B9%E6%AE%8A%E5%8E%9F%E5%9B%A0%E6%97%A0%E6%B3%95%E5%9C%A8OMS%E6%AD%A3%E5%B8%B8%E6%89%93%E5%8D%A1%EF%BC%8C%E9%9C%80%E8%A6%81%E5%9C%A8%E5%AE%A2%E6%88%B7TT%E6%89%93%E5%8D%A1%E7%BE%A4%E4%B8%AD%E5%8F%91%E9%80%81%20%60%E7%8E%B0%E5%9C%BA%E4%B8%8A%E7%8F%AD%E6%89%93%E5%8D%A1%E3%80%90%E5%B7%B2iknow%E5%81%A5%E5%BA%B7%E6%89%93%E5%8D%A1%E3%80%91%60%0A%0A%23%23%23%23%203%20%E8%B0%83%E4%BC%91%E8%AF%B7%E5%81%87%0A%3E%201.%20%E8%AF%B7%E5%81%87%E6%88%96%E8%B0%83%E4%BC%91%E9%9C%80%E6%8F%90%E4%BA%A4%E4%B8%80%E5%A4%A9%E5%90%91%E5%AE%A2%E6%88%B7%E6%8A%A5%E5%A4%87%E5%B9%B6%E6%8F%90%E4%BA%A4%E7%9B%B8%E5%85%B3%E4%B9%A6%E9%9D%A2%E7%94%B3%E8%AF%B7%20%0A%3E%202.%20%E4%B8%8D%E8%AE%B8%E5%9C%A8%E6%89%8B%E5%A4%B4%E5%B7%A5%E4%BD%9C%E6%B2%A1%E6%9C%89%E5%AE%8C%E6%88%90%E6%88%96%E6%B2%A1%E6%9C%89%E4%BA%A4%E5%BE%85%E6%B8%85%E6%A5%9A%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E8%AF%B7%E5%81%87%E6%88%96%E8%B0%83%E4%BC%91%E3%80%82%0A%3E%203.%20%E5%9C%A8%E4%B8%8A%E7%BA%BF%E5%89%8D%E4%B8%80%E5%A4%A9%E5%B0%BD%E9%87%8F%E4%B8%8D%E8%A6%81%E8%AF%B7%E5%81%87%E6%88%96%E8%B0%83%E4%BC%91%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%BA%8B%E4%BB%B6%E7%B4%A7%E6%80%A5%E9%9C%80%E5%90%91%E5%AE%A2%E6%88%B7%E6%96%B9%E8%B4%9F%E8%B4%A3%E4%BA%BA%E8%AF%B4%E6%98%8E%E5%8E%9F%E5%9B%A0%EF%BC%8C%20%E5%9C%A8%E5%BE%97%E5%88%B0%E6%98%8E%E7%A1%AE%E8%AE%B8%E5%8F%AF%E6%83%85%E5%86%B5%E4%B8%8B%E6%96%B9%E5%8F%AF%E8%AF%B7%E5%81%87%E6%88%96%E8%B0%83%E4%BC%91%E3%80%82%0A%0A%201.%20%20%E9%82%AE%E4%BB%B6%E5%8F%91%E9%80%81%E6%A0%BC%E5%BC%8F%0A%20%20%20%20%20%20%20%60%60%60%0A%20%20%20%20%20%20%20%E5%8F%91%E9%80%81%EF%BC%9Awangshun%40oppo.com%3Byangyuxiang%40oppo.com%0A%20%20%20%20%20%20%20%E6%8A%84%E9%80%81%EF%BC%9Azhengcan1%40oppo.com%3Blilun%40e-lead.cn%3B%20%E5%92%8C%E5%AF%B9%E5%BA%94%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%AF%B9%E5%BA%94%E9%A1%B9%E7%9B%AEBA%E3%80%81SE%E9%82%AE%E7%AE%B1%0A%20%20%20%20%20%20%20%60%60%60%0A%0A%202.%20OMS%E6%8F%90%E4%BA%A4%E7%94%B3%E8%AF%B7%0A%20%20%20%20%3E%20%E5%9C%A8OMS%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E5%8F%91%E8%B5%B7%E8%AF%B7%E5%81%87%2F%E8%A1%A5%E7%AD%BE%2F%E5%8A%A0%E7%8F%AD%E7%94%B3%E8%AF%B7%E7%AD%89%E6%B5%81%E7%A8%8B%E6%97%B6%EF%BC%8C%E6%B3%A8%E6%84%8F%E8%AF%BB%E8%80%85%E6%B7%BB%E5%8A%A0%EF%BC%9A%60%E7%8E%8B%E9%A1%BA%E3%80%81%E9%97%AB%E4%BC%9F%E3%80%81%E5%AF%B9%E5%BA%94%E9%A1%B9%E7%9B%AEBA%E3%80%81SE%60%0A%20%20%20%0A%203.%20PLM%E5%BE%AE%E4%BF%A1%E6%89%93%E5%8D%A1%E7%BE%A4%E5%8F%91%E9%80%81%E7%94%B3%E8%AF%B7%E5%91%8A%E7%9F%A5%0A%20%20%20%20%3E%20%E6%AF%8F%E6%AC%A1%E8%B0%83%E4%BC%91%E6%88%96%E8%AF%B7%E5%81%87%E9%83%BD%E9%9C%80%E8%A6%81%E5%9C%A8PLM%E5%BE%AE%E4%BF%A1%E6%89%93%E5%8D%A1%E7%BE%A4%E9%87%8C%E9%9D%A2%60%40%E7%8E%8B%E9%A1%BA%EF%BC%8C%E9%83%91%E7%81%BF%E5%92%8C%E5%AF%B9%E5%BA%94%E9%A1%B9%E7%9B%AEBA%E3%80%81SE%60%0A%20%20%20%0A4.%20%E5%9C%A8%E5%85%AC%E5%8F%B8OA%E4%B8%8A%E6%8F%90%E4%BA%A4%E8%B0%83%E4%BC%91%E6%88%96%E8%AF%B7%E5%81%87%E7%94%B3%E8%AF%B7%E7%94%B5%E5%AD%90%E6%B5%81%0A%0A%0A%23%23%23%23%204.%20%E5%8A%A0%E7%8F%AD%0A1.%20%20%E6%8F%90%E5%89%8D%E5%8F%91%E9%80%81%E5%8A%A0%E7%8F%AD%E9%82%AE%E4%BB%B6%EF%BC%8C%E5%86%99%E6%98%8E%E5%8A%A0%E7%8F%AD%E5%A4%84%E7%90%86%E4%BA%8B%E9%A1%B9%E5%8F%8A%E5%BC%80%E5%8F%91%E4%BB%BB%E5%8A%A1%E3%80%82%0A%20%20%20%20%E9%82%AE%E4%BB%B6%E5%8F%91%E9%80%81%E6%A0%BC%E5%BC%8F%0A%20%20%20%20%20%20%20%60%60%60%0A%20%20%20%20%20%20%20%E5%8F%91%E9%80%81%EF%BC%9A%E5%AF%B9%E5%BA%94%E9%A1%B9%E7%9B%AEBA%E3%80%81SE%E9%82%AE%E7%AE%B1%0A%20%20%20%20%20%20%20%E6%8A%84%E9%80%81%EF%BC%9Awangshun%40oppo.com%3Bzhengcan1%40oppo.com%3Blilun%40e-lead.cn%3B%20%0A%20%20%20%20%20%20%20%60%60%60%0A2.%20%20%E5%9C%A8%E5%85%AC%E5%8F%B8OA%E4%B8%8A%E6%8F%90%E4%BA%A4%E5%8A%A0%E7%8F%AD%E7%94%B5%E5%AD%90%E6%B5%81%0A%0A%0A%0A%23%23%23%23%205.%20%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%0A%0A%3E%201.%20%E4%B8%A5%E7%A6%81%E5%B0%86%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF%EF%BC%8C%E6%95%B0%E6%8D%AE%2C%20%20%E9%80%9A%E7%9F%A5%E7%AD%89...%E5%9C%A8%E6%9C%AA%E5%BE%97%E5%88%B0%E7%94%A8%E6%88%B7%E6%98%8E%E7%A1%AE%E6%8E%88%E6%9D%83%E6%97%B6%E9%80%9A%E8%BF%87%E4%BB%BB%E4%BD%95%E6%B8%A0%E9%81%93%E3%80%90%E5%BE%AE%E4%BF%A1%EF%BC%8CQQ%EF%BC%8C%E9%82%AE%E4%BB%B6%EF%BC%8C%E5%BE%AE%E5%8D%9A...%E3%80%91%E8%BD%AC%E5%8F%91%E6%88%96%E5%A4%96%E5%8F%91.%0A%3E%202.%20%E4%B8%A5%E7%A6%81%E5%B0%86%E7%A7%BB%E5%8A%A8%E8%AE%BE%E5%A4%87%E3%80%90U%E7%9B%98%EF%BC%8C%E6%89%8B%E6%9C%BA%EF%BC%8C%E7%A7%BB%E5%8A%A8%E7%A1%AC%E7%9B%98%E7%AD%89...%E3%80%91%E6%8E%A5%E5%85%A5%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E7%9A%84%E5%8A%9E%E5%85%AC%E8%AE%BE%E5%A4%87.%20%20%0A%3E%203.%20%E4%B8%A5%E7%A6%81%E9%80%9A%E8%BF%87%E7%AC%AC%E4%B8%89%E6%96%B9%E4%BB%93%E5%BA%93%E3%80%90GitHub%EF%BC%8CDockHub%2C%20GitLab...%E3%80%91%E7%AD%89%E4%B8%8A%E4%BC%A0%E7%94%A8%E6%88%B7%E4%BB%A3%E7%A0%81.%0A%20%20%20%0A%20%20%20%0A%E3%80%90%E6%9C%AA%E5%AE%8C%E5%BE%85%E7%BB%AD%E3%80%91%0A%0A%0A%0A%0A

查看性能命令

创建时间:2021/12/29 11:35
更新时间:2022/1/3 15:10
作者:Chris

1 系统信息

2 平均负载率

2.1 load average

0.05 表示从当前时间到过去的15分钟,大概有0.05个进程或线程在等待cpu资源,换句话说就是cpu的95%时间是闲置的,没有cpu压力
如果这个值是5表示5倍于cpu处理能力的进程或线程在等待cpu资源,但并不代表cpu在满负荷运行。

2.2 查看系统cpu核心数
  1. top命令后接着按数字1

  1. 使用如下命令
    grep 'model name' /proc/cpuinfo | wc -l

3 进程信息

Tasks: 189 total, 1 running, 188 sleeping, 0 stopped, 0 zombie

现在总共有 189个进程

1个在运行中
188个在休眠中
0个停止状态
0个僵尸进程
僵尸进程是指子进程退出后父进程还在运行,父进程没有获取子进程的退出状态,子进程为僵尸状态, 一般是因为程序问题,重启可以解决

4 cpu利用

%Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st

5 内存信息

KiB Mem :  2027904 total,  1292740 free,   409816 used,  
KiB Swap:  2097148 total,  2097148 free,        0 used.  1457132 avail Mem 

2027904 total 系统现在共有2027904KiB的内存
1292740 free 系统现在空闲的内存1292740KiB有内存
409816 used 被程序占用的内存有409816KiB
325348 buff/cache 磁盘交换或者缓存占用的空间有325348KiB

2097148 total 系统现在共有2097148KiB的交换分区空间
2097148 free 系统现在空闲的交换分区1292740KiB
1457132 avail Mem 表示可用于进程下一次分配的物理内存1457132KiB

6 参数信息

人为对进程的优先级是不能控制的,只能通过执行优先级加权

%0A%5Btoc%5D%0A%0A!%5B40ed02fcf32f0c355073d1d43aea8de1.png%5D(en-resource%3A%2F%2Fdatabase%2F1198%3A1)%0A%0A%23%23%23%23%201%20%E7%B3%BB%E7%BB%9F%E4%BF%A1%E6%81%AF%0A%0A-%20%6011%3A23%3A45%60%20%E5%BD%93%E5%89%8D%E7%B3%BB%E7%BB%9F%E6%97%B6%E9%97%B4%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%60data%60%20%E5%91%BD%E4%BB%A4%E8%8E%B7%E5%8F%96%0A-%20%60up%2015%20min%60%20%E8%8E%B7%E5%8F%96%E7%B3%BB%E7%BB%9F%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E9%87%8D%E5%90%AF%E5%88%B0%E7%8E%B0%E5%9C%A8%E8%BF%9E%E7%BB%AD%E8%BF%90%E8%A1%8C%E7%9A%84%E6%97%B6%E9%97%B4%0A-%20%60%201%20user%60%20%20%E5%BD%93%E5%89%8D%E7%B3%BB%E7%BB%9F%E7%99%BB%E5%BD%95%E7%94%A8%E6%88%B7%E6%95%B0%2C%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%60who%60%20%E5%91%BD%E4%BB%A4%E6%88%96%20%60w%60%20%E8%8E%B7%E5%8F%96%0A!%5B60ccd440d30a8c786c051ad35bf72eb3.png%5D(en-resource%3A%2F%2Fdatabase%2F1204%3A0)%0A%0A%23%23%23%23%202%20%E5%B9%B3%E5%9D%87%E8%B4%9F%E8%BD%BD%E7%8E%87%0A%23%23%23%23%23%202.1%20load%20average%0A-%20%60load%20average%60%20%20%E7%B3%BB%E7%BB%9F%E5%89%8D%201%2C%205%2C%2015%E5%88%86%E9%92%9F%E7%9A%84%E5%B9%B3%E5%9D%87%E8%B4%9F%E8%BD%BD%E7%8E%87%0A%E5%8A%A1%E5%BF%85%E5%B0%86%E6%AD%A4%E5%80%BC%E4%BF%9D%E6%8C%81%E5%9C%A81%E4%BB%A5%E4%B8%8B%EF%BC%8C%E4%B8%80%E8%88%AC0.7%E8%BE%83%E4%B8%BA%E6%AD%A3%E5%B8%B8%EF%BC%8C%E6%AD%A4%E5%80%BC%E6%98%AF%E9%92%88%E5%AF%B9%E5%8D%95%E6%A0%B8%E5%A4%84%E7%90%86%E5%AE%9A%E5%88%B6%E7%9A%84%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%98%AF%E5%A4%9A%E6%A0%B8%E5%A4%84%E7%90%86%E5%99%A8%E9%9C%80%E8%A6%81%E9%99%A4%E4%BB%A5%E5%AE%83%E7%9A%84%E6%A0%B8%E5%BF%83%E6%95%B0%0A%0A!%5B122fe936a7f7d9a8013b71b874da32c4.png%5D(en-resource%3A%2F%2Fdatabase%2F1210%3A0)%0A%0A0.05%20%E8%A1%A8%E7%A4%BA%E4%BB%8E%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4%E5%88%B0%E8%BF%87%E5%8E%BB%E7%9A%8415%E5%88%86%E9%92%9F%EF%BC%8C%E5%A4%A7%E6%A6%82%E6%9C%890.05%E4%B8%AA%E8%BF%9B%E7%A8%8B%E6%88%96%E7%BA%BF%E7%A8%8B%E5%9C%A8%E7%AD%89%E5%BE%85cpu%E8%B5%84%E6%BA%90%EF%BC%8C%E6%8D%A2%E5%8F%A5%E8%AF%9D%E8%AF%B4%E5%B0%B1%E6%98%AFcpu%E7%9A%8495%25%E6%97%B6%E9%97%B4%E6%98%AF%E9%97%B2%E7%BD%AE%E7%9A%84%EF%BC%8C%E6%B2%A1%E6%9C%89cpu%E5%8E%8B%E5%8A%9B%0A%E5%A6%82%E6%9E%9C%E8%BF%99%E4%B8%AA%E5%80%BC%E6%98%AF5%E8%A1%A8%E7%A4%BA5%E5%80%8D%E4%BA%8Ecpu%E5%A4%84%E7%90%86%E8%83%BD%E5%8A%9B%E7%9A%84%E8%BF%9B%E7%A8%8B%E6%88%96%E7%BA%BF%E7%A8%8B%E5%9C%A8%E7%AD%89%E5%BE%85cpu%E8%B5%84%E6%BA%90%EF%BC%8C%E4%BD%86%E5%B9%B6%E4%B8%8D%E4%BB%A3%E8%A1%A8cpu%E5%9C%A8%E6%BB%A1%E8%B4%9F%E8%8D%B7%E8%BF%90%E8%A1%8C%E3%80%82%0A%23%23%23%23%23%202.2%20%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9Fcpu%E6%A0%B8%E5%BF%83%E6%95%B0%0A1.%20top%E5%91%BD%E4%BB%A4%E5%90%8E%E6%8E%A5%E7%9D%80%E6%8C%89%E6%95%B0%E5%AD%971%0A%0A!%5B55c969c1af549028b9e83d1a7289421f.png%5D(en-resource%3A%2F%2Fdatabase%2F1206%3A0)%0A%0A2.%20%E4%BD%BF%E7%94%A8%E5%A6%82%E4%B8%8B%E5%91%BD%E4%BB%A4%0A%60grep%20'model%20name'%20%2Fproc%2Fcpuinfo%20%7C%20wc%20-l%60%0A%0A!%5Bfbcd5631953b5854574138a90ab7de41.png%5D(en-resource%3A%2F%2Fdatabase%2F1208%3A0)%0A%0A%23%23%23%23%203%20%E8%BF%9B%E7%A8%8B%E4%BF%A1%E6%81%AF%0A%0A%60Tasks%3A%20189%20total%2C%20%20%201%20running%2C%20188%20sleeping%2C%20%20%200%20stopped%2C%20%20%200%20zombie%60%0A%0A%E7%8E%B0%E5%9C%A8%E6%80%BB%E5%85%B1%E6%9C%89%20189%E4%B8%AA%E8%BF%9B%E7%A8%8B%0A%3E%201%E4%B8%AA%E5%9C%A8%E8%BF%90%E8%A1%8C%E4%B8%AD%0A%3E%20188%E4%B8%AA%E5%9C%A8%E4%BC%91%E7%9C%A0%E4%B8%AD%0A%3E%200%E4%B8%AA%E5%81%9C%E6%AD%A2%E7%8A%B6%E6%80%81%0A%3E%200%E4%B8%AA%E5%83%B5%E5%B0%B8%E8%BF%9B%E7%A8%8B%0A%3E%20%E5%83%B5%E5%B0%B8%E8%BF%9B%E7%A8%8B%E6%98%AF%E6%8C%87%E5%AD%90%E8%BF%9B%E7%A8%8B%E9%80%80%E5%87%BA%E5%90%8E%E7%88%B6%E8%BF%9B%E7%A8%8B%E8%BF%98%E5%9C%A8%E8%BF%90%E8%A1%8C%EF%BC%8C%E7%88%B6%E8%BF%9B%E7%A8%8B%E6%B2%A1%E6%9C%89%E8%8E%B7%E5%8F%96%E5%AD%90%E8%BF%9B%E7%A8%8B%E7%9A%84%E9%80%80%E5%87%BA%E7%8A%B6%E6%80%81%EF%BC%8C%E5%AD%90%E8%BF%9B%E7%A8%8B%E4%B8%BA%E5%83%B5%E5%B0%B8%E7%8A%B6%E6%80%81%2C%20%E4%B8%80%E8%88%AC%E6%98%AF%E5%9B%A0%E4%B8%BA%E7%A8%8B%E5%BA%8F%E9%97%AE%E9%A2%98%EF%BC%8C%E9%87%8D%E5%90%AF%E5%8F%AF%E4%BB%A5%E8%A7%A3%E5%86%B3%0A%0A%23%23%23%23%204%20cpu%E5%88%A9%E7%94%A8%0A%60%25Cpu(s)%3A%20%200.1%20us%2C%20%200.1%20sy%2C%20%200.0%20ni%2C%2099.8%20id%2C%20%200.0%20wa%2C%20%200.0%20hi%2C%20%200.1%20si%2C%20%200.0%20st%60%0A%0A!%5B2ec716f21d4720912f662e7aecf665c5.png%5D(en-resource%3A%2F%2Fdatabase%2F1212%3A0)%0A%0A!%5Bc1899fdd8b1d6b51fd1676364f2e2ec0.png%5D(en-resource%3A%2F%2Fdatabase%2F1216%3A0)%0A%0A%0A%23%23%23%23%205%20%E5%86%85%E5%AD%98%E4%BF%A1%E6%81%AF%0A%60%60%60%0AKiB%20Mem%20%3A%20%202027904%20total%2C%20%201292740%20free%2C%20%20%20409816%20used%2C%20%20%0AKiB%20Swap%3A%20%202097148%20total%2C%20%202097148%20free%2C%20%20%20%20%20%20%20%200%20used.%20%201457132%20avail%20Mem%20%0A%60%60%60%0A-%20KiB%20Mem%20%E5%86%85%E5%AD%98%E4%BF%A1%E6%81%AF%0A%3E%202027904%20total%20%E7%B3%BB%E7%BB%9F%E7%8E%B0%E5%9C%A8%E5%85%B1%E6%9C%892027904KiB%E7%9A%84%E5%86%85%E5%AD%98%0A%3E%201292740%20free%20%E7%B3%BB%E7%BB%9F%E7%8E%B0%E5%9C%A8%E7%A9%BA%E9%97%B2%E7%9A%84%E5%86%85%E5%AD%981292740KiB%E6%9C%89%E5%86%85%E5%AD%98%0A%3E%20409816%20used%20%E8%A2%AB%E7%A8%8B%E5%BA%8F%E5%8D%A0%E7%94%A8%E7%9A%84%E5%86%85%E5%AD%98%E6%9C%89409816KiB%0A%3E%20325348%20buff%2Fcache%20%E7%A3%81%E7%9B%98%E4%BA%A4%E6%8D%A2%E6%88%96%E8%80%85%E7%BC%93%E5%AD%98%E5%8D%A0%E7%94%A8%E7%9A%84%E7%A9%BA%E9%97%B4%E6%9C%89325348KiB%0A%0A-%20KiB%20Swap%20%E4%BA%A4%E6%8D%A2%E5%88%86%E5%8C%BA%E5%86%85%E5%AD%98%E4%BF%A1%E6%81%AF%0A%3E%202097148%20total%20%E7%B3%BB%E7%BB%9F%E7%8E%B0%E5%9C%A8%E5%85%B1%E6%9C%892097148KiB%E7%9A%84%E4%BA%A4%E6%8D%A2%E5%88%86%E5%8C%BA%E7%A9%BA%E9%97%B4%0A%3E%202097148%20free%20%E7%B3%BB%E7%BB%9F%E7%8E%B0%E5%9C%A8%E7%A9%BA%E9%97%B2%E7%9A%84%E4%BA%A4%E6%8D%A2%E5%88%86%E5%8C%BA1292740KiB%0A%3E%201457132%20avail%20Mem%20%E8%A1%A8%E7%A4%BA%E5%8F%AF%E7%94%A8%E4%BA%8E%E8%BF%9B%E7%A8%8B%E4%B8%8B%E4%B8%80%E6%AC%A1%E5%88%86%E9%85%8D%E7%9A%84%E7%89%A9%E7%90%86%E5%86%85%E5%AD%981457132KiB%0A%0A%0A%23%23%23%23%206%20%E5%8F%82%E6%95%B0%E4%BF%A1%E6%81%AF%0A!%5Bdab993a4533819e37b578783e9fc89af.png%5D(en-resource%3A%2F%2Fdatabase%2F1220%3A0)%0A%0A!%5Bb66079984b26fb20d9e9d3a8a90fa03c.png%5D(en-resource%3A%2F%2Fdatabase%2F1218%3A0)%0A%0A%E4%BA%BA%E4%B8%BA%E5%AF%B9%E8%BF%9B%E7%A8%8B%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%E6%98%AF%E4%B8%8D%E8%83%BD%E6%8E%A7%E5%88%B6%E7%9A%84%EF%BC%8C%E5%8F%AA%E8%83%BD%E9%80%9A%E8%BF%87%E6%89%A7%E8%A1%8C%E4%BC%98%E5%85%88%E7%BA%A7%E5%8A%A0%E6%9D%83

阻塞队列

创建时间:2021/12/31 15:37
更新时间:2023/4/2 13:59
作者:Chris
来源:https://www.cnblogs.com/bjxq-cs88/p/9759571.html

1 阻塞队列

1.1 阻塞队列是什么

https://blog.csdn.net/Firstlucky77/article/details/124730067

阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。
这两个附加的操作是:

    1. 在队列为空时,消费线程会等待队列变为非空。
    1. 当队列满时,生产线程会等待队列可用。

1.2 阻塞队列能干什么

阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。
阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。

1.3 BlockingQueue 核心方法

public interface BlockingQueue<E> extends Queue<E> {
    
    //将给定元素设置到队列中,如果设置成功返回true, 否则抛出异常。如果是往限定了长度的队列中设置值,推荐使用offer()方法。
    boolean add(E e);
 
    //将给定的元素设置到队列中,如果设置成功返回true, 否则返回false. e的值不能为空,否则抛出空指针异常。
    boolean offer(E e);
 
    //将元素设置到队列中,如果队列中没有多余的空间,该方法会一直阻塞,直到队列中有多余的空间。
    void put(E e) throws InterruptedException;
 
    //将给定元素在给定的时间内设置到队列中,如果设置成功返回true, 否则返回false.
    boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
 
    //从队列中获取值,如果队列中没有值,线程会一直阻塞,直到队列中有值,并且该方法取得了该值。
    E take() throws InterruptedException;
 
    //在给定的时间里,从队列中获取值,如果没有取到会抛出异常。
    E poll(long timeout, TimeUnit unit) throws InterruptedException;
 
    //获取队列中剩余的空间。
    int remainingCapacity();
 
    //从队列中移除指定的值。
    boolean remove(Object o);
 
    //判断队列中是否拥有该值。
    public boolean contains(Object o);
 
    //将队列中值,全部移除,并发设置到给定的集合中。
    int drainTo(Collection<? super E> c);
 
    //指定最多数量限制将队列中值,全部移除,并发设置到给定的集合中。
    int drainTo(Collection<? super E> c, int maxElements);
}

1.4 阻塞队列成员

  1. ArrayBlockingQueue :是一个用数组实现的有界阻塞队列,此队列按照先进先出(FIFO)的原则对元素进行排序。支持公平锁和非公平锁。【注:每一个线程在获取锁的时候可能都会排队等待,如果在等待时间上,先获取锁的线程的请求一定先被满足,那么这个锁就是公平的。反之,这个锁就是不公平的。公平的获取锁,也就是当前等待时间最长的线程先获取锁】

  2. LinkedBlockingQueue :一个由链表结构组成的有界队列,此队列的长度为Integer.MAX_VALUE。此队列按照先进先出的顺序进行排序。

  3. DelayQueue: 一个实现PriorityBlockingQueue实现延迟获取的无界队列,在创建元素时,可以指定多久才能从队列中获取当前元素。只有延时期满后才能从队列中获取元素。

    DelayQueue可以运用在以下应用场景:

    1. 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从 DelayQueue中获取元素时,表示缓存有效期到了。
    2. 定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。)

1.5 阻塞队列原理以及使用

DelayQueue的泛型参数需要实现Delayed接口,Delayed接口继承了Comparable接口,DelayQueue内部使用非线程安全的优先队列(PriorityQueue),并使用Leader/Followers模式,最小化不必要的等待时间。DelayQueue不允许包含null元素。

Leader/Followers模式:

  1. 有若干个线程(一般组成线程池)用来处理大量的事件
  2. 有一个线程作为领导者,等待事件的发生;其他的线程作为追随者,仅仅是睡眠。
  3. 假如有事件需要处理,领导者会从追随者中指定一个新的领导者,自己去处理事件。
  4. 唤醒的追随者作为新的领导者等待事件的发生。
  5. 处理事件的线程处理完毕以后,就会成为追随者的一员,直到被唤醒成为领导者。
  6. 假如需要处理的事件太多,而线程数量不够(能够动态创建线程处理另当别论),则有的事件可能会得不到处理。

所有线程会有三种身份中的一种:leader和follower,以及一个干活中的状态:proccesser。它的基本原则就是,永远最多只有一个leader。而所有follower都在等待成为leader。线程池启动时会自动产生一个Leader负责等待网络IO事件,当有一个事件产生时,Leader线程首先通知一个Follower线程将其提拔为新的Leader,然后自己就去干活了,去处理这个网络事件,处理完毕后加入Follower线程等待队列,等待下次成为Leader。这种方法可以增强CPU高速缓存相似性,及消除动态内存分配和线程间的数据交换。

    // 可重入锁
    private final transient ReentrantLock lock = new ReentrantLock();
    
    // 存储队列元素的队列——优先队列
    private final PriorityQueue<E> q = new PriorityQueue<E>();
 
    //用于优化阻塞通知的线程元素leader,Leader/Followers模式
    private Thread leader = null;
 
    //用于实现阻塞和通知的Condition对象
    private final Condition available = lock.newCondition();
    
    public DelayQueue() {}
    
    public DelayQueue(Collection<? extends E> c) {
        this.addAll(c);
    }
%5Btoc%5D%0A%0A%23%23%201%20%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%0A%23%23%23%23%201.1%20%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E6%98%AF%E4%BB%80%E4%B9%88%0Ahttps%3A%2F%2Fblog.csdn.net%2FFirstlucky77%2Farticle%2Fdetails%2F124730067%0A%0A%3E%20%20%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%EF%BC%88BlockingQueue%EF%BC%89%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%AF%E6%8C%81%E4%B8%A4%E4%B8%AA%E9%99%84%E5%8A%A0%E6%93%8D%E4%BD%9C%E7%9A%84%E9%98%9F%E5%88%97%E3%80%82%0A%3E%20%20%E8%BF%99%E4%B8%A4%E4%B8%AA%E9%99%84%E5%8A%A0%E7%9A%84%E6%93%8D%E4%BD%9C%E6%98%AF%EF%BC%9A%0A%3E%20%20-%201.%20%E5%9C%A8%E9%98%9F%E5%88%97%E4%B8%BA%E7%A9%BA%E6%97%B6%EF%BC%8C%E6%B6%88%E8%B4%B9%E7%BA%BF%E7%A8%8B%E4%BC%9A%E7%AD%89%E5%BE%85%E9%98%9F%E5%88%97%E5%8F%98%E4%B8%BA%E9%9D%9E%E7%A9%BA%E3%80%82%0A%3E%20%20-%202.%20%E5%BD%93%E9%98%9F%E5%88%97%E6%BB%A1%E6%97%B6%EF%BC%8C%E7%94%9F%E4%BA%A7%E7%BA%BF%E7%A8%8B%E4%BC%9A%E7%AD%89%E5%BE%85%E9%98%9F%E5%88%97%E5%8F%AF%E7%94%A8%E3%80%82%0A%0A%23%23%23%23%201.2%20%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%3E%20%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E5%B8%B8%E7%94%A8%E4%BA%8E%E7%94%9F%E4%BA%A7%E8%80%85%E5%92%8C%E6%B6%88%E8%B4%B9%E8%80%85%E7%9A%84%E5%9C%BA%E6%99%AF%EF%BC%8C%E7%94%9F%E4%BA%A7%E8%80%85%E6%98%AF%E5%BE%80%E9%98%9F%E5%88%97%E9%87%8C%E6%B7%BB%E5%8A%A0%E5%85%83%E7%B4%A0%E7%9A%84%E7%BA%BF%E7%A8%8B%EF%BC%8C%E6%B6%88%E8%B4%B9%E8%80%85%E6%98%AF%E4%BB%8E%E9%98%9F%E5%88%97%E9%87%8C%E6%8B%BF%E5%85%83%E7%B4%A0%E7%9A%84%E7%BA%BF%E7%A8%8B%E3%80%82%0A%3E%20%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E5%B0%B1%E6%98%AF%E7%94%9F%E4%BA%A7%E8%80%85%E5%AD%98%E6%94%BE%E5%85%83%E7%B4%A0%E7%9A%84%E5%AE%B9%E5%99%A8%EF%BC%8C%E8%80%8C%E6%B6%88%E8%B4%B9%E8%80%85%E4%B9%9F%E5%8F%AA%E4%BB%8E%E5%AE%B9%E5%99%A8%E9%87%8C%E6%8B%BF%E5%85%83%E7%B4%A0%E3%80%82%0A%0A!%5Bed5b675814e9eb5e0a7c730e1f850745.png%5D(en-resource%3A%2F%2Fdatabase%2F1189%3A1)%0A%0A%0A-%20%60%E5%BC%82%E5%B8%B8%60%20%EF%BC%9A%E6%98%AF%E6%8C%87%E5%BD%93%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E6%BB%A1%E6%97%B6%E5%80%99%EF%BC%8C%E5%86%8D%E5%BE%80%E9%98%9F%E5%88%97%E9%87%8C%E6%8F%92%E5%85%A5%E5%85%83%E7%B4%A0%EF%BC%8C%E4%BC%9A%E6%8A%9B%E5%87%BAIllegalStateException(%22Queue%20full%22)%E5%BC%82%E5%B8%B8%E3%80%82%E5%BD%93%E9%98%9F%E5%88%97%E4%B8%BA%E7%A9%BA%E6%97%B6%EF%BC%8C%E4%BB%8E%E9%98%9F%E5%88%97%E9%87%8C%E8%8E%B7%E5%8F%96%E5%85%83%E7%B4%A0%E6%97%B6%E4%BC%9A%E6%8A%9B%E5%87%BANoSuchElementException%E5%BC%82%E5%B8%B8%20%E3%80%82%0A-%20%60%E8%BF%94%E5%9B%9E%E7%89%B9%E6%AE%8A%E5%80%BC%60%20%EF%BC%9A%E6%8F%92%E5%85%A5%E6%96%B9%E6%B3%95%E4%BC%9A%E8%BF%94%E5%9B%9E%E6%98%AF%E5%90%A6%E6%88%90%E5%8A%9F%EF%BC%8C%E6%88%90%E5%8A%9F%E5%88%99%E8%BF%94%E5%9B%9Etrue%E3%80%82%E7%A7%BB%E9%99%A4%E6%96%B9%E6%B3%95%EF%BC%8C%E5%88%99%E6%98%AF%E4%BB%8E%E9%98%9F%E5%88%97%E9%87%8C%E6%8B%BF%E5%87%BA%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%88%99%E8%BF%94%E5%9B%9Enull%0A-%20%60%E4%B8%80%E7%9B%B4%E9%98%BB%E5%A1%9E%60%20%EF%BC%9A%E5%BD%93%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E6%BB%A1%E6%97%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%94%9F%E4%BA%A7%E8%80%85%E7%BA%BF%E7%A8%8B%E5%BE%80%E9%98%9F%E5%88%97%E9%87%8C%20%60put%60%20%E5%85%83%E7%B4%A0%EF%BC%8C%E9%98%9F%E5%88%97%E4%BC%9A%E4%B8%80%E7%9B%B4%E9%98%BB%E5%A1%9E%E7%94%9F%E4%BA%A7%E8%80%85%E7%BA%BF%E7%A8%8B%EF%BC%8C%E7%9B%B4%E5%88%B0%E6%8B%BF%E5%88%B0%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%88%96%E8%80%85%E5%93%8D%E5%BA%94%E4%B8%AD%E6%96%AD%E9%80%80%E5%87%BA%E3%80%82%E5%BD%93%E9%98%9F%E5%88%97%E7%A9%BA%E6%97%B6%EF%BC%8C%E6%B6%88%E8%B4%B9%E8%80%85%E7%BA%BF%E7%A8%8B%E8%AF%95%E5%9B%BE%E4%BB%8E%E9%98%9F%E5%88%97%E9%87%8C%20%60take%60%20%E5%85%83%E7%B4%A0%EF%BC%8C%E9%98%9F%E5%88%97%E4%B9%9F%E4%BC%9A%E9%98%BB%E5%A1%9E%E6%B6%88%E8%B4%B9%E8%80%85%E7%BA%BF%E7%A8%8B%EF%BC%8C%E7%9B%B4%E5%88%B0%E9%98%9F%E5%88%97%E5%8F%AF%E7%94%A8%E3%80%82%0A-%20%60%E8%B6%85%E6%97%B6%E9%80%80%E5%87%BA%60%20%EF%BC%9A%E5%BD%93%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E6%BB%A1%E6%97%B6%EF%BC%8C%E9%98%9F%E5%88%97%E4%BC%9A%E9%98%BB%E5%A1%9E%E7%94%9F%E4%BA%A7%E8%80%85%E7%BA%BF%E7%A8%8B%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%B6%85%E8%BF%87%E4%B8%80%E5%AE%9A%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%8C%E7%94%9F%E4%BA%A7%E8%80%85%E7%BA%BF%E7%A8%8B%E5%B0%B1%E4%BC%9A%E9%80%80%E5%87%BA%E3%80%82%0A%0A%23%23%23%23%201.3%20BlockingQueue%20%E6%A0%B8%E5%BF%83%E6%96%B9%E6%B3%95%0A%0A%60%60%60java%0Apublic%20interface%20BlockingQueue%3CE%3E%20extends%20Queue%3CE%3E%20%7B%0A%20%20%20%20%0A%20%20%20%20%2F%2F%E5%B0%86%E7%BB%99%E5%AE%9A%E5%85%83%E7%B4%A0%E8%AE%BE%E7%BD%AE%E5%88%B0%E9%98%9F%E5%88%97%E4%B8%AD%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AE%BE%E7%BD%AE%E6%88%90%E5%8A%9F%E8%BF%94%E5%9B%9Etrue%2C%20%E5%90%A6%E5%88%99%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E3%80%82%E5%A6%82%E6%9E%9C%E6%98%AF%E5%BE%80%E9%99%90%E5%AE%9A%E4%BA%86%E9%95%BF%E5%BA%A6%E7%9A%84%E9%98%9F%E5%88%97%E4%B8%AD%E8%AE%BE%E7%BD%AE%E5%80%BC%EF%BC%8C%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8offer()%E6%96%B9%E6%B3%95%E3%80%82%0A%20%20%20%20boolean%20add(E%20e)%3B%0A%20%0A%20%20%20%20%2F%2F%E5%B0%86%E7%BB%99%E5%AE%9A%E7%9A%84%E5%85%83%E7%B4%A0%E8%AE%BE%E7%BD%AE%E5%88%B0%E9%98%9F%E5%88%97%E4%B8%AD%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AE%BE%E7%BD%AE%E6%88%90%E5%8A%9F%E8%BF%94%E5%9B%9Etrue%2C%20%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9Efalse.%20e%E7%9A%84%E5%80%BC%E4%B8%8D%E8%83%BD%E4%B8%BA%E7%A9%BA%EF%BC%8C%E5%90%A6%E5%88%99%E6%8A%9B%E5%87%BA%E7%A9%BA%E6%8C%87%E9%92%88%E5%BC%82%E5%B8%B8%E3%80%82%0A%20%20%20%20boolean%20offer(E%20e)%3B%0A%20%0A%20%20%20%20%2F%2F%E5%B0%86%E5%85%83%E7%B4%A0%E8%AE%BE%E7%BD%AE%E5%88%B0%E9%98%9F%E5%88%97%E4%B8%AD%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%98%9F%E5%88%97%E4%B8%AD%E6%B2%A1%E6%9C%89%E5%A4%9A%E4%BD%99%E7%9A%84%E7%A9%BA%E9%97%B4%EF%BC%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E4%BC%9A%E4%B8%80%E7%9B%B4%E9%98%BB%E5%A1%9E%EF%BC%8C%E7%9B%B4%E5%88%B0%E9%98%9F%E5%88%97%E4%B8%AD%E6%9C%89%E5%A4%9A%E4%BD%99%E7%9A%84%E7%A9%BA%E9%97%B4%E3%80%82%0A%20%20%20%20void%20put(E%20e)%20throws%20InterruptedException%3B%0A%20%0A%20%20%20%20%2F%2F%E5%B0%86%E7%BB%99%E5%AE%9A%E5%85%83%E7%B4%A0%E5%9C%A8%E7%BB%99%E5%AE%9A%E7%9A%84%E6%97%B6%E9%97%B4%E5%86%85%E8%AE%BE%E7%BD%AE%E5%88%B0%E9%98%9F%E5%88%97%E4%B8%AD%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AE%BE%E7%BD%AE%E6%88%90%E5%8A%9F%E8%BF%94%E5%9B%9Etrue%2C%20%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9Efalse.%0A%20%20%20%20boolean%20offer(E%20e%2C%20long%20timeout%2C%20TimeUnit%20unit)%20throws%20InterruptedException%3B%0A%20%0A%20%20%20%20%2F%2F%E4%BB%8E%E9%98%9F%E5%88%97%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%80%BC%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%98%9F%E5%88%97%E4%B8%AD%E6%B2%A1%E6%9C%89%E5%80%BC%EF%BC%8C%E7%BA%BF%E7%A8%8B%E4%BC%9A%E4%B8%80%E7%9B%B4%E9%98%BB%E5%A1%9E%EF%BC%8C%E7%9B%B4%E5%88%B0%E9%98%9F%E5%88%97%E4%B8%AD%E6%9C%89%E5%80%BC%EF%BC%8C%E5%B9%B6%E4%B8%94%E8%AF%A5%E6%96%B9%E6%B3%95%E5%8F%96%E5%BE%97%E4%BA%86%E8%AF%A5%E5%80%BC%E3%80%82%0A%20%20%20%20E%20take()%20throws%20InterruptedException%3B%0A%20%0A%20%20%20%20%2F%2F%E5%9C%A8%E7%BB%99%E5%AE%9A%E7%9A%84%E6%97%B6%E9%97%B4%E9%87%8C%EF%BC%8C%E4%BB%8E%E9%98%9F%E5%88%97%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%80%BC%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%8F%96%E5%88%B0%E4%BC%9A%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E3%80%82%0A%20%20%20%20E%20poll(long%20timeout%2C%20TimeUnit%20unit)%20throws%20InterruptedException%3B%0A%20%0A%20%20%20%20%2F%2F%E8%8E%B7%E5%8F%96%E9%98%9F%E5%88%97%E4%B8%AD%E5%89%A9%E4%BD%99%E7%9A%84%E7%A9%BA%E9%97%B4%E3%80%82%0A%20%20%20%20int%20remainingCapacity()%3B%0A%20%0A%20%20%20%20%2F%2F%E4%BB%8E%E9%98%9F%E5%88%97%E4%B8%AD%E7%A7%BB%E9%99%A4%E6%8C%87%E5%AE%9A%E7%9A%84%E5%80%BC%E3%80%82%0A%20%20%20%20boolean%20remove(Object%20o)%3B%0A%20%0A%20%20%20%20%2F%2F%E5%88%A4%E6%96%AD%E9%98%9F%E5%88%97%E4%B8%AD%E6%98%AF%E5%90%A6%E6%8B%A5%E6%9C%89%E8%AF%A5%E5%80%BC%E3%80%82%0A%20%20%20%20public%20boolean%20contains(Object%20o)%3B%0A%20%0A%20%20%20%20%2F%2F%E5%B0%86%E9%98%9F%E5%88%97%E4%B8%AD%E5%80%BC%EF%BC%8C%E5%85%A8%E9%83%A8%E7%A7%BB%E9%99%A4%EF%BC%8C%E5%B9%B6%E5%8F%91%E8%AE%BE%E7%BD%AE%E5%88%B0%E7%BB%99%E5%AE%9A%E7%9A%84%E9%9B%86%E5%90%88%E4%B8%AD%E3%80%82%0A%20%20%20%20int%20drainTo(Collection%3C%3F%20super%20E%3E%20c)%3B%0A%20%0A%20%20%20%20%2F%2F%E6%8C%87%E5%AE%9A%E6%9C%80%E5%A4%9A%E6%95%B0%E9%87%8F%E9%99%90%E5%88%B6%E5%B0%86%E9%98%9F%E5%88%97%E4%B8%AD%E5%80%BC%EF%BC%8C%E5%85%A8%E9%83%A8%E7%A7%BB%E9%99%A4%EF%BC%8C%E5%B9%B6%E5%8F%91%E8%AE%BE%E7%BD%AE%E5%88%B0%E7%BB%99%E5%AE%9A%E7%9A%84%E9%9B%86%E5%90%88%E4%B8%AD%E3%80%82%0A%20%20%20%20int%20drainTo(Collection%3C%3F%20super%20E%3E%20c%2C%20int%20maxElements)%3B%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%23%201.4%20%20%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E6%88%90%E5%91%98%0A!%5B42a5702962022d4daa1bb544231a4521.png%5D(en-resource%3A%2F%2Fdatabase%2F1415%3A0)%0A%0A%0A1.%20%60ArrayBlockingQueue%60%20%EF%BC%9A%E6%98%AF%E4%B8%80%E4%B8%AA%E7%94%A8%E6%95%B0%E7%BB%84%E5%AE%9E%E7%8E%B0%E7%9A%84%E6%9C%89%E7%95%8C%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%EF%BC%8C%E6%AD%A4%E9%98%9F%E5%88%97%E6%8C%89%E7%85%A7%E5%85%88%E8%BF%9B%E5%85%88%E5%87%BA%EF%BC%88FIFO%EF%BC%89%E7%9A%84%E5%8E%9F%E5%88%99%E5%AF%B9%E5%85%83%E7%B4%A0%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%E3%80%82%E6%94%AF%E6%8C%81%E5%85%AC%E5%B9%B3%E9%94%81%E5%92%8C%E9%9D%9E%E5%85%AC%E5%B9%B3%E9%94%81%E3%80%82%E3%80%90%E6%B3%A8%EF%BC%9A%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%9C%A8%E8%8E%B7%E5%8F%96%E9%94%81%E7%9A%84%E6%97%B6%E5%80%99%E5%8F%AF%E8%83%BD%E9%83%BD%E4%BC%9A%E6%8E%92%E9%98%9F%E7%AD%89%E5%BE%85%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%9C%A8%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%E4%B8%8A%EF%BC%8C%E5%85%88%E8%8E%B7%E5%8F%96%E9%94%81%E7%9A%84%E7%BA%BF%E7%A8%8B%E7%9A%84%E8%AF%B7%E6%B1%82%E4%B8%80%E5%AE%9A%E5%85%88%E8%A2%AB%E6%BB%A1%E8%B6%B3%EF%BC%8C%E9%82%A3%E4%B9%88%E8%BF%99%E4%B8%AA%E9%94%81%E5%B0%B1%E6%98%AF%E5%85%AC%E5%B9%B3%E7%9A%84%E3%80%82%E5%8F%8D%E4%B9%8B%EF%BC%8C%E8%BF%99%E4%B8%AA%E9%94%81%E5%B0%B1%E6%98%AF%E4%B8%8D%E5%85%AC%E5%B9%B3%E7%9A%84%E3%80%82%E5%85%AC%E5%B9%B3%E7%9A%84%E8%8E%B7%E5%8F%96%E9%94%81%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%BD%93%E5%89%8D%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%E6%9C%80%E9%95%BF%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%85%88%E8%8E%B7%E5%8F%96%E9%94%81%E3%80%91%0A%0A2.%20%60LinkedBlockingQueue%60%20%EF%BC%9A%E4%B8%80%E4%B8%AA%E7%94%B1%E9%93%BE%E8%A1%A8%E7%BB%93%E6%9E%84%E7%BB%84%E6%88%90%E7%9A%84%E6%9C%89%E7%95%8C%E9%98%9F%E5%88%97%EF%BC%8C%E6%AD%A4%E9%98%9F%E5%88%97%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%BAInteger.MAX_VALUE%E3%80%82%E6%AD%A4%E9%98%9F%E5%88%97%E6%8C%89%E7%85%A7%E5%85%88%E8%BF%9B%E5%85%88%E5%87%BA%E7%9A%84%E9%A1%BA%E5%BA%8F%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%E3%80%82%0A%0A3.%20%60DelayQueue%60%EF%BC%9A%20%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%8E%B0PriorityBlockingQueue%E5%AE%9E%E7%8E%B0%E5%BB%B6%E8%BF%9F%E8%8E%B7%E5%8F%96%E7%9A%84%E6%97%A0%E7%95%8C%E9%98%9F%E5%88%97%EF%BC%8C%E5%9C%A8%E5%88%9B%E5%BB%BA%E5%85%83%E7%B4%A0%E6%97%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E5%A4%9A%E4%B9%85%E6%89%8D%E8%83%BD%E4%BB%8E%E9%98%9F%E5%88%97%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E5%85%83%E7%B4%A0%E3%80%82%E5%8F%AA%E6%9C%89%E5%BB%B6%E6%97%B6%E6%9C%9F%E6%BB%A1%E5%90%8E%E6%89%8D%E8%83%BD%E4%BB%8E%E9%98%9F%E5%88%97%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%85%83%E7%B4%A0%E3%80%82%0A%20%20%20%3E%20DelayQueue%E5%8F%AF%E4%BB%A5%E8%BF%90%E7%94%A8%E5%9C%A8%E4%BB%A5%E4%B8%8B%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%EF%BC%9A%0A%20%20%20%3E%201.%20%E7%BC%93%E5%AD%98%E7%B3%BB%E7%BB%9F%E7%9A%84%E8%AE%BE%E8%AE%A1%EF%BC%9A%E5%8F%AF%E4%BB%A5%E7%94%A8DelayQueue%E4%BF%9D%E5%AD%98%E7%BC%93%E5%AD%98%E5%85%83%E7%B4%A0%E7%9A%84%E6%9C%89%E6%95%88%E6%9C%9F%EF%BC%8C%E4%BD%BF%E7%94%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%BE%AA%E7%8E%AF%E6%9F%A5%E8%AF%A2DelayQueue%EF%BC%8C%E4%B8%80%E6%97%A6%E8%83%BD%E4%BB%8E%20%20%20%20%20%20%20DelayQueue%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%85%83%E7%B4%A0%E6%97%B6%EF%BC%8C%E8%A1%A8%E7%A4%BA%E7%BC%93%E5%AD%98%E6%9C%89%E6%95%88%E6%9C%9F%E5%88%B0%E4%BA%86%E3%80%82%0A%20%20%20%3E%202.%20%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E3%80%82%E4%BD%BF%E7%94%A8DelayQueue%E4%BF%9D%E5%AD%98%E5%BD%93%E5%A4%A9%E5%B0%86%E4%BC%9A%E6%89%A7%E8%A1%8C%E7%9A%84%E4%BB%BB%E5%8A%A1%E5%92%8C%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%EF%BC%8C%E4%B8%80%E6%97%A6%E4%BB%8EDelayQueue%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%88%B0%E4%BB%BB%E5%8A%A1%E5%B0%B1%E5%BC%80%E5%A7%8B%E6%89%A7%E8%A1%8C%EF%BC%8C%E4%BB%8E%E6%AF%94%E5%A6%82TimerQueue%E5%B0%B1%E6%98%AF%E4%BD%BF%E7%94%A8DelayQueue%E5%AE%9E%E7%8E%B0%E7%9A%84%E3%80%82%EF%BC%89%0A%0A%0A%0A%23%23%23%23%201.5%20%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E5%8E%9F%E7%90%86%E4%BB%A5%E5%8F%8A%E4%BD%BF%E7%94%A8%0A%3E%20DelayQueue%E7%9A%84%E6%B3%9B%E5%9E%8B%E5%8F%82%E6%95%B0%E9%9C%80%E8%A6%81%E5%AE%9E%E7%8E%B0Delayed%E6%8E%A5%E5%8F%A3%EF%BC%8CDelayed%E6%8E%A5%E5%8F%A3%E7%BB%A7%E6%89%BF%E4%BA%86Comparable%E6%8E%A5%E5%8F%A3%EF%BC%8CDelayQueue%E5%86%85%E9%83%A8%E4%BD%BF%E7%94%A8%E9%9D%9E%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E4%BC%98%E5%85%88%E9%98%9F%E5%88%97%EF%BC%88PriorityQueue%EF%BC%89%EF%BC%8C%E5%B9%B6%E4%BD%BF%E7%94%A8Leader%2FFollowers%E6%A8%A1%E5%BC%8F%EF%BC%8C%E6%9C%80%E5%B0%8F%E5%8C%96%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4%E3%80%82DelayQueue%E4%B8%8D%E5%85%81%E8%AE%B8%E5%8C%85%E5%90%ABnull%E5%85%83%E7%B4%A0%E3%80%82%0A%0A%0A%3E%20Leader%2FFollowers%E6%A8%A1%E5%BC%8F%EF%BC%9A%0A%3E%201.%20%E6%9C%89%E8%8B%A5%E5%B9%B2%E4%B8%AA%E7%BA%BF%E7%A8%8B(%E4%B8%80%E8%88%AC%E7%BB%84%E6%88%90%E7%BA%BF%E7%A8%8B%E6%B1%A0)%E7%94%A8%E6%9D%A5%E5%A4%84%E7%90%86%E5%A4%A7%E9%87%8F%E7%9A%84%E4%BA%8B%E4%BB%B6%0A%3E%202.%20%E6%9C%89%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E4%BD%9C%E4%B8%BA%E9%A2%86%E5%AF%BC%E8%80%85%EF%BC%8C%E7%AD%89%E5%BE%85%E4%BA%8B%E4%BB%B6%E7%9A%84%E5%8F%91%E7%94%9F%EF%BC%9B%E5%85%B6%E4%BB%96%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%BD%9C%E4%B8%BA%E8%BF%BD%E9%9A%8F%E8%80%85%EF%BC%8C%E4%BB%85%E4%BB%85%E6%98%AF%E7%9D%A1%E7%9C%A0%E3%80%82%0A%3E%203.%20%E5%81%87%E5%A6%82%E6%9C%89%E4%BA%8B%E4%BB%B6%E9%9C%80%E8%A6%81%E5%A4%84%E7%90%86%EF%BC%8C%E9%A2%86%E5%AF%BC%E8%80%85%E4%BC%9A%E4%BB%8E%E8%BF%BD%E9%9A%8F%E8%80%85%E4%B8%AD%E6%8C%87%E5%AE%9A%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E9%A2%86%E5%AF%BC%E8%80%85%EF%BC%8C%E8%87%AA%E5%B7%B1%E5%8E%BB%E5%A4%84%E7%90%86%E4%BA%8B%E4%BB%B6%E3%80%82%0A%3E%204.%20%E5%94%A4%E9%86%92%E7%9A%84%E8%BF%BD%E9%9A%8F%E8%80%85%E4%BD%9C%E4%B8%BA%E6%96%B0%E7%9A%84%E9%A2%86%E5%AF%BC%E8%80%85%E7%AD%89%E5%BE%85%E4%BA%8B%E4%BB%B6%E7%9A%84%E5%8F%91%E7%94%9F%E3%80%82%0A%3E%206.%20%E5%A4%84%E7%90%86%E4%BA%8B%E4%BB%B6%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%A4%84%E7%90%86%E5%AE%8C%E6%AF%95%E4%BB%A5%E5%90%8E%EF%BC%8C%E5%B0%B1%E4%BC%9A%E6%88%90%E4%B8%BA%E8%BF%BD%E9%9A%8F%E8%80%85%E7%9A%84%E4%B8%80%E5%91%98%EF%BC%8C%E7%9B%B4%E5%88%B0%E8%A2%AB%E5%94%A4%E9%86%92%E6%88%90%E4%B8%BA%E9%A2%86%E5%AF%BC%E8%80%85%E3%80%82%0A%3E%207.%20%E5%81%87%E5%A6%82%E9%9C%80%E8%A6%81%E5%A4%84%E7%90%86%E7%9A%84%E4%BA%8B%E4%BB%B6%E5%A4%AA%E5%A4%9A%EF%BC%8C%E8%80%8C%E7%BA%BF%E7%A8%8B%E6%95%B0%E9%87%8F%E4%B8%8D%E5%A4%9F(%E8%83%BD%E5%A4%9F%E5%8A%A8%E6%80%81%E5%88%9B%E5%BB%BA%E7%BA%BF%E7%A8%8B%E5%A4%84%E7%90%86%E5%8F%A6%E5%BD%93%E5%88%AB%E8%AE%BA)%EF%BC%8C%E5%88%99%E6%9C%89%E7%9A%84%E4%BA%8B%E4%BB%B6%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%BE%97%E4%B8%8D%E5%88%B0%E5%A4%84%E7%90%86%E3%80%82%0A%0A%3E%20%E6%89%80%E6%9C%89%E7%BA%BF%E7%A8%8B%E4%BC%9A%E6%9C%89%E4%B8%89%E7%A7%8D%E8%BA%AB%E4%BB%BD%E4%B8%AD%E7%9A%84%E4%B8%80%E7%A7%8D%EF%BC%9Aleader%E5%92%8Cfollower%EF%BC%8C%E4%BB%A5%E5%8F%8A%E4%B8%80%E4%B8%AA%E5%B9%B2%E6%B4%BB%E4%B8%AD%E7%9A%84%E7%8A%B6%E6%80%81%EF%BC%9Aproccesser%E3%80%82%E5%AE%83%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%8E%9F%E5%88%99%E5%B0%B1%E6%98%AF%EF%BC%8C%E6%B0%B8%E8%BF%9C%E6%9C%80%E5%A4%9A%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AAleader%E3%80%82%E8%80%8C%E6%89%80%E6%9C%89follower%E9%83%BD%E5%9C%A8%E7%AD%89%E5%BE%85%E6%88%90%E4%B8%BAleader%E3%80%82%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%90%AF%E5%8A%A8%E6%97%B6%E4%BC%9A%E8%87%AA%E5%8A%A8%E4%BA%A7%E7%94%9F%E4%B8%80%E4%B8%AALeader%E8%B4%9F%E8%B4%A3%E7%AD%89%E5%BE%85%E7%BD%91%E7%BB%9CIO%E4%BA%8B%E4%BB%B6%EF%BC%8C%E5%BD%93%E6%9C%89%E4%B8%80%E4%B8%AA%E4%BA%8B%E4%BB%B6%E4%BA%A7%E7%94%9F%E6%97%B6%EF%BC%8CLeader%E7%BA%BF%E7%A8%8B%E9%A6%96%E5%85%88%E9%80%9A%E7%9F%A5%E4%B8%80%E4%B8%AAFollower%E7%BA%BF%E7%A8%8B%E5%B0%86%E5%85%B6%E6%8F%90%E6%8B%94%E4%B8%BA%E6%96%B0%E7%9A%84Leader%EF%BC%8C%E7%84%B6%E5%90%8E%E8%87%AA%E5%B7%B1%E5%B0%B1%E5%8E%BB%E5%B9%B2%E6%B4%BB%E4%BA%86%EF%BC%8C%E5%8E%BB%E5%A4%84%E7%90%86%E8%BF%99%E4%B8%AA%E7%BD%91%E7%BB%9C%E4%BA%8B%E4%BB%B6%EF%BC%8C%E5%A4%84%E7%90%86%E5%AE%8C%E6%AF%95%E5%90%8E%E5%8A%A0%E5%85%A5Follower%E7%BA%BF%E7%A8%8B%E7%AD%89%E5%BE%85%E9%98%9F%E5%88%97%EF%BC%8C%E7%AD%89%E5%BE%85%E4%B8%8B%E6%AC%A1%E6%88%90%E4%B8%BALeader%E3%80%82%E8%BF%99%E7%A7%8D%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E5%A2%9E%E5%BC%BACPU%E9%AB%98%E9%80%9F%E7%BC%93%E5%AD%98%E7%9B%B8%E4%BC%BC%E6%80%A7%EF%BC%8C%E5%8F%8A%E6%B6%88%E9%99%A4%E5%8A%A8%E6%80%81%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E5%92%8C%E7%BA%BF%E7%A8%8B%E9%97%B4%E7%9A%84%E6%95%B0%E6%8D%AE%E4%BA%A4%E6%8D%A2%E3%80%82%0A%0A%60%60%60java%0A%20%20%20%20%2F%2F%20%E5%8F%AF%E9%87%8D%E5%85%A5%E9%94%81%0A%20%20%20%20private%20final%20transient%20ReentrantLock%20lock%20%3D%20new%20ReentrantLock()%3B%0A%20%20%20%20%0A%20%20%20%20%2F%2F%20%E5%AD%98%E5%82%A8%E9%98%9F%E5%88%97%E5%85%83%E7%B4%A0%E7%9A%84%E9%98%9F%E5%88%97%E2%80%94%E2%80%94%E4%BC%98%E5%85%88%E9%98%9F%E5%88%97%0A%20%20%20%20private%20final%20PriorityQueue%3CE%3E%20q%20%3D%20new%20PriorityQueue%3CE%3E()%3B%0A%20%0A%20%20%20%20%2F%2F%E7%94%A8%E4%BA%8E%E4%BC%98%E5%8C%96%E9%98%BB%E5%A1%9E%E9%80%9A%E7%9F%A5%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%85%83%E7%B4%A0leader%EF%BC%8CLeader%2FFollowers%E6%A8%A1%E5%BC%8F%0A%20%20%20%20private%20Thread%20leader%20%3D%20null%3B%0A%20%0A%20%20%20%20%2F%2F%E7%94%A8%E4%BA%8E%E5%AE%9E%E7%8E%B0%E9%98%BB%E5%A1%9E%E5%92%8C%E9%80%9A%E7%9F%A5%E7%9A%84Condition%E5%AF%B9%E8%B1%A1%0A%20%20%20%20private%20final%20Condition%20available%20%3D%20lock.newCondition()%3B%0A%20%20%20%20%0A%20%20%20%20public%20DelayQueue()%20%7B%7D%0A%20%20%20%20%0A%20%20%20%20public%20DelayQueue(Collection%3C%3F%20extends%20E%3E%20c)%20%7B%0A%20%20%20%20%20%20%20%20this.addAll(c)%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%0A

ThreadLocal

创建时间:2021/12/26 13:59
更新时间:2024/2/3 8:48
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247501989&idx=2&sn=9adb0c19dfc982b8fbabface2591612a&chksm=fd63d81aca14510c82e3afb0ec6a04e0d55e053060c8a0aef4198efacd33fb1481b9c34fdda4&mpshare=1&scene=24&srcid=0416VUxBeMrkmmPIA7vLBWT6&sharer_sharetime=1618553119268&sharer_shareid=5b3482cc84e779e76f71a8abd134e217&key=756768bae9c758c25730a59d5e4609080cb3542f94215fc2932d5af8c96093ba94060ba3fd1e124d332aa53b44b4880d9da7d52976847ea2e4df73ec536e8928ae2b586b775a9c7bec3d12e4aec78e4373721e849759f26b584db0422e6d2c5a54170a29c7947cb940d25d84d3a3f910010a1a6546e3f2e1c452534b3e9f6805&ascene=14&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=63030073&lang=en&exportkey=AYja%2BVkGVtk0ExnNtu0fW%2BM%3D&pass_ticket=FHcU%2Fn%2Fryrosiu1u0Hb5RgpjmPTMl1vKqtVMiaWKzbreRDQmB2hENp30rS3ObHQa&wx_header=0&fontgear=2

1 ThreadLocal概述

1.1 是什么

ThreadLocal 一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本。通过ThreadLocal可以将对象的可见范围限制在同一个线程内.

1.2 能干什么

没有ThreadLocal 的时候,一个线程在其生命周期内,可能穿过多个层级,多个方法,如果有个对象需要在此线程周期内多次调用,且是跨层级的(线程内共享),通常的做法是通过参数进行传递;而
ThreadLocal 将变量绑定在线程上,在一个线程周期内,无论“你身处何地”,只需通过其提供的get方法就可轻松获取到对象。极大地提高了对于“线程级变量”的访问便利性。

1.3 跳出误区

不要拿 ThreadLocalsynchronized 做类比,因为这种比较压根就是无意义
sysnchronized 是一种互斥同步机制,是为了保证在多线程环境下对于共享资源的正确访问
ThreadLocal 从本质上讲,无非是提供了一个“线程级”的变量作用域,它是一种线程封闭(每个线程独享变量)技术,更直白点讲,ThreadLocal 可以理解为将对象的作用范围限制在一个线程上下文中,使得变量的作用域为“线程级”

2 怎么玩

2.1 案例

为每个线程关联一个唯一的序号,在每个线程周期内,我们需要多次访问这个序号,这时我们就可以使用ThreadLocal了

执行结果,可以看到每个线程都分配到了一个唯一的ID,同时在此线程范围内的"任何地点",我们都可以通过ThreadId.get()这种方式直接获取。

2.2 源码

set操作,为线程绑定变量

可以看到,ThreadLocal不过是个入口,真正的变量是绑定在线程上的。

下面给是Thread类中的定义,每个线程对象都拥有一个ThreadLocalMap对象

ThreadLocal.ThreadLocalMap threadLocals = null;

现在可以看出ThreadLocal的设计思想了:

  • ThreadLocal仅仅是个变量访问的入口;
  • 每一个Thread对象都有一个ThreadLocalMap对象,这个ThreadLocalMap持有对象的引用;
  • ThreadLocalMap以当前的threadlocal对象为key,以真正的存储对象为value。get时通过threadlocal实例就可以找到绑定在当前线程上的对象。

乍看上去,这种设计确实有些绕。我们完全可以在设计成 Map<Thread,T> 这种形式,一个线程对应一个存储对象。
ThreadLocal这样设计的目的主要有两个:

  • 可以保证当前线程结束时相关对象能尽快被回收;
  • ThreadLocalMap中的元素会大大减少,我们都知道map过大更容易造成哈希冲突而导致性能变差。

3 线程独享变量

  • 还有一个会引起疑惑的问题,我们说ThreadLocal为每一个线程维护一个独立的变量副本,那么是不是说各个线程之间真正的做到对于对象的“完全自治”而不对其他线程的对象产生影响呢?其实这已经不属于对于ThreadLocal的讨论,而是你出于何种目的去使用ThreadLocal。如果我们为一个线程关联的对象是“完全独享”的,也就是每个线程拥有一整套的新的 栈中的对象引用+堆中的对象,那么这种情况下是真正的彻底的“线程独享变量”,相当于一种深度拷贝,每个线程自己玩自己的,对该对象做任何的操作也不会对别的线程有任何影响。
  • 另一种更普遍的情况,所谓的独享变量副本,其实也就是每个线程都拥有一个独立的对象引用,而堆中的对象还是线程间共享的,这种情况下,自然还是会涉及到对共享资源的访问操作,依然会有线程不安全的风险。所以说,ThreadLocal无法解决线程安全问题。  所以,需不需要完全独享变量,进行完全隔离,就取决于你的应用场景了。可以想象,对象过大的时候,如果每个线程都有这么一份“深拷贝”,并发又比较大,对于服务器的压力自然是很大的。像web开发中的servlet,servlet是线程不安全的,一请求一线程,多个线程共享一个servlet对象;而早期的CGI设计中,N个请求就对应N个对象,并发量大了之后性能自然就很差。

  • ThreadLocal在spring的事务管理,包括Hibernate的session管理等都有出现,在web开发中,有时会用来管理用户会话 HttpSession,web交互中这种典型的一请求一线程的场景似乎比较适合使用ThreadLocal,但是需要特别注意的是,由于此时session与线程关联,而tomcat这些web服务器多会采用线程池机制,也就是说线程是可复用的,所以在每一次进入的时候都需要重新进行set,或者在结束时及时remove。

4 内存泄漏

4.1 内存泄漏原因

在ThreadLocalMap中,也是用Entry来保存K-V结构数据的。但是Entry中key只能是ThreadLocal对象,这点被Entry的构造方法已经限定死了。

Entry继承自WeakReference(弱引用,生命周期只能存活到下次GC前),但只有Key是弱引用类型的,Value并非弱引用。

由于ThreadLocalMap的key是弱引用,而Value是强引用。这就导致了一个问题,ThreadLocal在没有外部对象强引用时,发生GC时弱引用Key会被回收,而Value不会回收。当线程没有结束,但是ThreadLocal已经被回收,则可能导致线程中存在ThreadLocalMap<null, Object>的键值对,造成内存泄露。(ThreadLocal被回收,ThreadLocal关联的线程共享变量还存在)

4.2 如何避免泄漏

有两种手段。
1、使用完线程共享变量后,显示调用ThreadLocalMap.remove方法清除线程共享变量;既然Key是弱引用,那么我们要做的事,就是在调用ThreadLocal的get()、set()方法时完成后再调用remove方法,将Entry节点和Map的引用关系移除,这样整个Entry对象在GC Roots分析后就变成不可达了,下次GC的时候就可以被回收。

2、JDK建议ThreadLocal定义为private static,这样ThreadLocal的弱引用问题则不存在了。

%5Btoc%5D%0A%0A%23%23%201%20ThreadLocal%E6%A6%82%E8%BF%B0%0A%23%23%23%23%201.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20%60ThreadLocal%60%20%E4%B8%80%E8%88%AC%E7%A7%B0%E4%B8%BA%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%EF%BC%8C%E5%AE%83%E6%98%AF%E4%B8%80%E7%A7%8D%E7%89%B9%E6%AE%8A%E7%9A%84%E7%BA%BF%E7%A8%8B%E7%BB%91%E5%AE%9A%E6%9C%BA%E5%88%B6%EF%BC%8C%E5%B0%86%E5%8F%98%E9%87%8F%E4%B8%8E%E7%BA%BF%E7%A8%8B%E7%BB%91%E5%AE%9A%E5%9C%A8%E4%B8%80%E8%B5%B7%EF%BC%8C%E4%B8%BA%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%BB%B4%E6%8A%A4%E4%B8%80%E4%B8%AA%E7%8B%AC%E7%AB%8B%E7%9A%84%E5%8F%98%E9%87%8F%E5%89%AF%E6%9C%AC%E3%80%82%E9%80%9A%E8%BF%87ThreadLocal%E5%8F%AF%E4%BB%A5%E5%B0%86%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%8F%AF%E8%A7%81%E8%8C%83%E5%9B%B4%E9%99%90%E5%88%B6%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%86%85.%0A%0A%23%23%23%23%201.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%20%3E%20%E6%B2%A1%E6%9C%89%60ThreadLocal%60%20%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%9C%A8%E5%85%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%86%85%EF%BC%8C%E5%8F%AF%E8%83%BD%E7%A9%BF%E8%BF%87%E5%A4%9A%E4%B8%AA%E5%B1%82%E7%BA%A7%EF%BC%8C%E5%A4%9A%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9C%89%E4%B8%AA%E5%AF%B9%E8%B1%A1%E9%9C%80%E8%A6%81%E5%9C%A8%E6%AD%A4%E7%BA%BF%E7%A8%8B%E5%91%A8%E6%9C%9F%E5%86%85%E5%A4%9A%E6%AC%A1%E8%B0%83%E7%94%A8%EF%BC%8C%E4%B8%94%E6%98%AF%E8%B7%A8%E5%B1%82%E7%BA%A7%E7%9A%84%EF%BC%88%E7%BA%BF%E7%A8%8B%E5%86%85%E5%85%B1%E4%BA%AB%EF%BC%89%EF%BC%8C%E9%80%9A%E5%B8%B8%E7%9A%84%E5%81%9A%E6%B3%95%E6%98%AF%E9%80%9A%E8%BF%87%E5%8F%82%E6%95%B0%E8%BF%9B%E8%A1%8C%E4%BC%A0%E9%80%92%EF%BC%9B%E8%80%8C%0A%20%3E%20%60ThreadLocal%60%20%E5%B0%86%E5%8F%98%E9%87%8F%E7%BB%91%E5%AE%9A%E5%9C%A8%E7%BA%BF%E7%A8%8B%E4%B8%8A%EF%BC%8C%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%91%A8%E6%9C%9F%E5%86%85%EF%BC%8C%E6%97%A0%E8%AE%BA%E2%80%9C%E4%BD%A0%E8%BA%AB%E5%A4%84%E4%BD%95%E5%9C%B0%E2%80%9D%EF%BC%8C%E5%8F%AA%E9%9C%80%E9%80%9A%E8%BF%87%E5%85%B6%E6%8F%90%E4%BE%9B%E7%9A%84get%E6%96%B9%E6%B3%95%E5%B0%B1%E5%8F%AF%E8%BD%BB%E6%9D%BE%E8%8E%B7%E5%8F%96%E5%88%B0%E5%AF%B9%E8%B1%A1%E3%80%82%E6%9E%81%E5%A4%A7%E5%9C%B0%E6%8F%90%E9%AB%98%E4%BA%86%E5%AF%B9%E4%BA%8E%E2%80%9C%E7%BA%BF%E7%A8%8B%E7%BA%A7%E5%8F%98%E9%87%8F%E2%80%9D%E7%9A%84%E8%AE%BF%E9%97%AE%E4%BE%BF%E5%88%A9%E6%80%A7%E3%80%82%0A%0A%0A%23%23%23%23%201.3%20%E8%B7%B3%E5%87%BA%E8%AF%AF%E5%8C%BA%0A%3E%20%E4%B8%8D%E8%A6%81%E6%8B%BF%20%60ThreadLocal%60%20%E5%92%8C%20%60synchronized%60%20%E5%81%9A%E7%B1%BB%E6%AF%94%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%BF%99%E7%A7%8D%E6%AF%94%E8%BE%83%E5%8E%8B%E6%A0%B9%E5%B0%B1%E6%98%AF%E6%97%A0%E6%84%8F%E4%B9%89%0A%3E%20%60sysnchronized%60%20%E6%98%AF%E4%B8%80%E7%A7%8D%E4%BA%92%E6%96%A5%E5%90%8C%E6%AD%A5%E6%9C%BA%E5%88%B6%EF%BC%8C%E6%98%AF%E4%B8%BA%E4%BA%86%E4%BF%9D%E8%AF%81%E5%9C%A8%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%8E%AF%E5%A2%83%E4%B8%8B%E5%AF%B9%E4%BA%8E%E5%85%B1%E4%BA%AB%E8%B5%84%E6%BA%90%E7%9A%84%E6%AD%A3%E7%A1%AE%E8%AE%BF%E9%97%AE%0A%3E%20%E8%80%8C%20%60ThreadLocal%60%20%E4%BB%8E%E6%9C%AC%E8%B4%A8%E4%B8%8A%E8%AE%B2%EF%BC%8C%E6%97%A0%E9%9D%9E%E6%98%AF%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E4%B8%AA%E2%80%9C%E7%BA%BF%E7%A8%8B%E7%BA%A7%E2%80%9D%E7%9A%84%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%8C%E5%AE%83%E6%98%AF%E4%B8%80%E7%A7%8D%E7%BA%BF%E7%A8%8B%E5%B0%81%E9%97%AD%EF%BC%88%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%8B%AC%E4%BA%AB%E5%8F%98%E9%87%8F%EF%BC%89%E6%8A%80%E6%9C%AF%EF%BC%8C%E6%9B%B4%E7%9B%B4%E7%99%BD%E7%82%B9%E8%AE%B2%EF%BC%8C%60ThreadLocal%60%20%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BA%E5%B0%86%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%BD%9C%E7%94%A8%E8%8C%83%E5%9B%B4%E9%99%90%E5%88%B6%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%EF%BC%8C%E4%BD%BF%E5%BE%97%E5%8F%98%E9%87%8F%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%BA%E2%80%9C%E7%BA%BF%E7%A8%8B%E7%BA%A7%E2%80%9D%0A%0A%0A%23%23%202%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%23%23%23%23%202.1%20%E6%A1%88%E4%BE%8B%0A%3E%20%E4%B8%BA%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%85%B3%E8%81%94%E4%B8%80%E4%B8%AA%E5%94%AF%E4%B8%80%E7%9A%84%E5%BA%8F%E5%8F%B7%EF%BC%8C%E5%9C%A8%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%91%A8%E6%9C%9F%E5%86%85%EF%BC%8C%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E5%A4%9A%E6%AC%A1%E8%AE%BF%E9%97%AE%E8%BF%99%E4%B8%AA%E5%BA%8F%E5%8F%B7%EF%BC%8C%E8%BF%99%E6%97%B6%E6%88%91%E4%BB%AC%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8ThreadLocal%E4%BA%86%0A%0A!%5B65b8c317527075eb285cbd2ad8f76101.png%5D(en-resource%3A%2F%2Fdatabase%2F1192%3A1)%0A%0A%3E%20%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%2C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%83%BD%E5%88%86%E9%85%8D%E5%88%B0%E4%BA%86%E4%B8%80%E4%B8%AA%E5%94%AF%E4%B8%80%E7%9A%84ID%EF%BC%8C%E5%90%8C%E6%97%B6%E5%9C%A8%E6%AD%A4%E7%BA%BF%E7%A8%8B%E8%8C%83%E5%9B%B4%E5%86%85%E7%9A%84%22%E4%BB%BB%E4%BD%95%E5%9C%B0%E7%82%B9%22%EF%BC%8C%E6%88%91%E4%BB%AC%E9%83%BD%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87ThreadId.get()%E8%BF%99%E7%A7%8D%E6%96%B9%E5%BC%8F%E7%9B%B4%E6%8E%A5%E8%8E%B7%E5%8F%96%E3%80%82%0A%0A!%5Bb2fa7cf06462954e42dd593f2b4d6c58.png%5D(en-resource%3A%2F%2Fdatabase%2F1193%3A1)%0A%0A%23%23%23%23%202.2%20%E6%BA%90%E7%A0%81%0A%3E%20set%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%B8%BA%E7%BA%BF%E7%A8%8B%E7%BB%91%E5%AE%9A%E5%8F%98%E9%87%8F%0A%0A!%5B1a98f157a721d61d86425f1a1c84171f.png%5D(en-resource%3A%2F%2Fdatabase%2F1194%3A1)%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%EF%BC%8CThreadLocal%E4%B8%8D%E8%BF%87%E6%98%AF%E4%B8%AA%E5%85%A5%E5%8F%A3%EF%BC%8C%E7%9C%9F%E6%AD%A3%E7%9A%84%E5%8F%98%E9%87%8F%E6%98%AF%E7%BB%91%E5%AE%9A%E5%9C%A8%E7%BA%BF%E7%A8%8B%E4%B8%8A%E7%9A%84%E3%80%82%0A%0A!%5B88ca6c6465887c7ee5bbbf6e0f761cbd.png%5D(en-resource%3A%2F%2Fdatabase%2F1195%3A1)%0A%0A%3E%20%E4%B8%8B%E9%9D%A2%E7%BB%99%E6%98%AFThread%E7%B1%BB%E4%B8%AD%E7%9A%84%E5%AE%9A%E4%B9%89%EF%BC%8C%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%AF%B9%E8%B1%A1%E9%83%BD%E6%8B%A5%E6%9C%89%E4%B8%80%E4%B8%AAThreadLocalMap%E5%AF%B9%E8%B1%A1%0A%0A%60%60%60java%20%0AThreadLocal.ThreadLocalMap%20threadLocals%20%3D%20null%3B%0A%60%60%60%0A%0A%0A%3E%20%E7%8E%B0%E5%9C%A8%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BAThreadLocal%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%80%9D%E6%83%B3%E4%BA%86%EF%BC%9A%0A%3E%20-%20ThreadLocal%E4%BB%85%E4%BB%85%E6%98%AF%E4%B8%AA%E5%8F%98%E9%87%8F%E8%AE%BF%E9%97%AE%E7%9A%84%E5%85%A5%E5%8F%A3%EF%BC%9B%0A%3E%20-%20%E6%AF%8F%E4%B8%80%E4%B8%AAThread%E5%AF%B9%E8%B1%A1%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AAThreadLocalMap%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%BF%99%E4%B8%AAThreadLocalMap%E6%8C%81%E6%9C%89%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BC%95%E7%94%A8%EF%BC%9B%0A%3E%20-%20ThreadLocalMap%E4%BB%A5%E5%BD%93%E5%89%8D%E7%9A%84threadlocal%E5%AF%B9%E8%B1%A1%E4%B8%BAkey%EF%BC%8C%E4%BB%A5%E7%9C%9F%E6%AD%A3%E7%9A%84%E5%AD%98%E5%82%A8%E5%AF%B9%E8%B1%A1%E4%B8%BAvalue%E3%80%82get%E6%97%B6%E9%80%9A%E8%BF%87threadlocal%E5%AE%9E%E4%BE%8B%E5%B0%B1%E5%8F%AF%E4%BB%A5%E6%89%BE%E5%88%B0%E7%BB%91%E5%AE%9A%E5%9C%A8%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E4%B8%8A%E7%9A%84%E5%AF%B9%E8%B1%A1%E3%80%82%0A%0A%0A%3E%20%E4%B9%8D%E7%9C%8B%E4%B8%8A%E5%8E%BB%EF%BC%8C%E8%BF%99%E7%A7%8D%E8%AE%BE%E8%AE%A1%E7%A1%AE%E5%AE%9E%E6%9C%89%E4%BA%9B%E7%BB%95%E3%80%82%E6%88%91%E4%BB%AC%E5%AE%8C%E5%85%A8%E5%8F%AF%E4%BB%A5%E5%9C%A8%E8%AE%BE%E8%AE%A1%E6%88%90%20%60Map%3CThread%2CT%3E%60%20%E8%BF%99%E7%A7%8D%E5%BD%A2%E5%BC%8F%EF%BC%8C%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%AF%B9%E5%BA%94%E4%B8%80%E4%B8%AA%E5%AD%98%E5%82%A8%E5%AF%B9%E8%B1%A1%E3%80%82%0A%3E%20ThreadLocal%E8%BF%99%E6%A0%B7%E8%AE%BE%E8%AE%A1%E7%9A%84%E7%9B%AE%E7%9A%84%E4%B8%BB%E8%A6%81%E6%9C%89%E4%B8%A4%E4%B8%AA%EF%BC%9A%0A%3E%20-%20%E5%8F%AF%E4%BB%A5%E4%BF%9D%E8%AF%81%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E7%BB%93%E6%9D%9F%E6%97%B6%E7%9B%B8%E5%85%B3%E5%AF%B9%E8%B1%A1%E8%83%BD%E5%B0%BD%E5%BF%AB%E8%A2%AB%E5%9B%9E%E6%94%B6%EF%BC%9B%0A%3E%20-%20ThreadLocalMap%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%E4%BC%9A%E5%A4%A7%E5%A4%A7%E5%87%8F%E5%B0%91%EF%BC%8C%E6%88%91%E4%BB%AC%E9%83%BD%E7%9F%A5%E9%81%93map%E8%BF%87%E5%A4%A7%E6%9B%B4%E5%AE%B9%E6%98%93%E9%80%A0%E6%88%90%E5%93%88%E5%B8%8C%E5%86%B2%E7%AA%81%E8%80%8C%E5%AF%BC%E8%87%B4%E6%80%A7%E8%83%BD%E5%8F%98%E5%B7%AE%E3%80%82%0A%0A%23%23%203%20%E7%BA%BF%E7%A8%8B%E7%8B%AC%E4%BA%AB%E5%8F%98%E9%87%8F%0A%0A%3E%20-%20%E8%BF%98%E6%9C%89%E4%B8%80%E4%B8%AA%E4%BC%9A%E5%BC%95%E8%B5%B7%E7%96%91%E6%83%91%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E6%88%91%E4%BB%AC%E8%AF%B4ThreadLocal%E4%B8%BA%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%BB%B4%E6%8A%A4%E4%B8%80%E4%B8%AA%E7%8B%AC%E7%AB%8B%E7%9A%84%E5%8F%98%E9%87%8F%E5%89%AF%E6%9C%AC%EF%BC%8C%E9%82%A3%E4%B9%88%E6%98%AF%E4%B8%8D%E6%98%AF%E8%AF%B4%E5%90%84%E4%B8%AA%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E7%9C%9F%E6%AD%A3%E7%9A%84%E5%81%9A%E5%88%B0%E5%AF%B9%E4%BA%8E%E5%AF%B9%E8%B1%A1%E7%9A%84%E2%80%9C%E5%AE%8C%E5%85%A8%E8%87%AA%E6%B2%BB%E2%80%9D%E8%80%8C%E4%B8%8D%E5%AF%B9%E5%85%B6%E4%BB%96%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%AF%B9%E8%B1%A1%E4%BA%A7%E7%94%9F%E5%BD%B1%E5%93%8D%E5%91%A2%EF%BC%9F%E5%85%B6%E5%AE%9E%E8%BF%99%E5%B7%B2%E7%BB%8F%E4%B8%8D%E5%B1%9E%E4%BA%8E%E5%AF%B9%E4%BA%8EThreadLocal%E7%9A%84%E8%AE%A8%E8%AE%BA%EF%BC%8C%E8%80%8C%E6%98%AF%E4%BD%A0%E5%87%BA%E4%BA%8E%E4%BD%95%E7%A7%8D%E7%9B%AE%E7%9A%84%E5%8E%BB%E4%BD%BF%E7%94%A8ThreadLocal%E3%80%82%E5%A6%82%E6%9E%9C%E6%88%91%E4%BB%AC%E4%B8%BA%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%85%B3%E8%81%94%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%98%AF%E2%80%9C%E5%AE%8C%E5%85%A8%E7%8B%AC%E4%BA%AB%E2%80%9D%E7%9A%84%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%8B%A5%E6%9C%89%E4%B8%80%E6%95%B4%E5%A5%97%E7%9A%84%E6%96%B0%E7%9A%84%26nbsp%3B%E6%A0%88%E4%B8%AD%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%BC%95%E7%94%A8%2B%E5%A0%86%E4%B8%AD%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E9%82%A3%E4%B9%88%E8%BF%99%E7%A7%8D%E6%83%85%E5%86%B5%E4%B8%8B%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84%E5%BD%BB%E5%BA%95%E7%9A%84%E2%80%9C%E7%BA%BF%E7%A8%8B%E7%8B%AC%E4%BA%AB%E5%8F%98%E9%87%8F%E2%80%9D%EF%BC%8C%E7%9B%B8%E5%BD%93%E4%BA%8E%E4%B8%80%E7%A7%8D%E6%B7%B1%E5%BA%A6%E6%8B%B7%E8%B4%9D%EF%BC%8C%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E8%87%AA%E5%B7%B1%E7%8E%A9%E8%87%AA%E5%B7%B1%E7%9A%84%EF%BC%8C%E5%AF%B9%E8%AF%A5%E5%AF%B9%E8%B1%A1%E5%81%9A%E4%BB%BB%E4%BD%95%E7%9A%84%E6%93%8D%E4%BD%9C%E4%B9%9F%E4%B8%8D%E4%BC%9A%E5%AF%B9%E5%88%AB%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%9C%89%E4%BB%BB%E4%BD%95%E5%BD%B1%E5%93%8D%E3%80%82%E3%80%80%E3%80%80%0A%0A%3E%20-%20%E5%8F%A6%E4%B8%80%E7%A7%8D%E6%9B%B4%E6%99%AE%E9%81%8D%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%8C%E6%89%80%E8%B0%93%E7%9A%84%E7%8B%AC%E4%BA%AB%E5%8F%98%E9%87%8F%E5%89%AF%E6%9C%AC%EF%BC%8C%E5%85%B6%E5%AE%9E%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%83%BD%E6%8B%A5%E6%9C%89%E4%B8%80%E4%B8%AA%E7%8B%AC%E7%AB%8B%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%BC%95%E7%94%A8%EF%BC%8C%E8%80%8C%E5%A0%86%E4%B8%AD%E7%9A%84%E5%AF%B9%E8%B1%A1%E8%BF%98%E6%98%AF%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%85%B1%E4%BA%AB%E7%9A%84%EF%BC%8C%E8%BF%99%E7%A7%8D%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E8%87%AA%E7%84%B6%E8%BF%98%E6%98%AF%E4%BC%9A%E6%B6%89%E5%8F%8A%E5%88%B0%E5%AF%B9%E5%85%B1%E4%BA%AB%E8%B5%84%E6%BA%90%E7%9A%84%E8%AE%BF%E9%97%AE%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%BE%9D%E7%84%B6%E4%BC%9A%E6%9C%89%E7%BA%BF%E7%A8%8B%E4%B8%8D%E5%AE%89%E5%85%A8%E7%9A%84%E9%A3%8E%E9%99%A9%E3%80%82%E6%89%80%E4%BB%A5%E8%AF%B4%EF%BC%8CThreadLocal%E6%97%A0%E6%B3%95%E8%A7%A3%E5%86%B3%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98%E3%80%82%E3%80%80%E3%80%80%E6%89%80%E4%BB%A5%EF%BC%8C%E9%9C%80%E4%B8%8D%E9%9C%80%E8%A6%81%E5%AE%8C%E5%85%A8%E7%8B%AC%E4%BA%AB%E5%8F%98%E9%87%8F%EF%BC%8C%E8%BF%9B%E8%A1%8C%E5%AE%8C%E5%85%A8%E9%9A%94%E7%A6%BB%EF%BC%8C%E5%B0%B1%E5%8F%96%E5%86%B3%E4%BA%8E%E4%BD%A0%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E4%BA%86%E3%80%82%E5%8F%AF%E4%BB%A5%E6%83%B3%E8%B1%A1%EF%BC%8C%E5%AF%B9%E8%B1%A1%E8%BF%87%E5%A4%A7%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%83%BD%E6%9C%89%E8%BF%99%E4%B9%88%E4%B8%80%E4%BB%BD%E2%80%9C%E6%B7%B1%E6%8B%B7%E8%B4%9D%E2%80%9D%EF%BC%8C%E5%B9%B6%E5%8F%91%E5%8F%88%E6%AF%94%E8%BE%83%E5%A4%A7%EF%BC%8C%E5%AF%B9%E4%BA%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E5%8E%8B%E5%8A%9B%E8%87%AA%E7%84%B6%E6%98%AF%E5%BE%88%E5%A4%A7%E7%9A%84%E3%80%82%E5%83%8Fweb%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84servlet%EF%BC%8Cservlet%E6%98%AF%E7%BA%BF%E7%A8%8B%E4%B8%8D%E5%AE%89%E5%85%A8%E7%9A%84%EF%BC%8C%E4%B8%80%E8%AF%B7%E6%B1%82%E4%B8%80%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%85%B1%E4%BA%AB%E4%B8%80%E4%B8%AAservlet%E5%AF%B9%E8%B1%A1%EF%BC%9B%E8%80%8C%E6%97%A9%E6%9C%9F%E7%9A%84CGI%E8%AE%BE%E8%AE%A1%E4%B8%AD%EF%BC%8CN%E4%B8%AA%E8%AF%B7%E6%B1%82%E5%B0%B1%E5%AF%B9%E5%BA%94N%E4%B8%AA%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%B9%B6%E5%8F%91%E9%87%8F%E5%A4%A7%E4%BA%86%E4%B9%8B%E5%90%8E%E6%80%A7%E8%83%BD%E8%87%AA%E7%84%B6%E5%B0%B1%E5%BE%88%E5%B7%AE%E3%80%82%0A%0A!%5Bb550711811ed40a9c252ea9e9319e2a0.png%5D(en-resource%3A%2F%2Fdatabase%2F1473%3A1)%0A%0A%0A%3E%20-%20ThreadLocal%E5%9C%A8spring%E7%9A%84%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%EF%BC%8C%E5%8C%85%E6%8B%ACHibernate%E7%9A%84session%E7%AE%A1%E7%90%86%E7%AD%89%E9%83%BD%E6%9C%89%E5%87%BA%E7%8E%B0%EF%BC%8C%E5%9C%A8web%E5%BC%80%E5%8F%91%E4%B8%AD%EF%BC%8C%E6%9C%89%E6%97%B6%E4%BC%9A%E7%94%A8%E6%9D%A5%E7%AE%A1%E7%90%86%E7%94%A8%E6%88%B7%E4%BC%9A%E8%AF%9D%20HttpSession%EF%BC%8Cweb%E4%BA%A4%E4%BA%92%E4%B8%AD%E8%BF%99%E7%A7%8D%E5%85%B8%E5%9E%8B%E7%9A%84%E4%B8%80%E8%AF%B7%E6%B1%82%E4%B8%80%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%9C%BA%E6%99%AF%E4%BC%BC%E4%B9%8E%E6%AF%94%E8%BE%83%E9%80%82%E5%90%88%E4%BD%BF%E7%94%A8ThreadLocal%EF%BC%8C%E4%BD%86%E6%98%AF%E9%9C%80%E8%A6%81%E7%89%B9%E5%88%AB%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%EF%BC%8C%E7%94%B1%E4%BA%8E%E6%AD%A4%E6%97%B6session%E4%B8%8E%E7%BA%BF%E7%A8%8B%E5%85%B3%E8%81%94%EF%BC%8C%E8%80%8Ctomcat%E8%BF%99%E4%BA%9Bweb%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%A4%9A%E4%BC%9A%E9%87%87%E7%94%A8%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%9C%BA%E5%88%B6%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%E7%BA%BF%E7%A8%8B%E6%98%AF%E5%8F%AF%E5%A4%8D%E7%94%A8%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E5%9C%A8%E6%AF%8F%E4%B8%80%E6%AC%A1%E8%BF%9B%E5%85%A5%E7%9A%84%E6%97%B6%E5%80%99%E9%83%BD%E9%9C%80%E8%A6%81%E9%87%8D%E6%96%B0%E8%BF%9B%E8%A1%8Cset%EF%BC%8C%E6%88%96%E8%80%85%E5%9C%A8%E7%BB%93%E6%9D%9F%E6%97%B6%E5%8F%8A%E6%97%B6remove%E3%80%82%0A%0A%0A%0A%23%23%204%20%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%0A%0A%23%23%23%23%204.1%20%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E5%8E%9F%E5%9B%A0%0A%0A!%5B6ba50a34d9576d3c672df6a699cb18b9.png%5D(en-resource%3A%2F%2Fdatabase%2F1475%3A1)%0A%0A%3E%20%E5%9C%A8ThreadLocalMap%E4%B8%AD%EF%BC%8C%E4%B9%9F%E6%98%AF%E7%94%A8Entry%E6%9D%A5%E4%BF%9D%E5%AD%98K-V%E7%BB%93%E6%9E%84%E6%95%B0%E6%8D%AE%E7%9A%84%E3%80%82%E4%BD%86%E6%98%AFEntry%E4%B8%ADkey%E5%8F%AA%E8%83%BD%E6%98%AFThreadLocal%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%BF%99%E7%82%B9%E8%A2%ABEntry%E7%9A%84%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E5%B7%B2%E7%BB%8F%E9%99%90%E5%AE%9A%E6%AD%BB%E4%BA%86%E3%80%82%0A%3E%20%0A%3E%20Entry%E7%BB%A7%E6%89%BF%E8%87%AAWeakReference%EF%BC%88%E5%BC%B1%E5%BC%95%E7%94%A8%EF%BC%8C%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%8F%AA%E8%83%BD%E5%AD%98%E6%B4%BB%E5%88%B0%E4%B8%8B%E6%AC%A1GC%E5%89%8D%EF%BC%89%EF%BC%8C%E4%BD%86%E5%8F%AA%E6%9C%89Key%E6%98%AF%E5%BC%B1%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E7%9A%84%EF%BC%8CValue%E5%B9%B6%E9%9D%9E%E5%BC%B1%E5%BC%95%E7%94%A8%E3%80%82%0A%3E%20%0A%3E%20%E7%94%B1%E4%BA%8EThreadLocalMap%E7%9A%84key%E6%98%AF%E5%BC%B1%E5%BC%95%E7%94%A8%EF%BC%8C%E8%80%8CValue%E6%98%AF%E5%BC%BA%E5%BC%95%E7%94%A8%E3%80%82%E8%BF%99%E5%B0%B1%E5%AF%BC%E8%87%B4%E4%BA%86%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%8CThreadLocal%E5%9C%A8%E6%B2%A1%E6%9C%89%E5%A4%96%E9%83%A8%E5%AF%B9%E8%B1%A1%E5%BC%BA%E5%BC%95%E7%94%A8%E6%97%B6%EF%BC%8C%E5%8F%91%E7%94%9FGC%E6%97%B6%E5%BC%B1%E5%BC%95%E7%94%A8Key%E4%BC%9A%E8%A2%AB%E5%9B%9E%E6%94%B6%EF%BC%8C%E8%80%8CValue%E4%B8%8D%E4%BC%9A%E5%9B%9E%E6%94%B6%E3%80%82%E5%BD%93%E7%BA%BF%E7%A8%8B%E6%B2%A1%E6%9C%89%E7%BB%93%E6%9D%9F%EF%BC%8C%E4%BD%86%E6%98%AFThreadLocal%E5%B7%B2%E7%BB%8F%E8%A2%AB%E5%9B%9E%E6%94%B6%EF%BC%8C%E5%88%99%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E7%BA%BF%E7%A8%8B%E4%B8%AD%E5%AD%98%E5%9C%A8ThreadLocalMap%3Cnull%2C%20Object%3E%E7%9A%84%E9%94%AE%E5%80%BC%E5%AF%B9%EF%BC%8C%E9%80%A0%E6%88%90%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E3%80%82%EF%BC%88ThreadLocal%E8%A2%AB%E5%9B%9E%E6%94%B6%EF%BC%8CThreadLocal%E5%85%B3%E8%81%94%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%85%B1%E4%BA%AB%E5%8F%98%E9%87%8F%E8%BF%98%E5%AD%98%E5%9C%A8%EF%BC%89%0A%0A%23%23%23%23%204.2%20%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D%E6%B3%84%E6%BC%8F%0A%0A%E6%9C%89%E4%B8%A4%E7%A7%8D%E6%89%8B%E6%AE%B5%E3%80%82%0A1%E3%80%81%E4%BD%BF%E7%94%A8%E5%AE%8C%E7%BA%BF%E7%A8%8B%E5%85%B1%E4%BA%AB%E5%8F%98%E9%87%8F%E5%90%8E%EF%BC%8C%E6%98%BE%E7%A4%BA%E8%B0%83%E7%94%A8ThreadLocalMap.remove%E6%96%B9%E6%B3%95%E6%B8%85%E9%99%A4%E7%BA%BF%E7%A8%8B%E5%85%B1%E4%BA%AB%E5%8F%98%E9%87%8F%EF%BC%9B%E6%97%A2%E7%84%B6Key%E6%98%AF%E5%BC%B1%E5%BC%95%E7%94%A8%EF%BC%8C%E9%82%A3%E4%B9%88%E6%88%91%E4%BB%AC%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B%EF%BC%8C%E5%B0%B1%E6%98%AF%E5%9C%A8%E8%B0%83%E7%94%A8ThreadLocal%E7%9A%84get()%E3%80%81set()%E6%96%B9%E6%B3%95%E6%97%B6%E5%AE%8C%E6%88%90%E5%90%8E%E5%86%8D%E8%B0%83%E7%94%A8remove%E6%96%B9%E6%B3%95%EF%BC%8C%E5%B0%86Entry%E8%8A%82%E7%82%B9%E5%92%8CMap%E7%9A%84%E5%BC%95%E7%94%A8%E5%85%B3%E7%B3%BB%E7%A7%BB%E9%99%A4%EF%BC%8C%E8%BF%99%E6%A0%B7%E6%95%B4%E4%B8%AAEntry%E5%AF%B9%E8%B1%A1%E5%9C%A8GC%20Roots%E5%88%86%E6%9E%90%E5%90%8E%E5%B0%B1%E5%8F%98%E6%88%90%E4%B8%8D%E5%8F%AF%E8%BE%BE%E4%BA%86%EF%BC%8C%E4%B8%8B%E6%AC%A1GC%E7%9A%84%E6%97%B6%E5%80%99%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%A2%AB%E5%9B%9E%E6%94%B6%E3%80%82%0A%0A2%E3%80%81JDK%E5%BB%BA%E8%AE%AEThreadLocal%E5%AE%9A%E4%B9%89%E4%B8%BAprivate%20static%EF%BC%8C%E8%BF%99%E6%A0%B7ThreadLocal%E7%9A%84%E5%BC%B1%E5%BC%95%E7%94%A8%E9%97%AE%E9%A2%98%E5%88%99%E4%B8%8D%E5%AD%98%E5%9C%A8%E4%BA%86%E3%80%82

CompletableFuture组合处理allOf和anyOf

创建时间:2021/12/23 23:03
更新时间:2021/12/23 23:07
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503565&idx=2&sn=561c817f25a0b1e6ed41c0805b97dfa1&chksm=fd63de72ca145764e2ed147632515fce82f8e45a06c7ed9b31fb84ab71a5317c3b93a9e05346&mpshare=1&scene=24&srcid=0531BL46xMgbjdgBI1SSkjyt&sharer_sharetime=1622442665148&sharer_shareid=5b3482cc84e779e76f71a8abd134e217&key=e317cdf821cd22ccb7191edb72978b3ae2fdf16394e4adb4801bcab7bda754ca1f40df2ca1ef9946fb00b056eed5df981019455dcc15e90b027f0a97f92b1d201ab3a9af3cd6c33ed82de0658a2a7c6370a455bb48fd7e0a2d0e28cf551d9b882d62f26a48e5b11c7024ee1bcad5d8d330c17504c7386cb3e38a76c39c91652d&ascene=0&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+10+x64&version=63040026&lang=zh_CN&exportkey=AV0Xp3AvjWDYv4im%2BPjuPUk%3D&pass_ticket=o7%2F8p1PSOO%2BtRsKPjs3sz7l5tAR5yd9LgwTkgOPaP4222NMyyAvezKo6QoKIkYw2&wx_header=0&fontgear=2

前段时间写了一篇关于CompletableFuture的异步提交操作以后,一些粉丝问到CompletableFuture其他问题,今儿顺便扒了CompletableFure源码其他的用法和一些函数特性介绍。

allOf 和 anyOf 可以组合任意多个 CompletableFuture。函数接口定义如下所示。

首先,这两个函数都是静态函数,参数是变长的 CompletableFuture 的集合。其次,allOf 和 anyOf 的区别,前者是「与」,后者是「或」。

例 1:allOf

allOf 的返回值是 CompletableFuture<Void>类型,这是因为 每个传入的 CompletableFuture 的返回值都可能不同,所以组合的结果是 无法用某种类型来表示的,索性返回 Void 类型。那么,如何获取每个 CompletableFuture 的执行结果呢?

参看下面的例子:并行地下载 100 个网页。待下载完成之后,统计在 100 个网页中,含有某个单词的网页个数。

这里有个关键问题,因为allof没有返回值,所以通过theApply,给allFutures附上一个回调函数。在回调函数里面,以此调用么一个Future的Get()函数,获取到100个结果,存入List<String>

接下里要做就是统计这100个网页中,含有单词[XXX] 的网页的个数

例 2:anyOf

anyOf 的含义是只要有任意一个 CompletableFuture 结束,就可以做 接下来的事情,而无须像 AllOf 那样,等待所有的 CompletableFuture 结束。

但由于每个 CompletableFuture 的返回值类型都可能不同,任意一个, 意味着无法判断是什么类型,所以 anyOf 的返回值是 CompletableFuture<Object>类型。考虑下面的例子。
在该例子中,因为future1、future2、future3的返回值都是CompletableFuture<String>,所以anyOf的返回的Object一定也是 String 类型。

并且在 3 个 future 中,future2 睡眠时间最短,会最先执行完成, anyOfFuture.get()获取的也就是 future2 的内容。future1、future3 的 返回结果被丢弃了

回顾整个CompletableFuture的用法主要可概括为以下几点

拓展学习:
到这里大概对CompletableFuture的常用用法有个大致的了解怎么去使用,什么场景用!其实写了这么多案例,不难发现CompletableFuture执行任务一共四种类型
回顾整个CompletableFuture的用法主要可概括为以下几点
runAsync 与 supplierAsync 是 CompletableFutre 的静态方法
而 thenAccept、thenAsync、thenApply 是 CompletableFutre 的成员方法 因为初始的时候没有 CompletableFuture 对象,也没有参数可传,所以提交的只能是 Runnable 或者 Supplier,只能是静态方法;
通过静态方法生成 CompletableFuture 对象之后,便可以链式地提交其他任务了,这个时候就可以提交 Runnable、Consumer、Function且都是成员方法

jvm调优

创建时间:2020/9/2 14:45
更新时间:2021/12/16 16:45
作者:Chris

3. JVM调优

3.1. 工作原理

影响JVM工作性能的主要是内存,因此对JVM的调优主要是针对内存的调优

为了更好更充分的使用内存,JVM在设计时对内存进行分类,分为:堆内存和栈内存

3.1.1堆和栈的区别

1. 堆是存储单元,所有需要使用到的数据都在堆中,堆是可以共享的。
2. 栈是运行单元,所有的运行对象都在栈里面,每一个线程都分会被分配栈内存,栈分为私有栈和本地栈,私有栈之间是不共享的,本地栈之间是可以共享的。

​ 3. 堆是用来处理数据的,栈是用来处理逻辑的,这样的好处是可以将数据与逻辑处理分离提交处理效率。

​ 因为对大片内存扫描效率很低,为了更好的进行GC,将堆分为三代

  1. Young Generation

    1.1 Eden : 对象首先存在Eden区
    1.2 Survivor 0: Eden区满了之后再将对象复制到S0
    1.3 Survivor 1: S0满了之后再将对象复制到S1

  2. Old Generation: Survivor区满了之后再将对象复制到Old Generation, Old Generation处理在Young Generation中通过GC回收后还存活的对象

  3. Permaneent Generation , JDK8之后更名为Metaspace [元空间], 存放静态方法和类。

  4. Metaspace:元空间是本地内存里面,主要解决OOM及不方便设置的问题。

3.2 GC 回收
3.2.1 回收机制

​ 回收的是内存,主要对堆中的三代进行回收
​ 回收分为两种:Scavenge GC , Full GC

  1. Scavenge GC 主要针对Young Generation进行回收, 先对Edan区进行回收,如果回收完后还有存活对象,会将对象复制到Survivor区,由于Edan对象变化很频繁,因此Young Generation会经常使用Scavenge GC进行回收。

  2. Full GC 对三代都回进行回收,但由于jdk8之后没有Permanent Generation,取尔代之的是metaspace,所以只能Young Generation和Old Generation进行回收

  3. 因为Full GC回收的内容比较多,所以一般情况下不会频繁触发Full GC,只有在如下情况下才会触发

    3.1 年老代写满,此时年轻代肯定也写满

    3.2 持久代写满

    3.3 system.gc()被调用

    3.4 上一次GC后,heap分配的策略重新分配了

3.2.2 回收算法
  1. 引用计数

    对象的引用进行计数,如果对此对象引用一次,则记数增加1,如是引用释放则减1; 如果对象的记数为0,则表示此对象需要进行回处理。

  2. 标记清除

    此算法会不断的扫描GC Roots, 将存活的对象标记出来,等到不用的时候再清除, 这个方法效率低,清除完后内存不会连续在一块,形成内存碎片。

  3. 复制算法

    将内存分为两份,每次只使用其中的一份内存,当回收完成之后,将回收到的内容全部拼接到未使用的那一份内存上面,这样效率高,没有内存碎片

3.2.3 回收器
  1. 串行回收器

    年轻代和年老代都串行,只有一个线程在工作,无需线程交互,所以效率高,但是无法发挥多处理器的优势。

    通常在小数据量【100M左右】的多处理器的机器上可以使用串行

    使用 -XX:+UseSerialGC 打开串行回收器

  2. 并行回收器

    在年轻代处理并行回收处理,年老代仍然为串行,会制约回收能力

    使用 -XX:+UseParallelGC 打开年轻代并行回收器

  3. 并发回收器

    在年轻代处理并行回收处理的同时将年老代设置为并行回收

    使用 -XX:+UseParallelOldGC 打开年老代并行回收器

    使用 -XX:ParallelGCTheads=n 设置并行回收的线程数,此值一般设置为与处理器数相等

3.3 JVM参数设置

修改JVM参数的方式

  1. eclipse

  2. 修改tomcat中的文件

    2.1 bin/catalina.sh

    2.2 bin/startup.sh 服务器停止之后修改的JVM值还是生效的

    每个参数用空格隔开,参数区分大小写

    第一种语法
    set CATALINA_OPTS = -Xmx512m -Xms512m -XX:SurvivorRatio=3 -XX:NewSize=250m -XX:MetaspaceSize=300m
    
    第二种语法
    set JAVA_OPTS = -Xmx512m -Xms512m -XX:SurvivorRatio=3 -XX:NewSize=250m -XX:MetaspaceSize=300m
    
    第三种语法
    JAVA_OPTS = "-Xmx512m -Xms512m -XX:SurvivorRatio=3 -XX:NewSize=250m -XX:MetaspaceSize=300m"
    

例:

JAVA_OPTS= "-Xms2048M -Xmx2048M -XX:+PrintGCDetails 
-XX:+PrintGCDateStamps -Xloggc:${BAYMAX_APP_WORKDIR}/logs/gc-%t.log 
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=14 
-XX:GCLogFileSize=100M -XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=${BAYMAX_APP_WORKDIR}/logs/"
3.3.1 heap 相关参数
-Xms: 初始堆大小
-Xmx: 最大堆大小
初始堆大小一般设置与最在堆大小一至

-XX:NewSize=n 设置年轻代大小
-XX:MaxNewSize=n 设置年轻代最大空间大小
-XX:NewRatio=n 设置年轻代与年老代的比例,如果为3,年轻代:年老代=1:3 , 表示年轻代占年轻代和年老代总和的1/4

-XX:SurvivorRatio=n 设置年轻代中Eden区与两个survivor区的比例,eden:survivor=3:2, 一个survivor占整个年轻代的1/5
-XX:MaxPermSize=n 设置持久代大小
-Xss:设置每个线程的堆大小

总内存大小:
Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]

3.3.2 metaspace 参数设置
-XX:MetasapceSize  初始元空间大小,内存使用达到该值时就会触发垃圾收集,同时GC会对该值进行调整,如果释放大量的空间就适当下调该值,如果释放很少的空间则在不超过MaxMetaspaceSize前提下,上调该值。

-XX:MaxMetaspaceSize 最大元空间大小,默认没有限制

-XX:MinMetaspaceFreeRatio 在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾回收

-XX:MaxMetaspaceFreeRatio 在GC之后,最大的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾回收
3.3.3 收集器参数设置
-XX:+UseSerialGC 设置串行收集器

-XX:+UseParallelGC 设置并行收集器

-XX:+UseParallelOldGC 设置并行年老代收集器

-XX:+UseConcMarkSweepGC 设置并发收集器
3.3.4 查看参数设置是否成功
ps aux | grep tomcat
%0A%0A%23%23%23%23%203.%20JVM%E8%B0%83%E4%BC%98%0A%0A%23%23%23%23%23%203.1.%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%0A%0A%E5%BD%B1%E5%93%8DJVM%E5%B7%A5%E4%BD%9C%E6%80%A7%E8%83%BD%E7%9A%84%E4%B8%BB%E8%A6%81%E6%98%AF%E5%86%85%E5%AD%98%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%AF%B9JVM%E7%9A%84%E8%B0%83%E4%BC%98%E4%B8%BB%E8%A6%81%E6%98%AF%E9%92%88%E5%AF%B9%E5%86%85%E5%AD%98%E7%9A%84%E8%B0%83%E4%BC%98%09%0A%0A%E4%B8%BA%E4%BA%86%E6%9B%B4%E5%A5%BD%E6%9B%B4%E5%85%85%E5%88%86%E7%9A%84%E4%BD%BF%E7%94%A8%E5%86%85%E5%AD%98%2CJVM%E5%9C%A8%E8%AE%BE%E8%AE%A1%E6%97%B6%E5%AF%B9%E5%86%85%E5%AD%98%E8%BF%9B%E8%A1%8C%E5%88%86%E7%B1%BB%EF%BC%8C%E5%88%86%E4%B8%BA%EF%BC%9A%E5%A0%86%E5%86%85%E5%AD%98%E5%92%8C%E6%A0%88%E5%86%85%E5%AD%98%0A%0A%23%23%23%23%23%23%203.1.1%E5%A0%86%E5%92%8C%E6%A0%88%E7%9A%84%E5%8C%BA%E5%88%AB%0A%0A%091.%20%E5%A0%86%E6%98%AF%E5%AD%98%E5%82%A8%E5%8D%95%E5%85%83%EF%BC%8C%E6%89%80%E6%9C%89%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E5%88%B0%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E5%9C%A8%E5%A0%86%E4%B8%AD%EF%BC%8C%E5%A0%86%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%85%B1%E4%BA%AB%E7%9A%84%E3%80%82%0A%20%092.%20%E6%A0%88%E6%98%AF%E8%BF%90%E8%A1%8C%E5%8D%95%E5%85%83%EF%BC%8C%E6%89%80%E6%9C%89%E7%9A%84%E8%BF%90%E8%A1%8C%E5%AF%B9%E8%B1%A1%E9%83%BD%E5%9C%A8%E6%A0%88%E9%87%8C%E9%9D%A2%EF%BC%8C%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%83%BD%E5%88%86%E4%BC%9A%E8%A2%AB%E5%88%86%E9%85%8D%E6%A0%88%E5%86%85%E5%AD%98%EF%BC%8C%E6%A0%88%E5%88%86%E4%B8%BA%E7%A7%81%E6%9C%89%E6%A0%88%E5%92%8C%E6%9C%AC%E5%9C%B0%E6%A0%88%EF%BC%8C%E7%A7%81%E6%9C%89%E6%A0%88%E4%B9%8B%E9%97%B4%E6%98%AF%E4%B8%8D%E5%85%B1%E4%BA%AB%E7%9A%84%EF%BC%8C%E6%9C%AC%E5%9C%B0%E6%A0%88%E4%B9%8B%E9%97%B4%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%85%B1%E4%BA%AB%E7%9A%84%E3%80%82%0A%0A%E2%80%8B%093.%20%E5%A0%86%E6%98%AF%E7%94%A8%E6%9D%A5%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE%E7%9A%84%EF%BC%8C%E6%A0%88%E6%98%AF%E7%94%A8%E6%9D%A5%E5%A4%84%E7%90%86%E9%80%BB%E8%BE%91%E7%9A%84%EF%BC%8C%E8%BF%99%E6%A0%B7%E7%9A%84%E5%A5%BD%E5%A4%84%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%B0%86%E6%95%B0%E6%8D%AE%E4%B8%8E%E9%80%BB%E8%BE%91%E5%A4%84%E7%90%86%E5%88%86%E7%A6%BB%E6%8F%90%E4%BA%A4%E5%A4%84%E7%90%86%E6%95%88%E7%8E%87%E3%80%82%0A%0A%E2%80%8B%09%E5%9B%A0%E4%B8%BA%E5%AF%B9%E5%A4%A7%E7%89%87%E5%86%85%E5%AD%98%E6%89%AB%E6%8F%8F%E6%95%88%E7%8E%87%E5%BE%88%E4%BD%8E%EF%BC%8C%E4%B8%BA%E4%BA%86%E6%9B%B4%E5%A5%BD%E7%9A%84%E8%BF%9B%E8%A1%8CGC%EF%BC%8C%E5%B0%86%E5%A0%86%E5%88%86%E4%B8%BA%E4%B8%89%E4%BB%A3%0A%0A%201.%20Young%20Generation%0A%0A%20%20%20%201.1%20Eden%20%3A%20%E5%AF%B9%E8%B1%A1%E9%A6%96%E5%85%88%E5%AD%98%E5%9C%A8Eden%E5%8C%BA%0A%20%20%20%201.2%20Survivor%200%3A%20Eden%E5%8C%BA%E6%BB%A1%E4%BA%86%E4%B9%8B%E5%90%8E%E5%86%8D%E5%B0%86%E5%AF%B9%E8%B1%A1%E5%A4%8D%E5%88%B6%E5%88%B0S0%0A%20%20%20%201.3%20Survivor%201%3A%20S0%E6%BB%A1%E4%BA%86%E4%B9%8B%E5%90%8E%E5%86%8D%E5%B0%86%E5%AF%B9%E8%B1%A1%E5%A4%8D%E5%88%B6%E5%88%B0S1%0A%0A%202.%20Old%20Generation%3A%20Survivor%E5%8C%BA%E6%BB%A1%E4%BA%86%E4%B9%8B%E5%90%8E%E5%86%8D%E5%B0%86%E5%AF%B9%E8%B1%A1%E5%A4%8D%E5%88%B6%E5%88%B0Old%20Generation%EF%BC%8C%20Old%20Generation%E5%A4%84%E7%90%86%E5%9C%A8Young%20Generation%E4%B8%AD%E9%80%9A%E8%BF%87GC%E5%9B%9E%E6%94%B6%E5%90%8E%E8%BF%98%E5%AD%98%E6%B4%BB%E7%9A%84%E5%AF%B9%E8%B1%A1%0A%0A%203.%20Permaneent%20Generation%20%2C%20JDK8%E4%B9%8B%E5%90%8E%E6%9B%B4%E5%90%8D%E4%B8%BAMetaspace%20%5B%E5%85%83%E7%A9%BA%E9%97%B4%5D%EF%BC%8C%20%E5%AD%98%E6%94%BE%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%E5%92%8C%E7%B1%BB%E3%80%82%0A%20%20%20%20%0A%204.%20Metaspace%EF%BC%9A%E5%85%83%E7%A9%BA%E9%97%B4%E6%98%AF%E6%9C%AC%E5%9C%B0%E5%86%85%E5%AD%98%E9%87%8C%E9%9D%A2%EF%BC%8C%E4%B8%BB%E8%A6%81%E8%A7%A3%E5%86%B3OOM%E5%8F%8A%E4%B8%8D%E6%96%B9%E4%BE%BF%E8%AE%BE%E7%BD%AE%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%0A%0A%23%23%23%23%23%203.2%20GC%20%E5%9B%9E%E6%94%B6%0A%0A%23%23%23%23%23%23%203.2.1%20%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%0A%0A%E2%80%8B%09%E5%9B%9E%E6%94%B6%E7%9A%84%E6%98%AF%E5%86%85%E5%AD%98%EF%BC%8C%E4%B8%BB%E8%A6%81%E5%AF%B9%E5%A0%86%E4%B8%AD%E7%9A%84%E4%B8%89%E4%BB%A3%E8%BF%9B%E8%A1%8C%E5%9B%9E%E6%94%B6%0A%E2%80%8B%09%E5%9B%9E%E6%94%B6%E5%88%86%E4%B8%BA%E4%B8%A4%E7%A7%8D%EF%BC%9A**Scavenge%20GC%20%2C%20Full%20GC**%0A%0A1.%20**Scavenge%20GC**%20%E4%B8%BB%E8%A6%81%E9%92%88%E5%AF%B9**Young%20Generation**%E8%BF%9B%E8%A1%8C%E5%9B%9E%E6%94%B6%EF%BC%8C%20%E5%85%88%E5%AF%B9**Edan**%E5%8C%BA%E8%BF%9B%E8%A1%8C%E5%9B%9E%E6%94%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%9B%9E%E6%94%B6%E5%AE%8C%E5%90%8E%E8%BF%98%E6%9C%89%E5%AD%98%E6%B4%BB%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BC%9A%E5%B0%86%E5%AF%B9%E8%B1%A1%E5%A4%8D%E5%88%B6%E5%88%B0**Survivor**%E5%8C%BA%EF%BC%8C%E7%94%B1%E4%BA%8EEdan%E5%AF%B9%E8%B1%A1%E5%8F%98%E5%8C%96%E5%BE%88%E9%A2%91%E7%B9%81%EF%BC%8C%E5%9B%A0%E6%AD%A4Young%20Generation%E4%BC%9A%E7%BB%8F%E5%B8%B8%E4%BD%BF%E7%94%A8Scavenge%20GC%E8%BF%9B%E8%A1%8C%E5%9B%9E%E6%94%B6%E3%80%82%0A%0A2.%20**Full%20GC**%20%E5%AF%B9%E4%B8%89%E4%BB%A3%E9%83%BD%E5%9B%9E%E8%BF%9B%E8%A1%8C%E5%9B%9E%E6%94%B6%EF%BC%8C%E4%BD%86%E7%94%B1%E4%BA%8Ejdk8%E4%B9%8B%E5%90%8E%E6%B2%A1%E6%9C%89Permanent%20Generation%EF%BC%8C%E5%8F%96%E5%B0%94%E4%BB%A3%E4%B9%8B%E7%9A%84%E6%98%AFmetaspace%EF%BC%8C%E6%89%80%E4%BB%A5%E5%8F%AA%E8%83%BDYoung%20Generation%E5%92%8COld%20Generation%E8%BF%9B%E8%A1%8C%E5%9B%9E%E6%94%B6%0A%0A3.%20%E5%9B%A0%E4%B8%BAFull%20GC%E5%9B%9E%E6%94%B6%E7%9A%84%E5%86%85%E5%AE%B9%E6%AF%94%E8%BE%83%E5%A4%9A%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%80%E8%88%AC%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%8D%E4%BC%9A%E9%A2%91%E7%B9%81%E8%A7%A6%E5%8F%91Full%20GC%EF%BC%8C%E5%8F%AA%E6%9C%89%E5%9C%A8%E5%A6%82%E4%B8%8B%E6%83%85%E5%86%B5%E4%B8%8B%E6%89%8D%E4%BC%9A%E8%A7%A6%E5%8F%91%0A%0A%20%20%20%3E%203.1%20%E5%B9%B4%E8%80%81%E4%BB%A3%E5%86%99%E6%BB%A1%EF%BC%8C%E6%AD%A4%E6%97%B6%E5%B9%B4%E8%BD%BB%E4%BB%A3%E8%82%AF%E5%AE%9A%E4%B9%9F%E5%86%99%E6%BB%A1%0A%20%20%20%3E%0A%20%20%20%3E%203.2%20%E6%8C%81%E4%B9%85%E4%BB%A3%E5%86%99%E6%BB%A1%0A%20%20%20%3E%0A%20%20%20%3E%203.3%20system.gc()%E8%A2%AB%E8%B0%83%E7%94%A8%0A%20%20%20%3E%0A%20%20%20%3E%203.4%20%E4%B8%8A%E4%B8%80%E6%AC%A1GC%E5%90%8E%EF%BC%8Cheap%E5%88%86%E9%85%8D%E7%9A%84%E7%AD%96%E7%95%A5%E9%87%8D%E6%96%B0%E5%88%86%E9%85%8D%E4%BA%86%0A%0A%23%23%23%23%23%23%203.2.2%20%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95%0A%0A%20%201.%20%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0%0A%0A%20%20%20%20%20%3E%20%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BC%95%E7%94%A8%E8%BF%9B%E8%A1%8C%E8%AE%A1%E6%95%B0%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%AF%B9%E6%AD%A4%E5%AF%B9%E8%B1%A1%E5%BC%95%E7%94%A8%E4%B8%80%E6%AC%A1%EF%BC%8C%E5%88%99%E8%AE%B0%E6%95%B0%E5%A2%9E%E5%8A%A01%EF%BC%8C%E5%A6%82%E6%98%AF%E5%BC%95%E7%94%A8%E9%87%8A%E6%94%BE%E5%88%99%E5%87%8F1%3B%20%E5%A6%82%E6%9E%9C%E5%AF%B9%E8%B1%A1%E7%9A%84%E8%AE%B0%E6%95%B0%E4%B8%BA0%EF%BC%8C%E5%88%99%E8%A1%A8%E7%A4%BA%E6%AD%A4%E5%AF%B9%E8%B1%A1%E9%9C%80%E8%A6%81%E8%BF%9B%E8%A1%8C%E5%9B%9E%E5%A4%84%E7%90%86%E3%80%82%20%0A%0A%20%202.%20%E6%A0%87%E8%AE%B0%E6%B8%85%E9%99%A4%0A%0A%20%20%20%20%20%3E%20%E6%AD%A4%E7%AE%97%E6%B3%95%E4%BC%9A%E4%B8%8D%E6%96%AD%E7%9A%84%E6%89%AB%E6%8F%8F**GC%20Roots**%2C%20%E5%B0%86%E5%AD%98%E6%B4%BB%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%A0%87%E8%AE%B0%E5%87%BA%E6%9D%A5%EF%BC%8C%E7%AD%89%E5%88%B0%E4%B8%8D%E7%94%A8%E7%9A%84%E6%97%B6%E5%80%99%E5%86%8D%E6%B8%85%E9%99%A4%2C%20%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E6%95%88%E7%8E%87%E4%BD%8E%EF%BC%8C%E6%B8%85%E9%99%A4%E5%AE%8C%E5%90%8E%E5%86%85%E5%AD%98%E4%B8%8D%E4%BC%9A%E8%BF%9E%E7%BB%AD%E5%9C%A8%E4%B8%80%E5%9D%97%EF%BC%8C%E5%BD%A2%E6%88%90%E5%86%85%E5%AD%98%E7%A2%8E%E7%89%87%E3%80%82%0A%0A%20%203.%20%E5%A4%8D%E5%88%B6%E7%AE%97%E6%B3%95%0A%0A%20%20%20%20%20%3E%20%E5%B0%86%E5%86%85%E5%AD%98%E5%88%86%E4%B8%BA%E4%B8%A4%E4%BB%BD%EF%BC%8C%E6%AF%8F%E6%AC%A1%E5%8F%AA%E4%BD%BF%E7%94%A8%E5%85%B6%E4%B8%AD%E7%9A%84%E4%B8%80%E4%BB%BD%E5%86%85%E5%AD%98%EF%BC%8C%E5%BD%93%E5%9B%9E%E6%94%B6%E5%AE%8C%E6%88%90%E4%B9%8B%E5%90%8E%EF%BC%8C%E5%B0%86%E5%9B%9E%E6%94%B6%E5%88%B0%E7%9A%84%E5%86%85%E5%AE%B9%E5%85%A8%E9%83%A8%E6%8B%BC%E6%8E%A5%E5%88%B0%E6%9C%AA%E4%BD%BF%E7%94%A8%E7%9A%84%E9%82%A3%E4%B8%80%E4%BB%BD%E5%86%85%E5%AD%98%E4%B8%8A%E9%9D%A2%2C%E8%BF%99%E6%A0%B7%E6%95%88%E7%8E%87%E9%AB%98%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%86%85%E5%AD%98%E7%A2%8E%E7%89%87%0A%0A%23%23%23%23%23%23%203.2.3%20%E5%9B%9E%E6%94%B6%E5%99%A8%0A%0A%201.%20%E4%B8%B2%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8%0A%0A%20%20%20%20%3E%20%20%E5%B9%B4%E8%BD%BB%E4%BB%A3%E5%92%8C%E5%B9%B4%E8%80%81%E4%BB%A3%E9%83%BD%E4%B8%B2%E8%A1%8C%EF%BC%8C%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%9C%A8%E5%B7%A5%E4%BD%9C%EF%BC%8C%E6%97%A0%E9%9C%80%E7%BA%BF%E7%A8%8B%E4%BA%A4%E4%BA%92%EF%BC%8C%E6%89%80%E4%BB%A5%E6%95%88%E7%8E%87%E9%AB%98%EF%BC%8C%E4%BD%86%E6%98%AF%E6%97%A0%E6%B3%95%E5%8F%91%E6%8C%A5%E5%A4%9A%E5%A4%84%E7%90%86%E5%99%A8%E7%9A%84%E4%BC%98%E5%8A%BF%E3%80%82%0A%20%20%20%20%3E%0A%20%20%20%20%3E%20%20%E9%80%9A%E5%B8%B8%E5%9C%A8%E5%B0%8F%E6%95%B0%E6%8D%AE%E9%87%8F%E3%80%90100M%E5%B7%A6%E5%8F%B3%E3%80%91%E7%9A%84%E5%A4%9A%E5%A4%84%E7%90%86%E5%99%A8%E7%9A%84%E6%9C%BA%E5%99%A8%E4%B8%8A%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E4%B8%B2%E8%A1%8C%0A%20%20%20%20%3E%0A%20%20%20%20%3E%20%20%E4%BD%BF%E7%94%A8%20**-XX%3A%2BUseSerialGC**%20%E6%89%93%E5%BC%80%E4%B8%B2%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8%0A%0A%202.%20%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8%0A%0A%20%20%20%20%3E%20%E5%9C%A8%E5%B9%B4%E8%BD%BB%E4%BB%A3%E5%A4%84%E7%90%86%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%A4%84%E7%90%86%EF%BC%8C%E5%B9%B4%E8%80%81%E4%BB%A3%E4%BB%8D%E7%84%B6%E4%B8%BA%E4%B8%B2%E8%A1%8C%EF%BC%8C%E4%BC%9A%E5%88%B6%E7%BA%A6%E5%9B%9E%E6%94%B6%E8%83%BD%E5%8A%9B%0A%20%20%20%20%3E%0A%20%20%20%20%3E%20%E4%BD%BF%E7%94%A8%20**-XX%3A%2BUseParallelGC**%20%20%E6%89%93%E5%BC%80%E5%B9%B4%E8%BD%BB%E4%BB%A3%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8%0A%20%20%20%20%3E%0A%20%20%20%20%3E%20%0A%0A%203.%20%E5%B9%B6%E5%8F%91%E5%9B%9E%E6%94%B6%E5%99%A8%0A%0A%20%20%20%20%3E%20%E5%9C%A8%E5%B9%B4%E8%BD%BB%E4%BB%A3%E5%A4%84%E7%90%86%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%A4%84%E7%90%86%E7%9A%84%E5%90%8C%E6%97%B6%E5%B0%86%E5%B9%B4%E8%80%81%E4%BB%A3%E8%AE%BE%E7%BD%AE%E4%B8%BA%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%0A%20%20%20%20%3E%0A%20%20%20%20%3E%20%E4%BD%BF%E7%94%A8%20**-XX%3A%2BUseParallelOldGC**%20%20%E6%89%93%E5%BC%80%E5%B9%B4%E8%80%81%E4%BB%A3%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8%0A%20%20%20%20%3E%0A%20%20%20%20%3E%20%E4%BD%BF%E7%94%A8%20**-XX%3AParallelGCTheads%3Dn**%20%E8%AE%BE%E7%BD%AE%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%95%B0%EF%BC%8C%E6%AD%A4%E5%80%BC%E4%B8%80%E8%88%AC%E8%AE%BE%E7%BD%AE%E4%B8%BA%E4%B8%8E%E5%A4%84%E7%90%86%E5%99%A8%E6%95%B0%E7%9B%B8%E7%AD%89%0A%0A%0A%0A%23%23%23%23%23%203.3%20JVM%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE%0A%0A%E4%BF%AE%E6%94%B9JVM%E5%8F%82%E6%95%B0%E7%9A%84%E6%96%B9%E5%BC%8F%0A%0A1.%20eclipse%0A%0A2.%20%E4%BF%AE%E6%94%B9tomcat%E4%B8%AD%E7%9A%84%E6%96%87%E4%BB%B6%0A%0A%20%20%202.1%20bin%2Fcatalina.sh%0A%0A%20%20%202.2%20bin%2Fstartup.sh%20%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%81%9C%E6%AD%A2%E4%B9%8B%E5%90%8E%E4%BF%AE%E6%94%B9%E7%9A%84JVM%E5%80%BC%E8%BF%98%E6%98%AF%E7%94%9F%E6%95%88%E7%9A%84%0A%0A%20%20%20%E6%AF%8F%E4%B8%AA%E5%8F%82%E6%95%B0%E7%94%A8%E7%A9%BA%E6%A0%BC%E9%9A%94%E5%BC%80%EF%BC%8C%E5%8F%82%E6%95%B0%E5%8C%BA%E5%88%86%E5%A4%A7%E5%B0%8F%E5%86%99%0A%0A%20%20%20%60%60%60%0A%20%20%20%E7%AC%AC%E4%B8%80%E7%A7%8D%E8%AF%AD%E6%B3%95%0A%20%20%20set%20CATALINA_OPTS%20%3D%20-Xmx512m%20-Xms512m%20-XX%3ASurvivorRatio%3D3%20-XX%3ANewSize%3D250m%20-XX%3AMetaspaceSize%3D300m%0A%20%20%20%0A%20%20%20%E7%AC%AC%E4%BA%8C%E7%A7%8D%E8%AF%AD%E6%B3%95%0A%20%20%20set%20JAVA_OPTS%20%3D%20-Xmx512m%20-Xms512m%20-XX%3ASurvivorRatio%3D3%20-XX%3ANewSize%3D250m%20-XX%3AMetaspaceSize%3D300m%0A%20%20%20%0A%20%20%20%E7%AC%AC%E4%B8%89%E7%A7%8D%E8%AF%AD%E6%B3%95%0A%20%20%20JAVA_OPTS%20%3D%20%22-Xmx512m%20-Xms512m%20-XX%3ASurvivorRatio%3D3%20-XX%3ANewSize%3D250m%20-XX%3AMetaspaceSize%3D300m%22%0A%20%20%20%60%60%60%0A%0A%E4%BE%8B%EF%BC%9A%0A%60%60%60%0AJAVA_OPTS%3D%20%22-Xms2048M%20-Xmx2048M%20-XX%3A%2BPrintGCDetails%20%0A-XX%3A%2BPrintGCDateStamps%20-Xloggc%3A%24%7BBAYMAX_APP_WORKDIR%7D%2Flogs%2Fgc-%25t.log%20%0A-XX%3A%2BUseGCLogFileRotation%20-XX%3ANumberOfGCLogFiles%3D14%20%0A-XX%3AGCLogFileSize%3D100M%20-XX%3A%2BHeapDumpOnOutOfMemoryError%20%0A-XX%3AHeapDumpPath%3D%24%7BBAYMAX_APP_WORKDIR%7D%2Flogs%2F%22%0A%60%60%60%0A%0A%0A%23%23%23%23%23%23%20%09%093.3.1%20heap%20%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0%0A%0A%60%60%60%0A-Xms%3A%20%E5%88%9D%E5%A7%8B%E5%A0%86%E5%A4%A7%E5%B0%8F%0A-Xmx%3A%20%E6%9C%80%E5%A4%A7%E5%A0%86%E5%A4%A7%E5%B0%8F%0A%E5%88%9D%E5%A7%8B%E5%A0%86%E5%A4%A7%E5%B0%8F%E4%B8%80%E8%88%AC%E8%AE%BE%E7%BD%AE%E4%B8%8E%E6%9C%80%E5%9C%A8%E5%A0%86%E5%A4%A7%E5%B0%8F%E4%B8%80%E8%87%B3%0A%0A-XX%3ANewSize%3Dn%20%E8%AE%BE%E7%BD%AE%E5%B9%B4%E8%BD%BB%E4%BB%A3%E5%A4%A7%E5%B0%8F%0A-XX%3AMaxNewSize%3Dn%20%E8%AE%BE%E7%BD%AE%E5%B9%B4%E8%BD%BB%E4%BB%A3%E6%9C%80%E5%A4%A7%E7%A9%BA%E9%97%B4%E5%A4%A7%E5%B0%8F%0A-XX%3ANewRatio%3Dn%20%E8%AE%BE%E7%BD%AE%E5%B9%B4%E8%BD%BB%E4%BB%A3%E4%B8%8E%E5%B9%B4%E8%80%81%E4%BB%A3%E7%9A%84%E6%AF%94%E4%BE%8B%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%BA3%EF%BC%8C%E5%B9%B4%E8%BD%BB%E4%BB%A3%3A%E5%B9%B4%E8%80%81%E4%BB%A3%3D1%EF%BC%9A3%20%2C%20%E8%A1%A8%E7%A4%BA%E5%B9%B4%E8%BD%BB%E4%BB%A3%E5%8D%A0%E5%B9%B4%E8%BD%BB%E4%BB%A3%E5%92%8C%E5%B9%B4%E8%80%81%E4%BB%A3%E6%80%BB%E5%92%8C%E7%9A%841%2F4%0A%0A-XX%3ASurvivorRatio%3Dn%20%E8%AE%BE%E7%BD%AE%E5%B9%B4%E8%BD%BB%E4%BB%A3%E4%B8%ADEden%E5%8C%BA%E4%B8%8E%E4%B8%A4%E4%B8%AAsurvivor%E5%8C%BA%E7%9A%84%E6%AF%94%E4%BE%8B%EF%BC%8Ceden%3Asurvivor%3D3%3A2%2C%20%E4%B8%80%E4%B8%AAsurvivor%E5%8D%A0%E6%95%B4%E4%B8%AA%E5%B9%B4%E8%BD%BB%E4%BB%A3%E7%9A%841%2F5%0A-XX%3AMaxPermSize%3Dn%20%E8%AE%BE%E7%BD%AE%E6%8C%81%E4%B9%85%E4%BB%A3%E5%A4%A7%E5%B0%8F%0A-Xss%3A%E8%AE%BE%E7%BD%AE%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%A0%86%E5%A4%A7%E5%B0%8F%0A%0A%E6%80%BB%E5%86%85%E5%AD%98%E5%A4%A7%E5%B0%8F%EF%BC%9A%0AMax%20memory%20%3D%20%5B-Xmx%5D%20%2B%20%5B-XX%3AMaxPermSize%5D%20%2B%20number_of_threads%20*%20%5B-Xss%5D%0A%0A%60%60%60%0A!%5B9a8af0bbbe89099769c8dd62d36f1e22.png%5D(en-resource%3A%2F%2Fdatabase%2F577%3A1)%0A%0A%0A%23%23%23%23%23%23%203.3.2%20metaspace%20%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE%0A%0A%60%60%60%0A-XX%3AMetasapceSize%20%20%E5%88%9D%E5%A7%8B%E5%85%83%E7%A9%BA%E9%97%B4%E5%A4%A7%E5%B0%8F%EF%BC%8C%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E8%BE%BE%E5%88%B0%E8%AF%A5%E5%80%BC%E6%97%B6%E5%B0%B1%E4%BC%9A%E8%A7%A6%E5%8F%91%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%EF%BC%8C%E5%90%8C%E6%97%B6GC%E4%BC%9A%E5%AF%B9%E8%AF%A5%E5%80%BC%E8%BF%9B%E8%A1%8C%E8%B0%83%E6%95%B4%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%87%8A%E6%94%BE%E5%A4%A7%E9%87%8F%E7%9A%84%E7%A9%BA%E9%97%B4%E5%B0%B1%E9%80%82%E5%BD%93%E4%B8%8B%E8%B0%83%E8%AF%A5%E5%80%BC%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%87%8A%E6%94%BE%E5%BE%88%E5%B0%91%E7%9A%84%E7%A9%BA%E9%97%B4%E5%88%99%E5%9C%A8%E4%B8%8D%E8%B6%85%E8%BF%87MaxMetaspaceSize%E5%89%8D%E6%8F%90%E4%B8%8B%EF%BC%8C%E4%B8%8A%E8%B0%83%E8%AF%A5%E5%80%BC%E3%80%82%0A%0A-XX%3AMaxMetaspaceSize%20%E6%9C%80%E5%A4%A7%E5%85%83%E7%A9%BA%E9%97%B4%E5%A4%A7%E5%B0%8F%EF%BC%8C%E9%BB%98%E8%AE%A4%E6%B2%A1%E6%9C%89%E9%99%90%E5%88%B6%0A%0A-XX%3AMinMetaspaceFreeRatio%20%E5%9C%A8GC%E4%B9%8B%E5%90%8E%EF%BC%8C%E6%9C%80%E5%B0%8F%E7%9A%84Metaspace%E5%89%A9%E4%BD%99%E7%A9%BA%E9%97%B4%E5%AE%B9%E9%87%8F%E7%9A%84%E7%99%BE%E5%88%86%E6%AF%94%EF%BC%8C%E5%87%8F%E5%B0%91%E4%B8%BA%E5%88%86%E9%85%8D%E7%A9%BA%E9%97%B4%E6%89%80%E5%AF%BC%E8%87%B4%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%0A%0A-XX%3AMaxMetaspaceFreeRatio%20%E5%9C%A8GC%E4%B9%8B%E5%90%8E%EF%BC%8C%E6%9C%80%E5%A4%A7%E7%9A%84Metaspace%E5%89%A9%E4%BD%99%E7%A9%BA%E9%97%B4%E5%AE%B9%E9%87%8F%E7%9A%84%E7%99%BE%E5%88%86%E6%AF%94%EF%BC%8C%E5%87%8F%E5%B0%91%E4%B8%BA%E5%88%86%E9%85%8D%E7%A9%BA%E9%97%B4%E6%89%80%E5%AF%BC%E8%87%B4%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%203.3.3%20%20%E6%94%B6%E9%9B%86%E5%99%A8%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE%0A%0A%60%60%60%0A-XX%3A%2BUseSerialGC%20%E8%AE%BE%E7%BD%AE%E4%B8%B2%E8%A1%8C%E6%94%B6%E9%9B%86%E5%99%A8%0A%0A-XX%3A%2BUseParallelGC%20%E8%AE%BE%E7%BD%AE%E5%B9%B6%E8%A1%8C%E6%94%B6%E9%9B%86%E5%99%A8%0A%0A-XX%3A%2BUseParallelOldGC%20%E8%AE%BE%E7%BD%AE%E5%B9%B6%E8%A1%8C%E5%B9%B4%E8%80%81%E4%BB%A3%E6%94%B6%E9%9B%86%E5%99%A8%0A%0A-XX%3A%2BUseConcMarkSweepGC%20%E8%AE%BE%E7%BD%AE%E5%B9%B6%E5%8F%91%E6%94%B6%E9%9B%86%E5%99%A8%0A%60%60%60%0A%0A%23%23%23%23%23%23%203.3.4%20%20%E6%9F%A5%E7%9C%8B%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE%E6%98%AF%E5%90%A6%E6%88%90%E5%8A%9F%0A%0A%60%60%60%0Aps%20aux%20%7C%20grep%20tomcat%0A%60%60%60%0A

arthas

创建时间:2021/11/23 17:49
更新时间:2023/3/26 14:29
作者:Chris

1. 概述

1.1 arthas是什么

Alibaba开源的Java诊断工具
当遇到如下问题时,Arthas可以帮助你解决:

- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
- 怎样直接从JVM内查找某个类的实例?

1.2 运行环境要求

1.3 文档

2. 安装

2.1 在windows下在线安装

创建目录

C:\chris\arthas
进入此目录下载文件

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

在运行java -jar arthas-boot.jar之前需要确保内存中有一个java进程,idea,mvn,tomcat都是一个java进程,否则会报找不到java进程错误

如果通过jps命令找不到jvm进程,解决办法见【jps找不到jvm进程】

第一次下载时遇到如下问题,但是第二次再试就Ok了

$ java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.4
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 10228 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [2]: 31736 org.jetbrains.jps.cmdline.Launcher
  [3]: 30620
3
[INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/3.5.4?mirror=aliyun
[INFO] File size: 12.72 MB, downloaded size: 4.17 MB, downloading ...
[INFO] File size: 12.72 MB, downloaded size: 10.49 MB, downloading ...
[INFO] Download arthas success.
[INFO] arthas home: C:\Users\13622314539\.arthas\lib\3.5.4\arthas
[INFO] Try to attach process 30620
[WARN] Current VM java version: 1.8 do not match target VM java version: 11, attach may fail.
[WARN] Target VM JAVA_HOME is C:\Program Files\JetBrains\IntelliJ IDEA 2020.1.1\jbr, arthas-boot JAVA_HOME is C:\Program Files\Java\jdk1.8.0_131\jre, try to set the same JAVA_HOME.
[ERROR] Start arthas failed, exception stack trace:
java.io.IOException: Non-numeric value found - int expected
        at sun.tools.attach.HotSpotVirtualMachine.readInt(HotSpotVirtualMachine.java:299)
        at sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:63)
        at sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:79)
        at sun.tools.attach.HotSpotVirtualMachine.loadAgent(HotSpotVirtualMachine.java:103)
        at com.taobao.arthas.core.Arthas.attachAgent(Arthas.java:120)
        at com.taobao.arthas.core.Arthas.<init>(Arthas.java:26)
        at com.taobao.arthas.core.Arthas.main(Arthas.java:139)
[ERROR] attach fail, targetPid: 30620

$ java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.4
[INFO] Process 30620 already using port 3658
[INFO] Process 30620 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 30620
  [2]: 10228 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [3]: 31736 org.jetbrains.jps.cmdline.Launcher
1
[INFO] arthas home: C:\Users\13622314539\.arthas\lib\3.5.4\arthas
[INFO] The target process already listen port 3658, skip attach.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'


wiki       https://arthas.aliyun.com/doc
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
version    3.5.4
main_class
pid        30620
time       2021-11-03 15:05:15

可以看到arthas安装包下载到了目录

arthas home: C:\Users\13622314539\.arthas\lib\3.5.4\arthas

在C:\Users\13622314539下有两个目录和arthas有关

如果启动时端口号被占用,可以用如下命令更换端口号

$ java -jar arthas-boot.jar --telnet-port 9090 --http-port 8090

启动后arthas支持游览器查看

http://localhost:3658/

2.2 在Linux下在线安装

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

在运行java -jar arthas-boot.jar之前需要确保内存中有一个java进程,idea,mvn,tomcat都是一个java进程,否则会报找不到java进程错误

在家目录下可以看到与arthas相关的两个目录

cd ~
ls -a 
- .arthas
- logs

2.3 离线安装

https://arthas.aliyun.com/doc/en/download.html#download-from-maven-central

3 卸载arthas

3.1 在windows下卸载

在C:\Users\13622314539下有两个目录和arthas有关

直接手动删除就可以完成在windows下的卸载

3.2 在liunx下卸载

rm -rf ~/.arthas
rm -rf ~/logs

4 attach一个进程

4.1 启动jar包

进行目录,启动需要被诊断的进程
C:\Users\13622314539\.arthas\lib\3.5.4\arthas

启动math-game.jar
java -jar math-game.jar

4.2 启动arthas

选择需要被诊断的进程math-game,会自动attach成功

13622314539@OC136223145391 MINGW64 /c/chris/arthas
$ java -jar arthas-boot.jar --telnet-port 9090 --http-port 8090
[INFO] arthas-boot version: 3.5.4
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 33616 math-game.jar
  [2]: 10228 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [3]: 31736 org.jetbrains.jps.cmdline.Launcher
  [4]: 30620
1
[INFO] arthas home: C:\Users\13622314539\.arthas\lib\3.5.4\arthas
[INFO] Try to attach process 33616
[INFO] Attach process 33616 success.
[INFO] arthas-client connect 127.0.0.1 9090
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'


wiki       https://arthas.aliyun.com/doc
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
version    3.5.4
main_class
pid        33616
time       2021-11-03 16:14:36

[arthas@33616]$

5 常用命令

5.1 dashboard 面板

第一部分显示当前进程中运行的所有线程
第二部分显示JVM的内存使用情况
第三部分显示操作系统信息和JAVA版本号

5.2 thread

[arthas@18824]$ thread
[arthas@30620]$ thread 1
"main" Id=1 RUNNABLE

5.3 jad 反编译class文件

[arthas@33616]$ jad demo.MathGame
jad demo.MathGame

ClassLoader:
+-sun.misc.Launcher$AppClassLoader@42a57993 -- 程序加载器
  +-sun.misc.Launcher$ExtClassLoader@544bdaf7 -- 扩展加载器

Location: -- 定位到相应的jar包
/C:/Users/13622314539/.arthas/lib/3.5.4/arthas/math-game.jar

-- 反编译原代码
       /*
        * Decompiled with CFR.
        */
       package demo;

5.4 watch 监视

通过watch命令可以查看方法的入参和返回值分别是什么

watch package.class method returnObj

[arthas@18824]$ watch demo.MathGame primeFactors returnObj

method=demo.MathGame.primeFactors location=AtExit
ts=2021-11-11 14:50:00; [cost=0.0738ms] result=@ArrayList[
    @Integer[2],
    @Integer[5],
    @Integer[5],
    @Integer[2287],
]

5.5 退出arthas

6 基础命令

6.1 help

help 查看命令帮助信息

[arthas@18824]$ help
NAME         DESCRIPTION
 help         Display Arthas Help
 auth         Authenticates the current session
 keymap       Display all the available keymap for the specified connection.

6.2 cat

打印某个文件的内容, 如果没有写路径则显示当前目录下的文件

在C:\Users\13622314539\.arthas\lib\3.5.4\arthas目录下新增文件test.txt

[arthas@18824]$ cat test.txt
cat test.txt
dddd
[arthas@18824]$

6.3 grep

匹配查找

参数列表作用
-n显示行号
-i忽略大小写
-m最大显示行数,要与查询字符串一起使用
-e使用正则表达式

只显示包含java字符串的系统属性

[arthas@18824]$ sysprop | grep java

显示包含java字符串的行和行号的系统属性

[arthas@18824]$ sysprop | grep -n java

显示包含system字符串的前10行系统属性

[arthas@18824]$ sysprop | grep -m 10 java

6.4 pwd

打印当前工作目录路径

6.5 cls

清屏

6.6 session

查看当前会话的信息, 两个会话可以同时监听同一个PID

[arthas@21904]$ session
session
 Name        Value
--------------------------------------------------
 JAVA_PID    21904
 SESSION_ID  c54d94b2-f155-4db1-8a51-8ab7dd09a03a
[arthas@21904]$

6.7 reset

重置增强类,将被arthas增强过的类全部还原,Arthas服务端关闭时会重置所有增强过的类

6.8 version

输出当前java进程所加载的arthas的版本号

[arthas@21904]$ version
version
3.5.4

6.9 history

输出arthas的命令历史

[arthas@21904]$ history
history
    1  dashboard
    2  cls
    3  thread
    4  cls
    5  thead
    6  thread
    7  thread 1
    8  jad demo.MathGame
    9  jad demo.MathGame
   10  jad demo.MathGame
   11  jad demo.MathGame
   12  dashboard

6.10 keymap

输出arthas快捷键列表及自定义快捷键

[arthas@21904]$ keymap
keymap
 Shortcut            Description         Name
-------------------------------------------------------------------------------
 "\C-a"              Ctrl + a             beginning-of-line
 "\C-e"              Ctrl + e             end-of-line
 "\C-f"              Ctrl + f             forward-word
 "\C-b"              Ctrl + b             backward-word
 "\e[D"              Left arrow           backward-char
 "\e[C"              Right arrow          forward-char
 "\e[A"              Up arrow             history-search-backward
 "\e[B"              Down arrow           history-search-forward
 "\C-h"              Ctrl + h             backward-delete-char

6.11 trace

[arthas@21904]$ trace demo.MathGame print
trace demo.MathGame print
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 301 ms, listenerId: 1
`---ts=2021-11-23 16:25:27;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@42a57993
    `---[0.7906ms] demo.MathGame:print()

`---ts=2021-11-23 16:25:28;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@42a57993
    `---[0.1149ms] demo.MathGame:print()

7 jvm相关命令

7.1 dashboard

%5Btoc%5D%0A%0A%23%23%201.%20%E6%A6%82%E8%BF%B0%0A%23%23%23%201.1%20arthas%E6%98%AF%E4%BB%80%E4%B9%88%0AAlibaba%E5%BC%80%E6%BA%90%E7%9A%84Java%E8%AF%8A%E6%96%AD%E5%B7%A5%E5%85%B7%0A%E5%BD%93%E9%81%87%E5%88%B0%E5%A6%82%E4%B8%8B%E9%97%AE%E9%A2%98%E6%97%B6%EF%BC%8CArthas%E5%8F%AF%E4%BB%A5%E5%B8%AE%E5%8A%A9%E4%BD%A0%E8%A7%A3%E5%86%B3%EF%BC%9A%0A%0A%60%60%60%0A-%20%E8%BF%99%E4%B8%AA%E7%B1%BB%E4%BB%8E%E5%93%AA%E4%B8%AA%20jar%20%E5%8C%85%E5%8A%A0%E8%BD%BD%E7%9A%84%EF%BC%9F%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E6%8A%A5%E5%90%84%E7%A7%8D%E7%B1%BB%E7%9B%B8%E5%85%B3%E7%9A%84%20Exception%EF%BC%9F%0A-%20%E6%88%91%E6%94%B9%E7%9A%84%E4%BB%A3%E7%A0%81%E4%B8%BA%E4%BB%80%E4%B9%88%E6%B2%A1%E6%9C%89%E6%89%A7%E8%A1%8C%E5%88%B0%EF%BC%9F%E9%9A%BE%E9%81%93%E6%98%AF%E6%88%91%E6%B2%A1%20commit%EF%BC%9F%E5%88%86%E6%94%AF%E6%90%9E%E9%94%99%E4%BA%86%EF%BC%9F%0A-%20%E9%81%87%E5%88%B0%E9%97%AE%E9%A2%98%E6%97%A0%E6%B3%95%E5%9C%A8%E7%BA%BF%E4%B8%8A%20debug%EF%BC%8C%E9%9A%BE%E9%81%93%E5%8F%AA%E8%83%BD%E9%80%9A%E8%BF%87%E5%8A%A0%E6%97%A5%E5%BF%97%E5%86%8D%E9%87%8D%E6%96%B0%E5%8F%91%E5%B8%83%E5%90%97%EF%BC%9F%0A-%20%E7%BA%BF%E4%B8%8A%E9%81%87%E5%88%B0%E6%9F%90%E4%B8%AA%E7%94%A8%E6%88%B7%E7%9A%84%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86%E6%9C%89%E9%97%AE%E9%A2%98%EF%BC%8C%E4%BD%86%E7%BA%BF%E4%B8%8A%E5%90%8C%E6%A0%B7%E6%97%A0%E6%B3%95%20debug%EF%BC%8C%E7%BA%BF%E4%B8%8B%E6%97%A0%E6%B3%95%E9%87%8D%E7%8E%B0%EF%BC%81%0A-%20%E6%98%AF%E5%90%A6%E6%9C%89%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E8%A7%86%E8%A7%92%E6%9D%A5%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E7%9A%84%E8%BF%90%E8%A1%8C%E7%8A%B6%E5%86%B5%EF%BC%9F%0A-%20%E6%9C%89%E4%BB%80%E4%B9%88%E5%8A%9E%E6%B3%95%E5%8F%AF%E4%BB%A5%E7%9B%91%E6%8E%A7%E5%88%B0JVM%E7%9A%84%E5%AE%9E%E6%97%B6%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81%EF%BC%9F%0A-%20%E6%80%8E%E4%B9%88%E5%BF%AB%E9%80%9F%E5%AE%9A%E4%BD%8D%E5%BA%94%E7%94%A8%E7%9A%84%E7%83%AD%E7%82%B9%EF%BC%8C%E7%94%9F%E6%88%90%E7%81%AB%E7%84%B0%E5%9B%BE%EF%BC%9F%0A-%20%E6%80%8E%E6%A0%B7%E7%9B%B4%E6%8E%A5%E4%BB%8EJVM%E5%86%85%E6%9F%A5%E6%89%BE%E6%9F%90%E4%B8%AA%E7%B1%BB%E7%9A%84%E5%AE%9E%E4%BE%8B%EF%BC%9F%0A%60%60%60%0A%0A%0A%0A%23%23%23%201.2%20%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E8%A6%81%E6%B1%82%0A-%20Arthas%E6%94%AF%E6%8C%81jdk1.6%2B%20%0A-%20Mac%2FLinux%2FWindows%0A-%20%E9%87%87%E7%94%A8%E5%91%BD%E4%BB%A4%E4%BA%A4%E4%BA%92%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%90%8C%E6%97%B6%E6%8F%90%E4%BE%9B%E4%B8%B0%E5%AF%8C%E7%9A%84Tab%E8%87%AA%E5%8A%A8%E8%A1%A5%E5%85%A8%E5%8A%9F%E8%83%BD%0A%0A%23%23%23%201.3%20%E6%96%87%E6%A1%A3%0A-%20%E5%BC%80%E6%BA%90%E5%9C%B0%E5%9D%80%20%0Ahttps%3A%2F%2Fgithub.com%2Falibaba%2Farthas%0A-%20%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%20%0Ahttps%3A%2F%2Farthas.aliyun.com%2Fdoc%2F%0A-%20%E5%8F%82%E8%80%83%E5%8D%9A%E5%AE%A2%20%0Ahttps%3A%2F%2Fblog.csdn.net%2Fmonokai%2Farticle%2Fdetails%2F107457772%0Ahttps%3A%2F%2Fmofan212.github.io%2Fposts%2FQuick-Start-To-Arthas%2F%0A-%20Arthas%E8%84%91%E5%9B%BE%E2%80%94%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E6%B1%87%E6%80%BB%20%0Ahttps%3A%2F%2Fgithub.com%2Falibaba%2Farthas%2Fissues%2F1003%0A%0A%0A%23%23%202.%20%E5%AE%89%E8%A3%85%0A%0A%23%23%23%202.1%20%E5%9C%A8windows%E4%B8%8B%E5%9C%A8%E7%BA%BF%E5%AE%89%E8%A3%85%0A%E5%88%9B%E5%BB%BA%E7%9B%AE%E5%BD%95%0A%3E%20C%3A%5Cchris%5Carthas%20%20%0A%3E%20%E8%BF%9B%E5%85%A5%E6%AD%A4%E7%9B%AE%E5%BD%95%E4%B8%8B%E8%BD%BD%E6%96%87%E4%BB%B6%0A%60%60%60%0Acurl%20-O%20https%3A%2F%2Farthas.aliyun.com%2Farthas-boot.jar%0Ajava%20-jar%20arthas-boot.jar%0A%60%60%60%0A%3E%E5%9C%A8%E8%BF%90%E8%A1%8Cjava%20-jar%20arthas-boot.jar%E4%B9%8B%E5%89%8D%E9%9C%80%E8%A6%81%E7%A1%AE%E4%BF%9D%E5%86%85%E5%AD%98%E4%B8%AD%E6%9C%89%E4%B8%80%E4%B8%AAjava%E8%BF%9B%E7%A8%8B%2Cidea%2Cmvn%2Ctomcat%E9%83%BD%E6%98%AF%E4%B8%80%E4%B8%AAjava%E8%BF%9B%E7%A8%8B%EF%BC%8C%E5%90%A6%E5%88%99%E4%BC%9A%E6%8A%A5%E6%89%BE%E4%B8%8D%E5%88%B0java%E8%BF%9B%E7%A8%8B%E9%94%99%E8%AF%AF%0A%0A%3E%E5%A6%82%E6%9E%9C%E9%80%9A%E8%BF%87jps%E5%91%BD%E4%BB%A4%E6%89%BE%E4%B8%8D%E5%88%B0jvm%E8%BF%9B%E7%A8%8B%EF%BC%8C%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%E8%A7%81%E3%80%90jps%E6%89%BE%E4%B8%8D%E5%88%B0jvm%E8%BF%9B%E7%A8%8B%E3%80%91%0A%0A%0A%3E%20%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B8%8B%E8%BD%BD%E6%97%B6%E9%81%87%E5%88%B0%E5%A6%82%E4%B8%8B%E9%97%AE%E9%A2%98%EF%BC%8C%E4%BD%86%E6%98%AF%E7%AC%AC%E4%BA%8C%E6%AC%A1%E5%86%8D%E8%AF%95%E5%B0%B1Ok%E4%BA%86%0A%60%60%60%0A%24%20java%20-jar%20arthas-boot.jar%0A%5BINFO%5D%20arthas-boot%20version%3A%203.5.4%0A%5BINFO%5D%20Found%20existing%20java%20process%2C%20please%20choose%20one%20and%20input%20the%20serial%20number%20of%20the%20process%2C%20eg%20%3A%201.%20Then%20hit%20ENTER.%0A*%20%5B1%5D%3A%2010228%20org.jetbrains.idea.maven.server.RemoteMavenServer36%0A%20%20%5B2%5D%3A%2031736%20org.jetbrains.jps.cmdline.Launcher%0A%20%20%5B3%5D%3A%2030620%0A3%0A%5BINFO%5D%20Start%20download%20arthas%20from%20remote%20server%3A%20https%3A%2F%2Farthas.aliyun.com%2Fdownload%2F3.5.4%3Fmirror%3Daliyun%0A%5BINFO%5D%20File%20size%3A%2012.72%20MB%2C%20downloaded%20size%3A%204.17%20MB%2C%20downloading%20...%0A%5BINFO%5D%20File%20size%3A%2012.72%20MB%2C%20downloaded%20size%3A%2010.49%20MB%2C%20downloading%20...%0A%5BINFO%5D%20Download%20arthas%20success.%0A%5BINFO%5D%20arthas%20home%3A%20C%3A%5CUsers%5C13622314539%5C.arthas%5Clib%5C3.5.4%5Carthas%0A%5BINFO%5D%20Try%20to%20attach%20process%2030620%0A%5BWARN%5D%20Current%20VM%20java%20version%3A%201.8%20do%20not%20match%20target%20VM%20java%20version%3A%2011%2C%20attach%20may%20fail.%0A%5BWARN%5D%20Target%20VM%20JAVA_HOME%20is%20C%3A%5CProgram%20Files%5CJetBrains%5CIntelliJ%20IDEA%202020.1.1%5Cjbr%2C%20arthas-boot%20JAVA_HOME%20is%20C%3A%5CProgram%20Files%5CJava%5Cjdk1.8.0_131%5Cjre%2C%20try%20to%20set%20the%20same%20JAVA_HOME.%0A%5BERROR%5D%20Start%20arthas%20failed%2C%20exception%20stack%20trace%3A%0Ajava.io.IOException%3A%20Non-numeric%20value%20found%20-%20int%20expected%0A%20%20%20%20%20%20%20%20at%20sun.tools.attach.HotSpotVirtualMachine.readInt(HotSpotVirtualMachine.java%3A299)%0A%20%20%20%20%20%20%20%20at%20sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java%3A63)%0A%20%20%20%20%20%20%20%20at%20sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java%3A79)%0A%20%20%20%20%20%20%20%20at%20sun.tools.attach.HotSpotVirtualMachine.loadAgent(HotSpotVirtualMachine.java%3A103)%0A%20%20%20%20%20%20%20%20at%20com.taobao.arthas.core.Arthas.attachAgent(Arthas.java%3A120)%0A%20%20%20%20%20%20%20%20at%20com.taobao.arthas.core.Arthas.%3Cinit%3E(Arthas.java%3A26)%0A%20%20%20%20%20%20%20%20at%20com.taobao.arthas.core.Arthas.main(Arthas.java%3A139)%0A%5BERROR%5D%20attach%20fail%2C%20targetPid%3A%2030620%0A%0A%60%60%60%0A%0A%60%60%60%0A%24%20java%20-jar%20arthas-boot.jar%0A%5BINFO%5D%20arthas-boot%20version%3A%203.5.4%0A%5BINFO%5D%20Process%2030620%20already%20using%20port%203658%0A%5BINFO%5D%20Process%2030620%20already%20using%20port%208563%0A%5BINFO%5D%20Found%20existing%20java%20process%2C%20please%20choose%20one%20and%20input%20the%20serial%20number%20of%20the%20process%2C%20eg%20%3A%201.%20Then%20hit%20ENTER.%0A*%20%5B1%5D%3A%2030620%0A%20%20%5B2%5D%3A%2010228%20org.jetbrains.idea.maven.server.RemoteMavenServer36%0A%20%20%5B3%5D%3A%2031736%20org.jetbrains.jps.cmdline.Launcher%0A1%0A%5BINFO%5D%20arthas%20home%3A%20C%3A%5CUsers%5C13622314539%5C.arthas%5Clib%5C3.5.4%5Carthas%0A%5BINFO%5D%20The%20target%20process%20already%20listen%20port%203658%2C%20skip%20attach.%0A%5BINFO%5D%20arthas-client%20connect%20127.0.0.1%203658%0A%20%20%2C---.%20%20%2C------.%20%2C--------.%2C--.%20%20%2C--.%20%20%2C---.%20%20%20%2C---.%0A%20%2F%20%20O%20%20%5C%20%7C%20%20.--.%20''--.%20%20.--'%7C%20%20'--'%20%20%7C%20%2F%20%20O%20%20%5C%20'%20%20%20.-'%0A%7C%20%20.-.%20%20%7C%7C%20%20'--'.'%20%20%20%7C%20%20%7C%20%20%20%7C%20%20.--.%20%20%7C%7C%20%20.-.%20%20%7C%60.%20%20%60-.%0A%7C%20%20%7C%20%7C%20%20%7C%7C%20%20%7C%5C%20%20%5C%20%20%20%20%7C%20%20%7C%20%20%20%7C%20%20%7C%20%20%7C%20%20%7C%7C%20%20%7C%20%7C%20%20%7C.-'%20%20%20%20%7C%0A%60--'%20%60--'%60--'%20'--'%20%20%20%60--'%20%20%20%60--'%20%20%60--'%60--'%20%60--'%60-----'%0A%0A%0Awiki%20%20%20%20%20%20%20https%3A%2F%2Farthas.aliyun.com%2Fdoc%0Atutorials%20%20https%3A%2F%2Farthas.aliyun.com%2Fdoc%2Farthas-tutorials.html%0Aversion%20%20%20%203.5.4%0Amain_class%0Apid%20%20%20%20%20%20%20%2030620%0Atime%20%20%20%20%20%20%202021-11-03%2015%3A05%3A15%0A%0A%60%60%60%0A%0A%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0arthas%E5%AE%89%E8%A3%85%E5%8C%85%E4%B8%8B%E8%BD%BD%E5%88%B0%E4%BA%86%E7%9B%AE%E5%BD%95%20%20%20%20%20%20%0A%3Earthas%20home%3A%20C%3A%5CUsers%5C13622314539%5C%5C.arthas%5Clib%5C3.5.4%5Carthas%20%20%0A%0A%E5%9C%A8C%3A%5CUsers%5C13622314539%E4%B8%8B%E6%9C%89%E4%B8%A4%E4%B8%AA%E7%9B%AE%E5%BD%95%E5%92%8Carthas%E6%9C%89%E5%85%B3%0A-%20.arthas%0A-%20logs%0A%0A%E5%A6%82%E6%9E%9C%E5%90%AF%E5%8A%A8%E6%97%B6%E7%AB%AF%E5%8F%A3%E5%8F%B7%E8%A2%AB%E5%8D%A0%E7%94%A8%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%A6%82%E4%B8%8B%E5%91%BD%E4%BB%A4%E6%9B%B4%E6%8D%A2%E7%AB%AF%E5%8F%A3%E5%8F%B7%0A%0A%60%60%60%0A%24%20java%20-jar%20arthas-boot.jar%20--telnet-port%209090%20--http-port%208090%0A%60%60%60%0A%E5%90%AF%E5%8A%A8%E5%90%8Earthas%E6%94%AF%E6%8C%81%E6%B8%B8%E8%A7%88%E5%99%A8%E6%9F%A5%E7%9C%8B%0A%3E%20http%3A%2F%2Flocalhost%3A3658%2F%0A%0A%0A%23%23%23%202.2%20%E5%9C%A8Linux%E4%B8%8B%E5%9C%A8%E7%BA%BF%E5%AE%89%E8%A3%85%0A%60%60%60%0Acurl%20-O%20https%3A%2F%2Farthas.aliyun.com%2Farthas-boot.jar%0Ajava%20-jar%20arthas-boot.jar%0A%60%60%60%0A%0A%3E%E5%9C%A8%E8%BF%90%E8%A1%8Cjava%20-jar%20arthas-boot.jar%E4%B9%8B%E5%89%8D%E9%9C%80%E8%A6%81%E7%A1%AE%E4%BF%9D%E5%86%85%E5%AD%98%E4%B8%AD%E6%9C%89%E4%B8%80%E4%B8%AAjava%E8%BF%9B%E7%A8%8B%2Cidea%2Cmvn%2Ctomcat%E9%83%BD%E6%98%AF%E4%B8%80%E4%B8%AAjava%E8%BF%9B%E7%A8%8B%EF%BC%8C%E5%90%A6%E5%88%99%E4%BC%9A%E6%8A%A5%E6%89%BE%E4%B8%8D%E5%88%B0java%E8%BF%9B%E7%A8%8B%E9%94%99%E8%AF%AF%0A%0A%E5%9C%A8%E5%AE%B6%E7%9B%AE%E5%BD%95%E4%B8%8B%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E4%B8%8Earthas%E7%9B%B8%E5%85%B3%E7%9A%84%E4%B8%A4%E4%B8%AA%E7%9B%AE%E5%BD%95%0A%60%60%60%0Acd%20~%0Als%20-a%20%0A-%20.arthas%0A-%20logs%0A%60%60%60%0A%0A%23%23%23%202.3%20%E7%A6%BB%E7%BA%BF%E5%AE%89%E8%A3%85%0A%0Ahttps%3A%2F%2Farthas.aliyun.com%2Fdoc%2Fen%2Fdownload.html%23download-from-maven-central%0A%0A%23%23%203%20%E5%8D%B8%E8%BD%BDarthas%0A%23%23%23%203.1%20%E5%9C%A8windows%E4%B8%8B%E5%8D%B8%E8%BD%BD%0A%E5%9C%A8C%3A%5CUsers%5C13622314539%E4%B8%8B%E6%9C%89%E4%B8%A4%E4%B8%AA%E7%9B%AE%E5%BD%95%E5%92%8Carthas%E6%9C%89%E5%85%B3%0A-%20.arthas%0A-%20logs%20%20%0A%0A%E7%9B%B4%E6%8E%A5%E6%89%8B%E5%8A%A8%E5%88%A0%E9%99%A4%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%AE%8C%E6%88%90%E5%9C%A8windows%E4%B8%8B%E7%9A%84%E5%8D%B8%E8%BD%BD%0A%0A%23%23%23%203.2%20%E5%9C%A8liunx%E4%B8%8B%E5%8D%B8%E8%BD%BD%0A%0A%60%60%60%0Arm%20-rf%20~%2F.arthas%0Arm%20-rf%20~%2Flogs%0A%60%60%60%0A%0A%23%23%204%20attach%E4%B8%80%E4%B8%AA%E8%BF%9B%E7%A8%8B%0A%0A%23%23%23%204.1%20%E5%90%AF%E5%8A%A8jar%E5%8C%85%0A%E8%BF%9B%E8%A1%8C%E7%9B%AE%E5%BD%95%2C%E5%90%AF%E5%8A%A8%E9%9C%80%E8%A6%81%E8%A2%AB%E8%AF%8A%E6%96%AD%E7%9A%84%E8%BF%9B%E7%A8%8B%20%20%0AC%3A%5CUsers%5C13622314539%5C%5C.arthas%5Clib%5C3.5.4%5Carthas%20%20%0A%0A%60%60%60%0A%E5%90%AF%E5%8A%A8math-game.jar%0Ajava%20-jar%20math-game.jar%0A%60%60%60%0A%0A%23%23%23%204.2%20%E5%90%AF%E5%8A%A8arthas%0A%E9%80%89%E6%8B%A9%E9%9C%80%E8%A6%81%E8%A2%AB%E8%AF%8A%E6%96%AD%E7%9A%84%E8%BF%9B%E7%A8%8Bmath-game%2C%E4%BC%9A%E8%87%AA%E5%8A%A8attach%E6%88%90%E5%8A%9F%0A%0A%60%60%60%0A13622314539%40OC136223145391%20MINGW64%20%2Fc%2Fchris%2Farthas%0A%24%20java%20-jar%20arthas-boot.jar%20--telnet-port%209090%20--http-port%208090%0A%5BINFO%5D%20arthas-boot%20version%3A%203.5.4%0A%5BINFO%5D%20Found%20existing%20java%20process%2C%20please%20choose%20one%20and%20input%20the%20serial%20number%20of%20the%20process%2C%20eg%20%3A%201.%20Then%20hit%20ENTER.%0A*%20%5B1%5D%3A%2033616%20math-game.jar%0A%20%20%5B2%5D%3A%2010228%20org.jetbrains.idea.maven.server.RemoteMavenServer36%0A%20%20%5B3%5D%3A%2031736%20org.jetbrains.jps.cmdline.Launcher%0A%20%20%5B4%5D%3A%2030620%0A1%0A%5BINFO%5D%20arthas%20home%3A%20C%3A%5CUsers%5C13622314539%5C.arthas%5Clib%5C3.5.4%5Carthas%0A%5BINFO%5D%20Try%20to%20attach%20process%2033616%0A%5BINFO%5D%20Attach%20process%2033616%20success.%0A%5BINFO%5D%20arthas-client%20connect%20127.0.0.1%209090%0A%20%20%2C---.%20%20%2C------.%20%2C--------.%2C--.%20%20%2C--.%20%20%2C---.%20%20%20%2C---.%0A%20%2F%20%20O%20%20%5C%20%7C%20%20.--.%20''--.%20%20.--'%7C%20%20'--'%20%20%7C%20%2F%20%20O%20%20%5C%20'%20%20%20.-'%0A%7C%20%20.-.%20%20%7C%7C%20%20'--'.'%20%20%20%7C%20%20%7C%20%20%20%7C%20%20.--.%20%20%7C%7C%20%20.-.%20%20%7C%60.%20%20%60-.%0A%7C%20%20%7C%20%7C%20%20%7C%7C%20%20%7C%5C%20%20%5C%20%20%20%20%7C%20%20%7C%20%20%20%7C%20%20%7C%20%20%7C%20%20%7C%7C%20%20%7C%20%7C%20%20%7C.-'%20%20%20%20%7C%0A%60--'%20%60--'%60--'%20'--'%20%20%20%60--'%20%20%20%60--'%20%20%60--'%60--'%20%60--'%60-----'%0A%0A%0Awiki%20%20%20%20%20%20%20https%3A%2F%2Farthas.aliyun.com%2Fdoc%0Atutorials%20%20https%3A%2F%2Farthas.aliyun.com%2Fdoc%2Farthas-tutorials.html%0Aversion%20%20%20%203.5.4%0Amain_class%0Apid%20%20%20%20%20%20%20%2033616%0Atime%20%20%20%20%20%20%202021-11-03%2016%3A14%3A36%0A%0A%5Barthas%4033616%5D%24%0A%0A%60%60%60%0A%0A%0A%23%23%205%20%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%0A%23%23%23%205.1%20dashboard%20%E9%9D%A2%E6%9D%BF%0A-%20dashboard%20%E6%8C%89q%E6%88%96ctrl%2Bc%E9%80%80%E5%87%BA%0A%3E%20%E7%AC%AC%E4%B8%80%E9%83%A8%E5%88%86%E6%98%BE%E7%A4%BA%E5%BD%93%E5%89%8D%E8%BF%9B%E7%A8%8B%E4%B8%AD%E8%BF%90%E8%A1%8C%E7%9A%84%E6%89%80%E6%9C%89%E7%BA%BF%E7%A8%8B%20%20%0A%3E%20%E7%AC%AC%E4%BA%8C%E9%83%A8%E5%88%86%E6%98%BE%E7%A4%BAJVM%E7%9A%84%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E6%83%85%E5%86%B5%20%20%0A%3E%20%E7%AC%AC%E4%B8%89%E9%83%A8%E5%88%86%E6%98%BE%E7%A4%BA%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%BF%A1%E6%81%AF%E5%92%8CJAVA%E7%89%88%E6%9C%AC%E5%8F%B7%20%20%0A%0A!%5Ba6ed42b45b5d4e4489fc4582c18ea737.png%5D(en-resource%3A%2F%2Fdatabase%2F1208%3A1)%0A%0A%0A%0A%23%23%23%205.2%20thread%20%0A-%20thread%20%E6%98%BE%E7%A4%BA%E8%BF%9B%E7%A8%8B%E9%87%8C%E9%9D%A2%E6%9C%89%E6%89%80%E6%9C%89%E7%BA%BF%E7%A8%8B%20thread%201%20%20%20%0A-%20%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%8F%96%E7%BA%BF%E7%A8%8BID%E4%B8%BA1%E7%9A%84%E6%A0%88%E4%BF%A1%E6%81%AF%E9%80%9A%E5%B8%B8%E6%98%AFmain%E5%87%BD%E6%95%B0%E7%9A%84%E7%BA%BF%E7%A8%8B%0A%0A%60%60%60%0A%5Barthas%4018824%5D%24%20thread%0A%60%60%60%0A%0A%60%60%60%0A%5Barthas%4030620%5D%24%20thread%201%0A%22main%22%20Id%3D1%20RUNNABLE%0A%60%60%60%0A%0A%23%23%23%205.3%20jad%20%E5%8F%8D%E7%BC%96%E8%AF%91class%E6%96%87%E4%BB%B6%0A%0A%60%60%60%0A%5Barthas%4033616%5D%24%20jad%20demo.MathGame%0Ajad%20demo.MathGame%0A%0AClassLoader%3A%0A%2B-sun.misc.Launcher%24AppClassLoader%4042a57993%20--%20%E7%A8%8B%E5%BA%8F%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%20%20%2B-sun.misc.Launcher%24ExtClassLoader%40544bdaf7%20--%20%E6%89%A9%E5%B1%95%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0ALocation%3A%20--%20%E5%AE%9A%E4%BD%8D%E5%88%B0%E7%9B%B8%E5%BA%94%E7%9A%84jar%E5%8C%85%0A%2FC%3A%2FUsers%2F13622314539%2F.arthas%2Flib%2F3.5.4%2Farthas%2Fmath-game.jar%0A%0A--%20%E5%8F%8D%E7%BC%96%E8%AF%91%E5%8E%9F%E4%BB%A3%E7%A0%81%0A%20%20%20%20%20%20%20%2F*%0A%20%20%20%20%20%20%20%20*%20Decompiled%20with%20CFR.%0A%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20package%20demo%3B%0A%0A%60%60%60%0A%0A%23%23%23%205.4%20watch%20%20%E7%9B%91%E8%A7%86%0A%E9%80%9A%E8%BF%87watch%E5%91%BD%E4%BB%A4%E5%8F%AF%E4%BB%A5%E6%9F%A5%E7%9C%8B%E6%96%B9%E6%B3%95%E7%9A%84%E5%85%A5%E5%8F%82%E5%92%8C%E8%BF%94%E5%9B%9E%E5%80%BC%E5%88%86%E5%88%AB%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20watch%20package.class%20method%20returnObj%0A%0A%60%60%60%0A%5Barthas%4018824%5D%24%20watch%20demo.MathGame%20primeFactors%20returnObj%0A%0Amethod%3Ddemo.MathGame.primeFactors%20location%3DAtExit%0Ats%3D2021-11-11%2014%3A50%3A00%3B%20%5Bcost%3D0.0738ms%5D%20result%3D%40ArrayList%5B%0A%20%20%20%20%40Integer%5B2%5D%2C%0A%20%20%20%20%40Integer%5B5%5D%2C%0A%20%20%20%20%40Integer%5B5%5D%2C%0A%20%20%20%20%40Integer%5B2287%5D%2C%0A%5D%0A%60%60%60%0A%0A%23%23%23%205.5%20%E9%80%80%E5%87%BAarthas%0A-%20quit%20%7C%20exit%20%E5%8F%AA%E6%98%AF%E9%80%80%E5%87%BA%E5%BD%93%E5%89%8D%E9%93%BE%E6%8E%A5%EF%BC%8Cattach%E5%88%B0%E7%9B%AE%E6%A0%87%E8%BF%9B%E7%A8%8B%E4%B8%8A%E7%9A%84arthas%E8%BF%98%E4%BC%9A%E7%BB%A7%E7%BB%AD%E8%BF%90%E8%A1%8C%EF%BC%8C%E7%AB%AF%E5%8F%A3%E4%BF%9D%E6%8C%81%E5%BC%80%E6%94%BE%EF%BC%8C%E4%B8%8B%E6%AC%A1%E9%93%BE%E6%8E%A5%E6%97%B6%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E8%BF%9E%E4%B8%8A%0A-%20stop%20%E7%BB%93%E6%9D%9F%E6%95%B4%E4%B8%AAarthas%E7%9A%84%E4%BC%9A%E8%AF%9D%EF%BC%8C%20%E5%85%B3%E9%97%ADarthas%E6%9C%8D%E5%8A%A1%E7%AB%AF%0A%0A%23%23%206%20%E5%9F%BA%E7%A1%80%E5%91%BD%E4%BB%A4%0A%23%23%23%206.1%20help%20%0A%3E%20help%20%E6%9F%A5%E7%9C%8B%E5%91%BD%E4%BB%A4%E5%B8%AE%E5%8A%A9%E4%BF%A1%E6%81%AF%0A%0A%60%60%60%0A%5Barthas%4018824%5D%24%20help%0ANAME%20%20%20%20%20%20%20%20%20DESCRIPTION%0A%20help%20%20%20%20%20%20%20%20%20Display%20Arthas%20Help%0A%20auth%20%20%20%20%20%20%20%20%20Authenticates%20the%20current%20session%0A%20keymap%20%20%20%20%20%20%20Display%20all%20the%20available%20keymap%20for%20the%20specified%20connection.%0A%60%60%60%0A%23%23%23%206.2%20cat%0A%3E%20%E6%89%93%E5%8D%B0%E6%9F%90%E4%B8%AA%E6%96%87%E4%BB%B6%E7%9A%84%E5%86%85%E5%AE%B9%2C%20%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%86%99%E8%B7%AF%E5%BE%84%E5%88%99%E6%98%BE%E7%A4%BA%E5%BD%93%E5%89%8D%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%20%20%0A%0A%E5%9C%A8C%3A%5CUsers%5C13622314539%5C%5C.arthas%5Clib%5C3.5.4%5Carthas%E7%9B%AE%E5%BD%95%E4%B8%8B%E6%96%B0%E5%A2%9E%E6%96%87%E4%BB%B6test.txt%0A%0A%60%60%60%0A%5Barthas%4018824%5D%24%20cat%20test.txt%0Acat%20test.txt%0Adddd%0A%5Barthas%4018824%5D%24%0A%60%60%60%0A%0A%23%23%23%206.3%20grep%0A%E5%8C%B9%E9%85%8D%E6%9F%A5%E6%89%BE%0A%0A%E5%8F%82%E6%95%B0%E5%88%97%E8%A1%A8%20%7C%20%E4%BD%9C%E7%94%A8%0A---%7C---%0A-n%20%7C%20%E6%98%BE%E7%A4%BA%E8%A1%8C%E5%8F%B7%0A-i%20%7C%20%E5%BF%BD%E7%95%A5%E5%A4%A7%E5%B0%8F%E5%86%99%0A-m%20%7C%20%E6%9C%80%E5%A4%A7%E6%98%BE%E7%A4%BA%E8%A1%8C%E6%95%B0%EF%BC%8C%E8%A6%81%E4%B8%8E%E6%9F%A5%E8%AF%A2%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8%0A-e%20%7C%20%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%0A%0A%0A%3E%20%E5%8F%AA%E6%98%BE%E7%A4%BA%E5%8C%85%E5%90%ABjava%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7%0A%60%60%60%0A%5Barthas%4018824%5D%24%20sysprop%20%7C%20grep%20java%0A%60%60%60%0A%3E%20%E6%98%BE%E7%A4%BA%E5%8C%85%E5%90%ABjava%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E8%A1%8C%E5%92%8C%E8%A1%8C%E5%8F%B7%E7%9A%84%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7%0A%60%60%60%0A%5Barthas%4018824%5D%24%20sysprop%20%7C%20grep%20-n%20java%0A%60%60%60%0A%3E%20%E6%98%BE%E7%A4%BA%E5%8C%85%E5%90%ABsystem%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%89%8D10%E8%A1%8C%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7%0A%60%60%60%0A%5Barthas%4018824%5D%24%20sysprop%20%7C%20grep%20-m%2010%20java%0A%60%60%60%0A%0A%23%23%23%206.4%20pwd%0A%3E%20%E6%89%93%E5%8D%B0%E5%BD%93%E5%89%8D%E5%B7%A5%E4%BD%9C%E7%9B%AE%E5%BD%95%E8%B7%AF%E5%BE%84%0A%0A%23%23%23%206.5%20cls%0A%E6%B8%85%E5%B1%8F%0A%0A%23%23%23%206.6%20session%0A%3E%20%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9D%E7%9A%84%E4%BF%A1%E6%81%AF%2C%20%E4%B8%A4%E4%B8%AA%E4%BC%9A%E8%AF%9D%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E7%9B%91%E5%90%AC%E5%90%8C%E4%B8%80%E4%B8%AAPID%0A%60%60%60%0A%5Barthas%4021904%5D%24%20session%0Asession%0A%20Name%20%20%20%20%20%20%20%20Value%0A--------------------------------------------------%0A%20JAVA_PID%20%20%20%2021904%0A%20SESSION_ID%20%20c54d94b2-f155-4db1-8a51-8ab7dd09a03a%0A%5Barthas%4021904%5D%24%0A%60%60%60%0A%0A%23%23%23%206.7%20reset%0A%3E%20%E9%87%8D%E7%BD%AE%E5%A2%9E%E5%BC%BA%E7%B1%BB%EF%BC%8C%E5%B0%86%E8%A2%ABarthas%E5%A2%9E%E5%BC%BA%E8%BF%87%E7%9A%84%E7%B1%BB%E5%85%A8%E9%83%A8%E8%BF%98%E5%8E%9F%EF%BC%8CArthas%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%85%B3%E9%97%AD%E6%97%B6%E4%BC%9A%E9%87%8D%E7%BD%AE%E6%89%80%E6%9C%89%E5%A2%9E%E5%BC%BA%E8%BF%87%E7%9A%84%E7%B1%BB%0A%0A%23%23%23%206.8%20version%0A%3E%20%E8%BE%93%E5%87%BA%E5%BD%93%E5%89%8Djava%E8%BF%9B%E7%A8%8B%E6%89%80%E5%8A%A0%E8%BD%BD%E7%9A%84arthas%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%0A%0A%60%60%60%0A%5Barthas%4021904%5D%24%20version%0Aversion%0A3.5.4%0A%60%60%60%0A%23%23%23%206.9%20history%0A%3E%20%E8%BE%93%E5%87%BAarthas%E7%9A%84%E5%91%BD%E4%BB%A4%E5%8E%86%E5%8F%B2%0A%60%60%60%0A%5Barthas%4021904%5D%24%20history%0Ahistory%0A%20%20%20%201%20%20dashboard%0A%20%20%20%202%20%20cls%0A%20%20%20%203%20%20thread%0A%20%20%20%204%20%20cls%0A%20%20%20%205%20%20thead%0A%20%20%20%206%20%20thread%0A%20%20%20%207%20%20thread%201%0A%20%20%20%208%20%20jad%20demo.MathGame%0A%20%20%20%209%20%20jad%20demo.MathGame%0A%20%20%2010%20%20jad%20demo.MathGame%0A%20%20%2011%20%20jad%20demo.MathGame%0A%20%20%2012%20%20dashboard%0A%0A%60%60%60%0A%0A%23%23%23%206.10%20keymap%0A%3E%20%E8%BE%93%E5%87%BAarthas%E5%BF%AB%E6%8D%B7%E9%94%AE%E5%88%97%E8%A1%A8%E5%8F%8A%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BF%AB%E6%8D%B7%E9%94%AE%0A%0A%60%60%60%0A%5Barthas%4021904%5D%24%20keymap%0Akeymap%0A%20Shortcut%20%20%20%20%20%20%20%20%20%20%20%20Description%20%20%20%20%20%20%20%20%20Name%0A-------------------------------------------------------------------------------%0A%20%22%5CC-a%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Ctrl%20%2B%20a%20%20%20%20%20%20%20%20%20%20%20%20%20beginning-of-line%0A%20%22%5CC-e%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Ctrl%20%2B%20e%20%20%20%20%20%20%20%20%20%20%20%20%20end-of-line%0A%20%22%5CC-f%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Ctrl%20%2B%20f%20%20%20%20%20%20%20%20%20%20%20%20%20forward-word%0A%20%22%5CC-b%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Ctrl%20%2B%20b%20%20%20%20%20%20%20%20%20%20%20%20%20backward-word%0A%20%22%5Ce%5BD%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Left%20arrow%20%20%20%20%20%20%20%20%20%20%20backward-char%0A%20%22%5Ce%5BC%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Right%20arrow%20%20%20%20%20%20%20%20%20%20forward-char%0A%20%22%5Ce%5BA%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Up%20arrow%20%20%20%20%20%20%20%20%20%20%20%20%20history-search-backward%0A%20%22%5Ce%5BB%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Down%20arrow%20%20%20%20%20%20%20%20%20%20%20history-search-forward%0A%20%22%5CC-h%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20Ctrl%20%2B%20h%20%20%20%20%20%20%20%20%20%20%20%20%20backward-delete-char%0A%0A%60%60%60%0A%0A%0A%23%23%23%206.11%20trace%0A%0A%60%60%60%0A%5Barthas%4021904%5D%24%20trace%20demo.MathGame%20print%0Atrace%20demo.MathGame%20print%0APress%20Q%20or%20Ctrl%2BC%20to%20abort.%0AAffect(class%20count%3A%201%20%2C%20method%20count%3A%201)%20cost%20in%20301%20ms%2C%20listenerId%3A%201%0A%60---ts%3D2021-11-23%2016%3A25%3A27%3Bthread_name%3Dmain%3Bid%3D1%3Bis_daemon%3Dfalse%3Bpriority%3D5%3BTCCL%3Dsun.misc.Launcher%24AppClassLoader%4042a57993%0A%20%20%20%20%60---%5B0.7906ms%5D%20demo.MathGame%3Aprint()%0A%0A%60---ts%3D2021-11-23%2016%3A25%3A28%3Bthread_name%3Dmain%3Bid%3D1%3Bis_daemon%3Dfalse%3Bpriority%3D5%3BTCCL%3Dsun.misc.Launcher%24AppClassLoader%4042a57993%0A%20%20%20%20%60---%5B0.1149ms%5D%20demo.MathGame%3Aprint()%0A%0A%60%60%60%0A%0A%23%23%207%20jvm%E7%9B%B8%E5%85%B3%E5%91%BD%E4%BB%A4%0A-%20dashboard%20%E4%BB%AA%E8%A1%A8%E7%9B%98%0A-%20thread%20%20%20%20%E7%BA%BF%E7%A8%8B%E7%9B%B8%E5%85%B3%20%0A-%20jvm%20%20%20%20%20%20%20%E8%99%9A%E6%8B%9F%E6%9C%BA%E7%9B%B8%E5%85%B3%0A-%20sysprop%20%20%20%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7%E7%9B%B8%E5%85%B3%0A%0A%23%23%23%207.1%20dashboard%0A%0A

JAVA_OPTS_EXT -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:${BAYMAX_APP_WO

创建时间:2021/11/4 14:32
更新时间:2021/11/4 14:32
作者:Chris

JAVA_OPTS_EXT -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:${BAYMAX_APP_WORKDIR}/logs/gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=14 -XX:GCLogFileSize=100M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BAYMAX_APP_WORKDIR}/logs/

自费的EV71疫苗到底值不值得打

创建时间:2020/11/24 12:51
更新时间:2021/6/4 10:15
作者:Chris
来源:https://www.120ask.com/question/67330848.htm



WebMvcConfigurer之HttpMessageConverter

创建时间:2021/4/7 10:02
更新时间:2021/4/7 10:04
作者:Chris

WebMvcConfigurer之HttpMessageConverter

在SpringMVC中,可以使用@RequestBody和@ResponseBody两个注解,分别完成请求报文到对象和对象到响应报文的转换

底层这种灵活的消息转换机制就是利用HttpMessageConverter来实现的,

Spring内置了很多HttpMessageConverter,比如MappingJackson2HttpMessageConverterStringHttpMessageConverter

配置使用FastJson插件返回json数据
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.31</version>
</dependency>

通过实现WebMvcConfigurer 接口来配置FastJsonHttpMessageConverter

Springboot2.0版本以后推荐使用这种方式来进行web配置,这样不会覆盖掉springboot的一些默认配置。

配置类如下


/**
 * 消息内容转换配置
 * 配置fastJson返回json转换
 * @param converters
 */
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    //调用父类的配置
    super.configureMessageConverters(converters);
    //创建fastJson消息转换器
    FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
    //创建配置类
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    //修改配置返回内容的过滤
    fastJsonConfig.setSerializerFeatures(
            SerializerFeature.DisableCircularReferenceDetect,
            SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteNullStringAsEmpty
    );
    fastConverter.setFastJsonConfig(fastJsonConfig);
    //将fastjson添加到视图消息转换器列表内
    converters.add(fastConverter);
 
}

fastJson配置实体调用setSerializerFeatures方法可以配置多个过滤方式,常用的如下:

1、WriteNullListAsEmpty :List字段如果为null,输出为[],而非null
2、WriteNullStringAsEmpty : 字符类型字段如果为null,输出为"",而非null
3、DisableCircularReferenceDetect :消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)
4、WriteNullBooleanAsFalse:Boolean字段如果为null,输出为false,而非null
5、WriteMapNullValue:是否输出值为null的字段,默认为false。
配置使用MappingJackson返回json数据
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.clear();
    stringConverter();
    MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
    //不显示为null的字段
    objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
        @Override
        public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            String fieldName = gen.getOutputContext().getCurrentName();
            try {
                //反射获取字段类型
                Field field = gen.getCurrentValue().getClass().getDeclaredField(fieldName);
                if (Objects.equals(field.getType(), String.class)) {
                    //字符串型空值""
                    gen.writeString("");
                    return;
                } else if (Objects.equals(field.getType(), List.class)) {
                    //列表型空值返回[]
                    gen.writeStartArray();
                    gen.writeEndArray();
                    return;
                } else if (Objects.equals(field.getType(), Map.class)) {
                    //map型空值返回{}
                    gen.writeStartObject();
                    gen.writeEndObject();
                    return;
                }
            } catch (NoSuchFieldException e) {
            }
            //默认返回""
            gen.writeString("");
        }
    });
    
    objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS );
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
    objectMapper.registerModule(simpleModule);

    jackson2HttpMessageConverter.setObjectMapper(objectMapper);
    //放到第一个
    converters.add(0, jackson2HttpMessageConverter);
}
WebMvcConfigurer%E4%B9%8B%5BHttpMessageConverter%5D(https%3A%2F%2Fwww.cnblogs.com%2Fhhhshct%2Fp%2F9676604.html)%0A%0A%3E%20%E5%9C%A8SpringMVC%E4%B8%AD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%40RequestBody%E5%92%8C%40ResponseBody%E4%B8%A4%E4%B8%AA%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%88%86%E5%88%AB%E5%AE%8C%E6%88%90%E8%AF%B7%E6%B1%82%E6%8A%A5%E6%96%87%E5%88%B0%E5%AF%B9%E8%B1%A1%E5%92%8C%E5%AF%B9%E8%B1%A1%E5%88%B0%E5%93%8D%E5%BA%94%E6%8A%A5%E6%96%87%E7%9A%84%E8%BD%AC%E6%8D%A2%0A%3E%0A%3E%20%E5%BA%95%E5%B1%82%E8%BF%99%E7%A7%8D%E7%81%B5%E6%B4%BB%E7%9A%84%E6%B6%88%E6%81%AF%E8%BD%AC%E6%8D%A2%E6%9C%BA%E5%88%B6%E5%B0%B1%E6%98%AF%E5%88%A9%E7%94%A8%60HttpMessageConverter%60%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8C%0A%3E%0A%3E%20Spring%E5%86%85%E7%BD%AE%E4%BA%86%E5%BE%88%E5%A4%9AHttpMessageConverter%EF%BC%8C%E6%AF%94%E5%A6%82%60MappingJackson2HttpMessageConverter%60%EF%BC%8C%60StringHttpMessageConverter%60%20%E7%AD%89%0A%0A%23%23%23%23%23%20%E9%85%8D%E7%BD%AE%E4%BD%BF%E7%94%A8FastJson%E6%8F%92%E4%BB%B6%E8%BF%94%E5%9B%9Ejson%E6%95%B0%E6%8D%AE%0A%0A%60%60%60xml%0A%3Cdependency%3E%0A%20%20%20%20%3CgroupId%3Ecom.alibaba%3C%2FgroupId%3E%0A%20%20%20%20%3CartifactId%3Efastjson%3C%2FartifactId%3E%0A%20%20%20%20%3Cversion%3E1.2.31%3C%2Fversion%3E%0A%3C%2Fdependency%3E%0A%60%60%60%0A%0A%3E%20%E9%80%9A%E8%BF%87%E5%AE%9E%E7%8E%B0%60WebMvcConfigurer%60%20%E6%8E%A5%E5%8F%A3%E6%9D%A5%E9%85%8D%E7%BD%AE%60FastJsonHttpMessageConverter%60%0A%3E%0A%3E%20Springboot2.0%E7%89%88%E6%9C%AC%E4%BB%A5%E5%90%8E%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8%E8%BF%99%E7%A7%8D%E6%96%B9%E5%BC%8F%E6%9D%A5%E8%BF%9B%E8%A1%8Cweb%E9%85%8D%E7%BD%AE%EF%BC%8C%E8%BF%99%E6%A0%B7%E4%B8%8D%E4%BC%9A%E8%A6%86%E7%9B%96%E6%8E%89springboot%E7%9A%84%E4%B8%80%E4%BA%9B%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E3%80%82%0A%3E%0A%3E%20%E9%85%8D%E7%BD%AE%E7%B1%BB%E5%A6%82%E4%B8%8B%0A%0A%60%60%60java%0A%0A%2F**%0A%20*%20%E6%B6%88%E6%81%AF%E5%86%85%E5%AE%B9%E8%BD%AC%E6%8D%A2%E9%85%8D%E7%BD%AE%0A%20*%20%E9%85%8D%E7%BD%AEfastJson%E8%BF%94%E5%9B%9Ejson%E8%BD%AC%E6%8D%A2%0A%20*%20%40param%20converters%0A%20*%2F%0A%40Override%0Apublic%20void%20configureMessageConverters(List%3CHttpMessageConverter%3C%3F%3E%3E%20converters)%20%7B%0A%20%20%20%20%2F%2F%E8%B0%83%E7%94%A8%E7%88%B6%E7%B1%BB%E7%9A%84%E9%85%8D%E7%BD%AE%0A%20%20%20%20super.configureMessageConverters(converters)%3B%0A%20%20%20%20%2F%2F%E5%88%9B%E5%BB%BAfastJson%E6%B6%88%E6%81%AF%E8%BD%AC%E6%8D%A2%E5%99%A8%0A%20%20%20%20FastJsonHttpMessageConverter%20fastConverter%20%3D%20new%20FastJsonHttpMessageConverter()%3B%0A%20%20%20%20%2F%2F%E5%88%9B%E5%BB%BA%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%20%20%20%20FastJsonConfig%20fastJsonConfig%20%3D%20new%20FastJsonConfig()%3B%0A%20%20%20%20%2F%2F%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE%E8%BF%94%E5%9B%9E%E5%86%85%E5%AE%B9%E7%9A%84%E8%BF%87%E6%BB%A4%0A%20%20%20%20fastJsonConfig.setSerializerFeatures(%0A%20%20%20%20%20%20%20%20%20%20%20%20SerializerFeature.DisableCircularReferenceDetect%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20SerializerFeature.WriteMapNullValue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20SerializerFeature.WriteNullStringAsEmpty%0A%20%20%20%20)%3B%0A%20%20%20%20fastConverter.setFastJsonConfig(fastJsonConfig)%3B%0A%20%20%20%20%2F%2F%E5%B0%86fastjson%E6%B7%BB%E5%8A%A0%E5%88%B0%E8%A7%86%E5%9B%BE%E6%B6%88%E6%81%AF%E8%BD%AC%E6%8D%A2%E5%99%A8%E5%88%97%E8%A1%A8%E5%86%85%0A%20%20%20%20converters.add(fastConverter)%3B%0A%20%0A%7D%0A%60%60%60%0A%0A%3E%20fastJson%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BD%93%E8%B0%83%E7%94%A8setSerializerFeatures%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E9%85%8D%E7%BD%AE%E5%A4%9A%E4%B8%AA%E8%BF%87%E6%BB%A4%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%B8%B8%E7%94%A8%E7%9A%84%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60%0A1%E3%80%81WriteNullListAsEmpty%20%EF%BC%9AList%E5%AD%97%E6%AE%B5%E5%A6%82%E6%9E%9C%E4%B8%BAnull%2C%E8%BE%93%E5%87%BA%E4%B8%BA%5B%5D%2C%E8%80%8C%E9%9D%9Enull%0A2%E3%80%81WriteNullStringAsEmpty%20%EF%BC%9A%20%E5%AD%97%E7%AC%A6%E7%B1%BB%E5%9E%8B%E5%AD%97%E6%AE%B5%E5%A6%82%E6%9E%9C%E4%B8%BAnull%2C%E8%BE%93%E5%87%BA%E4%B8%BA%22%22%2C%E8%80%8C%E9%9D%9Enull%0A3%E3%80%81DisableCircularReferenceDetect%20%EF%BC%9A%E6%B6%88%E9%99%A4%E5%AF%B9%E5%90%8C%E4%B8%80%E5%AF%B9%E8%B1%A1%E5%BE%AA%E7%8E%AF%E5%BC%95%E7%94%A8%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAfalse%EF%BC%88%E5%A6%82%E6%9E%9C%E4%B8%8D%E9%85%8D%E7%BD%AE%E6%9C%89%E5%8F%AF%E8%83%BD%E4%BC%9A%E8%BF%9B%E5%85%A5%E6%AD%BB%E5%BE%AA%E7%8E%AF%EF%BC%89%0A4%E3%80%81WriteNullBooleanAsFalse%EF%BC%9ABoolean%E5%AD%97%E6%AE%B5%E5%A6%82%E6%9E%9C%E4%B8%BAnull%2C%E8%BE%93%E5%87%BA%E4%B8%BAfalse%2C%E8%80%8C%E9%9D%9Enull%0A5%E3%80%81WriteMapNullValue%EF%BC%9A%E6%98%AF%E5%90%A6%E8%BE%93%E5%87%BA%E5%80%BC%E4%B8%BAnull%E7%9A%84%E5%AD%97%E6%AE%B5%2C%E9%BB%98%E8%AE%A4%E4%B8%BAfalse%E3%80%82%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20%E9%85%8D%E7%BD%AE%E4%BD%BF%E7%94%A8MappingJackson%E8%BF%94%E5%9B%9Ejson%E6%95%B0%E6%8D%AE%0A%0A%60%60%60java%0A%40Override%0Apublic%20void%20configureMessageConverters(List%3CHttpMessageConverter%3C%3F%3E%3E%20converters)%20%7B%0A%20%20%20%20converters.clear()%3B%0A%20%20%20%20stringConverter()%3B%0A%20%20%20%20MappingJackson2HttpMessageConverter%20jackson2HttpMessageConverter%20%3D%20new%20MappingJackson2HttpMessageConverter()%3B%0A%20%20%20%20ObjectMapper%20objectMapper%20%3D%20jackson2HttpMessageConverter.getObjectMapper()%3B%0A%20%20%20%20%2F%2F%E4%B8%8D%E6%98%BE%E7%A4%BA%E4%B8%BAnull%E7%9A%84%E5%AD%97%E6%AE%B5%0A%20%20%20%20objectMapper.getSerializerProvider().setNullValueSerializer(new%20JsonSerializer%3CObject%3E()%20%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20serialize(Object%20value%2C%20JsonGenerator%20gen%2C%20SerializerProvider%20serializers)%20throws%20IOException%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20String%20fieldName%20%3D%20gen.getOutputContext().getCurrentName()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%8F%8D%E5%B0%84%E8%8E%B7%E5%8F%96%E5%AD%97%E6%AE%B5%E7%B1%BB%E5%9E%8B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Field%20field%20%3D%20gen.getCurrentValue().getClass().getDeclaredField(fieldName)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(Objects.equals(field.getType()%2C%20String.class))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%9E%8B%E7%A9%BA%E5%80%BC%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gen.writeString(%22%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(Objects.equals(field.getType()%2C%20List.class))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%88%97%E8%A1%A8%E5%9E%8B%E7%A9%BA%E5%80%BC%E8%BF%94%E5%9B%9E%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gen.writeStartArray()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gen.writeEndArray()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(Objects.equals(field.getType()%2C%20Map.class))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fmap%E5%9E%8B%E7%A9%BA%E5%80%BC%E8%BF%94%E5%9B%9E%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gen.writeStartObject()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gen.writeEndObject()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(NoSuchFieldException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E9%BB%98%E8%AE%A4%E8%BF%94%E5%9B%9E%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20gen.writeString(%22%22)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D)%3B%0A%20%20%20%20%0A%20%20%20%20objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS%20)%3B%0A%20%20%20%20SimpleModule%20simpleModule%20%3D%20new%20SimpleModule()%3B%0A%20%20%20%20simpleModule.addSerializer(Long.class%2C%20ToStringSerializer.instance)%3B%0A%20%20%20%20simpleModule.addSerializer(Long.TYPE%2C%20ToStringSerializer.instance)%3B%0A%20%20%20%20objectMapper.registerModule(simpleModule)%3B%0A%0A%20%20%20%20jackson2HttpMessageConverter.setObjectMapper(objectMapper)%3B%0A%20%20%20%20%2F%2F%E6%94%BE%E5%88%B0%E7%AC%AC%E4%B8%80%E4%B8%AA%0A%20%20%20%20converters.add(0%2C%20jackson2HttpMessageConverter)%3B%0A%7D%0A%60%60%60%0A%0A

mysql 性能优化

创建时间:2020/9/2 15:33
更新时间:2021/2/9 15:59
作者:Chris
来源:https://www.processon.com/diagraming/5f8143f21e085307a080a11f

1. 性能分析的三个方面

  1. 慢查询日志, 把有问题的SQL记录下来
  2. explain执行计划,会看执行计划
  3. show profile,查看SQL执行时的硬件消耗

在执行查询时一般只会用到一个索引,由优化器去选择。

解析过程 www.cnblogs.com/annsshadow/p/5037667.html

1.客户端连接数据库,验证身份。
2.获取当前用户权限。
3.当你查询时,会先去缓存看看,如果有返回。
4.如果没有,分析器对sql做词法分析和语义分析。
5.优化器对sql进行“它认为比较好的优化”。
6.执行器负责具体执行sql语句。
7.最后把数据返回给客户端。

from
on

join
where

group by 
having

select

order by 

2. BTree介绍

3层Btree可以存放上百万条数据
Btree一般指B+树,数据都存放在叶节点里面

3. SQL的性能问题

show index from table_name;

mysql 的优化器分干扰我们的优化

分析SQL的执行计划, explain, 可以模拟优化器执行。

4. SQL执行计划

4.1 id
  1. id 相同,从上向下依次执行。

    表的执行顺序因表中数据量的改变而改变,原因是因为笛卡尔积
    多表关联时,结果记录数没有变,但是中间结果不同, 中间结果小,占用内存小,所以数据少的表作为驱动表优先查询。

  2. id 值不相同时,值越大越优先执行。因为嵌套子查询时先查内层再查外层。

    嵌套查询时先查内层,再查外层

4.2 select_type 查询类型
类型描述
primary包含子查询SQL的主查询语句一般为最外层
SUBQUERY包含子查询SQL的子查询语句一般为非最外层
SIMPLE简单查询,不包含子查询和union连接查询
DERIVED衍生查询,在查询时用到了临时表
a.在子查询的from后面只有一张表
b.在子查询from后面有两张表, 如果table 1 union table2, 则table1就是derived,table2就是union

数字2表示衍生查询使用了id为2的表

4.3 type 索引类型
system >  const >  eq_ref >  ref > range >  index >  all, 越往左越高效
其中 system,const 只是理想情况,通过自己优化实际能达到 ref > range
4.3.1 system

只有一条数据的系统表,或衍生表只有一条数据的主查询

4.3.2 const

必须通过primarykey 或 unique索引查询时,并且仅仅能查到一条数据。

4.3.3 eq_ref

唯一性索引
对于每一个索件键的查询返回值匹配唯一一行数据,有且只有一个值,不能多也不能是0,查询的结果和表中实际的条数是一样的,常见于primary key或unique索引查询时。
比如通过名字查询时,每个名字只有一个值,不能出现两个John

alter table taechercard add constraint pk_tcid primary key(tcid);
alter table taecher add constraint uk_tcid unique index(tcid);

select t.tcid from teacher t , teachercard tc where t.tcid=tc.tcid;
通过外键tcid查询时,teacher里面的记录数要和teachercard里面的记录数一致,并全tcid在teacher里面作为外键是唯一值。

4.3.4 ref

非唯一性索引, 对于每一个索件键的查询返回值匹配一行,0行或多行数据。
alter table teacher add index index_name(tname);


4.3.5 range

范围索引
检索指定范围的行, where后面是一个范围查询, between, in > < >= <=, in有时走range有时会是all.

4.3.6 index

将索引树全部查询了一遍
也就是将索引列的所有值全部查询了一遍
alter table teacher add index tid_index(tid);

4.37. all:将全表查询了一遍

在tid上没有建立索引,所以需要将全表扫描

5. possible_keys 和 key

possible_keys 可能用到的索引,是一种预测,但是不准确
key 实际用到的索引
如果对应的值为null说明没有索引

6. key_len 索引长度

用于判断复合索引是否被完全使用

alter table teacher add index index_name(tid);
create table test_kl(
 name char(20) not null default ''
);
alter table test_kl add index index_name(name);
select * from test_kl where name='';
uft8  一个字符3个字节
gbk   一个字符2个字节
latin 一个字符1个字节

20 x 3 = 60

mysql对于为空的牵引列额外用1个字节标识

alter table add column name1 char(20);
alter table test_k1 add index index_name1(name1);

20 x 3 +1= 61

5. ref 与type中的ref值区分

指明当前表参照的字段:

select * from where a.c=b.x; (其中b.x可以是常量, const)

6. rows 被索引优化后查询的数据条数

7. extra
  1. using filesort:

    性能消耗大,需要额外的一次排序(查询),常见于排序中

  2. 1 对于单牵引如果查找和排序不是同一个字段就会出现using filesort
    如果查找和排序是同一个字段则不会出现using filesort
    可以按照查找什么字段就用什么字段进行排序

     select * from test02 where a1= '' order by a1;   --不会出现 using filesort
     select * from test02 where a1= '' order by a2;   -- using filesort
    

    1.2 复合索引,最佳左前缀,不能跨列.

    alter table test02 add index idx_a1_a2_a3
    explain select * from test02 where a1='' order by a3 -- using filesort
    explain select * from test02 where a2='' order by a3 -- using filesort
    explain select * from test02 where a1='' order by a2 --不会出现 using filesort
    
  3. using temporary:

    性能损耗比较大,用到了临时表,常见于group by 中.

    如果查找和分组不是同一个字段则会出现using temporary
    所以如果查找哪些队就用这些列进行分组

    select * from test02 where a1 in ('1''2''3') group by a1; -- 不会出现using temporary
    select * from test02 where a1 in ('1''2''3') group by a2; -- using temporary
    
  4. using index

    意味着性能提升,因为所有的查询列都在索引中即【索引覆盖】

    原因是不需要读取原文件,只从索引文件获取数据, 即没有回表查询

    alter table test01 add index a1_a2_a3_inx (a1,a2,a3);
    select a1, a2, a3 from test01 where  a1=''  --using index
    
    drop index a1_a2_a3_inx  on table test01 ;
    alter table test01 add index a1_a2_inx (a1,a2); 
    select a1, a3 from test01 where  a1='' and a3='' -- 不用使用using index
    
  5. using where

    需要回表查询,即需要从索引查又需要回原表查,

    alter table test01 add index age_inx(age);
    select name , age from test01 where age=''  此语句必须回原表查name,因此会显示using where
    
  6. impossible where

    where 永远为false.

    select * from test02 where a1='x' and a1='y'  -- impossible where
    

%5Btoc%5D%0A%23%23%23%23%201.%20%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E7%9A%84%E4%B8%89%E4%B8%AA%E6%96%B9%E9%9D%A2%0A%0A%3E%20%0A%3E%201.%20%E6%85%A2%E6%9F%A5%E8%AF%A2%E6%97%A5%E5%BF%97%2C%20%E6%8A%8A%E6%9C%89%E9%97%AE%E9%A2%98%E7%9A%84SQL%E8%AE%B0%E5%BD%95%E4%B8%8B%E6%9D%A5%0A%3E%202.%20explain%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%EF%BC%8C%E4%BC%9A%E7%9C%8B%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%0A%3E%203.%20show%20profile%EF%BC%8C%E6%9F%A5%E7%9C%8BSQL%E6%89%A7%E8%A1%8C%E6%97%B6%E7%9A%84%E7%A1%AC%E4%BB%B6%E6%B6%88%E8%80%97%0A%0A%20%3E%E5%9C%A8%E6%89%A7%E8%A1%8C%E6%9F%A5%E8%AF%A2%E6%97%B6%E4%B8%80%E8%88%AC%E5%8F%AA%E4%BC%9A%E7%94%A8%E5%88%B0%E4%B8%80%E4%B8%AA%E7%B4%A2%E5%BC%95%EF%BC%8C%E7%94%B1%E4%BC%98%E5%8C%96%E5%99%A8%E5%8E%BB%E9%80%89%E6%8B%A9%E3%80%82%0A%0A%20%20%20%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B%20www.cnblogs.com%2Fannsshadow%2Fp%2F5037667.html%0A%0A!%5Bb4f8dd2dd1483517f2951558316a274b.png%5D(en-resource%3A%2F%2Fdatabase%2F687%3A1)%0A%0A%3E%201.%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BF%9E%E6%8E%A5%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%8C%E9%AA%8C%E8%AF%81%E8%BA%AB%E4%BB%BD%E3%80%82%0A%3E%202.%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%E3%80%82%0A%3E%203.%E5%BD%93%E4%BD%A0%E6%9F%A5%E8%AF%A2%E6%97%B6%EF%BC%8C%E4%BC%9A%E5%85%88%E5%8E%BB%E7%BC%93%E5%AD%98%E7%9C%8B%E7%9C%8B%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9C%89%E8%BF%94%E5%9B%9E%E3%80%82%0A%3E%204.%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%EF%BC%8C%E5%88%86%E6%9E%90%E5%99%A8%E5%AF%B9sql%E5%81%9A%E8%AF%8D%E6%B3%95%E5%88%86%E6%9E%90%E5%92%8C%E8%AF%AD%E4%B9%89%E5%88%86%E6%9E%90%E3%80%82%0A%3E%205.%E4%BC%98%E5%8C%96%E5%99%A8%E5%AF%B9sql%E8%BF%9B%E8%A1%8C%E2%80%9C%E5%AE%83%E8%AE%A4%E4%B8%BA%E6%AF%94%E8%BE%83%E5%A5%BD%E7%9A%84%E4%BC%98%E5%8C%96%E2%80%9D%E3%80%82%0A%3E%206.%E6%89%A7%E8%A1%8C%E5%99%A8%E8%B4%9F%E8%B4%A3%E5%85%B7%E4%BD%93%E6%89%A7%E8%A1%8Csql%E8%AF%AD%E5%8F%A5%E3%80%82%0A%3E%207.%E6%9C%80%E5%90%8E%E6%8A%8A%E6%95%B0%E6%8D%AE%E8%BF%94%E5%9B%9E%E7%BB%99%E5%AE%A2%E6%88%B7%E7%AB%AF%E3%80%82%0A%0A%0A%60%60%60sql%0Afrom%0Aon%0A%0Ajoin%0Awhere%0A%0Agroup%20by%20%0Ahaving%0A%0Aselect%0A%0Aorder%20by%20%0A%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%202.%20BTree%E4%BB%8B%E7%BB%8D%0A%0A3%E5%B1%82Btree%E5%8F%AF%E4%BB%A5%E5%AD%98%E6%94%BE%E4%B8%8A%E7%99%BE%E4%B8%87%E6%9D%A1%E6%95%B0%E6%8D%AE%0ABtree%E4%B8%80%E8%88%AC%E6%8C%87B%2B%E6%A0%91%EF%BC%8C%E6%95%B0%E6%8D%AE%E9%83%BD%E5%AD%98%E6%94%BE%E5%9C%A8%E5%8F%B6%E8%8A%82%E7%82%B9%E9%87%8C%E9%9D%A2%0A%0A%0A%23%23%23%23%203.%20SQL%E7%9A%84%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98%0A%60%60%60%0Ashow%20index%20from%20table_name%3B%0A%60%60%60%0A%0A%3E%20mysql%20%E7%9A%84%E4%BC%98%E5%8C%96%E5%99%A8%E5%88%86%E5%B9%B2%E6%89%B0%E6%88%91%E4%BB%AC%E7%9A%84%E4%BC%98%E5%8C%96%0A%3E%0A%3E%20%E5%88%86%E6%9E%90SQL%E7%9A%84%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%2C%20explain%2C%20%E5%8F%AF%E4%BB%A5%E6%A8%A1%E6%8B%9F%E4%BC%98%E5%8C%96%E5%99%A8%E6%89%A7%E8%A1%8C%E3%80%82%0A%0A%23%23%23%23%204.%20SQL%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%0A%0A%23%23%23%23%23%204.1%20id%0A%0A1.%20id%20%E7%9B%B8%E5%90%8C%EF%BC%8C%E4%BB%8E%E4%B8%8A%E5%90%91%E4%B8%8B%E4%BE%9D%E6%AC%A1%E6%89%A7%E8%A1%8C%E3%80%82%0A%20%20%20%3E%20%E8%A1%A8%E7%9A%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E5%9B%A0%E8%A1%A8%E4%B8%AD%E6%95%B0%E6%8D%AE%E9%87%8F%E7%9A%84%E6%94%B9%E5%8F%98%E8%80%8C%E6%94%B9%E5%8F%98%EF%BC%8C%E5%8E%9F%E5%9B%A0%E6%98%AF%E5%9B%A0%E4%B8%BA%E7%AC%9B%E5%8D%A1%E5%B0%94%E7%A7%AF%0A%20%20%20%3E%20%E5%A4%9A%E8%A1%A8%E5%85%B3%E8%81%94%E6%97%B6%EF%BC%8C%E7%BB%93%E6%9E%9C%E8%AE%B0%E5%BD%95%E6%95%B0%E6%B2%A1%E6%9C%89%E5%8F%98%EF%BC%8C%E4%BD%86%E6%98%AF%E4%B8%AD%E9%97%B4%E7%BB%93%E6%9E%9C%E4%B8%8D%E5%90%8C%EF%BC%8C%20%E4%B8%AD%E9%97%B4%E7%BB%93%E6%9E%9C%E5%B0%8F%EF%BC%8C%E5%8D%A0%E7%94%A8%E5%86%85%E5%AD%98%E5%B0%8F%EF%BC%8C%E6%89%80%E4%BB%A5%E6%95%B0%E6%8D%AE%E5%B0%91%E7%9A%84%E8%A1%A8%E4%BD%9C%E4%B8%BA%E9%A9%B1%E5%8A%A8%E8%A1%A8%E4%BC%98%E5%85%88%E6%9F%A5%E8%AF%A2%E3%80%82%0A%20%20%20%0A%20%20%20!%5Bc514e2d9c97f50312447c227f4565b72.png%5D(en-resource%3A%2F%2Fdatabase%2F679%3A1)%0A%20%20%20%0A%20%20%20%0A%20%20%20!%5Be82b3fbcf33e747586442f05ccf24888.png%5D(en-resource%3A%2F%2Fdatabase%2F677%3A1)%0A%20%20%20%0A%0A2.%20id%20%E5%80%BC%E4%B8%8D%E7%9B%B8%E5%90%8C%E6%97%B6%EF%BC%8C%E5%80%BC%E8%B6%8A%E5%A4%A7%E8%B6%8A%E4%BC%98%E5%85%88%E6%89%A7%E8%A1%8C%E3%80%82%E5%9B%A0%E4%B8%BA%E5%B5%8C%E5%A5%97%E5%AD%90%E6%9F%A5%E8%AF%A2%E6%97%B6%E5%85%88%E6%9F%A5%E5%86%85%E5%B1%82%E5%86%8D%E6%9F%A5%E5%A4%96%E5%B1%82%E3%80%82%0A%20%20%20%20%3E%20%E5%B5%8C%E5%A5%97%E6%9F%A5%E8%AF%A2%E6%97%B6%E5%85%88%E6%9F%A5%E5%86%85%E5%B1%82%EF%BC%8C%E5%86%8D%E6%9F%A5%E5%A4%96%E5%B1%82%0A%20%20%20%0A%20%20%20%20!%5Bae2ce5a31f5f848fa4da5cd07d975534.png%5D(en-resource%3A%2F%2Fdatabase%2F675%3A1)%0A%20%20%20%20%0A%0A%0A%0A%23%23%23%23%23%204.2%20select_type%20%E6%9F%A5%E8%AF%A2%E7%B1%BB%E5%9E%8B%0A%0A%7C%20%E7%B1%BB%E5%9E%8B%20%20%20%20%20%7C%20%E6%8F%8F%E8%BF%B0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20--------%20%7C%20------------------------------------------------------------%20%7C%0A%7C%20primary%20%20%7C%20%E5%8C%85%E5%90%AB%E5%AD%90%E6%9F%A5%E8%AF%A2SQL%E7%9A%84%E4%B8%BB%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5%E4%B8%80%E8%88%AC%E4%B8%BA%E6%9C%80%E5%A4%96%E5%B1%82%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20SUBQUERY%20%7C%20%E5%8C%85%E5%90%AB%E5%AD%90%E6%9F%A5%E8%AF%A2SQL%E7%9A%84%E5%AD%90%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5%E4%B8%80%E8%88%AC%E4%B8%BA%E9%9D%9E%E6%9C%80%E5%A4%96%E5%B1%82%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20SIMPLE%20%20%20%7C%20%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2%EF%BC%8C%E4%B8%8D%E5%8C%85%E5%90%AB%E5%AD%90%E6%9F%A5%E8%AF%A2%E5%92%8Cunion%E8%BF%9E%E6%8E%A5%E6%9F%A5%E8%AF%A2%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20DERIVED%20%20%7C%20%E8%A1%8D%E7%94%9F%E6%9F%A5%E8%AF%A2%EF%BC%8C%E5%9C%A8%E6%9F%A5%E8%AF%A2%E6%97%B6%E7%94%A8%E5%88%B0%E4%BA%86%E4%B8%B4%E6%97%B6%E8%A1%A8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%20%20%20%20%20%20%7C%20a.%E5%9C%A8%E5%AD%90%E6%9F%A5%E8%AF%A2%E7%9A%84from%E5%90%8E%E9%9D%A2%E5%8F%AA%E6%9C%89%E4%B8%80%E5%BC%A0%E8%A1%A8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%20%20%20%20%20%20%20%20%20%7C%20b.%E5%9C%A8%E5%AD%90%E6%9F%A5%E8%AF%A2from%E5%90%8E%E9%9D%A2%E6%9C%89%E4%B8%A4%E5%BC%A0%E8%A1%A8%EF%BC%8C%20%E5%A6%82%E6%9E%9Ctable%201%20union%20table2%EF%BC%8C%20%E5%88%99table1%E5%B0%B1%E6%98%AFderived%EF%BC%8Ctable2%E5%B0%B1%E6%98%AFunion%20%7C%0A%0A%3E%20%E6%95%B0%E5%AD%972%E8%A1%A8%E7%A4%BA%E8%A1%8D%E7%94%9F%E6%9F%A5%E8%AF%A2%E4%BD%BF%E7%94%A8%E4%BA%86id%E4%B8%BA2%E7%9A%84%E8%A1%A8%0A%0A!%5B76b8f8116a7e8b0b58823b1b2e0bb4bf.png%5D(en-resource%3A%2F%2Fdatabase%2F673%3A1)%0A%0A%0A%23%23%23%23%23%204.3%20type%20%E7%B4%A2%E5%BC%95%E7%B1%BB%E5%9E%8B%0A%0A%60%60%60%0Asystem%20%3E%20%20const%20%3E%20%20eq_ref%20%3E%20%20ref%20%3E%20range%20%3E%20%20index%20%3E%20%20all%EF%BC%8C%20%E8%B6%8A%E5%BE%80%E5%B7%A6%E8%B6%8A%E9%AB%98%E6%95%88%0A%E5%85%B6%E4%B8%AD%20system%2Cconst%20%E5%8F%AA%E6%98%AF%E7%90%86%E6%83%B3%E6%83%85%E5%86%B5%EF%BC%8C%E9%80%9A%E8%BF%87%E8%87%AA%E5%B7%B1%E4%BC%98%E5%8C%96%E5%AE%9E%E9%99%85%E8%83%BD%E8%BE%BE%E5%88%B0%20ref%20%3E%20range%0A%60%60%60%0A%0A%23%23%23%23%23%23%204.3.1%20system%0A%3E%20%E5%8F%AA%E6%9C%89%E4%B8%80%E6%9D%A1%E6%95%B0%E6%8D%AE%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%A1%A8%EF%BC%8C%E6%88%96%E8%A1%8D%E7%94%9F%E8%A1%A8%E5%8F%AA%E6%9C%89%E4%B8%80%E6%9D%A1%E6%95%B0%E6%8D%AE%E7%9A%84%E4%B8%BB%E6%9F%A5%E8%AF%A2%0A%0A!%5B24f2c50639a58fec6caa98a686cb566c.png%5D(en-resource%3A%2F%2Fdatabase%2F672%3A1)%0A%0A%23%23%23%23%23%23%204.3.2%20const%0A%3E%20%E5%BF%85%E9%A1%BB%E9%80%9A%E8%BF%87primarykey%20%E6%88%96%20unique%E7%B4%A2%E5%BC%95%E6%9F%A5%E8%AF%A2%E6%97%B6%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BB%85%E4%BB%85%E8%83%BD%E6%9F%A5%E5%88%B0%E4%B8%80%E6%9D%A1%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A!%5Bfe7906ae6b120cd0c9b76fa7ead3df47.png%5D(en-resource%3A%2F%2Fdatabase%2F680%3A1)%0A%0A%0A%23%23%23%23%23%23%204.3.3%20eq_ref%0A%3E%20%E5%94%AF%E4%B8%80%E6%80%A7%E7%B4%A2%E5%BC%95%0A%3E%20%E5%AF%B9%E4%BA%8E%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%B4%A2%E4%BB%B6%E9%94%AE%E7%9A%84%E6%9F%A5%E8%AF%A2%E8%BF%94%E5%9B%9E%E5%80%BC%E5%8C%B9%E9%85%8D%E5%94%AF%E4%B8%80%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%9C%89%E4%B8%94%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%80%BC%EF%BC%8C%E4%B8%8D%E8%83%BD%E5%A4%9A%E4%B9%9F%E4%B8%8D%E8%83%BD%E6%98%AF0%EF%BC%8C%E6%9F%A5%E8%AF%A2%E7%9A%84%E7%BB%93%E6%9E%9C%E5%92%8C%E8%A1%A8%E4%B8%AD%E5%AE%9E%E9%99%85%E7%9A%84%E6%9D%A1%E6%95%B0%E6%98%AF%E4%B8%80%E6%A0%B7%E7%9A%84%EF%BC%8C%E5%B8%B8%E8%A7%81%E4%BA%8Eprimary%20key%E6%88%96unique%E7%B4%A2%E5%BC%95%E6%9F%A5%E8%AF%A2%E6%97%B6%E3%80%82%0A%E6%AF%94%E5%A6%82%E9%80%9A%E8%BF%87%E5%90%8D%E5%AD%97%E6%9F%A5%E8%AF%A2%E6%97%B6%EF%BC%8C%E6%AF%8F%E4%B8%AA%E5%90%8D%E5%AD%97%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%80%BC%EF%BC%8C%E4%B8%8D%E8%83%BD%E5%87%BA%E7%8E%B0%E4%B8%A4%E4%B8%AAJohn%0A%0Aalter%20table%20taechercard%20add%20constraint%20pk_tcid%20primary%20key(tcid)%3B%0Aalter%20table%20taecher%20%20%20%20%20%20%20add%20constraint%20uk_tcid%20unique%20%20index(tcid)%3B%0A%0A%3E%20select%20t.tcid%20from%20teacher%20t%20%2C%20teachercard%20tc%20where%20t.tcid%3Dtc.tcid%3B%0A%E9%80%9A%E8%BF%87%E5%A4%96%E9%94%AEtcid%E6%9F%A5%E8%AF%A2%E6%97%B6%EF%BC%8Cteacher%E9%87%8C%E9%9D%A2%E7%9A%84%E8%AE%B0%E5%BD%95%E6%95%B0%E8%A6%81%E5%92%8Cteachercard%E9%87%8C%E9%9D%A2%E7%9A%84%E8%AE%B0%E5%BD%95%E6%95%B0%E4%B8%80%E8%87%B4%EF%BC%8C%E5%B9%B6%E5%85%A8tcid%E5%9C%A8teacher%E9%87%8C%E9%9D%A2%E4%BD%9C%E4%B8%BA%E5%A4%96%E9%94%AE%E6%98%AF%E5%94%AF%E4%B8%80%E5%80%BC%E3%80%82%0A%0A!%5B330bfb328b2c9aa0e9642ac346120836.png%5D(en-resource%3A%2F%2Fdatabase%2F681%3A1)%0A%0A%0A%23%23%23%23%23%23%204.3.4%20ref%0A%3E%20%E9%9D%9E%E5%94%AF%E4%B8%80%E6%80%A7%E7%B4%A2%E5%BC%95%EF%BC%8C%20%E5%AF%B9%E4%BA%8E%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%B4%A2%E4%BB%B6%E9%94%AE%E7%9A%84%E6%9F%A5%E8%AF%A2%E8%BF%94%E5%9B%9E%E5%80%BC%E5%8C%B9%E9%85%8D%E4%B8%80%E8%A1%8C%EF%BC%8C0%E8%A1%8C%E6%88%96%E5%A4%9A%E8%A1%8C%E6%95%B0%E6%8D%AE%E3%80%82%0Aalter%20table%20teacher%20add%20index%20index_name(tname)%3B%0A%0A!%5B7ff24030da584971ac70360d5c14de05.png%5D(en-resource%3A%2F%2Fdatabase%2F683%3A1)%0A!%5B791c818bab315776f603ed64bb434ddc.png%5D(en-resource%3A%2F%2Fdatabase%2F682%3A1)%0A%0A%23%23%23%23%23%23%204.3.5%20range%0A%3E%20%E8%8C%83%E5%9B%B4%E7%B4%A2%E5%BC%95%0A%3E%20%E6%A3%80%E7%B4%A2%E6%8C%87%E5%AE%9A%E8%8C%83%E5%9B%B4%E7%9A%84%E8%A1%8C%EF%BC%8C%20where%E5%90%8E%E9%9D%A2%E6%98%AF%E4%B8%80%E4%B8%AA%E8%8C%83%E5%9B%B4%E6%9F%A5%E8%AF%A2%EF%BC%8C%20between%2C%20in%20%20%3E%20%3C%20%3E%3D%20%3C%3D%2C%20in%E6%9C%89%E6%97%B6%E8%B5%B0range%E6%9C%89%E6%97%B6%E4%BC%9A%E6%98%AFall.%0A%0A%23%23%23%23%23%23%204.3.6%20index%0A%3E%20%E5%B0%86%E7%B4%A2%E5%BC%95%E6%A0%91%E5%85%A8%E9%83%A8%E6%9F%A5%E8%AF%A2%E4%BA%86%E4%B8%80%E9%81%8D%0A%3E%20%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%B0%86%E7%B4%A2%E5%BC%95%E5%88%97%E7%9A%84%E6%89%80%E6%9C%89%E5%80%BC%E5%85%A8%E9%83%A8%E6%9F%A5%E8%AF%A2%E4%BA%86%E4%B8%80%E9%81%8D%0A%3E%20alter%20table%20teacher%20add%20index%20tid_index(tid)%3B%0A%0A!%5B87b4e0ce5b89a11909e40b518f9561aa.png%5D(en-resource%3A%2F%2Fdatabase%2F674%3A1)%0A%0A%0A%23%23%23%23%23%23%204.37.%20all%EF%BC%9A%E5%B0%86%E5%85%A8%E8%A1%A8%E6%9F%A5%E8%AF%A2%E4%BA%86%E4%B8%80%E9%81%8D%0A%3E%20%E5%9C%A8tid%E4%B8%8A%E6%B2%A1%E6%9C%89%E5%BB%BA%E7%AB%8B%E7%B4%A2%E5%BC%95%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E5%B0%86%E5%85%A8%E8%A1%A8%E6%89%AB%E6%8F%8F%0A%0A!%5Bdfeaa68ae4214d54212fe736d4753c74.png%5D(en-resource%3A%2F%2Fdatabase%2F684%3A1)%0A%0A%23%23%23%23%23%23%20%205.%20possible_keys%20%E5%92%8C%20key%0A%3E%20possible_keys%20%E5%8F%AF%E8%83%BD%E7%94%A8%E5%88%B0%E7%9A%84%E7%B4%A2%E5%BC%95%EF%BC%8C%E6%98%AF%E4%B8%80%E7%A7%8D%E9%A2%84%E6%B5%8B%EF%BC%8C%E4%BD%86%E6%98%AF%E4%B8%8D%E5%87%86%E7%A1%AE%0A%3E%20key%20%E5%AE%9E%E9%99%85%E7%94%A8%E5%88%B0%E7%9A%84%E7%B4%A2%E5%BC%95%0A%3E%20%E5%A6%82%E6%9E%9C%E5%AF%B9%E5%BA%94%E7%9A%84%E5%80%BC%E4%B8%BAnull%E8%AF%B4%E6%98%8E%E6%B2%A1%E6%9C%89%E7%B4%A2%E5%BC%95%0A%0A%0A%23%23%23%23%23%23%206.%20key_len%20%E7%B4%A2%E5%BC%95%E9%95%BF%E5%BA%A6%0A%0A%3E%20%E7%94%A8%E4%BA%8E%E5%88%A4%E6%96%AD%E5%A4%8D%E5%90%88%E7%B4%A2%E5%BC%95%E6%98%AF%E5%90%A6%E8%A2%AB%E5%AE%8C%E5%85%A8%E4%BD%BF%E7%94%A8%0A%0A%60%60%60%0Aalter%20table%20teacher%20add%20index%20index_name(tid)%3B%0Acreate%20table%20test_kl(%0A%20name%20char(20)%20not%20null%20default%20''%0A)%3B%0Aalter%20table%20test_kl%20add%20index%20index_name(name)%3B%0Aselect%20*%20from%20test_kl%20where%20name%3D''%3B%0A%60%60%60%0A%0A%60%60%60%0Auft8%20%20%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A63%E4%B8%AA%E5%AD%97%E8%8A%82%0Agbk%20%20%20%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A62%E4%B8%AA%E5%AD%97%E8%8A%82%0Alatin%20%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A61%E4%B8%AA%E5%AD%97%E8%8A%82%0A%60%60%60%0A20%20x%203%20%3D%2060%20%0A!%5Bdcaaf2a42fac111ba88d23aac6397764.png%5D(en-resource%3A%2F%2Fdatabase%2F685%3A1)%0A%0A%3E%20mysql%E5%AF%B9%E4%BA%8E%E4%B8%BA%E7%A9%BA%E7%9A%84%E7%89%B5%E5%BC%95%E5%88%97%E9%A2%9D%E5%A4%96%E7%94%A81%E4%B8%AA%E5%AD%97%E8%8A%82%E6%A0%87%E8%AF%86%0A%60%60%60%0Aalter%20table%20add%20column%20name1%20char(20)%3B%0Aalter%20table%20test_k1%20add%20index%20index_name1(name1)%3B%0A%60%60%60%0A20%20x%203%20%2B1%3D%2061%0A!%5Bd56f95dc76a502c0eea6857d8e899435.png%5D(en-resource%3A%2F%2Fdatabase%2F686%3A1)%0A%0A%0A%23%23%23%23%23%23%20%205.%20ref%20%E4%B8%8Etype%E4%B8%AD%E7%9A%84ref%E5%80%BC%E5%8C%BA%E5%88%86%0A%0A%E6%8C%87%E6%98%8E%E5%BD%93%E5%89%8D%E8%A1%A8%E5%8F%82%E7%85%A7%E7%9A%84%E5%AD%97%E6%AE%B5%EF%BC%9A%0A%0Aselect%20*%20from%20where%20a.c%3Db.x%3B%20(%E5%85%B6%E4%B8%ADb.x%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%B8%B8%E9%87%8F%2C%20const)%0A%0A!%5Bc3bad6c3641ed053f3145410f17f07b6.png%5D(en-resource%3A%2F%2Fdatabase%2F676%3A1)%0A%0A%0A%23%23%23%23%23%23%206.%20rows%20%E8%A2%AB%E7%B4%A2%E5%BC%95%E4%BC%98%E5%8C%96%E5%90%8E%E6%9F%A5%E8%AF%A2%E7%9A%84%E6%95%B0%E6%8D%AE%E6%9D%A1%E6%95%B0%0A%0A!%5B051fc1db8e1dbb0f7610204df11c942b.png%5D(en-resource%3A%2F%2Fdatabase%2F671%3A1)%0A%0A%0A%0A%23%23%23%23%23%23%207.%20extra%0A%201.%20**using%20filesort**%3A%0A%0A%20%20%20%20%E6%80%A7%E8%83%BD%E6%B6%88%E8%80%97%E5%A4%A7%EF%BC%8C%E9%9C%80%E8%A6%81%E9%A2%9D%E5%A4%96%E7%9A%84%E4%B8%80%E6%AC%A1%E6%8E%92%E5%BA%8F(%E6%9F%A5%E8%AF%A2)%EF%BC%8C%E5%B8%B8%E8%A7%81%E4%BA%8E%E6%8E%92%E5%BA%8F%E4%B8%AD%0A%0A1.%201%20%E5%AF%B9%E4%BA%8E%E5%8D%95%E7%89%B5%E5%BC%95%E5%A6%82%E6%9E%9C%E6%9F%A5%E6%89%BE%E5%92%8C%E6%8E%92%E5%BA%8F%E4%B8%8D%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%E5%B0%B1%E4%BC%9A%E5%87%BA%E7%8E%B0using%20filesort%0A%20%20%20%E5%A6%82%E6%9E%9C%E6%9F%A5%E6%89%BE%E5%92%8C%E6%8E%92%E5%BA%8F%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%E5%88%99%E4%B8%8D%E4%BC%9A%E5%87%BA%E7%8E%B0using%20filesort%0A%20%20%20%E5%8F%AF%E4%BB%A5%E6%8C%89%E7%85%A7%E6%9F%A5%E6%89%BE%E4%BB%80%E4%B9%88%E5%AD%97%E6%AE%B5%E5%B0%B1%E7%94%A8%E4%BB%80%E4%B9%88%E5%AD%97%E6%AE%B5%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%0A%20%20%20%0A%20%20%20%60%60%60sql%0A%09select%20*%20from%20test02%20where%20a1%3D%20''%20order%20by%20a1%3B%20%20%20--%E4%B8%8D%E4%BC%9A%E5%87%BA%E7%8E%B0%20using%20filesort%0A%09select%20*%20from%20test02%20where%20a1%3D%20''%20order%20by%20a2%3B%20%20%20--%20using%20filesort%0A%09%60%60%60%0A%20%20%20%0A%20%20%20%0A%20%20%20%0A%20%20%201.2%20%E5%A4%8D%E5%90%88%E7%B4%A2%E5%BC%95%EF%BC%8C%E6%9C%80%E4%BD%B3%E5%B7%A6%E5%89%8D%E7%BC%80%EF%BC%8C%E4%B8%8D%E8%83%BD%E8%B7%A8%E5%88%97.%0A%20%20%20%0A%20%20%20%60%60%60sql%0A%20%20%20alter%20table%20test02%20add%20index%20idx_a1_a2_a3%0A%20%20%20explain%20select%20*%20from%20test02%20where%20a1%3D''%20order%20by%20a3%20--%20using%20filesort%0A%20%20%20explain%20select%20*%20from%20test02%20where%20a2%3D''%20order%20by%20a3%20--%20using%20filesort%0A%20%20%20explain%20select%20*%20from%20test02%20where%20a1%3D''%20order%20by%20a2%20--%E4%B8%8D%E4%BC%9A%E5%87%BA%E7%8E%B0%20using%20filesort%0A%09%60%60%60%0A%0A%20%20%20%0A%0A2.%20**using%20temporary**%3A%20%0A%0A%20%20%20%E6%80%A7%E8%83%BD%E6%8D%9F%E8%80%97%E6%AF%94%E8%BE%83%E5%A4%A7%EF%BC%8C%E7%94%A8%E5%88%B0%E4%BA%86%E4%B8%B4%E6%97%B6%E8%A1%A8%EF%BC%8C%E5%B8%B8%E8%A7%81%E4%BA%8Egroup%20by%20%E4%B8%AD.%0A%0A%20%20%20%E5%A6%82%E6%9E%9C%E6%9F%A5%E6%89%BE%E5%92%8C%E5%88%86%E7%BB%84%E4%B8%8D%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%E5%88%99%E4%BC%9A%E5%87%BA%E7%8E%B0using%20temporary%0A%20%20%20%E6%89%80%E4%BB%A5%E5%A6%82%E6%9E%9C%E6%9F%A5%E6%89%BE%E5%93%AA%E4%BA%9B%E9%98%9F%E5%B0%B1%E7%94%A8%E8%BF%99%E4%BA%9B%E5%88%97%E8%BF%9B%E8%A1%8C%E5%88%86%E7%BB%84%0A%0A%09%60%60%60sql%0A%09select%20*%20from%20test02%20where%20a1%20in%20('1'%EF%BC%8C'2'%EF%BC%8C'3')%20group%20by%20a1%3B%20--%20%E4%B8%8D%E4%BC%9A%E5%87%BA%E7%8E%B0using%20temporary%0A%09select%20*%20from%20test02%20where%20a1%20in%20('1'%EF%BC%8C'2'%EF%BC%8C'3')%20group%20by%20a2%3B%20--%20using%20temporary%0A%09%60%60%60%0A%0A3.%20**using%20index**%0A%0A%20%20%20%E6%84%8F%E5%91%B3%E7%9D%80%E6%80%A7%E8%83%BD%E6%8F%90%E5%8D%87%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%89%80%E6%9C%89%E7%9A%84%E6%9F%A5%E8%AF%A2%E5%88%97%E9%83%BD%E5%9C%A8%E7%B4%A2%E5%BC%95%E4%B8%AD%E5%8D%B3%E3%80%90%E7%B4%A2%E5%BC%95%E8%A6%86%E7%9B%96%E3%80%91%0A%0A%20%20%20%E5%8E%9F%E5%9B%A0%E6%98%AF%E4%B8%8D%E9%9C%80%E8%A6%81%E8%AF%BB%E5%8F%96%E5%8E%9F%E6%96%87%E4%BB%B6%2C%E5%8F%AA%E4%BB%8E%E7%B4%A2%E5%BC%95%E6%96%87%E4%BB%B6%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE%EF%BC%8C%20%E5%8D%B3%E6%B2%A1%E6%9C%89%E5%9B%9E%E8%A1%A8%E6%9F%A5%E8%AF%A2%0A%0A%20%20%20%60%60%60sql%0A%20%20%20alter%20table%20test01%20add%20index%20a1_a2_a3_inx%20(a1%2Ca2%2Ca3)%3B%0A%20%20%20select%20a1%2C%20a2%2C%20a3%20from%20test01%20where%20%20a1%3D''%20%20--using%20index%0A%20%20%20%0A%20%20%20drop%20index%20a1_a2_a3_inx%20%20on%20table%20test01%20%3B%0A%20%20%20alter%20table%20test01%20add%20index%20a1_a2_inx%20(a1%2Ca2)%3B%20%0A%20%20%20select%20a1%2C%20a3%20from%20test01%20where%20%20a1%3D''%20and%20a3%3D''%20--%20%E4%B8%8D%E7%94%A8%E4%BD%BF%E7%94%A8using%20index%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A4.%20**using%20where**%0A%0A%20%20%20%E9%9C%80%E8%A6%81%E5%9B%9E%E8%A1%A8%E6%9F%A5%E8%AF%A2%EF%BC%8C%E5%8D%B3%E9%9C%80%E8%A6%81%E4%BB%8E%E7%B4%A2%E5%BC%95%E6%9F%A5%E5%8F%88%E9%9C%80%E8%A6%81%E5%9B%9E%E5%8E%9F%E8%A1%A8%E6%9F%A5%EF%BC%8C%0A%0A%20%20%20%60%60%60%0A%20%20%20alter%20table%20test01%20add%20index%20age_inx(age)%3B%0A%20%20%20select%20name%20%2C%20age%20from%20test01%20where%20age%3D''%20%20%E6%AD%A4%E8%AF%AD%E5%8F%A5%E5%BF%85%E9%A1%BB%E5%9B%9E%E5%8E%9F%E8%A1%A8%E6%9F%A5name%2C%E5%9B%A0%E6%AD%A4%E4%BC%9A%E6%98%BE%E7%A4%BAusing%20where%0A%20%20%20%60%60%60%0A%0A%0A%0A5.%20impossible%20where%0A%0A%20%20%20where%20%E6%B0%B8%E8%BF%9C%E4%B8%BAfalse.%0A%20%20%20%0A%20%20%20%60%60%60sql%0A%20%20%20select%20*%20from%20test02%20where%20a1%3D'x'%20and%20a1%3D'y'%20%20--%20impossible%20where%0A%09%60%60%60%0A%20%20%20%20!%5B14f4a2d0eeb0e11cda394f88a849416f.png%5D(en-resource%3A%2F%2Fdatabase%2F678%3A1)%0A%20%20%20%20%0A%20%20%20%0A%20%20%20

Kafka

创建时间:2020/9/2 14:35
更新时间:2020/9/2 14:39
作者:Chris

Kafka: LinkedIn开源的分布式发布-订阅消息系统

为何引入消息队列
  1. 解耦
    需求是变化的,应对变化的需要

  2. 冗余
    机器故障,避免数据丢失

  3. 扩展性
    消息队列解耦了处理过程,增大消息入队和处理的能力变得容易

  4. 灵活性与峰值处理能力
    消息队列能够使关键组件顶住突发的访问压力而不会因为突发的超负荷的请求而完全崩溃

Kafka特点

高吞吐率、低延迟
• 每秒处理几十万条消息,延迟最低几毫秒
可扩展性
• 支持动态扩展节点数据
持久性与可靠性
• 数据被持久化到磁盘上,支持数据多副本防止数据丢失
高容错
• 允许节点失败
高并发
• 支持上千个客户端同时读写

消息在一个partition中是有序的,但大于两个partition则存储时变成了无序将消息设置为同一个Key,这样就到存到同一个partition中

producer将数据写入到kafka的memstore, 当存满时会刷到本地磁盘中去当消费时会先去memstore查数据如果没有则去本地磁盘中检索。

producer

向broker发送消息, 可通过任意一个broker发现其他broker的位置信息,因为所有broker的信息在zoopkeeper中注册
消息组成
topic+key+value+timestamp

broker
  1. Producer 和 consumer之间的桥梁从producer端接收消息,并保存下来将消息发送给订阅的consumer
  2. 可将消息可靠地缓存一段时间每个消息保存成多副本(默认是3)可设置保存时间(默认一周)
partition与topic

Topic

用户划分message的逻辑概念,一个topic可以分布到不同broker上

Partition

Kafka横向扩展和一切并行化的基础,每个topic至少被切分成1个partition消息在Partition中是有编号的,称为“offset”
Kafka以Partition为单位对消息进行备份(replica),每个partition可以配置至少有1个replica

consumer

用户应用程序,负责从kafka中读取数据,并进行处理;

Consumer group

多个consumer可形成一个group,同时读取某个topic;
每个consumer读取一个或多个partition

Consumer position

每个consumer自己维护读取的位置(offset,一旦挂掉后,重启可继续读取)
Message 被追加到append-only文件中
Producer向文件中追加消息(顺序写)
Consumer从文件中读取一定范围的消息 (顺序读)

Kafka producer 程序设计
KafkaProducer -> 通过加载配置文件生成Producer Bean producer
ProducerRecord -> 封装了 topic, key, value, partition 和 timestamp
RecordMetadata -> Broker确认收到一条消息后,应答的元信息,包括
offset,checksum和partition等信息
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("acks", "all");
props.put("retries", 0);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 33554432);
props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");
KafkaProducer<Integer, String> producer = newKafkaProducer<>(props)
Kafka producer重要参数
bootstrap.servers -> 初始化Broker列表
key.serializer/value.serializer  -> Key和value序列化器
acks -> 可靠性级别:可选值:0,1(default),all
buffer.memory -> Producer数据缓存大小(等到满后会发给broker)
compression.type -> 数据压缩方式:none, gzip, snappy, 或lz4.
max.request.size/batch.size  -> 每个batch数据量
发送信息到kafka broker

producer.send(new ProducerRecord<String, String>("test", Integer.toString(i), Integer.toString(i)));

producer configuration doc

http://kafka.apache.org/0100/documentation.html#producerconfigs

Kafka consumer程序
KafkaConsumer -> 与Kafka broker通信的类,常用方法是subscribe和poll
ConsumerRecord -> 一个返回结果,包含topic,offset,key/value,timestamp等信息
ConsumerRecords -> 一组返回结果,保存每个partition对应的结果集
ConsumerConfig -> 参数配置,可通过该对象设置程序参数
Properties props = new Properties();
props.put(“bootstrap.servers”, “test1,test2,test3”);
props.put("groupid", “123”);
props.put("enable.auto.commit", ”true");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"
consumer = new KafkaConsumer<>(props);
Kafka consumer重要参数
bootstrap.servers -> 初始化Broker列表
key.deserializer/value.deserializer -> Key和value反序列化器
fetch.min.bytes -> 每次请求至少返回的数据大小(默认是1字节)
group.id -> Consumer所在的group
session.timeout.ms  -> Session超时时间,一旦超时,该consuemer将被移除所在group
enable.auto.commit  -> 是否自动提交offset
// subscribe topics
consumer.subscribe(Arrays.asList(topic));
// read data from subscribed topics
ConsumerRecords<String, String> records = consumer.poll(10000);
consumer configuration doc

http://kafka.apache.org/0100/documentation.html#consumerconfigs

Kafka consumer程序说明

如果某个topic的分区数小于接收线程数,则部分线程空闲
如果topic的分区数大于接收线程数,则部分接收线程会同时读取多个分区中的数据
同一个线程收到的数据可能来自多个Partition,不保证数据的顺序性

启动zookeeper

bin/zookeeper-server-start.sh  config/zookeeper.properties &

启动Kafka Broker
bin/kafka-server-start.sh -daemon config/server.properties
jps | grep Kafka
如果启动失败,可以查看kafka安装目录下的logs/kafkaServer.out文件,寻找失败原因
创建topic,名字为test,包含5个分区,副本数为1,数据保留时长为2天(默认是1天)
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 5 --topic test --config delete.retention.ms=172800000
生产数据

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test

启动一个终端消费数据
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning
open issues

为什么说Partition是Kafka横向扩展和一切并行化的基础,每个topic至少被切分成1个partition ?

Kafka%3A%20%20LinkedIn%E5%BC%80%E6%BA%90%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E5%8F%91%E5%B8%83-%E8%AE%A2%E9%98%85%E6%B6%88%E6%81%AF%E7%B3%BB%E7%BB%9F%0A%0A%23%23%23%23%23%20%E4%B8%BA%E4%BD%95%E5%BC%95%E5%85%A5%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%0A%0A%3E%201.%20%E8%A7%A3%E8%80%A6%0A%3E%20%20%20%20%E9%9C%80%E6%B1%82%E6%98%AF%E5%8F%98%E5%8C%96%E7%9A%84%EF%BC%8C%E5%BA%94%E5%AF%B9%E5%8F%98%E5%8C%96%E7%9A%84%E9%9C%80%E8%A6%81%0A%3E%0A%3E%202.%20%E5%86%97%E4%BD%99%0A%3E%20%20%20%20%E6%9C%BA%E5%99%A8%E6%95%85%E9%9A%9C%EF%BC%8C%E9%81%BF%E5%85%8D%E6%95%B0%E6%8D%AE%E4%B8%A2%E5%A4%B1%0A%3E%0A%3E%203.%20%E6%89%A9%E5%B1%95%E6%80%A7%0A%3E%20%20%20%20%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E8%A7%A3%E8%80%A6%E4%BA%86%E5%A4%84%E7%90%86%E8%BF%87%E7%A8%8B%EF%BC%8C%E5%A2%9E%E5%A4%A7%E6%B6%88%E6%81%AF%E5%85%A5%E9%98%9F%E5%92%8C%E5%A4%84%E7%90%86%E7%9A%84%E8%83%BD%E5%8A%9B%E5%8F%98%E5%BE%97%E5%AE%B9%E6%98%93%0A%3E%0A%3E%204.%20%E7%81%B5%E6%B4%BB%E6%80%A7%E4%B8%8E%E5%B3%B0%E5%80%BC%E5%A4%84%E7%90%86%E8%83%BD%E5%8A%9B%0A%3E%20%20%20%20%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E8%83%BD%E5%A4%9F%E4%BD%BF%E5%85%B3%E9%94%AE%E7%BB%84%E4%BB%B6%E9%A1%B6%E4%BD%8F%E7%AA%81%E5%8F%91%E7%9A%84%E8%AE%BF%E9%97%AE%E5%8E%8B%E5%8A%9B%E8%80%8C%E4%B8%8D%E4%BC%9A%E5%9B%A0%E4%B8%BA%E7%AA%81%E5%8F%91%E7%9A%84%E8%B6%85%E8%B4%9F%E8%8D%B7%E7%9A%84%E8%AF%B7%E6%B1%82%E8%80%8C%E5%AE%8C%E5%85%A8%E5%B4%A9%E6%BA%83%0A%0A%23%23%23%23%23%20Kafka%E7%89%B9%E7%82%B9%0A%0A%3E%20%E9%AB%98%E5%90%9E%E5%90%90%E7%8E%87%E3%80%81%E4%BD%8E%E5%BB%B6%E8%BF%9F%0A%3E%20%E2%80%A2%20%E6%AF%8F%E7%A7%92%E5%A4%84%E7%90%86%E5%87%A0%E5%8D%81%E4%B8%87%E6%9D%A1%E6%B6%88%E6%81%AF%EF%BC%8C%E5%BB%B6%E8%BF%9F%E6%9C%80%E4%BD%8E%E5%87%A0%E6%AF%AB%E7%A7%92%0A%3E%20%E5%8F%AF%E6%89%A9%E5%B1%95%E6%80%A7%0A%3E%20%E2%80%A2%20%E6%94%AF%E6%8C%81%E5%8A%A8%E6%80%81%E6%89%A9%E5%B1%95%E8%8A%82%E7%82%B9%E6%95%B0%E6%8D%AE%0A%3E%20%E6%8C%81%E4%B9%85%E6%80%A7%E4%B8%8E%E5%8F%AF%E9%9D%A0%E6%80%A7%0A%3E%20%E2%80%A2%20%E6%95%B0%E6%8D%AE%E8%A2%AB%E6%8C%81%E4%B9%85%E5%8C%96%E5%88%B0%E7%A3%81%E7%9B%98%E4%B8%8A%EF%BC%8C%E6%94%AF%E6%8C%81%E6%95%B0%E6%8D%AE%E5%A4%9A%E5%89%AF%E6%9C%AC%E9%98%B2%E6%AD%A2%E6%95%B0%E6%8D%AE%E4%B8%A2%E5%A4%B1%0A%3E%20%E9%AB%98%E5%AE%B9%E9%94%99%0A%3E%20%E2%80%A2%20%E5%85%81%E8%AE%B8%E8%8A%82%E7%82%B9%E5%A4%B1%E8%B4%A5%0A%3E%20%E9%AB%98%E5%B9%B6%E5%8F%91%0A%3E%20%E2%80%A2%20%E6%94%AF%E6%8C%81%E4%B8%8A%E5%8D%83%E4%B8%AA%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%8C%E6%97%B6%E8%AF%BB%E5%86%99%0A!%5B4932dbc8788c7c96ef5df630a17eef9b.png%5D(en-resource%3A%2F%2Fdatabase%2F1059%3A0)%0A%0A%0A%3E%20%E6%B6%88%E6%81%AF%E5%9C%A8%E4%B8%80%E4%B8%AApartition%E4%B8%AD%E6%98%AF%E6%9C%89%E5%BA%8F%E7%9A%84%EF%BC%8C%E4%BD%86%E5%A4%A7%E4%BA%8E%E4%B8%A4%E4%B8%AApartition%E5%88%99%E5%AD%98%E5%82%A8%E6%97%B6%E5%8F%98%E6%88%90%E4%BA%86%E6%97%A0%E5%BA%8F%E5%B0%86%E6%B6%88%E6%81%AF%E8%AE%BE%E7%BD%AE%E4%B8%BA%E5%90%8C%E4%B8%80%E4%B8%AAKey%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%B0%B1%E5%88%B0%E5%AD%98%E5%88%B0%E5%90%8C%E4%B8%80%E4%B8%AApartition%E4%B8%AD%0A%0A!%5Bd007e7fd10dc3f229b21fc27a9973425.png%5D(en-resource%3A%2F%2Fdatabase%2F1061%3A0)%0A%0A%3E%20producer%E5%B0%86%E6%95%B0%E6%8D%AE%E5%86%99%E5%85%A5%E5%88%B0kafka%E7%9A%84memstore%2C%20%E5%BD%93%E5%AD%98%E6%BB%A1%E6%97%B6%E4%BC%9A%E5%88%B7%E5%88%B0%E6%9C%AC%E5%9C%B0%E7%A3%81%E7%9B%98%E4%B8%AD%E5%8E%BB%E5%BD%93%E6%B6%88%E8%B4%B9%E6%97%B6%E4%BC%9A%E5%85%88%E5%8E%BBmemstore%E6%9F%A5%E6%95%B0%E6%8D%AE%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%88%99%E5%8E%BB%E6%9C%AC%E5%9C%B0%E7%A3%81%E7%9B%98%E4%B8%AD%E6%A3%80%E7%B4%A2%E3%80%82%0A%0A%23%23%23%23%23%20producer%20%0A%0A%3E%20%E5%90%91broker%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%2C%20%E5%8F%AF%E9%80%9A%E8%BF%87%E4%BB%BB%E6%84%8F%E4%B8%80%E4%B8%AAbroker%E5%8F%91%E7%8E%B0%E5%85%B6%E4%BB%96broker%E7%9A%84%E4%BD%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%2C%E5%9B%A0%E4%B8%BA%E6%89%80%E6%9C%89broker%E7%9A%84%E4%BF%A1%E6%81%AF%E5%9C%A8zoopkeeper%E4%B8%AD%E6%B3%A8%E5%86%8C%0A%3E%20%E6%B6%88%E6%81%AF%E7%BB%84%E6%88%90%0A%3E%20%60topic%2Bkey%2Bvalue%2Btimestamp%60%0A%0A%23%23%23%23%23%20broker%0A%0A%3E%201.%20Producer%20%E5%92%8C%20consumer%E4%B9%8B%E9%97%B4%E7%9A%84%E6%A1%A5%E6%A2%81%E4%BB%8Eproducer%E7%AB%AF%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%EF%BC%8C%E5%B9%B6%E4%BF%9D%E5%AD%98%E4%B8%8B%E6%9D%A5%E5%B0%86%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E7%BB%99%E8%AE%A2%E9%98%85%E7%9A%84consumer%0A%3E%202.%20%E5%8F%AF%E5%B0%86%E6%B6%88%E6%81%AF%E5%8F%AF%E9%9D%A0%E5%9C%B0%E7%BC%93%E5%AD%98%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%E6%AF%8F%E4%B8%AA%E6%B6%88%E6%81%AF%E4%BF%9D%E5%AD%98%E6%88%90%E5%A4%9A%E5%89%AF%E6%9C%AC%EF%BC%88%E9%BB%98%E8%AE%A4%E6%98%AF3%EF%BC%89%E5%8F%AF%E8%AE%BE%E7%BD%AE%E4%BF%9D%E5%AD%98%E6%97%B6%E9%97%B4%EF%BC%88%E9%BB%98%E8%AE%A4%E4%B8%80%E5%91%A8%EF%BC%89%0A%0A%23%23%23%23%23%20partition%E4%B8%8Etopic%0A!%5Bimage.png%5D(data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAA4AAAAH4CAYAAAAb2oPSAAAgAElEQVR4AeydB3xUVfbHf1Mzk957o4UQWui99yJgAwEL1rWuq2tZd3Vd%2Feu6u7ZV1y6KFUEERJDeayBASEiBJKSQQnpPZjLt%2Fzk3zGQmCZhAgCRz7uczee2%2Bc%2B%2F9vvte3nnn3HMlyXmJJnBiAkyACTABJsAEmAATYAJMgAkwgS5NoOBsEaRduoXcOCbABJgAE2ACTIAJMAEmwASYABMQBIxGIyuA3BeYABNgAkyACTABJsAEmAATYAL2QIAVQHu4ytxGJsAEmAATYAJMgAkwASbABJgAAJPJxBZA7glMgAkwASbABJgAE2ACTIAJMAF7IcBjAO3lSnM7mQATYAJMgAkwASbABJgAE7B7AqwA2n0XYABMgAkwASbABJgAE2ACTIAJ2AsBVgDt5UpzO5kAE2ACTIAJMAEmwASYABOwewKsANp9F2AATIAJMAEmwASYABNgAkyACdgLAVYA7eVKczuZABNgAkyACTABJsAEmAATsHsCrADafRdgAEyACTABJsAEmAATYAJMgAnYCwFWAO3lSnM7mQATYAJMgAkwASbABJgAE7B7AqwA2n0XYABMgAkwASbABJgAE2ACTIAJ2AsBVgDt5UpzO5kAE2ACTIAJMAEmwASYABOwewKsANp9F2AATIAJMAEmwASYABNgAkyACdgLAVYA7eVKczuZABNgAkyACTABJsAEmAATsHsCrADafRdgAEyACTABJsAEmAATYAJMgAnYCwFWAO3lSnM7mQATYAJMgAkwASbABJgAE7B7AqwA2n0XYABMgAkwASbABJgAE2ACTIAJ2AsBVgDt5UpzO5kAE2ACTIAJMAEmwASYABOwewKsANp9F2AATIAJMAEmwASYABNgAkyACdgLAVYA7eVKczuZABNgAkyACTABJsAEmAATsHsCrADafRdgAEyACTABJsAEmAATYAJMgAnYCwFWAO3lSnM7mQATYAJMgAkwASbABJgAE7B7AqwA2n0XYABMgAkwASbABJgAE2ACTIAJ2AsBVgDt5UpzO5kAE2ACTIAJMAEmwASYABOwewKsANp9F2AATIAJMAEmwASYABNgAkyACdgLAVYA7eVKczuZABNgAkyACTABJsAEmAATsHsCrADafRdgAEyACTABJsAEmAATYAJMgAnYCwFWAO3lSnM7mQATYAJMgAkwASbABJgAE7B7AqwA2n0XYABMgAkwASbABJgAE2ACTIAJ2AsBVgDt5UpzO5kAE2ACTIAJMAEmwASYABOwewKsANp9F2AATIAJMAEmwASYABNgAkyACdgLAbm9NJTbyQSYABNgAkyACTCBzkTAZDSitqwcRp0O2uqazlR1risTuGYEJDIZlGoVFGo1VG6u16ycriyYFcCufHW5bUyACTABJsAEmECHJ1BfU4uiM2koSc9A%2BfkclJ%2FPRdWFQmirqzt83bmCTOBGE1B7esDVzxce4aFwDwmCV89u8O7ZHTKF4kZXrcOWzwpgh700XDEmwASYABNgAkygqxIoTD6L88fjkHcyHsWp52AyGbtqU7ldTOCaEqgrLQP9CpLPWMqRK5Xw6xuJwEEDEDZiCFwDAyzHeAWQJOclmhgEE2ACTIAJMAEmwASYwLUlQJa99N37kbpzH2pLSy9ZmBYy1ECOaokCWokUBkhRL5GCX9guiYwP2BEBGQC5yQg5jFCZDHA26eAMHeSXuUM8QkPQa%2Fok9Bg%2FGmoPdzui1bypOYl5rAA2x8J7mAATYAJMgAkwASbQfgTy4xMRv%2BYX5J6Mbya0HlIUS1QokqpQJnFAqVQFnYRj9DUDxTuYwO8QUJv08DBq4WnUwsdYBy%2FQpxTbzyZSmQzhY0Zi4KKb4REa%2FDsSu%2BZhVgC75nXlVjEBJsAEmAATYAIdgMCF00mI%2FXoVClMaXdOoWqT05UidkC11RqFUDZNE0gFqy1VgAl2LgNxkQqCxBiGGagSaamD7WUWC8DEjMGjJbXanCLIC2LX6ObeGCTABJsAEmAAT6AAEKnLzcXT5tzh%2F7IRNbUqgwlm5G3KlTjCw0mfDhjeYwLUkoDAZEW6oQoShHM7QW4oii2DkzKmIXnobVC4ulv1deYUVwK58dbltTIAJMAEmwASYwHUlYNQbcHr9RsT98DP0unpL2RckaiTJPYWbp2UnrzABJnD9CZhMCDHWIEpfBnc03qOk%2FI169D50Gzvq%2BtfpOpfICuB1Bs7FMQEmwASYABNgAl2TQGVePva8%2BQGK085ZGlgKB5ySe6FQprbs4xUmwAQ6AAGTCd0MVYgylNlYBMNGDMWYJx7q0vMLsgLYAfofV4EJMAEmwASYABPo3ATO7TuEAx98Br1GIxpCY%2FxOyzyRKnMF2NWzc19crn2XJkDjBKP0pYg0lsM8EtfR0xMTn%2Fsj%2FPtGdsm2swLYJS8rN4oJMAEmwASYABO4HgRMRiOOf7tKRPg0l1coUSFG4YtaCU9CbWbCSybQ0Qm4G7UYpSuAK3SiqjK5HGMefwg9p4zv6FVvc%2F1YAWwzMj6BCTABJsAEmAATYAKAQafD3rc%2BQOahowIHBZtPlHogUe7BVj%2FuIEygExKQmUwYrC9Cd2OVpfYDF92CwUtvh6QLWfJJAbSNiGppLq8wASbABJgAE2ACTIAJtETAoNNj%2B6v%2FsSh%2FOkhxQO6PRIUnK38tAeN9TKATEKDIvMcUvjgh87bMHnhq1Voc%2Fmg5TCbb%2BQQ7QXMuW0X5ZY%2FyQSbABJgAE2ACTIAJMAELAb1WK5Q%2FmtydEk01vUcRiHKp0pKHV5gAE%2Bi8BFLlbqiSKDBGfwFymJCyZYdozKhH7%2B8ylkC2AHbe%2Fsk1ZwJMgAkwASbABK4jAaPBgN3%2Ffg9m5a8acuxQBLHydx2vARfFBK4HgQsyR%2BxVBIICOlEiJTDux5%2BvR9HXpQxWAK8LZi6ECTABJsAEmAAT6OwEjny6wjK5ey1k2K0MRLWUg7109uvK9WcCLREolqqwTxEA%2FcX4oCd%2FWIOUzQ3WwJbyd6Z9rAB2pqvFdWUCTIAJMAEmwARuCAGyAKRs3i7KJrdPsg5wpM8bcim4UCZw3QiUSFU4KPeH8WKJhz%2F%2BEhcSGty%2Fr1slrkFBrABeA6gskgkwASbABJgAE%2Bg6BErSMxDz6QrRIAoFcUjuh0oe89d1LjC3hAlchgC5g8bJvEQOk8mI3W%2F9D7WlZZc5o%2BMfYgWw418jriETYAJMgAkwASZwgwjo6jTY8%2Bb7MOj1ogb0IlgoU9%2Bg2nCxTIAJ3AgCqXJ3ZEhdRNF1pWXY%2B%2FaHnToyKCuAN6IXcZlMgAkwASbABJhApyAQu%2BIHVOTmi7pmSZxxVu7eKerNlWQCTKB9CRyX%2B6AUDkJofvxpnNmys30LuI7SWAG8jrCvpiiaf6Sl39XIbM251mW2Jv%2B1zEN1MRqNnfqLy7Xkw7JbT8C6X9ust17EFec0l3fFAtrpRLqXjF1sXqN2QsNimICFwIWkFCT%2Ftk1s10GG4wofyzFeYQJMwL4I0DyBMQpfGC4GhTm6%2FFtUFxZ3Sgg8D2AnuGy5WZlIT8uCVquzra0EkMkVcHN3Q1j3HvDydIFEYpvlarYMOg2OHjqG6hotvINDEd2%2F1w2b%2F0Sn1SA9KRlZuSXwDwpGv%2BhIyNqxrVfDic%2FtXAQ0tbU4m5yEgoJy24pLAKlUBkcnJ%2FgHByIwyB8OivZ7RNK4gay0NGRmnIdU7YrogVFwdXWyrcM13jIa9MjJzER2Zi5q6jSARApXd0%2BE9%2BwGf1%2FPdn1%2BXOOmsHgmcM0JmIxGHHz%2FM0s5sXIf6CT83dwChFeYgB0SoLG%2Fp2UeGGgoBc0JenT5N5j8wtOdjkT7vd10uqZ3lgqbcOLIIaz4%2FAcUFFXaVloigULpAB8%2FHwwZOR6L71%2BEUP%2F2c03R15Tjk7ffR0Z2IUbNW4yB%2FXreEAWQxl1kJCfg0%2F%2F8D8dT8jFp9k3oM5AVQNvOwFutJVBeUozVX3%2BNPXtP2Z4ikQgF0NXDHb379sf8Rbdi%2BLAoqJTt85g0GQ04uH0rVn6%2FAcqACPzz9WevrwJoNODorm34Ze1WnIpLRmVNHUjj8%2FALwPCxo7Fw8W3o3SvIlglvMQE7JnB2xx5U5OYJAuclzsiTXd8PNnaMnpvOBDo0gbMyd4QZquGOemQeOiqigvr379uh69y0cu3zZtNUKm%2B3KwGyWJSWlKKkqAKRAwfA18ejwfhsMqEkNxtJJ%2BORdOoMZK6eePrx2yBtJzMgvbCWl5ShpKgElVW1oMhn1ztpa6txMuYoNqz6CXsOnYAOKtRU192QulzvtnN514aAwWBAVUWF6NeePj7o0bsnnNRKkDdkXWU50s%2Bew5Yz6Sir1iM8%2FE8ICfK56OxxlfUxmVBbU4uS4hKoVBXQGQxXKbBtpxefT8eHb3%2BEEwmZ8AwIwsgJ46CpLMbhfUewJi0ddfVy%2FP3lh6FSyNommHMzgS5IgAK%2FnPj%2BJ9EycveKUzREAOyCTeUmMQEm0EYCRokEJxTemKxr%2BEAU%2B80qzH3z1TZKubHZWQG8sfzbXPr0WxZg7MhoiHc0kwlF2an4v%2BdeRU5pLfZs34M%2FPXIrpHIJygrykXuhFHKlGn7eTjiTkg6jRIHQbmEICvSFUV%2BPwvwC5JzPQ02tBiq1IwJDg%2BEf4APl5dzeTCZkn0tDZXW9cBdz9fFDSIA3jAYDyooKkXHuPKpr66B2ckZQSDD8%2Fb0hlze8UJYXF6GwsARGiQN8PFXISM9CrdaIkG7dER7m18y6qKkqx6ovvsT2XYeRcOoM9AYTJNxj29xn%2BIRLEwiL6IW7H3kAIf4eYmxpbXkJfvpyBXbsOorEE7EoKq1EUKAPdNXlOJeZC6NJitDwYGSkJKO0og7e%2FoGIiuoJmRSora5CRnomSkooNLQMHj7eCAkLgpuby2UVyOILuSgsKofRCCicXBDRI0TcC%2BSueT7tHHLyC1CvM4Isk6Hh3eDt7SrkkVt0QX4%2Byiu1cHd3gU5TjZzcIrh6eKNHzzA4O9tGKUyOPYLUzCJI5TLcfN%2B9WLhgMurKCmAsL8Ce2HM4snsPyp%2B5D%2F7utuddmh4fYQJdl0Dqjj2gSH%2BUzkldUMv%2FfLruxeaWMYErIFAkVSNf4ogAUy0KU87iwulk%2BPfrcwWSbswp%2FDp9Y7hfcal%2BgQHoEdEDDjIJjCYDXNRGKGQyYb1wcXMHvRlScIfEowfx1fdboXDxQu8QZ8TExEPh5IGbFi3EzInRiNmzFzt3HcL57DzU1mmgVKsRGBKCMZOnYsrUkXB3c25eR5MJCbFH8NXn36Oiuh7eYT2w7MG7oK%2FXIvnYMaxfuxFnUs%2BLsUUqRyeEdu%2BB6XOmY8TowXB2dEDKyVisW7cNNSZHBHnKkZSYihqNHnOX3Ie7l0yzKIqiYLKWVJXhpxXfoBSeGDlpEnLiTyCrVNO8XryHCVwhARrvF9o9HD2CvBsUwAp3eHq4CQVMpXaGQi4TylbR%2BVR8%2BNZX0BikGDSoN2IPHkFFlRYRg0bjldf%2BiPPJiVj78yYkJqWhrLQCJokUHl5eiBoYjWmzp6Ff327NlUCTCReyzuHb5d%2FibFoO5M7uuH3ZnejVIwRGbS02r1qD7TsPI7%2BwGPU6A5zd3NEzMgpzbpmFIYOjUFlWjO3r1%2BNAbDoCAryEkpqekY8e%2FYfggYeXopdzsA2VgO598OjTj6K6qhbzFs1FsJczDD4eCPTzEBZ1fb0OBuONsPPbVJM3mMANJ2DQG3B6%2FSZRD7L%2BJck9b3iduAJMgAl0PAKJcg8E6GpFxU6tXscKYMe7RF2nRjt%2F%2BRUZ8Schl0qg1%2BuQk3oGeWV18A0KxeIlCyCTSkGum0V553Fo32FIlSokeTjC1d0brkotZAo5Yg%2FsxacffIHUzAL4h4YgPCwAF7KysCchCYnxqTBIJZg7ayyaOoKlxh7B%2B29%2BiMNH4uHp3wuTbrkdwQFeKMg6h8%2Fe%2BwSHYhPhHRiCvgP7oDA7A7t%2B24Tc%2FGI4ODtj9Ih%2BKL6Qh5NHY5FfqoFapUBgQCCqa6vh7kPBJ5pEdJEACgc1Js5bgNB%2BgxEa6IsvX0lnBbDrdOUO0ZLs9HT88NkKeLiqYSSX58IixB4%2BCYnSCTPmzEKgnyekEqC2ohxHDx1FdZ0Oyafi4OLmA6WsHgpnZ1QW5eDjdz7Ejt3HAAdHRPXvA6VEjzOn4pBwMhH5hWV44OE7EdHdz6bNpTlZ2LJ3N35euxVagxoLH74XURHdIIUJ%2Bzb9go%2Fe%2BwKZBWXoO3Q4%2BkcFIiHmKNadTEBhcSk8%2F%2F4M1PV1SE9JwaE9R6ByVMHHywNymQwKB5X42RQGoOegoejWfxB09Too1Sqh8KYc3Y8jJ9Mhk8kQEhkFd6eG8NZNz%2BVtJmBPBLKPHEV1YZFocqbUGRpJ0%2F%2BG9kSD28oEmMClCJRIVSiCCj7QIPdkAipy8uAWHHip7B1qP1sAO9Tl%2BP3KHNyxCzEXXSopqqC2VgODyQQvBxW8fb2EBbBRigkyiQlRwyfj7jtnQS6XQqGUY80n3yElPQeRQ4bjjrvvQL%2FewSjITMOXn6zAibizWLNqA4YO7Ycgq%2FHuF9JP47%2F%2FOYrDMYnw9A%2FH48%2F9EbPnjoGDxIh9B%2FbiQEw8XH0CsegPD2LSmAHITozHis%2B%2FxsnjxxF7JA79%2B%2FWyVEuvqcOASdOxZPFsSEx69B%2FWD1Jp08hqEji6emLpww%2FB09cHZXk5HKHQQpBX2otAXlYWNqy%2BIMbN0vQMZAXT6XRw9vCEh48nFHKFbVFGPZx9uuEvLz4GlUwHt4AwxG7%2FDdt3xQjlb%2F6dd2HBnHGQGuuxf8sW%2FPDtGhzcvQtRA6IQFjLDIktTUYLVX3%2BH%2BFPJ0BqVWPrgA1hy53z4ebnCoKvByi%2B%2BQ%2BaFUvhHDMSzLz6FYF93JBwbiNf%2F9gZOHT2GA%2FtOYNrIsAZ5Rj08vAMxf%2FGtGNg3HN5BQfD39bCU1bgigUwuFz%2FAhITDu8UHncy8Mjh7BmLhnTfDUckvuo28eM1eCZzZsks0nezhZ2TtF1jNXnlyu5lAVyaQIneHj%2F4C6P%2Fq2e27MezepZ2iuawAdorL1FjJsdOno3evMChkElBwmKL8HOzctgsl%2BTl4%2F5%2FvIPDDNxDq42g5gcb2TbrpJowaOxiAEQmHDyMlLhkytROGjBqGadPHws1ZhZ69wpCccAppadk4e%2Bo0LhSUwT%2B80Q00MzkBaVoNDEYjXHwDMGXmKDirlaitqsTp00nQ6Ixw0uuRk56OXVWFqC4rQZ1WD21NFbKzc1BSUWOpk0ShxsSZ0zBy3HARcEIilTZ3j6NRVAolAoLoSwq7pVng8Uq7EggK64axkyfA28MRFG22orQEJ2KOIiPzAjas%2FBEh3UMwdcIgmzKHTp6G8RNHCMugrl6Ln18%2FCI3OgKAQP9y29GZEdfMDjAbIoMPxo0dx%2BEQm0lMzUFZRZ5FTVXQBh4rzhGun2jMAE2aMhR%2BN7ZMAmopCHE86Lyx0UqMR8TExSJAA1RUVkMgkqK6uQtLpZEw1K4AAukVGYvyMqejXq8HK2MyibimZbicD9qz5CV98tRJxCelQubjh3icewuSxA%2FgjizUnXrdLAjXFpcg7dVq0vVCiQpVUaZccuNFMgAm0jkC%2B1BE0R6gaBqTt3o8hd90hxtq37uwbl4sVwBvH%2FopKHj1lEqZNGgEHhQR6nR6a2mr4uSrx2TcbER9zAAcPxSJ0%2FniLbJlchuDwwIsulnSODnU1dZArnOHm5gondYPLFwWL8fDygNJBjvqiOmjqdGJcoVmQpqYWMpUcEr0RBZkp2LPvFG6ZMwIGkxGVlTQ9hQnVVRU4vG8v1HKZcEOtq9XAz9%2BbJldDvVZvFgW5gwMCArzF2MXmlj9LNl5hAtecQGBYCG5adDO6B3mJsbP1Wg0SDvbBe%2B8uR1pqMvbu2ocxwyJt6hHWKwwy8gsFGdxNqCyvEtMpOKhV8PHxaviYIZXBycUFbh7uMBkM0FRrbe4Bg64eJoUMJlL4Kkuxbet%2B9IsIglrtgPqaCtToGz56lBbn4bdfNouyaE4yhZM7PJ0U0OsNMFrVysPTDfS7rOJHd6nJgC1fLsdHn6%2FCufMX4OoVgif%2B%2BjhmzZoIF3b%2FtCLKq%2FZKIOtQjOWjY5bU1V4xcLuZABNoJQGTRIJsqTN6GytQV1aO%2FPhEBA0e0Mqzb1w2VgBvHPsrKtnRxQmu7q5wkDe8gJpM7vD2pH9SEpiMOpSV2k5uTe%2Bpyosuo4AUCrUKTh5OqM%2BrQ3FBCapqtPBwVcFQX4cL2QWordVC7eENVxcV6W2W5BrcHc%2F97VGseeddxKXl4auPPsXQYX3g4yiFh7ObmFCaxiE%2B8uxT6B7ogXptHcrLKmCSyhEYHIqQAA%2BkXZQmlUogl0t%2B92XVUjivMIFrRECuUMDF1QWubhdf9EwmBPj7QKlUgFysK8srRIRb6%2BKV8sbHJlmvPQK9YDqWhuqKapzPLoRvVCBIWassK0NhbiGkcjlcPRzh6KyyiJE7umHxH%2B5BdVoctu2IwcYffsDYiSMwdmgEHJw94CSVoNokQc%2BBI%2FDS8%2FcIpVKv0yL3fD5cPDzgFxQEKeot8mQyCeh32WQyYu%2F6NXj%2F4%2B%2BRlVcM74DeeOH1v2Dc%2BAFwdmys22Vl8EEm0MUJZBw8IlpIH1hyed6%2FLn61uXlMoH0IZMlchAJI0rJjYlkBbB%2BsLMWaAIVqr8rPBul%2FRpMRxfl52LJ2q7BeQKZA7%2F79rLM3W%2Ffx9UXf6H5IzDqAA9t2wtfHC2PHDEDysSPYvfsIamq1GDl%2BFAIo%2BIW0MeJmn8HDMXP6JPjoy%2FDk0%2F9CdtIprPhiLZ5%2FehEGjhgM5ZpdqCgvQ0pyGqL7TkPG6Sz89O1qFFTqMH%2FxQgSFdo5Bsc2A8Y4uTSD%2FfA42%2FfwLfNydYDLSPH0ViN1%2FGJlZ%2BcJyHR7RGwrlpQOjSKRyjJkyASs3HUVZ0QV89vb%2FcO%2BDC6HQ12D9D6uRnJYLb%2F9Q9I7qA3eXRlcy94BgTJk8Dj7TByM5KR2pGfn47L9fof9nr8DNzQ%2FDB%2FXAzmNnkZ2cgJziGgwfEI7Y3dvxyYer4Obnj1vuugsj%2B%2Fm36drkpyXgg3e%2FRFZ%2BiXCq9g3wQXJcDM4lxgo5jk7OmLd0IbxcWBlsE1jO3GUI6GrrUJTS8KmyWKJCvcTqK2iXaSU3hAkwgfYmUCZRWtxAz8eexKj2LuAayGv8lH0NhLPI9iewY%2F2v2Gc1T59eV4%2Ba6lqYTFLMWnw3Rg4Iv2yh3kHBmL1gPlJTMnEq9RxWfPgRflqhgqamBpVV1QjtG407ly2Ar487jFU0qLUhqdVOUDkoMXzGHMyZuhU%2Fbz6O7T%2BvwripIzFg1HjMnLALm%2FacxM%2FLl2PfhnVi7F9hYSlCoqLhFxgER1WTYBpmwbxkAjeQQHZqGr7%2FdLmInkvVoPks62rroNPpETlkFGZNHw2ny1jHKHrm4EkzcPetx%2FHNmp2I2b0NZ08dBch6WFEBqdoFU%2BbNxMSJw6C46DZK5ciVSjiqHRDWqycWLZqOd95fifhDu7Bq3WQ8tGQaHn7mESQ%2B8DcUFOXijedegI%2B3J0ou5KO4tBq9PYMQ2S8CALletz5tXrMe57IviLGFdFZ68glkp52yCPD09saYeTexAmghwiv2RoDG%2FlE0YEq5UqsoaPYGgtvLBJhA2whIJLggdUQ3Y5WIIFxVUAgXP9%2B2ybjOuVkBvM7Ar6Q4v4BADBo6GCVl1TanK5WOcHJ2hJuXO6KHj8K48UPhrFbQRIDwDgrB8NHD4OLmBlenRsuDXOGA6LHj8Ld%2Fe2Lbpu04FnsKZWXV8PD2wcxhIzD35pno06c7lAoZdHIH9Bs0EB6BwYiMCIUEEqicXfHgU39EUe1HqDdIkXDkOMY8ugiPv%2FIieqz7Ffv3HhX1dHT3wpyJUzDnlrkYFB0JuUwKb%2F8ADBw6CGW1Jni4Obcp4IRSpUavAf1R7xksJrm2epe2YcIbTOD3CKjUKvSOjEJ5je3XfalUAUdHR7h4uKJnRCTGThqNHj1ChGulk7snBo8YAo1GiwBfN5sinD19cP9f%2FoLIocOwdes%2BZGXlwwQpIvoNxJTZ0zFxyqgGN22TAQEhoRg8fAgcfLsJt0sKdDRn8VKcSS1ARm4xUmOOoXbhFPQZOR7%2F%2B%2Fo9%2FPjDOpym%2BTJrauEREITpt47FgjsWICLUBxVFOnSLiMDw0Vr06B5q5eptU72LG0bUG3SIHj4YxkvM9UfPCpXVx6WWpPA%2BJtCVCdBkzuZUKFWbV3nJBJgAE%2FhdAvTMIAWQUmHy2Q6vAEqS8xI5xOLvXtYbm6G%2BXgutpr7BzdOqKhKJVChRFEhF4eAApdXLGwWzqKvTiukVaLJrmcz2ZZcmuqU8Gq0WRoMJNJbJQaWCSqUUc4JRMTQGqrqqRpRLbnCOFy0hZCWprq4RQWLkcgUcndVizFO9RoM6jUbIoxCJSqUSarXaMsE7RUzUaOrFeY5Ojpb9Vk265Cp9la2rqRUTVcsVSqgdVS1GDr2kAD7ABC4SoL6kqdMIK581FAqgYv7R2ECFUmGxDBr0OtTU1AnrmcrJCQ5W9xrJoCkkGvq3Frp6vQgKQzJI2VQqFJaPHVqNBvXaeuFe6uiobrjXTEbUVNVAbzSC7mlnV2cxLQXdo3V1tajX6sQ9KJFJoVKphUwKQkP3oZCn00OpdICD2kGcZ90m6%2FXa6iro9cZLxtSl54ijs7MlwI31ubzOBOyBwOa%2FvYb8%2BNOgyd%2FXKrvB2HR%2BWnuAwG287gQUcjn8fd1xPq9YlE3bOn1D4Dzr9etesWtYoNpBCalMippajfCGoX%2BStbWNw46uYdHXTLSrsR6zdOeF%2FKg5MzDy4XuvWVlXKzgnMQ9sAbxaitfhfHq5o19bktJBBfpdKlF0ULXcCWqnS7u50MsoBchomqQyWWPQjIsHSYFUOTqKX9P85m1SIi83nsqcr6Wl9GJUxZaO8T4m0BYC1Jfoo0hbkkyugKvbpd2YSXH8vXuOyqOPLPSzSRIpnFq4z5vSN1wAACAASURBVOgedXZxAZrfguJ0ug%2Fp%2Fm2tncLR%2BRKCbCrDG0zAfgmUZzW8vFVAecOVv3%2B%2FfD%2B6h9mO8zXBBK1Wh7wLpdh3MB6bd8Ve0qLfnldx2eLpmDNtGO7%2F4zuorG6czqY9y%2Bjqsi7H8J7FUxEc6IV%2F%2FPt7hAR645nHb8OzL3%2BBvpFhuHnuGPz9jW8seMaMiMLBmCTLdnuv9O0din88fxc%2BWbEJO%2FfFXZF4Fyc1PnvvScilMrz0xjdISW24r6yFvfD0HRgxpDduufv%2F8OF%2FHoNKpcAdD%2FzLOkunW6%2BUKKCHBHKYUJqZ3eHrzwpgh79EXEEmwASYABNgAkzgWhLQVFahrqJCFFHeAeb%2Bc3J0gIuLGvsOJViaTR9l1SolonqHIrp%2Fd%2FTsEYT3Pl1vOX6tVtQqBVxdHcUwkGtVRleXeymGvboHYcHs0Xj4z%2B8LBLfOG4sf1%2B5FvU6PuxdNwVsf%2FmxB86eHF2DM8L7XVAEkTxC1usE6Zym4jSuTxw%2BEm4sTtNp63DRjRIsKYGlZJQwGg%2FCeKSwuR3CQTxtL6YDZJRJUQglPaFGZX9ABK2hbJVYAbXnwFhNgAkyACTABJmBnBGqKSywtrpVc2tpvyXQdVmi%2Bz3%2B%2Bu6pZSa7Oarz3r0cwe9owrNt4ENm5Rc3y8I7OQeCRe%2BfgYEwici66f%2Fp6u2H%2BnFGIPXkWvj4euGXuGHzw%2BQbRGDp2rVNCcibmLn75qoqZMWUoEs9koaioAhPG9McnX21CVY2t5fh%2Fn%2F2K4UMiUaepx5sfrMErL9x1VWV2lJOrJQp4mrRiPkBDfT1kysYYHB2ljuZ6sAJoJsFLJsAEmAATYAJMwC4JWCuANZKO%2FWpEbphbdh7HfUunI6p3mFAAfbzd4OnugrPpuRg1NFKM2T96PMXiskljychq6O%2FrIaZ7ik88h%2BLSliMJ9%2B4ZjB7hAaiuqUPsydRm%2FcHZSY3gQG%2Fk55egorrWclwmlaJXjyCUl1fjQlGZZT%2BtkKWLZJJl60zaeeTmNyrc5owUcXnQgJ7wcHNCSWklTsano47GTF9M5GpPdSsqrhCB5YZG90Lm%2BUKhbJjzWC%2FdXZ2EG6WHhzMqK2sRn5iB8soa6yxi%2FffKpUyRvUJQXFKB8vIaRA%2FoDn8%2FDxFA7%2FipVGi0umYyf48hndAnIgR9%2B4ThpdcbXTzJtX9Q%2Fx5iHDnN7TpkYC8hm%2Fg5OVJMBamoS1PGJKt7WAAMBiPOpOUgI7sxijsJ8PFyg5enq7DG9QjzFzJq6rQ4eSrN5hpSdOrQYF9cKCi1YUXunAP6d0OArycqKmuQkJSJiqrmLOka02%2F5d1txLjMfUyZEY9qkwVi78aANo6ULJ2H3%2FjhhAfzDvXPwy2%2BHbY531o06iQw00J5iaNSVV8LZ17vDNqVjP%2BU6LDauGBNgAkyACTABJtBVCNSWNiostZ0gPIL0YoAaGhdIad7MkeK3adtRkBshJVp%2F%2F7Nf0D%2BqG17400KhAOh0BigUMuF%2B9%2F2a3fj%2Bp90iL%2F2hwBzmsVnknkfT3JDSk5lt685G48Re%2FevdeOOdH7HHykWVgsi998bD2LDlCD784lchlyJ%2B%2F%2FXPd2BAVDeQRZMSBaWjF%2F6Pv9oktunPxLED8OQf5sNRrYJGWy%2BmnaqorMa%2F%2FrsaJ%2BLTRT65TNYgf%2FNhTBo7EC4ujkKBWPrQf1BSZqvM0viyF59ZAoVcJhReZycVqO0ff7VRcDEX3JpySbGldq3fdAgD%2B%2FVAtzA%2F8%2BlCUX3m718g70KDQttahiRg%2FqxRqK7R4GR8w9yTtO%2BzFb%2BBFGy9wYBX3%2FzBMsbzny8uE264lMeasbenK156ZgkiI0LENSUXTlKUyar41gc%2Fo1ajFXWdM304Fi4Yj1Xr9mLJbZNQXlENVxdHoZC%2F%2B9E67DkYL%2FL17BaIN199ALRvy66GOWJJ%2BX3xz3fAx9sd2nodHJQKEdDvv5%2Bsx%2B4DjVMJkYCZU4cKOQeOJKKgsAyl5VWYO2NEMwXwtx3HhCJPmanN5AbaFZKWFMCLqa6sjBVAMwxeMgEmwASYABNgAkygoxGgSeDNSdfBJ4CnIBvTJw8W1U1KyTJXGw4OCmFxEePGjCakZ%2BbDz9sdr%2F31blRV14IUlcSUTHi4ueCJh27C3YumCmvOxq1HhYwH7p4pAnOQ9YaUHaVSgT8sm43pkxrKshTUhpW%2F%2FGkRoiJC8d4n67F9z0lx5iP3z8WCOaORei4PO%2FaeRN%2FeYfjLkwuRfCYb%2F%2FlgDfILSkUwFFJGX37%2BTjz89Adin7lYUmb2HTotlBayejZV%2FkhBeeGpRUg5ex7%2F9%2Bb3wgpK%2BV594S48et9cHDicKKxXbS13%2FuxR2LXvFF5642thCbxp5gjBZ%2FEtE%2FD2R2tF9VrLkJQ0su6dTEiHztCgGJOAc1mNlrukM42BRO55%2FG28%2FOxS9OgWgHsefUso01KpRCjioUE%2BQmGjoC2k8N5802hxbQ0GE15%2FZ6UZm1C8Sel8%2Fh%2FLEXf6HNzdnPHK83fiuT%2FeLsrNzim05DWvkLsxcSPl%2Fdm%2FfwFyESWl%2FuXnluLZJ27FmdQc5BU0KL9kZZ48LhrUJ80K8c69cbh9%2FjhE9%2BsuyjTLJSuuOXUV5Y%2Fao0NjxP16q2eKua0dadlY045UK64LE2ACTIAJMAEmwASuEwHrlzVTB5lkiCxlD909y%2FKj8WIv%2Fnkxvvn4GQT6e2HzjmOWqQMIEykV363ehe27T2D73pPipZ6UFrLMvfvxeiQkZQiLEilMb7y7GiVlVVh6%2B2RxnqPKATOnDMWR2BSsXr9PWIbIBfTdj9eiJcWgNZeFopiS2%2BmGzUdAFh%2Ba2oB%2BHy%2FfKJQzX293IWbxrRPFFDX%2F99ZKi6JHUyL8850fhSXw5jmjbYqrqKoV48aoriS3aSLXT7XKQYyrM0ctJUsUBcwhiyi551Fqa7nklvrWh2uE5YraQW6N5CrZLypcyGsLw5AgH2HRy2piXW3aFvM2TZFgMOhhMprE1AlkiRsWHSHcLakeZK2jOpHFj6y6h48lYfzofiDl0Dp9%2F9MuiyJGVkBSXKmfzZ810jqbZX3y%2BGi4uToJbvFJGcLiSixpXCJ9YAgJbnRxHDO8D8jSalb0Scj2PSeErLkzW5ZvKaiLrOisLIDGixbvjto0dgHtqFeG68UEmAATYAJMgAlcFwImq5e1hhnYrkuxly2E3PnM7pzmjOSaSePeduw5ifW%2FHTLvtiytLYK0k6YSoPl3aayadSIF4tiJM0LpC%2FDzBAUYkctlOB5nm89oNCHm%2BBkxLsz6%2FNasR0WGimzHTp6xyU6KypN%2F%2FcSyr3%2FfcJSUVqBX90DLPvMKKT5mBcu870zqeRiMDUqceZ%2F1sqi0QiitFCQnNNhHKLU0lpEsjvQzp7aWm3ou1%2BKSaZZRXlEDby9XsRnRM6jVDL09G6blsbaEmWW2dmnmQu6WTdO%2BQ4kYNSxKXH%2FrIEFNp5Ag5b6wqBx9IxuU2KZyaL%2FRaMTxuEY3VcqTlpGHJ57%2F2Cb7jKlDxfy6B48kWubQzcktRtq5XIwe1gdeHq7NrLU2AnjjuhJgBfC64ubCmAATYAJMgAkwgY5MwNhBXEBpzNrty16zoDKaTGIMlmVHCyuVTaItkvXmUsFeSkoaxs3RWDAK20%2BpsqoxqItZfGlZlXn1skuyQFonKptSRUXzYCHmfCoHhbDy%2Bft5CndG837rpblu5n1VVY3uuuZ91ktSWv%2F62gr84Z7ZGDm0D%2Fr1CccDd83EhcIyrPllP37dGoMrKVejaR7shYKu4KLF2FzP1jB0cXIUVabxjlea6LpRKr54Ha3lkLWSkouz7Uyx5v3Ween6%2Bvg0WGOt99O6u5sT6urqLRPTNz1u3iZXYwpeQ31g9Yq%2FmXfbLGdMGYIf1jSOObU5yBvXnQArgNcdORfIBJgAE2ACTIAJMIHfI2CyiYL5e7npOLkIWicKs%2B910dpkvZ%2FW3dwaFDQaH0iue5Tohb9paqpEmI9LpLajiJQK21fK%2BvoGWyq5oDZNFFiFrHik5FKiCJ3%2F%2BPd3TbOJbdsWAaQI%2F14iy9prb68EuWWSpY8ihk4YMwCPPzgPtXVa7DnQEPSkLeWaA%2B5cquyaOo041BqG5rw0r%2BOVJrLsUqL5Iskt0zq5uTYohxRkxjpRlE%2FryK10jK5PTZMPB%2BZztFqdGAtKip2pCXfzNaS8UycNEsofjR3NL2wMqETHKGDRfUtnYM60YVi1du9lrbfmcnl57QnY3r3XvjwugQkwASbABJgAE2ACTOA6EMjIuiDGcIUENo7VMhfbp3eocA8tLKpAeka%2BeMHvE9HgtmnOQ8uIHkHWm9ALqxfg6Ohgsz%2BoSRnm6KG9egbb5KONj996XESbJCWQxsF1Dw%2BA0WAU49tqajViSQokTYY%2Bckhks%2FMvt4PGvT1092xQREsaE0curB8u34jnXl4uTovu30MoIe1dblsYmq2qrhetpJdrj%2FUxayNrela%2BONSvBfdNcv2llHXeNrBLr56219LN2REhQd5i6gjrcszrmecLRNTY7qGNkU%2FpGI2z%2FHXlP7Bs8TSh%2BM2YNERMtfHFN1tEACFSBM0%2FGqNIUUm9vdwwbHCEWTQvbzABVgBv8AXg4pkAE2ACTIAJMAEmcC0IUKAYSk88NF%2FMDWgu47abxooAIrv2nxLufWUV1Th0tCFwyOCBPc3ZxNitoYNsX9pzL05aTlMoKGQNYe8dHVW4Z%2FFUy3m0EhefLqaRuH3eOBG0xnxwwqj%2BCAv1Q1xCw%2FQOFMiFLJCPPXiTRR7lXbZkqogWanYlNZ%2FfdEkK6rSJg0TEUzpGiuOt88bg7jumguavM6fgiwFRcvOLxa6rLdcs17xsC0Oa%2BJ3GYVpPKWGWc6mlTm%2BESuVguY4HjiShqroOS2%2BfJKKmms%2FrFxkGipRKY%2F%2BSzjZGEqXj9y6ZBooiS4midj7xh%2Fliuo%2FN25sH06E8NNaUxgA%2BuGy2sKbSPrIG3rlwijjvxKk0EeHTz9cDew8l2EQ0FYVc%2FLNlZ8OUEjfNGGG9u8V1Gi9I19P62rWYkXdeFQFbe%2F1Vibp2J2vqNKipbu5DrnRQwsW1YSAtlW7QG1BdXQ29znYIN%2BVzdHSETN74IKisqISuvrk%2Ft4ubC5TKRpM8yaoobwxXa26lA92ETo6gQdqXK1sqk8Ldw13cMOZza2tqUdc0PKxEAkdHNdSOjf7aWq0WlJe%2BilknlVol8pnLpmOlJaXNXD8gkcDNzRXyi24ZZL7XarQtsnRydgK1yezDX19fj%2Bqq6mYyiSG1x5xIJl0bkmudqN3Ex8Gh8QuhaDe5SDRxI6CyqU3mRA%2Bb8rLyFst2cXGxXEfKRzKblk1y3NzdLO2mbY1Gg5oWJi1VKBVwdWsYwE35qA%2FV1NQ06xuUj%2FqQmSXlraqsQn0L%2FvvOrs427SaZ5dSHmrSb%2BiW13XwdaXA%2FsWzaLyVSiWgPzcnUHonqU1VVJdpqLY%2FK8fD0sPQBOkb9lBhbJ8qnVre%2Br1I%2FMPcrklNWWtasT5NMupcVCoUo6rJ91cVJ8DXL1Ol0qKyoasaX%2Bir1A3O%2BS%2FWXtvRVaov1PXqpvkr9xNnZ%2Bff7apN7lBpP9311ZbU1crHelr7q5ORkKZtOvlRfdXJxgkrVeO%2B1pa%2FS86Hps5auIz0fzH2aym7x%2BS2RiBcZ6v%2FmRM8c6mtUB%2BvU9D6hvkHP5Kb56Hnn4ups8%2Fy%2BFMumzzvr8nidCXQlAhS2%2F%2BuVO4RytuJ%2FTyElNRd%2BPu4ID%2FUTIf0%2F%2F2azpbkffrFRBHt5%2FW%2F34HRKlnh20px%2FKak5iOzVaMWjSd73HUzA%2BDH9seKjP4tJ3cnalnw2G2VWrog0vQFF8nztb%2Ffg47cfR2JKNpRKOfr3CQdFlFy9br8om%2BYNpCkZpk0cLJQJCjASFOAt6kLRLH%2FdfMRSx5ZWJo4ZIILlUBTRguJyMQk9jTWj%2Be6%2B%2BvBpUPAWmjOQyqXIlRu2xLRLuS3VpbUM63V6MQUEKWutTTSx%2BsihkVi9%2FAXsPZiAN%2F%2B3Bm%2B8uwp%2Ff24JPnr7CSSmZIlpIMiKS9fh9bdWNnPbVKtVWP7Bn0Q%2F6BbqB18fd9E%2FEq2mnLCuD1kAP13xGx65by6%2B%2FN9TOJOWi0A%2FD4SG%2BIlosXQd%2F%2FKnheIUmtLjUinu9DkxBnNIdC8xmXx%2BYemlsgqrIn0goOk69Frb%2FweXPIkPtJlAp1AA447HYevGbTYdWSqToe%2BAKNx6xy2WRhcVFmHjuk3Iyc6x7KOViMgITJ09Bb5%2BvmI%2FvbStX70emeeyxJcN68xLli1GRJ%2BGr130opGXm48Vn66wyUcvN4OGDcLUmVMsL4NU9q9rNyL3fK61OKFcPPHs4zYvtocPHMH%2BXQ0PPnNmUoBGjxuF8VPGm3chNSUNu7buEsqdZSeAEWNGYMKU8ULBMu%2F%2F8uOvhMJm3qalg0qFu%2B5fiuDQhge3Xq%2FH6VOn8dsvm23bI5Nh5twZGDJ8sOWlMetcFtb%2F9EszZdEvwA8PP%2FkHy0s1vbTt3LITJ2PjrIuGl48XJk2bhH4D%2B1r2xxw6ipiDMeKF0LKTJg69aQaGjx5ueWkkpWP5R182L9vfDwvvvF3IpvPpxXLPjr2IPdLwZcksk%2FrG%2FY%2Fci6CQRleHpIRkbFy70abdpBj07N0TS%2B9dYj5VKJ6bfvkN51LPWfbRSnj3cEybPdVG5qb1v%2BFsSiqMVnP4UN5b7rgFAwb1F%2BdTHyoqKsaXH30JYmWd%2Bkf3w6x5syzXsbysQtQxIz3DOptQjB564kGbjx02Gdq4UVxcjLUr16Hggu3kvqTc%2FPlvT4uveiSS7pOjh45i9%2FY9NiVQvpFjR2L85HGW%2FWeSzmL3tt1CubPsFH11OCZNn2SjZHz92TeCs3U%2BkrnoroUI69bwz5D66qkT8di6cavNNaNz5t8%2BX%2FA1K8Tns3Kw6tvV0Gpsxzr4%2BfvhwccfsCjt1F%2FofjpxzPafFPXVydMnoe%2BAxr5K9%2BjRQ8eayZw6ayrGTBht6f%2FUV7%2F6ZIVQsKzbQ33v5oUL4O3b4HZFHyl2bduNE0cbQmKb85KSev8j9yEgKMAi82xyKtb%2BuNb2eSeVonuv7rjzvqXmU0HXkZ6LLfXVmfNmwj%2Bg0WVH9NXkszYsqf%2FfdOtNGDxskJB5ub4aPSQaU2dNgbOLs8hLCtjaH9c1e9aSYkXPB%2FOHOZIZd%2FwUtvy6xVJvWqEPQ0NGDMH0OdMs%2B8%2BlZWDXll0oLLB1WRoweIB4PlEfoUT9cvV3PyEvpzGan5CpUuHWO262PL8pH%2FXLdavW2bCkdlO5VL71xz5LRXiFCXQAAr9tPybmaWttVcgSQ5YvGt%2FWNP3w826ciE%2FD5HEDQZaas%2Bm5oOkAKCKkdTRNmh7ij89%2FjFlTh4LcQ0ned6t2iikhaM46jdVH8%2F%2B8%2F5NQYAYNaLAWfvHtFmzddRw07cT53CJLFUixePBP72HOtOEID%2FMTE6dTvp17ybLUMJaPlq%2B%2F%2B6OYE3DU8D7wcHdBQnIWvvp%2BGw4dS7bIonuaprkghc46xZ5KBY11tJ6u4usfd4CYjBvVDz7ebqCANzQX4Y69cZaAJq0u12QS5Z676HJpXfaW3bFwtvpw3xaGpESTe2uPMH%2BkW83%2FZy3fev2HNXtQWVWHsGAfocjSMYru%2BsCT%2F8XsKcME3%2FJ6HfZ%2F%2FZuYioFcaZumV%2F7zHUYN6yMU%2BmNxqdix5wSs5xukyduJMSnh5rT%2Bt8NCeRdWVh93nErMFC61pNRROpd5ARlZBUhJPW8%2BpdmS%2Fhd8%2BPmv6N0rWIw9vZwCuGHrETy8bI5N32wmkHdcNYFOoQDW1WlQVFhs84WfXpyafiXX6fSgl%2BhiymuV%2FAP9bb4WU0esqKhEcVGxrSVCIkG91QOO8tGLaElxic35ZDEgSw0dN6eGssublU0RoqzzUX46t2kd6eWmpomlhb5ek2Wvad6a6upmMstKyppZKkmppPqbE9VDo9E2aw%2BxJAuZdSJlpaS4FNWVtgOLSSbJMVtVaMB5VVV1szqSEtZU4aGv%2B6XFpc0sSrW1dTbtIfnNypZIhEKrNzS2h%2F4ZtMSSrC%2FUbut61mu1og%2BZrEJH0wB280cBc9tJPlmHmzIny5g1S8pPVpWSomKbvkH7dU0UPYPoQ6XNlAmyWlEbzIkUSXqxblo2WVnIOtheSVh5ypr3VSd6uW%2Fs0qK42traZvWhfE0t2MSXLHtN615NVtcmMqlPUz%2BwTiTT2vIp%2BmpdXbO%2BSlYeoehZyaR%2BVlpc0qxO1tZnKotkUn2a1rGhr9p6AzT01eYyNXW20efo%2BtG9RxZr60SKkN7qmlE%2Bel41LZusejTBrnUy91VrizE9c3x8bedzout4yb6qs22P6KtNnmPEksqyTnqdTtx7TZVpshgTP3Mir4SW%2BipdC%2Bs%2BTflJVtN208cpunetU73mUn2o2lamCYJ3U5n0bLJ%2BfpPsllhSu%2Bl%2FCicm0JEJtDS%2F3eXqSxOK0%2B9SiV7OL%2FeCbj6Pxsz9vPEgQD%2BrZK0k0G6y7lEdm9aTxns1TRSF9OtVO5rubrYdc%2BIM6HepRMrqt6t3NjtMih79miayftLv99LvlUvPvpbKJbnbdtl%2B1KN9rWW490CCsHbNnDpUKFS%2FV0%2BaPmPdpuZ8KeBNa%2FiSfF29AT%2Bu3XvJosiC2lJbSeluqnibhdC8ka1JR0%2BeAf1%2BLx05loIlt04SHx5%2BLy8fv3ICkuS8xMb%2F6lcu55qdSS8T5OIlk8pA7kXWiZQQa1cjuknNv6b5KK9ZaaFjJNf6hcacn%2BRZ56M8TV9oKK9ZnjmvudyWZJotFeYyLiWztWU3zUdyL6UgNM17tWVTe0mmdbpama2tY1PmVIerLbtpe0ie%2BWfdxmtVtlmuuS0tlU3HmjKyrltb10mhpGhmTa8jyeG%2B2kCzPfqV9bUlqe3xzLG%2BZua%2BQkvrZC6XluZ0vcqm8pr21atl2VQelXG17WlJppkVL%2B2TQOyKlYj%2F%2BRfR%2BF%2BVYaiVdIrv4%2FZ5sbpQq2dNGYoH756Fex59C1WXiMTZHs2lYC008f29j72DvIKS9hB5zWT8%2FdklOHI8pUXl%2BpoV2k6CwwzVGKlv8K6a9vfnEXLRw6adxLebmJzEPHT4J1xZaTn27tyL4aOGWVwZL0XA%2FOJzqePW%2B61fpKz3N10nmU1fipvmoe22lN0Wma0pm8pvbb5rUXZ7y2ytPDP31rS9tTIpH%2F1ak9ois7V1bKlsetklawlZi5patVpTT%2Bs8pPwdPXxUuL71G9jPZuyldT7zenu3keS2hgXluxZlt7fM1sqj9tzIZ86NLLu1jFqbrz1YkscDeS%2FQ%2BMLW9kcqlxMTYAJMoD0JbNl1HJPHR%2BOOWyfg829sXeXbs5zOJOuNd1db3HQ7U707W11tTTkdsPa52Tl4%2FcV%2FgsZwcWIC9kiA3BF%2FXrkWCScTWrRat4UJuRX%2F%2BM0qrP9pQ7Nxa22Rw3mZQGclQBZJGou5ffMOMWSgs7aD680EmEDnJ0DPozc%2FWIOCQtthBO3dsk3bjuLJFz5BUUnzoIbtXdbVyiNXV07XnkCHVwDp5qCxLrTkxATskUB1dY0INHLscGy73Ac0fstotB13Zo9cuc32SYD%2BlxzYcxC%2F%2FLRBjB21TwrcaibABDoKgcLiclAk1GuZSPGjMaCsXF1Lyp1LdodXADsXTq4tE2ACTIAJMAEmwASYABNgAkyg4xJgBbDjXhuuGRNgAkyACTABJsAEmAATYAJMoF0JdPggMA5qFcK7h4kJs9u15SyMCdghAQoG4hvgB2dn24nC7RAFN5kJMAEmwASYABNgAnZJoMMrgEHBgXjmpWcQGdXbLi%2FQ7zXapKvDzu0HodPbzvtlPk%2BhdED06NHwdlWZd13RsqasCAf3x0Lm5ILxk8ZA0WRKjtYKrSouQFxcCqpqaxE1aBBCgnwhazKtRGtl2Us%2BpVKB%2FoP6g%2BazpEiJV5No4muaLFuuUFgm9b4aeV3tXJPRgJTTiTifnd%2FyJLQmEyIGDUOPUNs5%2BdrMwWRCemISMrJyEdI7Ej3Dg0DzcbY1Geo1yExNx9m0LHgFBCIishfcXZ3aKsbu8oeEBovxtGqrCZztDgI3uEsQGDMiCi5OjtiyKxa3zB2Dc5n5iDt9DmNH9sP4UX3x8ZebUFZRfUPauvT2SQgL9gVFumxpnr5JYwdiwexR%2BOK7regfFY4Rg3vjtbdXdopAJTcE6HUqVCqV4N8v34%2Bffz2AI7Ep16lULuZ6E%2BjwCqCLqwvGThxzvbl0mvKMukp8%2FuFnqKqsbbHOrh4e%2BGtE9FUrgFUXcvDZ2x%2FBMbQbRowffWUKIEXfO7AXX61Yj8KSSoxfsAiPP3w7nJ2uTjltseFdaCfdA48%2B9TA8vT2vWgEkJaPvgL5diE47N8Wow4Gdu7B5015otC1%2FVLnvxVeuXgGECSd278bPG3dj9n33IyzY74oUwOK8XGxYuRLb98bBv0ckHnhkGUaN6Ier%2B0zQzkw7mDj6iDJx2kTQVBDevt4drHZcHSbQegKOagfcu2Q6Hnv2Q3QP88eoYX2wbtMhIaBbqB8mjBmAFT%2FsuCEKoIebM5beNlnUxcPDpUUF0MvDBZERIXBxUiHQ31OsK%2BQd%2FrW09Reok%2BY0Gk3YuCUGf%2FzDAiQk%2FRc1tZpO2hKu9uUI8J12OTqd4JhE4Ywl9yyBtl4HmLT44MU3UWY0YfHDT6JXmKuY5y3Ay7GhJRcjqup0ekgVcijkMotCYY6ySgYmg86Aep0eSgeFZY4sJ09fLFh6G5RunlBaWf%2BMBgO0Gi0kUikcVA4WeS2h01SVYd%2FOg0iIT0KtRoe6dRux4ObpiOjmAOlVWrZaKq%2Br7FMoFOjTr09XaU7HbodUjmFjx8ArIAR6vQ6bv12F40npGDvnZowbGQWZXIoBvYMtbaD7hvo%2FxSim%2Fm%2Fdj833FEwm1OtImZSArLlmK27vwYMx38kNvfv0hPziS0%2BDPA3oHzC5v1%2FOOm4yGZCRmobd2%2FYhI6cEufmlGDx8GPr36w0XJ4WljrxiS4D4BwQF2O7kLSbQa%2BGO3wAAIABJREFUCQkEBXhDpzMgPNQPoUE%2B0OkNQpHKzb%2FxE31PnRANsiT98tthLJgzGmEhvsg6X2hD%2Bbedsejfrxtq67T4fMVmRPUOQ20dKxs2kG7Qxr4jp7Ho1glYtngqPly%2B8QbVgou9lgQ6vAJIk2DrdDrxgsQT9jbvClK5I2bOn0nvmICxGiv%2B8Q7K9AaMnjkNo%2Fr6ipdNUiAqSouwbf0GHNh%2FHBVVdXDx8MKYqZMxZepYeLsqsW71Ohw7mYqeIb5ITT6DgpJyeAaGY8m9dyO6fzjqqspxZP8ROPoGYe4tc6GAAYmxh7F65S%2FIyimCXK5Et759Mf%2B2eegXGW55yW2ssQlp8XFITD4Ht8DuCDBVITcvHbv3Hke3kOlwUHT4rtjYlE68RgoGTatCL8FSmbSF69SJG9cOVZdIZegXHY3I%2Fv0Bkw4pu%2FYgLuUc%2Bgwdhrm3TIJCKYNCoQQpX8d278SGX7YhJ68EEqkc3SL7YMGim9G%2FTxiy09Pww1crIVU4QS2XIjExGVA6YsyU6Zg1dzx8PJyQey4Nxw4eg8o3FFG9w1Gck4lVX%2F8g3LeMJhNcvHwx8%2BZ5mD1jjI1iaW5mdVkJTh8%2FgfxKI7r36glNVSmOxcRiwqSRog7mfLxkAkygaxJQKuToHt5g%2BSsqrsCQgT3Ru2cIrkQBpI9Nvt7uwjW6oLj8qqccmj5lKM6m5%2BKXzUeEAjhn2nB89KWtIuHh5oQgfy%2BcTctFRM8gVFXXobyy5oovFv1f8%2FN2h95gQHFppUUOWRV9vNxQVl6FOm29Zb%2F1Smvbb5ZFH%2FWsy7CWRevkiu%2FoqEJpWeUlvUmovmQFVauUqKysRUV1y55cJM%2FZSQ1XF0cUFZVDZ7j8NE7enq7iYyP1iUtN%2B%2FB77aB3hW27juP%2Bu2bi%2B592X9V1acqGtzsGgQ7%2F1p15Lgtvv%2FY27nv0PgwZPrhjUOtItZBI4OBw0YXSqIM5rKuD2gEqVcP%2B2spK%2FPr9t1j%2B5QZIlc4I7x6AjOREnI5PQVlJBRYumoazScnY8es2HPPwQGTfXtBXVWDfls3Iyi7Gfz95DaaqShw%2FEAPn7r3E2Kic9AS88rd%2FISevFH2HDIFMW47fflyD0uJyPP3i0wj2cbGhZNBpcejAEeTkFmDiwnvQw7UaXyxfi9%2FWbsDN88fBz9OF3dZsiDVu0EeQqsoqYWEyX9PGo21bI2vVV5%2BsgKOTIxYsnA83d7e2CejyuSVifCSNkYRJBjkpyQDkDkphkVMqGsbpxe3fhtf%2B%2Fhbyi6sRNWAAUF%2BBjat%2FxrnUDDz10nOQ1JTi8L59KCjRoHvPHvBwdUB6YgLOJJ2D2kmNObPH4EJmFmIPH0O3kRNQW16If7%2F8Og7HJCC09wB0D3bFvp27cOZ0Mjx83seYId2akDchLzsHhw4chk9wGObNm4gzsQex79gJJCelIaJnCBwU5qdBk1PtfJNebDR1Guj1ejg6Ol6R662dI%2BTmdxACNLfbyp%2F3ID7xHGpqtWI9K%2FvCJWs3b%2BZI3H%2FnDOw7fBrvfrxWeBqQEnL7%2FHFYuGA8XJzV4tzS8ip8%2FcMOMa6QdkT3645X%2FnIXVq7dgx%2FX7rWRP2V8NP740Hy8%2BM9vkJCUIY5F9Q4VFsmvf9yBvAslSDl7HtMmDsKX32%2B1UYZcnB3x6ps%2FoFajBSkkr%2Fz7OxvZrdmgcYbUrtff%2FhF%2FfuwW%2BPt5itOozH%2F8%2BzsMGxKBh%2B6ebWnbpu3H8MFnv1gU3Na0nwSSsv30Y7dg%2FKj%2BkMkanq2FReX48vtt2H3glKWqwwZFCB6%2BPu5in8FgwKFjKfjg019QUdWg3JKyufS2SZg7cwTcrMZsp2fm450P1yItI88ijxTapx%2B7FdH9u4t91TUafPb1b7h5zhikZ%2BThzf%2BtseQdOTQSD90zG0EBXmKfRluPzdtjsfy7rRZFsLXtIAEHY5LwyH1zMWfGcKEEWgrilS5BoMMrgNWVVThyMAbzb5%2FfJYBf90aYjCgvycfPK3%2BFRO2Mh559FmOH9sDxfXux%2FMPl2L3nIKIH9xYTg9drNBg%2BfSbuXjoPDsZqvPTYXxB%2F4hBiEjIxzMMkXpjoy5rJaMKB3zbjTFouRsyeh5f%2F%2BgjqyouxY%2BNWuIf0hELefATShcxUxJ1MglbmgjHjhmNAuBM2bdiD1MQ4HD52FvOmDbqsu9t159aBCiwrLccLT76AabOn4dbFt4AieV5pon9GyYnJcHVzQ%2F0lvoReqWx7Oc9kqMePX%2FyAc5kXcNP9j%2BLRB%2BajvrocX779FrYcjMOm3%2FZgzvie4n7xDAjCrfcvw%2BhBPbF55Sp8%2B%2FXPOHw0DsNH9ofRYBR5TCYjkmKOIOZoIpT%2B3fHa2y%2FDw9kBA%2Ft2R14F4Obi0AytTlOD1MR4xCflYtSceZh5802Q11fg0KEExBw5iREjoxEW1PAS0OxkO99BCuDq735CVmY2lj10D0LDQ%2BycCDe%2FsxKgCcRXrNxuqf6ZtBzLetOVuTOG47EHbsLu%2Fafw34%2FXCeWP8jx410zcOm8s9hyIx%2BYdx8SwjwWzR%2BOpR2%2BGQiHDr1tjEJ%2BUIcaBTZs4uJkCOH3SEFTX1CExJdNS5IzJQ8T6zj0nxXLb7hP44x%2FmY%2BKYgRalkg7QxOTmdCzurHm1TUtSHEmR%2FMfzd2LDlhhRj%2BGDIzBv1ii8%2FtIyuLs5Y8XKbSgqqsCCuaMxZ9owxMWnCSWYCmpN%2Bynfo%2FfPxdgR%2FfDJV5tEvd1cnHDvndPxlz8tRPb5AqRnXUCgnxf%2B%2FtxSJKVk452P1gpmQ6MjcM%2FiqaCRM6TsUlq2ZJpQuEkZ3bP%2FlFBGBw%2FoiTtunYCnHlmAx577SORTOyjx5qsPwM3NCR9%2FtQnpGfkY3L8HnvxDw%2Ftwdk6ByEd%2FSPkjJT3tXK5QpCurajF6eF%2FcOm8MvL1cRXAdyteadpiF0gcGkjdmRF9WAM1QutCywyuA9M%2BaXNZoyantBExGI2pLi3G%2BoBJhfXpg9LghCPJ2Rn10X%2FToGYqTaUUoLigTY5gABaL69kZoeDDUCimi%2BoXhdHoOCi9UwOTRGKGQrkRm9nlIJFJERUUjONgfhgAf3BkaCqlMAZXK9oWVIiueOHIC6WnnUa%2FVY%2F2332CvqwOKK8qg01Zj7aoNmDFhABxVV67YtJ1M5zmDXKBTU1IxaNigdqk0KR5G4%2BVdSNqloC4qxKitQ2p6JiBRYPK0iQgJCYC%2B3gPjJ47Ahu3xyErKgn5cTzHmz9vHF3369EZgaCAiB0TA29cNpSUVqNPYuiHl5udBW69HRPd%2B6B4WBLlChvl3LYPeBKjUF8fwWvEsuVCEI3sOolarQ2pCPD56%2B33kpqdBZ9QhZv8hZM6fiuAAT8isxutanW73q4UFhcjOyIJWw%2BON7L4z2AGAOVOH4YkH5wuXvnc%2FaVT%2B%2FH08cMtNYxBz%2FAze%2BO8qC4kT8Wl497WHsGzJdJDyRjEGduw9iUU3T0BEjyDh2kmZfbzdMLBfN%2Fy4dp9FoSSlZcKY%2FohPzAC5klLaeygBj9w3BzfNHG6jAFoKvMoVssht2HLEogzHxqVi9PAo9AgPwDMvfY6E5AbllCxs33%2F2vBhrSFbQtrR%2FyMBeSE3PEeWYq0sKEil3Li4Nz%2Bi%2BUWHCUrhq3R6cTEgX2cgNVqVSwMmxMdjdsEG9kZichfc%2FXW8WJeoYFuorlC3KS4FXZk8bBj9fD7zx7irsORgv8pKVlSymD9w103IuWTEfXjYHJaWVePYfX6L2YtCW0ylZMBgNQtmM7BUiFNfWtMMiGEBaRj5mThkKFyc1qmrqrA%2FxeicnwG%2FcnfwC%2Fl71JVIJZCoHyGECuWFWVzW8eGpra1FTWQmFWgmlWnHR%2FdKIqmot9HpSDgyoKK%2BA0WSEzIG%2BEzRa9WhN4eAAGqdUUl4qlMfammoc3Lkdu3cfAn2VtE41ZYU4efwUCopLoautxOG9B7Bl4y4UF1cLxf70wd04fTaPlXxraE3WxfcP%2FgbShMqN2ZQoZHBQKumOQmlplagEWVbLCoshkcmgdHcUX3sBk7Cy1tbSPWdCXW0ttPVaSOUyERzBuvY0PQfFQSouLYbx4oGUkzFYt3YzUlKyrLPCZDAg%2F3wGDhw8IcYi5pxLxdZftuBUfArqtAaU5abj2NHTKK%2Fkf9Y24Kw26IMif1O0AsKrXZbArGlD8ceHFwgl7x0ryx81eMigXmIcOFn%2FyJJm%2FsllMhyOTRERuklxoLR113GxJJdPc5o8Llqcv2PvCfMujB3dD2qVg1A2zTvJQnjoaBJ6dg8SCqR5f3suY443TldA9%2FeFwjIRzM6s%2FFFZ5NpKyc2tQWFrS%2FvP5xYiKjIMf37sVgwe2FMoepnnC%2FDKf74X47ZJ7vmcIiH%2FyYdvxk0zRiDAt8EdldxEP%2Fh8gzhGfx7%2B8%2Ft4%2BqXPLNvkEkpBchyUDcG7yE2T0oihkajTaIUCbckMYNO2o9abCAn0RoC%2FJ44ePwNdvd5yHel6HjmWLPIOHxQhlq1ph7Xw%2FIJSsUmKKKeuRaDDWwC7Fu4b0BqJDK5e%2Fhg5JAx7T6Xhgzffw7RJgxGzexeOxmdh7JwF6NEjFMd3U930WPfdd3BXA4bSDMTEpUPm4IEh%2FUIhrcu2VJ6UyjGjh%2BPb73di%2F4Y1%2BDbYDZLyC1jx5Sr49uqL4J59EOBnzm5CyslTSD59Fu4hkfjL35%2FCoAE9xcuuUa%2FBq089g%2F1HUrB6zVYM6fsAZLJGRdMsgZdMoCMRkCocMW3aYJw6sxGfvvMmUH8fjOW5%2BOzrTXB1c8X4CSNhtpenJp3G6q%2B%2FR%2F7ZKOzauBU5eZUYd0s4PN1sx8hGDxkEF6UCWXEH8P77KzA0IgAf%2F%2BtdZJTU4LH%2F%2Bw8GXBz%2FQRyqy0sRs2svSurkmHXHXfjzs%2FdenJbFhJ3r1%2BCrT3%2FAnt37MWPmGHi6d7P6dNORKHJdmAATuB4EaGwfWfBoXB5NzWBWgqjsgIsv9c8%2FeTvo11Ii90FKFFiGrFYTxw7AZ19vFrEApk4chOQz2cjJK7acOmvyULE%2Bd%2BZITL%2FoCko7zHJIMXr7o7WW%2FO21UlFhG0CFIilXVTXfZ11eW9r%2FwWe%2F4qVnF2P6pMHiR5HSyVK6efsxy1x55NJK4%2B3uXjQFjz84TxRF3A4cOY21Gw%2Bh%2FOJ8jHKpDOPH9Mf40X0RHOgDf19P4W7b8PG9sYYUlIeCvjT1gKOoqRVWwXL8fBqUs1nThoF%2BLSVvr4bx%2Fq1ph%2FX5NTUNXhLubjy%2FrDWXrrDe4RVACoXerUc4nJy587Wmw5mNROQSYE7uXr548E9Po%2BSVf%2BPwlo04vHUjIFMgetx4LL17AcItY4UcIK2pxoevv4ma2hoRtXDZE08hqrsvipMaFEAJhZmRSDBoyhzctywZ3%2F%2BwEe%2B%2B%2BoYwEHr4%2BGPa%2FFno08Oi%2FUGnqcap46eQkZmP0QsWCxdTP%2F%2BLY5NMJtyyYDpiTqRj3y8bkP34EnTzdTZXm5fXgACNH%2FT19xWTwF%2FJxOPXoEodWmRL9xPw%2F%2Bx9B3hcxbn2u72vVlpJq967Zbk33LDBppvegukkBJIASW5C6r1J7k1CEv57QyCEEGpophgwLoB770Uusi2r915Wq%2B3tf75Z7apYxrLVVtKMn%2FWePWfOzDfvnHM07%2FmaEHc%2B%2FkNUlrVizZYjeO7ZXzENn0qnxz2PPowbls9A8Ul6Iy6EVCDCsZ27sHXd53C7vcibfzWWLV%2BAMF1Ps04BIlJy8eNfPon%2F%2FcPLePelv%2BN9kQBuF3DFtdfj1utn98DIi%2BamRmz7egfCo6MxZ9F8xEQbAiRv0eIF2L5lL%2FbsO4zjBWVITY2HkmnwezTBNzkCHIEJg8Bn6%2FYy7Rv5kj393VvwX8%2B9Exg7WfFQee3fX14wciiZAPrL19uO4EdP3oZpeakgHzNKPfHCK91mjHEx4ZiUncjaamvvjsJJ55stVmZGuHhBHv759pfMb9Df7lB8kxVG33IxLf%2BljL%2BusRVP%2FuTvyEyLw%2BzpmZielwrSqs2dkcX88z7vyr%2F40ec7GSmcPSMTZG45fUoqM51dunAKvvOjF5l55k%2BeuoMR6XMl1SDNJfmTnyuuxorr5jLfRf843B4PhCL%2F60T%2FXt%2B3XC4N7PCPY%2FP2Y9hzoCCwv%2BcGmatSGeg4%2FOf61wmUboSX8YVA0BPAjKx0fLDufVAqA14ugoBAiT%2Bteg12jxeZSd3qepFEiuy5V%2BBv77%2BN0qIStLV2QBsejtT0FOYgLXD7wy6LsPLp7yMjORKmThOi4pLYAlIukyAybTJe%2FeRNiBQaKCVCiKRaPPHrX%2BCGu%2B9EWWUdpDIF4lNTER9nYG%2By%2FJIKRTIsu%2FMuTL1yOQxxsYgy%2BCJjseMCARasuAuvZcwEuaTpFXyO%2Fbj1%2FJbJpJgxZwZiE2IHnbZBoVTg57%2F7GWven3uuZ198uycCItz%2Fkx%2Fhum8%2FipikFEjE3Rbz6tBI%2FPxvL%2BC%2B0lJUVNTBKxQhKSMDiXFRvYIgZU2djkeefBAidyeEUhVS0lIQERHCTEBvePghzLhxBQzxiSwa5XV3fwsz5y9EwelieCg8eGQscnJTIZd1%2F6En6Qyxcfj5X%2F8fJAo14hMTA%2BSPjkWn5eBnv%2F8tWlqMiIyNh5Rr1HtOaGA7KSWJpRaiaLi8cATGMwJffLkftQ0t2LDpEPMpIxPOLTvz2ZBr63zmfR2dVuztMhX0Y0EmifowLTp7JAHftfdUVxCRSejotIByCpN%2Fn79c26Xx%2B8fr69BfUJcH7roK9921FKQ59BMm%2F7mj8T3Q8ZMpJWlQyS%2BPAu3Q552PtrCgL3%2F%2Fy5MssAyNh0w%2B01JjGAkjjOlDuRAff%2FB6lgpj5pQ0NDS1M%2FK3e38B%2Fvt5X1AY%2F9hDQ33aVv8L%2FNKyOsyfm8P8B3smYyeTT7%2B5KJ1bV%2B%2BbR7LO6juPFKwmOzMe7UYzMw0dyDj88tA3pbOg0tLWm9D3rMO3xyYCQU8ASWMx2ND3Y3NqLkNqgQiTZvoChfgfIP5WhEIRQvV6TA8LY%2BYEdNxfp2c8EJlcickzprEQ8j3ryDQaTO1Kw%2BFXLkplcqTm5iJl0iTWTc%2F6%2Fn6JfMYnJyGeRbGnPv1HfN9ytRZTZ0wJnN%2F7KP9FCISGheLPLz4Herj752wwyPCXKQNETyBEfHoqmAcM3S89TxMIIJUrkJqdg5SsbHYkcP17%2FV58YD6Bhth4ZKSQ1rv3%2FBkSEkAf335SGIoRlZiEyITE3u317BcCKDUhmDLLlxKn7%2FUgFEuQlJaKJIpBQy33veF6tTUxf9DflDu%2BdTt7Dg4mou7ERI%2BPeqwi8K93vsKcGZl48tGbcOxECTMF3X%2FkLCNx99y2GLv2nWIJ2Wl8RC5%2B%2Fsw9iIkOw8rv%2FCkwZAo%2BsntfAebNzgaRRkoT4CcmZNZIxI5y7ZFpZH%2BF%2FAiJAN64fPZFCSC9eCbyYrbah1xb6JdtoON3AvjNs%2FehsqYZP%2FrlP5n5K7XR3GpkfoYWi501uXDeJJY37z%2F%2F%2BG%2Fmc0k7yRS1vtEXF4FMN5UKX5C8uvoWvxjsm0jdrGnpbFvU9bLxy62Hmanotx%2B4Fi%2B%2B%2BgXrl8joYw9e1%2BtcIvgU4GbxFZPxyZpdKK3oTgXy8H3LcN3Vs%2FCr%2F3kb%2BcbSAY2jZ%2BOUp5G0f5RTkJfxhUDQE8DxBffwj%2BZiC77AIrWXKCJEx8Uie3ImdKFq9saqv4VRf233316vxi%2B6CO2v3d4t8F9%2BMwyOxMgicLFr80LXv1KlQlpmOvSxcZDLxSxibl%2FJ%2B21bIOg36fuAzu2q1G%2B7fRuY4L%2F7e75NcEj48Mc5AhQZkkjEb362MmAKSj5plF6A8vj94%2F%2F9AGRCaLPZsXTRNCQnGvD319YyotcTGiJxRPQovcI%2F31wfODRzejpCdRqQySmZLvZXKCooRcecNjmVpbk5XlDaXzW2j0wrf%2F6je0AmleRXNxzlUsa%2F6rOdeOS%2B5Xj%2Bd48x4kvv1sgfknD42z%2FXMPEoYurN18%2FDL354D77acpjlQCSzWCJgRSU1jHjLZBIWrXPF9fNYUvqa2hYkJRhw07VzQXkFE%2BIiodOqGeE6eryYBXy5Yfls5GYnoayiARlpsQGfwJ4mrpTa4y%2B%2FfQz%2F94fHWe6%2F%2BqY2TMtNwdxZ2YzcHz5exM4byDh6Yk2Bb%2FJPljA%2F0p77%2BfbYR0D0%2FR9%2F7zfBPAxyfqWw9RdaaAWz7GNFNoFIjKmzZuK2e1YgNSWWJb8eK7JzOS8NAXY%2Fdf1x5kTh0rAbcG2BAKHhkbhmxQ1YtGQudFrFRV%2BCDLhtXpEjwBEYFgRq80%2Bh4Uwha%2FucSAenoNvke1g6HOZGDRE6qFUK7Nx7MqDZo2AtaqUCdKyyupERESImlDSdiMe8mdnIzkwA%2BYv9%2FfW12LqrO8G5X9zGZiOuWTqdJXSnOn4SsnBuLstR%2B%2BFnO9DWFezEf07PbwrMQqallKT8dGF3cLmedWibiNWkrERUVjcx4tT3uP83RaektAmUJoHa9Je05GimnaR0Dz0L5Vc9e64ap7pSQwx0%2FAVnK5j5JvkAzp2ViUlZSahraMOL%2F1qDg0d9143N7sTeA6cRolVial4a5s3KQqhOi03bjuL%2FXvmckSiny41Dx4pYAJ65s3Iwb2YWi6vw2ttfMjNdIoNkJlpe6cvxRyk6KqsaWSJ7tUqGI%2FkljMhT7kbyG9zXZbrb0mZifVOgH%2FI%2FnD4lnRE%2Bmo8339sYIOUDGYcfL%2FLxJO0waRWLSruT0%2FuP8%2B%2FzEdB5HYjz%2BNyqUhcvQEhs9PmVgmBPR5MJgjO1Bf44B0Eg0vkiFJ45h18880v86Bc%2FxPzFV5xfge%2FhCIxzBDweD6wWKyRSCShdwGAKtfPX516ASqPCykfuQ5jeF6Z6MG3yczkCYwkBegnicDhYflm5Qs4WrWNJfi7r8CBw%2BK0PcGK1T5OzVpoIi4AbSPWHNJHKVa%2F9DKvX7sGb72%2Fsr8qQ7Xt05TVoa%2B%2FEp%2Bv2DFmbY6kh8tcjckuawJ5aVdIqvv63H%2BK9j7bi3x9tGbYhUa7B5Uum4f7vPs81gANEOdHdibkuH3lf9p%2FPIn6I8jcPsPsBV6suqKWQjsFdbBYrSs6VoNPUGdyCcuk4AsOEQEtTC%2B6%2F7UGsensViAwOptD5NVU1qK%2BtZwvgwbTFz%2BUIjEUEiAC%2B9tLr%2BPV%2F%2FBcqynrnWByL4%2BEycwRGAgEKZkJ%2BfpTigBKvU%2FqD4SxJ8QYsumIyKFjKRC3Z6fH4n18%2BiAVzfHEWCAeagwfvvppB0l%2BgnaHCivxAl105DZ98sYeTv6ECNcja4a%2B4gmxCuDgcgb4I0Ju%2F1uZWmDt75zTqW4%2F%2F5ghwBAaGgNlsRntbO1xO18BO4LU4AhMcgf%2F66UrMmJIGiUSMNRv2gXzMhrOQP9zPf%2FsmGpt9AVSGs69gbZt8Cm%2B4Zg5%2B8eN7cFvRApbXMCUpipnQvv%2FJNpw5VzVsopMvY0eHmfl0DlsnvOFRRYATwFGFn3fOEeAIcAQ4AhwBjgBHILgR2LLjGKw2OwqLarDmy73DLixFHKXPRC4msxWP%2F%2FBvWLpoCss%2FqFbJsW33cezaVwBKOj9chbS9CXER%2BPOLq%2BF08Zdkw4XzaLc7Jggghb%2FnhSPAERgiBFhKA35PDRGavBmOAEeAIzDuEaBgKn0Dqoz7QQfBAImAUeRV%2BoxUodQVz7%2B0eqS64%2F2MEgJBTwDlSgXSMlKh1qhHCSLeLUdgdBGgcNNiiRhC0eBddin8fUxsNNRaNXhqidGdV9776CFAeVHFYhGPzjp6U8B75ghwBDgCHIFRRCDoCWBGVjpWrfuAR2obxYuEdz26CMhkMsycOxPxiXGDFoSiHj77m5%2ByhS%2FPhTZoOHkDYxSB5NRESKUSKFXKMToCLjZHgCPAEeAIcAQuH4GgJ4CUq0wkEl3%2BCPmZHIExjoAuVIfnXvjDkIyC309DAiNvZAwjQC8%2Bbr%2F39jE8Ai46R4AjwBHgCHAEBofA4G3KBtc%2FP5sjwBHgCHAEOAIcAY4AR4AjwBHgCHAERgiBoNcAUuJqytUUGx8LjVYzQrCc343X44bJaERdXQu8EID5ZYlFUGnUIA2NXCY5%2F6QL7KE8VDazGRKFCvA4UFdTi%2FDoBEhFgNPpgEQmh9NmRofJDKU6BBT5abDF5bSjuaEJHSYLlGotwiP1lyRzz%2F5J%2FsbqarSb7PAKACE8EEskUGm00OtDIRZf2nsFr9fD8jwqNRqIBAK01Neitc2G2OR4KOViFqrd7nBCqZDB1G5Ec6sJ%2BshwhGhVPcUa1DaNydppQl1dM3ThEdCHjd611t9ASD4qpMEbTHG73aitrmN5nCINkcy3cDDtXc65Ha1NqKs3gkYkEHggEoogVyqhjwiHQj7w%2B4j1TfNmMUMkVUAqEaGBXZcOJKUlQiYRwuV0wO7wQKWSw26zoqayAUqtFoYoPQaHpH%2FkdC93oqamAW6PF7owPcIjQiG8zHlyu%2BwoLaqC2zfdoPhXUrkUIbpQ6HQa9tzx93yxb4fNCq9IAqlYDFNrIzodQkQZ9KBnmdXmhFqtQHtTPcwuCWKj9RdrbsDHPW4XKkuqYEiMh0IWnH9ihup%2BGjAovCJHgCMwthDweuFpqwCEEgjkagjkIWNLfi4tR%2BAiCIi%2B%2F%2BPv%2FeYidUb1cFlxGf7zp79BSloy4hPjR00Wl8OGw7t345UXP0DxuUqcOXkGBSdO4uzpIoikSkRE6iERD8xU1WHpwLrV6xCekgm3uQ2fvvM%2BItPz4DDW48jB49DHJqK9thQH9x2DQK6FIUI3qHG7HA6cPXYUn69ei6NHT%2BHc6RJArEBUTATElxFYhAjbR%2F94CW%2B%2BuRZ7dh3Avu27cXD%2FYZSW1EAdEgaDIWzgC2CvB4XHj2PLxp1Iy50MmViIr1e9g7ffXo%2FMGTOhFjuxd8duVNa1ISE2HMd27cC%2F39kAbbgBSYlRg8LFfzItBjuNbdi%2Bfj3efPNTiEMMyM4YvL%2Bdv%2F3Bftvtdhw%2FcpwlgaeXIIMhgXabHf%2F6%2B2soKSpFZk4mFArFYMW75PMPbFqL%2F%2FvTW9i5fT%2F279qNfbvTnC77AAAgAElEQVQO4sTx03B6ZEhMibuka7K%2BqgJbN2yEIiIaOq0Kn732Ct79YCvmLF0IkdOMXZu3o6bVguTEaDRWluLFv7yCpg43ps3IYeTqkoXvc4LNYsLXn36Gt1%2F%2FALt27kdldQui4uOhD728oFX2jnr89Kn%2FwbmiGpw9eRanT57G6RMnUFRcg9jkRGjVA3sZ5HU7sHfrNlihRFiIBqf3bcHek%2FWYlJOCc%2FkHcaq4GakpMTi2dT32n27DtClpQ0KInXYbTh87jBf%2F8Cqy510BvW7kr68%2BU3TeT7rf6aVifW09VCoVJNJLfOlwXot8x3hAoDb%2FFBrOFLKhnBPp4BRc2ovM8YABH0MXAl4vvC4HvG1lgMMEr0AIoayLAF7myz2O7cRAQOd1IM5jZoNNXbwAIbHRQTnwjiYTgvP1bA%2B4SANYWFCIDqOpx96R3%2FR43GhrbYLRasYtV12BEJUYprZmbF7%2FNda2WmCIMSAhKgQtTS3oNFuZFi8yKgIKhRxuuxWtRis8DgvMViccbZX4y59ehmHyPGTHqhBpiAacNhzbtwvvr96FyPRchIlkCAnVQSGTAl4vTB1GtDS3we0GIqIioNao2AOqpd0MhQRorG8BpFLExERDIZf2AMiLjrYmfPr2B3CEJuKGaxbh0Lad2PDpOsQkxCItMaJH3YFtkjKqorQIJ08cx%2BLrr0VkiBKNdVVY%2B8GHaGy2IPl%2FnoFC6ERLcyusVgdkKiXCI%2FRQKGSwdJhgttogEgDtxk5IJQK8%2Br8vYHd%2BBaYsXILs1BgWnVIqE8DlsOPM0WP43S%2Bew4zl12NKbio7JpYIIejSiNmtVrS2tKKz0wIlaSAjwiCXSuBxOdHc0gqpXAlHpwnGjk4oNCGIjomEqEdaEY%2FHg8bqSmxc9xVWvfMx2m1iTFtiHBgQI1Sro70Df%2Frtn3HjbTdi5SP3DYoA0nirK6qh1WlHLQl2W30djh49iMlz5yIrLQkWUwf2bd2M48eKkJKTiaxEHVqbWmA0miCSShGq10OrVcPjtPueA0IhOk0mCARibPrkQ%2FzrtU%2FwQ108DGEhEEmE7Jpyuxw4cXgX%2FuvZP2LJ3SsxLS8TlNtIIhNCKPCp19xOF4ztbWhr64BIIoE%2BPBwqtYLdV%2B20TyqDvdMEU6cVqpAQREbqmeY0MO1eL8pOHsHzf3wRhvRpyEjWYP1Hq%2BCAFM8%2B%2BzCkdJFfYnE7rDiefww%2FvOsupMWoQc%2BduvISvP%2FmexBpDXj8weVw2G1obmyG2WKDTOm7t%2Biap%2BTm9Ly0WW2AsxNvvfo2Zt10LwwRoVCodAgLEcFhMePdf7wCS%2BQMzJqeCXWIHmHwadLdLjfampvQ1m6CTKEEPb%2FkMilsVivTnjocLpg6OiFTqgL3Wc%2FhWTvasGPjNny5dj127CnAY1Znz8NBs00E8Ms1X6G0uBRP%2FugJJKcmB41sXBCOAEcgOBDwumzdgghEzHJCwONRdGPCt8Y8AkFPAIMJYdK86A0GzF44DxFaKdxOO0xNddhzuBzN1TWoOHEQxaU1cLs9zHwzadJU3HLzEhjLz%2BKtT7ZDCicsNi8MoTLYHA4cP3gIEUtmobPDyBa2JWeK0NzcjMLThchKCIXVbIXD6UJ1WQl2b92LplYjaJGm1kdi6fVXIUxgxLvvfQ1diAo2sxUtre1IzZuGu%2B%2B8rpvkeDzoaGlAYVk9fvDd%2F8DcyfFQSb346IO1KCquvCwC6J8TqUyG%2B558HLOyYnDywF4U5f8KddVVqCqvQnXBERw6XIBOqw1ylRpzrrwSixbOxNkDu7HnQAF7mFZXN0IfocexE0Wwmez48O1VePpnT0GlDWHmgF6XHRvXfoWm1nYUHi%2FA9t3HkGZQMjNTmVwGY0sjDuzag%2F37j4MW7Bp9BGbPvwILFs6ExNmOVW9%2BBIFcBaexDdW1tVBqInDLA9%2FCzLwU%2FxDgcTtx6vA%2BfP75Jmh0WrTXWwLHgmXDTSS1vglmk%2B%2BtUrDINRg56F5adONNeOKBG9HWWIdflRfiZFUTis5WwdNwDl9t2I6mNiMjZqk5k3HVtUsgsbVg41dbYey0o6G%2BEXKlFmePH4bZasfGTz9n6WJUmlBERDgBWyc%2B%2F2w9jCYzCg4dxs49UzB%2FShzC9OHQaNQg88iik%2FnYtnEXqmsaIZIrkJ6bi6VXL4JaaMMXn30Fi1sAR4cRNbX1CAmPwq0r70VuZjwjkjR2IhLHdu9Bp12IJx58CFdOj0Rpfj5O5R9Dq%2Fk%2BRGlllwWRQCjEtHlzkZekZedbOiZj%2F9dfovRcCaydndi7ZRNOF9eAVHZOhxuZedMwd2YGDu87gFMFxXA6XQgLUaOxyYiiU6dQNWsqPGYzzBYpmmrKUVXVCqe1DMdPlUFjs6DTIoTb5cSJ%2FfuwZ3c%2BvMwqQICkzCwsuHIeWivPYc%2BOvbB5pbCbO%2BFwA3OXLMGM6TlQ9DB9N7Y2snsxIzsLB3afvqyxj9RJJpMJrS1to%2FYSZKTGyfvhCHAELhEBernMNIDdSeg9pA32uFk0evZaj2sBLxFUXj0YEeAE8BJmhRZ8zXX12L1tJ3RKETrb2nD4yGmERSZD6LXj6JFTiIhPRkpKLPJ3bcK7%2F%2FoYVy27Au21Jfj4nY9wx6MPIiVGC5XSyx4kEYZIeOwW7Pj6a8TNugYafQhkMgVCQ0Ngbm1E%2FuFjgFKHxjOHkX%2B2HguWLIBK6sQXH38Bi0eKG6Zr8dl7n2DJnXdgybw8FB3ehZef%2Fxeuu2kZQpU%2BsyYy17S2t8HulSAmVk9OV9BqVFBKpWhraff5YV0CBj2rupxObF%2F3JcoOa1FVXASLC0iLjITLasLJ%2FFMw2z3Q6VQ4uGsfapo6kZaWiKLjR%2FH5B19An5iOjNREyBUyJpNAJIBUJmFmeQVHDuCzD%2Fdh%2FjU3QiD0mdWKpUIIPR5UnDuLL9duRmxSBmyNhXjt5bcg1kZgUnYyzhw7iuNHTjIfr5woAdZ%2Fvg5mtxQ33LQMepUEH6z6EDZZOGbkfTdg7iYQiBCdmIoHHn8QrqZi%2FO8%2Fv%2B45RL49jAicOngAHwoszPy2qrEDKk04wnRyFJ46hPLqOiSmJqHk1AkcPXIGYVEGpGpt2Lr%2BS1S3ezB1ag504UoIRQI2lxKZGCKhEEf37MRnX5bgrkfuglDQde3IRMyslHwPN6xZj6mLRJg5PQHv%2FusNFBQ3Y9rs6bC01OPTt99lGvr5edHYvGEj6jtcuGrZIsgFTny%2B6iNI9QnISbsLlEOOihdeNDY1QyCUIiExGgqlAjHhahR1mtDR4bhsAuj1eHBo1y60FKnYQqSuogzVzTasuDUbncZWHNx9CPqMPGQmG7Bv%2B3Zs2fA1YsKUOLpzJ8402DB%2F%2FkzERYdAqpBBFxrGfIhPnTuOXcUKLJhxPZQhCrhIWx6qwdmNh7Cr2oAbr0zHWy%2B9AW3qVCxZnIfq4rPYuGYtxCot1LYabP9qC1LmXInpuenY%2BeV67NqmQEpKAhSG0MAVotEb8ND3H4cWrfjozc8C91igAt%2FgCHAEOAJjAAFaN8HVTQC9ZCzXRQwvyRF7DIyVizhxEQh6AkiaAkqAPRi%2Fp6GaXnooGFtbcPJoPlRSIRw2OyLjU7Bg2VIkxIYiJTODBYKoqaiCw%2B5CR1MrnG4KGQMIZeF46DsPwaCRoKXqNMRiCabMmgmdq55CykClViI5IxUhB8qRkZMFU9EBJnZnYwPOnqnG5LkLcN0t10ApFcJUW4Kvjx7F0py58Io0uOf%2Bu5GdGIGpKSH4xz%2FXot3i7EEAwXzHiOiIunwaCEuBwMs0GCwQx2UC5HK5sHvjJhxTyiASSzDrqqtw7c3XIyYmAsmZ6ZDUtcBtt7C56zS1w2a3sWenVyDG0ptvwx0rFkCtlODEgd2wVHXg4e89ijC1hOFBoMkUalx%2FyzVY9dlOTJoxHdcun4vNqyuZtLZOI85UFKHZJMSjD9%2BJFTdcgY2frMIrL7%2BHY8fPIEmXRiFGEJWYg8eefBQCYxlWrd6IqooS34O86w2eSCxG9rQZyMixYPfndZeJxNg6jTRMwlH2b6GXKWeOHEFLRQlInqi0HMy5cilyc%2BJQYE5ESmMHC35C94bFaoa50wSvxndtZEydjW8%2F%2FSAS4qPw1gvtKCqsxM0r70NOigGfCX1%2BO1JVKG669Wqs%2FXIvplxxBa65aiYqz5xg1wTcLtSWlyL%2FWAlmXn0Tvv8fj6CltAB%2F%2FfOLOHIoH%2BlRPs1dYnoeVj7yAGx1Bdi%2B6zBqqisZ6es522RSS9eZ%2Fx%2BZmdLawePpiuLSs%2FIAtwmbwpMn0V5J5t%2BA2WTCkltuxbKrZ0LqtSA1JxtOiQS1NfUwmSxwWT2wmSkgkwyz5s%2FCtx65A0qvEZ%2BtWoO03FzEx4TjbBcuEXFJiIwIgSc2CXm5ySjcxFSZaC4txZlSI174w0pkp%2BjRmJXITKMLjp%2FErIwwGBJSsGT5NZg%2FKw2WxnKcrurwmZr2GJNKowN9OqraeuzlmxwBjgBHYIwhQEpAt6P7JRZ76Xf5z%2FQxNnou7gRBIOgJYGRUJFvAUxCY0S705t8QH4flN10HnVICiUQCnT4MuhANyo4fQeHJ0xAr1UyDJxL5NXC%2Bh4ZIpUeoWgZad1%2BKZ5Db6YDb5YVSqWRRDom8aTQauB21jMBBroE%2BRMFIllRK2jQ77C53ACrKeSVXa5iGsq29E7FhCuaXZ3e6odaqMBg3dxr%2FDffchcwkA6QKBaJjYxEfb8C5%2FCPYv%2BcArB4JEmMpsqOcaRoDQomkiE9MRFh4OCSws4AxxMdkMmmv4DE0VuqDvikXpFjcfblSJEOnwwGxVI4QnRYqjQpheh1kUgnsNhs8blqYA%2FqYeCiJoApD2CLd4z3fL4nm1RPEJh0kGiVwH4pgFdTG8huWQS6Xj2oSbJrTmVdeieuWzmYvD8IiIpCSkQp7RysO796D%2FDO1yM5OZ75okj5zExkTB31EJLRaFSQSEbuhaFyiLm0gm%2Fiua4cOikWS3teO1wunwwmnG9BotNCFqOEOC4FarUa91Q56sUElLDqGYSQM0TCNPV07vZcAAiiUSni9TrS0GeGMEqHVaINcoYeqSwPPGrrE%2F%2BieXXDNcmREk2%2BegAXqMcREQyoWoLqwBMcOnYAuNh7hei2EIjEEcPle5kgV7NmgpMibtkt5ynjhstvgFYqhDVGy%2B4Si%2BlLUXaPDztqmhOlKtQoCgZBF%2FHUTFt7u58wlDnHUq9NzhT1vuojxqAvEBeAIcASCBgGy7oDbt1Zgz3whrT0u5ZkaNEPhgnAELohA94r6glVG9wARwEeefJgRgdGVxNe7WhuC1Ix05gPYLY8XZYWnUVRSg9sfuAd5OUnYvvpjeL2dsLs8vkWjUNwVdVAAgUgCoceFmsoayMO7WiFNp1AEp9mCpoYmCLtInCo8HAaDEmdOHEfx1DSopR4c2H8K0XHpkEokIEZJqRMuWIRCqMIMiA5TYtem3Qi9YRaLXmp1CZGYEHPB0wZygLRn0%2BfPw9zcpEB1CmJRU16KI4ePY%2Fqiq5CckojC4ydhdHqZJpJVZGP1UU8iAhQy32mzY9vXW7Fs%2BZJAW%2FS8pQWnx0lh5ctw6MjpwAJcqtBAFxcLWPdh%2B6bNcJkacGjrDphdIqSmJUMu92lxJLLL88PqFmL0t4jwf%2Ffpx5GWmTZoTbhUKsU1Ny5n7fQk1KMxypRJObjq2qt6dd1S3Y4DO3fAokhASmY6nB0tcLk9cNF91BX4h5kFd13ypMmkzaN79iLeEA5PVx1qlGk5PR6UFRbi4JGzCO%2BKjUSO%2FOGRBsRGqJF%2FZD9Wf6iDqbaM%2Be9OXrQMoWG%2BqLtiqZS9sOklYI8fdO1Onj4Fon9vwsbP18BYZEBloxl5S9MRHjKI604gQFJqGrK6fAD9XbqdNjRUFOPI8SL8x533ID1ai69aG9HYUg2nx8aeBXS%2FUKExSgRCNNc2oKPD0gsXuViC2uZmNDX7gh3ROaHx8QhV2rB10y5ct2Q6igvOoqS0GXlXz4JI4GD3ob9tvzxj9Zvm7cplV2LqzKkIj%2FQ%2FgMfqaLjcHAGOwJAjQH9HugggyJWAvblnC5Ih74o3yBEYLQSCngAyDZZ8YKHPhxNEWvwoVRqEh4d1B1gJdChAQmY2EmMLcXTfXpw7eRxuuxcxUSEwGq3QypWIiYsMmI7LNWGYPjkVmz9bDclNVyMiJpoRlpCIaIRrRNi7eRsmpRug04dCFxGFZTcsw4Yvt%2BLjf78Hsi%2BzycKwYsVVCFEbERMbybQTJIpQIkVcfFyf6IMC6MIjccNtN2DT1v14vbIADrsT0xfMR2ry5aVRoAV3aHgEYuNNLEpgAAa28JQgLjkF06Zmo7GqHEfhglSlgVaggNPpgVKrQ0xcDNPKMbM5oQRzZk9DVdNufLl6HfJmzEZIWBji4mMgl0uh00Vh6uQUtNRUYfeufExJ0yIqxgBduB5TM9JQW9OEwyeL8ElZESGAG%2B%2B%2BE%2FPm5EHlakZUTBT0pCUR%2Bkh3QnwcDBdY8NH8KlRaxMRFQ6NVMqL5DbS655CHfZu0LzfdfiMjbbR4HWwhEjiaRaXVIi4hFiGa83MtakJCMW%2FxYuw6cBb7dh2gxJiIiTOA%2FOIgkSEi2gBdmBqirlyTOZOykZB4BEe270D6pJnQhYUjLsHCUrJExydiUlYy6kuLsWtXPu64LhcxsTHQh%2BuRkJaJu1fegXUbdmDD6jUsqmz2jNlYcfNyRCociDQYEBqmYebnUpkCsbExiNCHMu2YHzuai7x5i3HX3aex92A%2B2quUSJkyE7fddQMUksvTrQtFEsQmxEImPf98enEUkZCKSVmx2LN5M85olWhtNSMsXA%2Bnyw1dmA5qjZKJJxQpMXlyJs4cO4D89CTQC5NwvZJdQ9NnzsDptQewdu1OGHR66K0h0MUm4Vv334J9u7ei5kw%2BiyYan5OHxQtnoqUkH7qwUMgoUSnA8n2Ghbkh6aGR92NC3wKxhN3jUmlw%2FnmheZsyPY%2BJTH9feOEIcAQ4AgEE%2FC8Ru6yFyDKCvYzu9fQP1OYbHIExi4DgTG1Bb6umMTuU4RXc43ajpbkRLa1mpKSnQNon2TlFFSwrLkVTczsEIjEM0ZEwNjUjKWcS5G4TCspaMGtGDtNWUKLkwhOn0GayIjEtDcbGGsSm50DssaPkbCE8IjkiI8NA%2Bd%2B0YeEIUUpQWV6B%2BvomuDxCREZFIyk1HgKHCSfO1GDK1GxmHuq2m3Ho0EnkzZ4FZddijVAhzQmF2i8uLEJ7hwXqEB2S0pIRRomlLwM2aq%2F0TAGa2qzImToZ2j6J6q3mTlSUlqGxoRUKjRYysQhOt4cF9XCY2lBT34KkjEyWK420f%2FUVZThXXAkIJJg8czpMjZWorW9HZl4e1DLgzImTaOuwIVQfAUOEGlU1zYhLTECEXouWhnpUVdTAZLZBodYgOS0Zen0IvHYLTpwshDLUgPSUGAg8DhzcfwzKUD3ycjPOGzWZlFI0yuLyRkQnJiJ%2BCBNjn9fZBN%2FRVF2BotIaJKRnIC66twbG7XKhoaYapaWVgFAKjVoFl8uJ0MhIhKqlqK6sgSIsEvFxUZBJKBBTMwoKimGz2ZGUOQkuUz0amq2YMnsa5EInThw9CaPJirCoWKQlReBMQRE0oRFIS4%2BHpcOIitIKZr4pFEsQHR%2BP2LgowGHFuXOlUOjCkRgfzdK3nDp%2BFmp9ODLSkwJRQGkayS%2B4qaYWRUVl7BoPj45BekYKk%2B1yptntsODQwZPInTkTarmPcPVsx2GzobTwLBqbTZApFVBp1JCIhAgJ0cJisTJz7%2BiocAjgRU15Gaqq6mGIT4ZCYEO7XYT0tDiYmhtRcKYYKm0EosLEaLNJkZURB4upHUVni9FhsrL0KXFJCYiJjgAFz2lt60RETCw0Khkaa6thsjp9KWcU57%2Bcc9k6kX%2FkDDKnToFGNbovG3pix7c5At%2BEwOG3PsCJ1WtYlbXSRFgEwfkC45vGwI8NAQIeD4vw7m085VuviVWALgEisZSZ3IO%2FNBoCkMdvE4nuTsx1NbABLvvPZxE%2Fa1pQDra6oBZBTwAp39WmDZsw%2F8r5SEhKCEogewpFQSHoDfNANDVEpM6rR%2BGH6S16P5oeWmxSSBkiTZdTqD9%2Fn%2F21fzltXugc6odFzRogFt%2BE28XkvtjxC8k4lvb7522wMjudTuzdsReURmPqjKnMt3CwbQ7H%2Bez6ucB90Lc%2F3%2FyjFzEL1PF6mfkjaXj7v2189wS94h3MPRG4BoU%2Bk9RA%2F8OyQebUvmfHxWS%2B0HXjw5fG3FvAwDgGeN%2F2Pnvs%2FPKNv%2F%2Fn7NgZBZd0KBHgBHAo0RyjbXWtkTz2TqC5kA3CLdVBoI3uIoAS8i0Yo4PjYo8EAmOJAAa9%2FUtjQyPeeOUtlBWXjcTcDboPMim62KLM30m%2F9b5h4UWL2Mslf9Qn9Xcp8vnlvJxv6ouiO%2FY7xn4a%2FCa5Lib3xY73092Y2mXqMOGff3sV%2B3fvD%2FjBXe4AKPjJxvWbsG3TDpjNwZfz0D8udv30ZSf%2Bg32%2BffN%2FgT%2FKgWu%2Bz0mBn0SCBn6dBk7rsxG4BvvsH56fA7%2BPSa7%2Big%2Ff848ExnGB884%2FY%2BztIfK3Y%2FNOrP5gNegFIy8cAY4ARyCAAL287pECAhRoix6j9F%2F%2Fj9PAqXyDIzCWEAh6AkgLVgqKQiZevHAEJiICVqsV6z5dh4ITpwdNAGnxa2w3wtTRATJr5oUjMNEQoHvg%2BNHj2L55J4zGjok2fD5ejgBH4BsR8MLrDwBD9YS%2BYHsUs4AXjsB4QiDoCeB4ApuPhSNwOQiQuV%2BnyQyH3XE5p%2FNzOAIcgT4IkH%2B11WLlL0H64MJ%2FcgQmPALkg%2BPpkS6KpYAgDeCER4YDMM4Q4F7OQzih7W3tePeN91BaVDpoTc0QigWK%2Bjh99nTc8a3bWT69oWz7Ym3ZrDZ8tfZr7NmxJ5Bf7WLnjMRxMnWLT4zHMz97esBmqiMhF%2B%2BjGwG3243D%2B4%2Fgi0%2B%2BgMUSXOaqoWGh%2BOHPn4FGe34k0%2B4RDM9WbXUt%2FvXSa6DnTTAVylX61LM%2FQKSBIh7z1VIwzQ2XhSPAERgYAr4cgD1etgolXfE%2F%2BTNtYAjyWmMFAU4Ah3CmGuobsXPLTljsLugjDRCKRv%2BB4XK6UFNRAPIju%2FXuW0acAFK%2Fh%2FYdwrGjJxAVHw%2FJKKcg8E23F9Wl5Ti0%2FzAjgEN4CfCmhhABClhz5tQZ7Nm1HxExMVCPAtnqbzjNdQ1oqNmL%2Bx9bOeIEkMwXm5tasH7NV4iKj4M%2BMqI%2FEUd8n7GlDeXFRbj9W7cjIjKCE8ARnwHeIUeAIzBoBPwx8QNJ4AUgH0BfHojRX88Neny8AY5ADwSCngBS8us3PnodyandycZ7yB9Um%2BRTRWZ6i66%2FAYuWXwNpEOQv7Oww4e0X%2FgqHwzoqWkmP1wNayGdOmYpb778fYZGRoz5nFE31vZdfxq4vvxp1WQYiAClTpDIJROLz0wIM5PyedeRyOZ5%2B9imIxGKEhIb0PBR82%2BSL73IhMiYOtz70IDIn5waFjFu%2F%2BALvvvR3eNyeUZGHciLK5HJcffPNWLB8%2BajI0LfTY7v34uU%2F%2FgGUxmMsFLFYzO4pngdwLMwWl5EjMFIIdEUv95uACikJvC8BPKd%2FIzUHvJ%2BRQiDoCSAlwZ46Y0rQvlHuNHVizSdfMC0XmWTVVNdi29r1OHnw0Ihr23peNCKRBFffchPSc3IhFonQ06e5Z73h2HY4HNi3cx%2B%2BWL0OHUYjiguL4REI0dbUBKlMNhxdDrjN%2BcuWgT5isWTA54x2xfDwcLy%2B6nVoQzQsiutg5CESmZqRypoIxsUvabhKi8vwxstvoLW1leX9a2xswSevvwZNyOgS1qwpU3HjvfeOyjVMz5m%2FPvcC6usafEF82o3YuPpTHN2zZzCXw6DPjUtOwY333AOJQha0z%2Bi%2BgyTz1Ie%2F%2BxB7MUWmvLxwBDgCHAGWtqorb7LfB9ArEDPzz4BJ%2Bxg2bZ%2BUmYCkhKjzJtrhdKKp2YizRVWw2Xv4Pp5Xc%2Bh2RBvCMD0vDUfyi1Df1DZ0DfOWLgmBoCeAdOMFbr5LGtrIVG5taWNkp%2BD0OZagPW1SLpOXtAOjpiHwenAm%2FwDCDZGMAI4MEt29kN%2FfifyT2Lt7P6LjExCdmMwOUrh9iuo6GoWIxdkTJyCSiBkBHA0ZLrdPIm1xCbFDdh8EI%2FHzY%2BN2uVFeWo4tG7chPCoa2rAIqEPD2dhH69oh2cqKi9BYV4fr777TL%2BqIfpMP5KcffsZMyyNjopE9beqoY1JfU42q8nIsvO4aWjaNKB6D6Yz%2BnuhCdayJYP7bMpgx8nM5AhyBS0DA42GaPlonwOuGgL6pUACYAOkb2zrARVdMxi03XHFBUCwWG%2F7%2B%2Bjps3nHsgnWG6kBqcgyeevxm%2FPZP73ICOFSgXkY7QU8AL2NMI3yKF26PG%2FOWLsFN994HbdfCYoSF6NUdmc1958YVoOTqo1W8Hi9Ss7Ox8nvfQ3xKymiJEejX7fbgP75136iR8oAgl7kxoRaqXi9Cw8NxxyOPYNaihZeJ2NCe9r%2B%2F%2BhXqKiuHttFLbI201ktX3IQV9913iWcOT%2FXVb76JA9t3jIpp%2BWBHNKHup8GCxc%2FnCIxXBLxeeFpL4bW0QqCNg0AV0TsHICOAvsGT64jAK%2BxBCMcmKH958ROUldf5hBcIIJGIkZocjW8%2FcC1%2B9ORtKC6tRXlVw9gcHJf6khAIegJIJk9rPl6Dq6%2B9KmC6dkkjHIbKFNhk17ZdOLj3EDqMJhSePgdZZR3amlsglY6uieOsxYsxZc6cYRj1NzdJfn4n809h3WfrYTFbcO7MOTQ1teLj19%2BAWjPykRJ7Sps7YwbmLF3CwzgDIPPcrV9vg0wuw5wrZoNMrEe70FvXupo6vP3qv1lyetpuaWjExtWrcWzv3lEVLzYpCVetuGnItK%2BXMhhKU%2FDi8y%2BBzD9Jq075IPdv2476qupLaWbI64ZFRPh8DwNvxoe8C94gR4AjwBEYXgSYts8LryFAh58AACAASURBVL2T9ePtrINXEQqvyxHI%2BOAVSkC50rzWNniNVRAo9RCGdcWjGKPPv%2BraZpRU1PfClsw%2F6aX909%2B9BVcvnorX3v2613H%2BY3wiEPQEsKG2Hv%2F4v1eQlJIUNASwoa4BG9Z8hYN7D0MTqoNIIofL7kRxwZlRvUrIJKutpWVUCCCRvh2bd%2BCzVZ8hNCICIpEYcoUSlcUlo4pJc1MDKouLMTNINEmXA0aHsQP%2F%2FNurmDl3Jq68evGgyAiZUVJSea1Oi9y8SUFBAMns8%2FjRE3jv7Q8QFh4BmUyOkDA9muob2OdyMBuKczra2yGRSTFz4UL4%2FUOGot2BtlFRVoG3%2Fvk2wiIjoFCoEBUbB4upE6eP5Q%2B0iSGvZ7VYWGCeuOQkeN3uIW9%2FJBoky4iv132N%2BtoGXH%2FLdTBEGUaiW94HR4AjEEwIkLWnxw3IQwBzE%2BBxw2tugReeAAEkE1Cv0w5BRxUzc%2Ffa2uD1JEAgFPr%2BJoxREtjfNJwrqWG7w8N9vvbpKTG4%2F%2B6r8c6HW7Dy7qVISYjCgSOFeOm1L1i96XmpuO3GBUhOjAKlbCISuerTHSjtQy7Dw7RYeddSTMlNgVAgwJ4DZ1BW0aWB7BIkMy0O9925FB9%2FvhMnz5QHxFMq5fjZ03dh%2F6Ez2LD5UGB%2FjEGPu25diMk5yZCIRaioasJHn%2B%2Foda5CJsVtK%2BZjwZxc6HQqtLR0YNuu41izYT9cNO8AJCIRfv3T%2B7Bx6xFkZcRjyYI8lFc24M8vfAxjZ3ClngoMfgg3gp4ADuFYh7QpkUiEJTfdiLsefRSqIAlP%2F9Sddw3pGC%2BnseTsLPz497%2BHPgiifdJC788%2F%2FSlMRuPlDCVozrFYrFj%2F2Qao1WosvmrRoAhg0AyqH0FCw%2FR4%2Bne%2Fw6RpU%2Fs5OvK7Pnz1NezdvGnkO%2B7qkTSjQpEQDz39DBYsXzZqcvTseO%2BWrfji3Xd67hqT22StQJYbC66czwngmJxBLjRHYBAIMB8%2FLzNf98p0gLkZAvJjtjYDElV3wwIhBKbqwAtArzIi8OKLkcDummN%2BKznJFyCmuaWDjSVEq8KcGZmI0IcgMkKH1rYOqNVyduyW6%2BfhiUduRG19C7bsPAaJWIyrFk%2FFFbNz8J%2FPvYOjx4tZvdAQNV744xMI0Srx9dYjMHXasGRhHpYvmdYLL11XX1v7%2BB9KhEImQ119S6B%2BSmIU%2Ft9%2Ff5tZdG3cehRtxk4sXTAFf%2F7to%2Fj1H%2F6Nw%2FlFkEkl%2BMvvHkNaSgy27zmB7XsakJEai%2B88dD3yJqfgN8%2B963NdEAgCY0yIi0BVTTNiY8JhslgD%2FY3nDU4Ax%2FPs8rFxBDgCHAGOAEeAI8AR4Aj0i4CX%2FPwkKgicnRC4HaQWDNQT2Np8%2BwB4xCp4pVoIWJAYMgwdm4V8%2FoiwUREKBSCiN2VSMr5z%2F3UsbsSWHb0tTJQKKR544i8wW2xMYxYRHoJvP3AdSsrr8ONfvgqr3cHaWr12N15%2B%2Fvv4yQ%2FuwAPffR5Ol4tp%2FsL1WvzkP1%2FDidNlvnpf7MILzz0Bjeby3E%2BIeFIgu%2B%2F99O8gc1YqX3x1AK%2B98Awe%2FtYyRgDvvmUR0lNj8fxLn2DT9u6gNneuWIDHHrgOSxdOwZad3eNMSojE93%2F6MhsTaQU9nrET1IwBcJn%2FcQJ4mcDx0zgCHAGOAEeAI8AR4AhwBMYYAn7TTRZlHvCQFtDp8wUUeLpzmQpdPjNAIokeRTgzDWXUYAwHBH3%2Bd4%2F1O1lOpxsvvLIGZZW9%2FQN37D3JyB%2Bd5HS7MX92DsRiEd77eGuA%2FNGx5tYOfL5%2BHx6892pMyU1mRGz%2BnBycPVcVIH9Uz2S2Ys2GvXjy0Zv6leObdoaolZickwQiqX7yR%2FUpgun%2FPP9%2BICDZkkVTQJrMnuSP6n2%2BYT8e%2BtZyLJo%2FuRcBPFdcw8gf1aExTpQS9ARQKBIxPyW64HjhCHAEBocART%2BkJOIy2djJ2za4EfOzOQIcAY4AR4AjcD4C9PdQIBABEgU8IhmEbvt5lYjwueXhLCUEpbKiD%2BgzRsu23cfR2moKSG%2B1OZgp55HjxWg3%2Bkhw4CCA2rrWnj8RFxPBfpeVnx8ptKS8lh2LiwnH6cJKhOo0OHjkXK%2Fz6UdpeW%2BSeV6FC%2BwwGEKZC0x%2FUUqpPypioQgxUXpYbXa88Ifv9ttSXHR4r%2F21Dd0mpr0OjPMfQU8Ak1OT8MK%2F%2Fg8p6b7k1eN8PvjwOALnIUBmGqFhOiiUivOOXeoOIn7feerbEItECAkd3cTqlyo7r88RGCoEKPptiE4LUZcp1FC1y9vhCHAExggCjPwJIRCKIBCJwXwBLeeTGo9UB69IDlJGUD0yP2RpZPxaxDEyXL%2BYpKWjgC0DLQ5nt0aUzhGLfOSXEsj3LU5Xt%2FaMTCmpCITnq0tdF9Ky9cFU0NWXvx%2BZTMo2Xa5uM13%2FMf%2B3WOKTr91o7necNPZOs81fnX07HL3H2OvgOP4R9ARQrVFj1rxZ43gK%2BNA4At%2BMgF6vxwuv%2FRUarYb98fnm2t98lJLKZ2ZnfHMlfpQjMAwIUFAbSm1BKUgoiNZoFVq83fvgvaDUNWH60NESg%2FfLEeAIjDYCARIohFeigUfYAmEPE1C3SAaPVAshET9G%2FkSMMI622KPZf1OrL6hetCGMmX32lIX2UWlpM6HDbIXN7kBU5PnP2Ei9rudpgSDboj6ET9vHT5AC0VCJ7IpU2rORGVPSER8XgY1bjjCTULvdiX%2B8ub5nFbatUSmYGep5BybgjrGrx56Ak8WHPDERINKWkJSA0LDzH6QTExE%2B6rGAABE%2BisRbWlyG99%2F8AE899gxuufpWfO%2FhH8DldAX8NUZ6LEQA9eFhiIo2QCr1vVEeaRl4fxwBjkCQICAUQigQk2oLXmm3VYxHIIRbpmdaP4FYAqFQwrZBWqo%2BmqogGcmIiOGP8HnDNbN79UeWSjcunwO324MTJ0vZ853MP3OzE0EmoT3L1VdO7%2FkTFqtPIxcbpe%2B1f8703i%2Bra%2Bpa0NjUjivm5AQC2dAJ9Ex%2F4O6rcO9ti2FzOHA4vxhJCQbkZiX2ao9SW3zy9q%2Fw4ydv67V%2Fov4Ieg0g5QgzmUzMD5D%2FsZ6olykf91AhQItyytlID0y5Qj5ojeJQycXbGfsI%2BAifFw67AyfzT2L%2FngM4sPsA6ut6m1VVllXCbDaztCaU5oKuRV44AhwBjsCII0AaQOpUKIBQKIJHFgKvvZWlffCRPykEIiJ%2FYpA5IntWTfDn1ZlzVdi9vwBLFkyBzebApm1HIZVKcOfNC5GSFIX3P9kWyKH3zoebMXdWFv7wq4fw6ttfMo3htUtnYMbU3i5dhcU1MHZ04vYVC9DS2oHKmiZMm5yKm2%2B4As4%2BJqhvvLcRP3vmLjz3Xw%2FjvU%2B2wWy24cbls1kev3%2B8sY5F8KR%2BZ8%2FIwG%2BeXQmqX1hUxXwXv%2FPQdUzm1Wv3jPilFowdBj0BbGxoxEfvfozrVlyLDG66FozXEJdpmBGgJKvNTc1QKpXMDHQw3ZHZ25avtrBAMPMXXwEyseaFIzAYBIj42SwWSCUSvP%2FW%2B%2Fj9r%2F%2FAXjL0bVMikSA7NwvX33wdO%2BT2uFmew771RuJ3h7GDLSxCQrQQS4L%2Bz%2BBIQML74AhMXATID5DSQYgl8Ei6tIASFYSk%2BROT%2BSc3%2Fex5cTz314%2Fw7QeuxfXLZuG6q30uWhRAhkwuP1%2B%2FN1CViNzPfvMGfvjkrfj1T77F9pMG75U3N%2BB7j3VHAaWUEX964RP86Mnb8NR3b2H1mluM%2BO%2B%2FvMfIXqBBABTERiwW4rH7r8Uff%2F0wO0QBX159awM%2B37CP%2FaZ%2BKfXEU9%2B5GU93tUcHSspq8fv%2FXYX%2Bgsj07GOibAf9X77G%2Bka8%2BcpbyJqUxQngRLkq%2BTh7IdBp6sRrL72OuQvnYunyJYPSmDgdTmxcvwlanRbTZ03jBLAX0vzHpSJA5K%2Bk4DTWvP0WVGolCk6cPq%2BJ1IxUzF80DxnZmex6o3oul5uZh9L5I60BpD53bt2Fupo63HT7TcwU9Dyh%2BQ6OAEdgHCDghVjmgVTpgkjmhlThhkjqhljugVjq2yYVoFDkhsflhsvmhqPTCw%2B8EIvbIZKJIJKKISATUQjhdorgsovgcgjhtongsIjhdojgtIrZvmAGjMhZfz5xF5KZEqpfc8cv%2Bz1MhO3lN9bhjfe%2BZhE37Q4nGhra4fJ0B4Hxn1hQWIFvP%2FMC8wWkBO1VNU1wezz44qv9%2Firs%2B8jxItz%2FxJ8DUUara5uYNu%2Bex57rVY9%2BUHoHyuPnj%2BZJkUr79n2upAbff%2FZlhIdpoQtRM%2B1j3yinNI4LjfG8TsfhjqAngOMQcz4kjsAlIWC12rBpw2aE6cOwZNmVI75gviRheeUJh0BCWiqmzpuHo3v29HttlpwrQXNjM5JSTiI9Kw150yZDq9UynIiMjXShPk%2BfPI3C0%2Bdw5dWLOQEc6Qng%2FXEEhhABocgLuc4BucYBudYJmcYJmdYBudoJqcYFOn6xQs8Ej9MLl50%2BbhCPEYkFEMmEEMsEEIopXcQ3m6q7nULYTRLYOiRwdEpgM0pgM0lg75CyfV7vN59%2FMRmD8bjN7kRpxcVTOhC%2BdQ2900n0Nx5KwF5Z3djfofP2sbo1Teft77uD8hPSh5fzEeAE8HxM%2BB6OAEeAI8ARuAgCjLx5vXC5XIhPS8OurzdBo1X3G9zF2G7E8aPH2eeT91dDpVYxq47JU3ORO2USsnKyIJVJ2SLrYguti4jFD3MEOALjFAGJwgVVuA3KMDtUejuUejsjfAMhed8ECT1zKB2gWAoIRCJ43aQVpNR%2FAghFFyd%2F1LZI4mFykWx9i9spgM0ohblFBnOzHNY23zeRRl44AqOFACeAo4U875cjwBHgCIxhBPoSNbvDjmsXL8e%2BXftYJDgaGqUuSUxOYOaWLc3db4DNnWYcOXCEfaieWCxGRnY6JuVNgo8U5jJzUbYwu8ib9zEMIRedI8ARuCACXijDHFBHWqCNskIVYYdC57hg7cEeIKJH2eVYJgKJL7KkL%2Bf74DV3IokXqnA7%2ByDTp43yeABrqwydjQp01CnYt71TMthh8PM5AgNGIOgJoCZEi3mL5iI8ond42AGPkFfkCHAEAghQSoms3CwWUIY0LrxwBAaFgEAAsVgCiYSuJQHSMtMQExeD1R98CgpeZOowMXL3xDNPwOFwoKaqBpXllSgrKUNtdS3z8aD%2BSYt4%2BuQZ9vn4vU%2BYJpBSn5B2MHdKLiZPm4xIQ0TADKsv%2BRzUGPjJHAGOQFAgIFG6oIvvREiMBdoYC6TK833KhlNQIoHeLqXccD9jhEIESKEhp50Ny9ouZWTQWK2CsUYFriEcztnmbQc9AYyOicJTP%2FkBYuNj%2BWxxBCYkAgqFHMuuv5ppSAb7R4lSqay4fQUo4apKpZqQePJBDx0CdD2KxGJIpD7zTaVKiczsDJZf78N3PmLJ1vOPHGdE766Vd7LE63nT85gAdpsNleVVqCirQFlJOSg9BJFEKmReSvvps%2F7zDWxfRGQEJuXl%2BAjh1FwkpSYFTEYv5b6gujmTc5hPLb1g5IUjwBEYPQQUIQ7oUzsQmtjJTDpHW%2BF%2FKc%2BSoUaNNJz0MWQbQRpCU70S7RVqNJdq4LQE%2FXJ9qOHg7Q0zAkF%2FRSmUCmTnZg8zDOOvea%2FXg6a6OuTv34%2FW5iaEqBXjb5CXMaL2llYc3rMb9dU1l3H26JyiVqvxyBMPB0ziBiOFUChEQlL8YJqYsOdaLRYc27sP5UVFExaDvgN32Ow4d%2BIkWhrq4XG7WW6%2FEF0I09jJZFK89%2Bb7sNnsOHHsBOQKGR547H6WRJnqUlqIzJxMpGel%2B%2FJuuT0BDWF5aTnKisvQ2WkOdNnU2ITtm3ewD%2B1Uq1XIIUKYl4vcqbnIyEofkB8hLfAWXDmfJaMPCe1O%2FBzoiG9wBDgCw4oAkb7wDCPCEjuhCB0%2Bs85hHcQwN04aQtKE0idhbiPMzTK0lmnRVKTlZHCYsZ8ozQc9AZwoEzHU4%2FR6PCg7dxY2ixlWkwlZmak86TeA%2BqoqfLVqFYytrUju0iAMNfZD3R6ZbUbHRg91s7y9S0TA1G7EVx99BLPJhNj4GBbI5BKbGHfVrRYzdn25AfS8CY8IR4QhArowHUQiEbInZ%2BPhJx7Gv%2F%2F1Dsjnr%2BhsEVRqNSQSMdPwUSoIl8vJiBiZgNLv5LQkJKYkMoJGYDU2NDEtYHkpaQnL0NLUEsCQyOHBvYfYh3aSdjstMxWTp05mpqPkT0jBZuilR9%2B3%2BrpQXaAdvsER4AgMPwISuQvhaSbo04xQR5wfKGX4JRi7PZBWlDBTRzQhbmYTTHVKNBdr0VqqgdvFA8mM3ZkdXcmDngDabDbUVNYgMipy0EmwRxfqke2dEpdmZqXj1rtvYQsjIhAUaGGil%2FiEGKx86C7mt6SdgOZfHo8HlFtTKBJCr9eDyCUvA0NAFxqCe1feBplcDjJ1DAsPG9iJ47iWSqnEDSuWMxN98ilNSUtmmj2hQMiusfSMNHz36cexd%2Bc%2BzL5iFuRyGeQKOSNlZOZJfoJE%2FJxOIoJO5gvocrp8v11uxMRGwxBtwKy5Mxlp7DSZQdpB%2F6enHyGZj%2Fr9CD98BxAKBSA%2FQiKEzHR06mRERIZfltnoOJ5CPjSOwLAioI6wInpyK0KTzANKyTCswoyDxplmMNaCkFgLkuY2oqlEi%2FoTobCZuE%2F%2FOJjeER1C0DMCIn%2B%2F%2F%2FUf2SKCFhC8fDMCpvZ2HNu%2FDx63C4nJibjmxmsCC55vPnP8HiXtw4kDB2GxWJCRlcow6U8rEKwI0ML21PECGKIiWYCNvtqMS5HbYXdg1b8%2FZJqRO%2B%2B7A1wT8s3oEfZnjh1Da0szNGoVll2%2FjBGYwczBN%2FcY%2FEfdbg%2FKiorQVFsHiVSMBUsWIC2j28LA4%2FYEnjmEk1QuY9p2MuenFw4SqQQSMYXZI2c%2FwO1xw%2B1yMzJ4IULo1xCS2agmZDKLFEoEksxLq8orUcECy%2Fj8CIlMUqE8UaQ5pM%2FaT9exfXQPkf8fBaohU%2Bg58%2Bewe2Eiz2fwX3FcwrGGgEDoRXhqB6Jy23yRL8faAMaIvCKZB1E57TBkt6OjRom6k6Forybf%2FsFHLh0jEHAxB4FA0BPATlMnjh48irbWtkEMc%2BKcWllaig9e%2Fge8Hi%2FCI8O52SeA5ro6rHr1n7B0mhiJGkvkj65ck9GEF%2F%2FyEq696RoQaRvMYpUW2MWFxdDqtHA6fAvliXN3XPpILWYz1rzzLoztbZg8JYcRmMHgf%2BkSBN8ZDrsdu778Cm6XC7FxUSBfv573FGmXyRyTcKJtuc3OyB3to49YJGb7%2FTiKIIJX4gVpp%2Bm55fF6QCSSrlUfISTzUBczFfVpCrs1hMyPcFIWMrIzAmaltTW1LKAMmYwS%2BaMXQP7SUN8I%2BvgLmYjm5k1iPoQUbTQzJ4NpMP2y%2Bevxb44AR%2BDiCFAuvMhMI6Imt0Kmdl38BF5jSBAgE9GQOAv7UCTRmmNhaCnVwuvhRHBIAB6njQQ9ARynuA%2FbsNLSk%2FGDn%2FyAmVrFJfJgHwR0dGwUfvjzZ1jUS3rzP9YWd06XiwXEaO2RR23YLiDecC8ENBoVHv%2FBw4iNj4M%2BPIybUQOQyWS45rolmH3FbBbVMyomqtc9RfcXMy0WAAKhgJE%2BInfkFyiW9CZ%2FfrDZOSIR0GWRzMig1xvQENJv0hLSN5FBPxH0bfsJopPVSU5NRmJSAvMjJC1hc1NzQBNYTn6EPe4jIocH9h5kH5KFCCqRQEo%2FMSkvl5mOqjXqXuPzy8y%2FOQIcAR8CIrGHafui81ohllE2PV5GCwGKIpq2pB7xM5tRfUyP5qIQTgRHazKCvF9OAIN8gnqKR4sZu80Oi7kTJmMHTG2tMHd2gsKpkzbH3GlCWloi5i2c2%2BuNfM82xuO2w%2BGE1WximrKO9jaYTR2wWawgc8emunpoNWrMnT8HZII21sjfeJyvYBoTEQib2QJzZweM7UZ0Go2wms0sHUFp4VmIhEJMnz2dmVOTlmsiFCJZNquVBbsxGY3oaG%2BHtdMMu92GcydPwW61ImtSJubMn820ZRfChAgfYcZ8j72%2BWkQIB4JjzzpCr5Bp90hLGNAQerq1hDSH5DfYlwwSSSTSGBUTjUhDJPMjJClont978wM01jdAo9Wipbk5kI%2BQTH5P5p9iH%2BBD5keYlJLEEtRT%2BgryJaRgN%2FQc4c%2BSC8083z9RECBTT8phFzu1GRIFJ37BNO8yjQupixoQO60FVQcj0FKq4aahwTRBQSALJ4BBMAkXEoEWYqYOI6pKSlF6thAVxcWM0JA5msNqYxH0aHFFUfXYYksAlhuLtsdrIRJstVhRW1GB0sJClJ8rRENNLYytLTCbLXA7nb5FZxcmNosFk%2FOymOaBL9jG61Ux8HHRAp9818oKC1F2rhA1FRVoa25mZoJOO4Uj97JrhcwUHQ474hNioVAqB0RaBi5FcNWk50xrYxPKis6hrPAcqkpK0NLchM52IyPClLKB5foTi%2BHxuBASokWIzhfp82IjoXtusM%2BjXmSrHw0hmYySqSiRQyKBTEtIgWRIU%2BigwDK9I42G6kUIDQuFqaMDlJuQAoxVllWgvKwSpCGk3IQ9%2FQhLi8tAH78fYVS0gRFCSj1BmkLyte4l48VA4cc5AmMeAS%2FCkjqRMLsJ8hDuShDM0ynXuJB%2BVR3T0Fbsi0RnE08JFszzNZKyBT0BJD%2B2ux%2B4e8LkLqPFi7G1DaePHsWxA%2FtRdvYsjG1GqJRyxCXGIjc3DfEJcTBER0IfHs60WlKphC1QaRGij9CP5PUzIn2xYA9WK86dOoX8vftx9sRxtDQ2smTmFCUwMTke8QtmIDommoWhp%2FxgFJGQFp6ECQU6IV8hXsDIzcKlC0HJ5Ska40QoFGWy%2FNw55O%2Ffh1NHj6KhugZOpwORkRFISk7EtClZIDNGQ5QBlBeO%2BbSJREz7Rz5iERHh4w4muqdqysuRv%2F8AThw6hJqKcqYJpUinSckJmDN7CovsSZqzMH0o5AqFz3xTIGDXDSVl76mlG2mAevZNPoT0IozGJPVIfT6EXf6ERAh9foTdkUbtdgekMgkoUrJMLoVKrURmlx8hjYOul5rqGlSVV7HUE0T%2BLGZLYIj1dQ2gz5avt7J9FE04Jzc74EeYnpUW8IEMnMQ3OALjBAEyMUyeXw9tjHWcjGhiDENjsGHSzZVoKdGgYn8knNagX%2F5PjIkZxVEG%2FRVAC7OnfvJ95ncyijgNe9c2qw1FBaewZ%2FMWFBw%2BAovZhLi4GFy5dAFmz5uJ5LRklgicBVEQ%2B%2FxoREIR87HxCzfe3kLTQqyqtBR7N2%2FGsb170NrUBJ0uBDPnzsDsK1YiKyeTkTuZXMYWgOR3RJhQACzCgkrfbz9WY%2BmbCO3jT38HWZOyAuO5XPnp%2Brn5jhUMI%2FLlGq%2BFyEBTfT32b9uKgzu2o7aiCjKpBFOmT8HNK5Zh8rQ8RBjCIZfL2csB%2F7VDJop9rxn%2F77GOFWFC%2BS8P7NiB%2FVu3obK4mGnLJuVl4577bsf0WdMY6aMXA%2FTChGHSZcbZEwPa7vk7GHAJyCQkN0KRz2TU62URR0kzSJFG2bfbRwSvumYpps5oBZl3EsnvmXpC4naz%2FT39CCkJfUVZJfPFpeAyrS3dQck6jB3Yv%2BcA%2BxAWlOqCgtJQHkJKQZGdm8We3cGGWTDMG5dh7CAgFHpZDrroyW0QTAxr%2BLEzOQOUlJZFlIsxNMGMyoPhaDhD%2BVB5oJgBwjfuqgU9ASQtDv2BHo%2FF6XShsbYGB7fTgmwr6qqrmWZv%2BfVLsHTZlUjNSA0sUCma3kRYQHg8brQ1t%2BDw7t2M%2BJWdLWSLp7kLZuOqa7%2BPKdPy2PVAwSTo2uipCRiP1wiNia7%2F2%2B%2B9jZHbwV4DdP541fxRMnKTycRSfuzZtAmnjx2DRCJC3tQ83LfyTsxdMAekraE0BKQxmgjXDpE%2BimR6Jv84CJMTBw4wM8mc3Ew8%2BcPHsXDJAoTpwwKYDNZcM1juQbrOA%2FcKxZbxdpNCevExf%2FF8hgPVYSajLBF9b19Cnw%2BhK%2BBHaIiO8vkRCgTMj7C8pJwlqS8rKUddTR0jnTR%2BSk1x4thJ9vng7VXMjzA5LYX5D9K1SGajlEOyl4zBAhyXgyPQDwJKvQ1pS%2BqgDCUzeV7GOgIiqQfJCxqhTzGheHs0HGZuITXW5%2FRy5A96Ang5gxqJc2jRcOrwEai0GmRO%2Fv%2FsXQd4VUXafm9P771DCJ1AgACCdAQVEAu6Kq67trWuu2vd7nZ33aq%2Fq2vvIoKidJXee6%2BBVNJ7L7f%2Bzzs35%2BbcmwQSQsgNOcNzOSdz5nwz886cc%2BabryUjMjYOfkJ9zNCy8HBpCJmb2poaFOScx8kDB3F4zx5kpqUJlbPRqaPw6JMPiAWGr79vr1ygckFTnJuHFZ98gmGjUxDdrz8Cg4MFE0t1q7YScayvrUNRfp6It3Z4z14hCbVZrKBk4ulf%2FUwsUqnaykX71bJAbQuL9vKIKyV3V3NiH%2FlsfLNsGUoK8hE%2FIAkh4WHw9PYW495W38nc0FlJWVER0o4ew6E9e3DqyGHhsIQByR96%2FH5Mnz0d0TFR9rmjtasEt0XLHfOIidViw8aVX6Ouuhr9Bg9CWFQUvHx8QbXvthIxYZgGSvrOnTyFo3v34Nj%2BA6gsL0dUTCTuWHQb5sybLezWJCkf67naE%2Fvo6CcZQm0LQyjFIuS7SAo%2F0Z5jGUmdNDg4SGgfjBwzEmiORyjZEWaeyxB2hKTBxHiE6Wnp4rdi2UqRFxkdKeIRJqeMEAxhbHyso32Odl7tg6L0z%2B0RUKlswolIVEoZ%2BogPLLcfk8vZQKrxjrwtC1m7w1CS5n85SSu0egECqlP5J5r9s7lnaxsbG8Fg8OGR4UIS5A6trKmuwXdr1%2BPrpV8jIz0LNZXV0Bn08A8KQnBIGALDQ%2BHn6w%2B9h17sCjc0NKKyrBzFBfkoLy4GPev5%2BfmKHeFps6bh2umTwAVBb5Zocbf80L7D%2BODND3DmVBrKVKLfPAAAIABJREFUSsvALwadRQSGhiI4NBR%2BgXZbIq43jQ1NIrYa1fRKC4tQVVkJD4NBuGCfMmMyps6cgvj%2B8Q5GWFkUXZ6ZzwVsSVGJiMMWHBxsd9d%2FeUhfMhUyLbk5efjvv17D8cPHhH0V1X99fH0RGBqC4NAw%2BAcFw8vHW9h9moxG4cCjtLAYJYUFqCgrg0atQkJiP1w7dSJmzJ6OQUMHCakWpXy9de4wRME%2F%2F%2FJvHNp3CHnn89DY0CQY4oDQYISEhiEwJATevj5CXdNssaC%2BphblJcUoLihEeWkJLCazUOkcPykVVHmkOqIXHdr0EW2CzkxIzkEmMoFUFeU%2FPisSQ8hzehSlYxmziY5l7JJBvveoyUHps4UMpNUqGELJjjA7I1vYETIeodyO0LVt%2FgH%2BGDJ8CEaOTsbQEUOQNDjJYbfcW%2Bevax%2Fd%2Fe%2F97y%2FG0S%2B%2BFs1cqY9Hvapv748bfEwYMD0fvhGN7j50SvsuAwK0DczYFgGLSdHv7Qqc8ZZaTDAXCRLX%2FfZ5xKamdIVct92beyIfbs8AUpXmgTsfxF%2F%2B%2FWdcd%2BOsbgOjs4S5YODHv6a6Fuezc5B26izSz2YgLycXJSWlqKupFR70SJcOFKh6Rocl%2FZP6i4XYoCEDxQ4yF2NXiyoaMeEiqb6%2BHvl5BTh7%2BqzY9aZXPbpcr66uESErWI4SLbpgZ4w%2B2jcyCDMXQCEhwY4FqrLwsc%2FKpqYmHD98XGyCRMdGd4mhIVPxq6d%2BLbCnbW1oeGhnp363lecim2FOGLft7JlzYv5kZ2ajML8QlRVVYgFts1mh1eqEWmx4RJjwest5Q7U62gtTqsV5c7XMHTIUfM9UlFcKD5Vpp9JAlUMyhGVlFUJ6brGYoVZr4OnthZCQIMQmxGHIsMEYMWo4KFmiym9vZoQv94Tj%2B4fzigwZbQC9vL3arILlxI8MId9tzXaEZP44LjxybGg%2FyLlLRpB%2FW4TjGTKDjFso0bCCdoRZ6dnIyshCxrkMMaZtVuywIxwk5jXHceiIoY4wNlfL3G6v7z2VrzCALcgHxNYiaXoBNEpMvxZQ%2BsBZY7UOad9Fo7786vUP0N3D2JsYQLff4uLOKl15i53V7h65TtDnR5hMDIND80fnEkxcKHDX2GwxiyDGzCOT5yrduxo%2F4uwTbfPI7PJHJlfCRHLEYN8htweIpsMWqmJJ6WrEROpbV45c%2FD%2Fz2LO44%2Ft34OEnf9Rl5sa%2BYLWrp3WlXZf7Xj4jXIzHeccJxoWSPCY%2BU9Kim%2Bp6tFlnmIa%2BMHfIuNFmjaEH%2BBs%2FabwDEyGVsljs7xkVxDuGGErPkXS83OPU2%2BlxPi39ZBnOnDyD5194Tkjb2uoT8RMYNm%2BIS3aEtCHl%2B4zhJ%2BQSQs5R8RMxCS3N53ZpISWC1PKgHeH4a8eLOU3nMZnnMpsZwkwUFRSJfLbFbkd4FEcPHRVN02jUkOwIR4y0q40GBgcqjH1bA6fkdQEBG6JGlYsg4n1AM7wLOF2dt3r4mTBsQTYytkSgLMPv6uyk0isHAm7PADpa6uYn0mKLRy7ayAj19STHBM3e%2Bfo6Jpfaf6Gh5tbK2pfas7bvk%2BYOr%2FL8areBbBuF1rkSLjzyPaOEN2mNUUdyyAQ2a312pLgoQ8wl%2FKGxb0zYtHYJn9yOkFoQkoSQ53ZJIZlD53iEQUGBCEgNgLAjJNPX0AiqjFJCyB%2B9jpLJZ7JYrDh35pz4fb10hciLiokSZgTUnqAEPCYuRrSP80JJCgKdRYBB3QdMK0BwYk1nb1XKX0UIaLQ2MG6gd0gjcvZSQ%2BjqtxG%2FioavU11RuJROwaUUVhBQEFAQUBBQELBvTDgYQrSEn7DqaAcIISEkA0dpoSTBpvSd2iH2APXNXkeFfaEZOq0WQ5OHYPDwwXapt8mM3PO5DqaQ8QjJJEopPzcf%2FH23Zr3IYrxT2g%2FS1pNqozQ3oOMsJ8ZVulk5KgjIENAaLBg4K0%2BJ7SfDpK%2BfRo2sgN7LjPStkbBZFSbwapwPbs8A8uOlOC24Gqee0qeeQkClVkOtBHLqKfiVeq9iBPi9ohouU3sB6iW1UUoJaTdIG07BGAqbQjqXaQlePyApEf0H9Hc4lykqLBJ2hIxFSIawqrLKgWZlRSV2bt0lfsyk7eegIYMEM0gJIW1lPb08FYbQgZhyQgR0nmYMnXceDPCuJAUBOQIhSTXQelpw9rtoWMyKZoEcm6vh3O0ZQMZLWnjXbYiNj7ka8Fb6oCDQaQRoi0G7I26EdDVRNXnilGvg6el51cYD7CpGyv1XPwJk0vgsyCV43dFrh%2FTNJUC9UEFtw46QEkO5UxlJbVTkmy2IiY1BZHQUJkyeIKSEZPoYj5BeRskU0mGSlCgtPHLwiPgxj3aEiUmJGJo8FCOoNjpqBAIC%2FYUqMa93NxZSu5Sj%2ByCg9zYJ5o%2B2X0pSEGgLgYCYegy%2BPhen1sbAaun6GqStOpS8nkHA7b2A9gwsSq0KAu6DAD130u5nyIghGDVmpLJQc5%2BhUVrSCxEg87V35z6Ul5VhwrUTEBgU2GO9sNsittgR0rEMmT1KCSkhlBhChp%2BgZFDYExpNYNgPISmkvSGd0TR7G22obxAeTskUkiE8n53rsCNsq5PRsVHCwyhVRoePHAH%2BLTGtfY0h7GteQBXmr60nQslrD4GqfC%2BcXhujqIO2B1BzvuIF9CIAKZcVBBQEOo6At4837r7vro7foJRUEFAQaBcBMjbjJ41r9%2FqVvCAxW1KdcrVREY%2BQXqWbvY067Ahl3kZFGIpmRzNkCOkUaFjyUMHUCRVTowl5uXnIPGd3LEPnMnI7wrzz%2BeBPbkfI%2B%2B0M4XAkDkwUEkI6lulrDKE0JlfjUaOzYvD1eVAkf1fj6HZPn%2Fyj6pE0Mx9p66MAm2IT2D0oX1mqbq8Cyh1SfsiUD9CVnRhKbVcvAnyemBRvgVfvGCs9670IOJhCmbYVn9n2wk9IUkK7t1GGnaAaqckuPdTrkZjU32FHyLBKhQVFdk%2BjQkqY1cqOcMeWneCPiXaEjCk5LHmYYAoHDxus2BH23qklWk5vn4Nm58IrqKmX90Rp%2FpVGICihFgkTi5G1I%2FxKV63U1w0IuD0DSPU3xmtisPCg4KBugEAhqSDg3ghwE4Q7%2Fa5xEy%2Bl1VwsMvYYY%2BjRbbwSRuBSUFTu6e0IiFANNqvDS6a798exWdMcNlXaxJHHV5WcyzgYQmFPaGoOTt8cl9BsQVx8LGLiojFxykRhR1heWo6crGyHlJAMopQoLTy0%2F7D4MY%2B2kwMGJtrVRlNGCMYwMCjAoTYq3acc3ReBhIlFirdP9x0et29ZxNBKGGt0yD%2BqrMfdfrAu0kC3ZwDp6eyJ%2B5%2FEH%2F%2Fxe8y6YdZFuqNcVhC4%2BhBoamzCjq07xcItaXBSlzpIWq%2F9%2B3%2Fw8%2FfFE08%2FjpCwkC7RU25WEOhtCHBDJe10GmqqazFk%2BGD4%2Bvn2ti60SO%2FVgNpmFxUKptAl%2FASZQcEQCjVR5ziElBhSbTQ8Mhyh4SFISR0tGEJuuuZk5Qgbwqz0bOTmnBdxCAkSaZ05lSZ%2Byz%2F%2FSuBGZpISQns8wuGIiol0tE9RG3WvqRUxrALhQ1o8x7pX65TW9BYEYlNLUFdqQFW%2Bd29pstLONhBwewaQKis0bGcgXCUpCPRFBCorq%2FDnX%2F8Fd9xzu8Mm51Jx4OLX2NQEo9EgFnuXSke5T0GgtyLAZ2DV8tVIO5WG5194rlcygHLsJSZLCj9BhpDx%2F9hP8XPxNkpGkRoFLUHqndVGqRXADaKhI4aK%2B01GI3JzcoWnUcm5TFNTS8iA3Jw88PfNqm9Fs4JDgsS9wpYwJRn9B%2FQTkkOHaqu88cr5FUPAJ7QBceNLrlh9SkVXLwKMIjVgRj6OLU%2BAsU539Xb0Ku%2BZ2zOAVzn%2BSvcUBDqEANW7qO6lJAUBBYGuI0DGSPKc2XVq7kVBYgilIzSwM4La1t5GpSD1dmmgRXgXpf2gcC7DoPV0OKPXY8CgAeiflAhuyJKBLMgvbPY2ag8%2FUV1V7QChrLQc2zZtFz9mMvYg7QgZi5ChJ3hu8DCI8gpT6ICtW0%2B0eguSZuVDrVG%2BId0KdB8irvO0Iml6AU6sjlWcwvTSce%2B1DGB9Xb0IhMsPuZT4MfEP8BcqKNJuKKWH%2FFhRrUWeDAYaxycKWygpvyCvAKUlZdKf4sjYScGhwQiPaDF6ramuQV5uPkxG59g53PkMCw8T8aV4M9VlzqWlwyjbLWW%2BWq0SddPAnokfVAb05S6qa4oQ6jmhjuz26vby9hI7rdJHnzRJTx4omET0Bj3CI8IQEBjgoFlSVIKS4pJWUtao6EgEBgc61Hm4KDh7%2BmyrcqTJXV7JnoxxrEpLSlFSXOqogyfaZrszucoVFwuF%2BQViMSYvzB3o%2BH7xjizWTZfmruNID5nEiP1n4nxgOS5I5HOD1%2BL7xcHP389B02g04szJNMff0omvnw9i42MdAZ2bmppEfK3qqhqpiDiy3%2F0SE6DX6x35DNRcXOi8y8rxpv1qZHSkoxz7kZ%2Bbj8ZGZ0N8jkt4ZJiDJscxOyMbjAfWnYn1nDtzDvKdfdbHtvdL7OfA90JzlfOFcTulOSjm6vk8Eexa3nZPTw8hyZTKkSaxqCivlBdrc64WFxWjrKRMOLqQF46MihDPqUST0g2q%2BdEhhjzxuU%2BQjRnLkWZbz31cQhw4vySa5WXlyM8taDWvOF8S%2Bic4quG8yjufh9oa53cO5yjb2ZG5GpcQK95lEtH25qp%2FgB%2BiY6Id7zHOVWLpWrdOpxWYS88o6fK5l9t7Ma%2BtucpxZHy5tuZqRFS447nn85aelo6Ghkap2eJI%2FBL6x8PH10f8zXKkmZN13glLlqMqYkhoiOPZ43v%2BfE5uq3con71BQwY66uEcKiooajWOdJwSGhYKvpulRJs3xs%2FjPX0lEVtpHrPPcm%2BjeqtejIMIQWG2q4wKtVEygM1B6h0MocUivnvxCXHiHTlx8jUCQr7HszOzm2MSZqGosNgBLb%2FBB%2FcdEj9Rt0YDqrIPGzEUw0bancvwu%2B3aRgcB5aTLCMRNKIbBx9xlOgoBBQE5Ar6RDYgcXoGCYy3vV%2Fl15dy9EXB7BpC7h1xUSosmwskFBJm6N155U9gwSBCrNRqMHT8Gd%2F7ge44FBJmQFctWCHUfqRyPEdGReOoXP3UsSpi3ffMObPp2k7wYPDw9MfP6GZh7842OfAbdXfLR5ygvdWYWp103DdfPn%2BNgMvjR%2FPidT0Q5OTPCxcszv35aOOEgUX5s006dxQdvfuCogyc0%2FL9p4U2YPfc6R35mehY%2B%2F3hpq7q5Q%2FuT55909JsSo%2FVr12P%2F7v2Oe3lCm695t8zDuImpjnwa%2BX%2B7%2BltwsSVPd9xzByZNm%2BhgAHn93dffa1UuODQEP%2FvFTxxOehoaGrBz2y6sX7NeTk5g%2FcOHf4Ahw4c4FiMnjp7Al5996bTA40IgeXQyHn7yR477a2tqsfKLlcIhkCMTEAsJYkRPd0xc1G1YtwGH9h8SAZXlZR%2F5ycOCrpRXXVmN1%2F%2F9uvSn40h7lgcev9%2BBJRmTNV%2BvxbFDxxxleMJ%2B%2F%2FT5JwXjIV3Yt2s%2F1ny1RvpTHDnek6dfi9vuus2Rz0X6Zx8tQUFugSOPJ%2BMnjce8W%2Bc5FqycQ9%2Bs%2FhYajVYEbXYqfAl%2FcGMkICgQZFr4vEiJ9Xz6%2FmLBFMjnKjcpfvzsE4IJZFlhA3QyDR%2B%2B9aF0qzhyrt52922YOnOKY2xpR%2FTxu5%2BgqsLZ5iSuXxye%2B%2B2zjnKse9N3m7Fr6y4nmqHhoZh%2F6zyMnTDWkX9gz0Fs%2FGZjq40A1j1t5lQHI9TY2Ij3%2Fvc%2BOG%2FkKSIqAo%2F97FGH7SPn6o4tO7DxG%2Bfnnu%2Bbh378EJIGDXC0k86oFn%2FwmdO8Yr%2BpKvfYU486quG8oorhqWOnHHk84TN68x03i80S%2Fk2c%2BYwyWLfrZtIDj92PMePHOO6nvVpbc3XU2FFYdN%2FdglFlYW74tFW3f6A%2Ffv67552YysMHjmD5kuWOOnhCyQydg9y%2BaKEjn8zsF4u%2FFEytI7N5rt60cL4jjh77w3cTy8vnEAOuP%2FbUYxg8dJC4ne%2BmjHMZeOe195ze3yw3e%2B5szLphpuPZ43ue79CyEufNJL7Hfv%2FS7xxjQ5o7t%2B7EhnUb5U0UbZszfw6mzJgs8tmu40dOiM0xOi8hg9hXk4Phknsb1do1DYiTFH6Cz7xgCOVxCHluMoPxCXnkJhzHZHRqihh7bnBlZ%2BU41EbzzjMeoZ3hJq3TJ06L3xeffSng54YbVUbtdoTDxGYZny0509pXx6mr%2FfaPqkPowBYJbVfpKfcrCMgRiBlTirIMX0UVVA5KLzl3ewaQUpP7H73PscCXcOXO%2FKgxyY6PCvMprYvvH%2B9YPDDPy8tTLLzkDCTzGfyXdhLyRGN2LqjkidIdLhrlibvu%2FFhxF1ueeL%2BcJhfbUjmnBZFWC09PT8etapUaQcGBrermB5DSOnkKCPTHsBFDUNPGwlb%2BsVSpVULSQRUeeaIEjHXJE%2BtIThnRaoefu%2FFsm5TYt7bKUaInl4JRyhAVHdWqP2QmfHydHS6EhAYjOSVZqBpJ9bAfcukf80mTC2huCMgT5wfngpTEvf3jBSPIhYaUmM9FsJQ4HmTMXMeb1%2BXSP%2F7t4WEQDJAkVZZoiH4b7LvnEvaU8LjSJG7RsdHSbeJIaQhVoeSSZV5gv%2FWyRSk9f1J1KjomEqnXpHZ5QcQF75x5swWe3s1SU9bLesiY0zOofK4Sdzm%2B0lxNSU1x6g%2F7T0mLPPn6%2BYkFnevGAiU88sS6KVGQxyfjdc5VuaSaeXwWR6SMAJ3ZyJOoWxaaiF5Oh48a3qoc6XHcpUSmg3127Q8lhb7NEiupbFBIMEaOHukkOWK%2Feb88kYmip0QPD7uEX7rGtnv72CXVUh7fV0zyucq%2FyaTLE9vj2kZep%2BSRfZWSwWAQ70rXuvn%2Bk0v%2FWJ7PvStNzlW%2Bx%2BSJ83zw8MEIc3kX2edqC5a8Z9CwQaKcfA7xuXHCUgXBiPL9TTVMKfF9x%2BdH%2Fpxx7knvUKkcj5I0Ucrj%2B47PmGt%2FvL29Eeri6IjvNT4DZFqCQ4IlEsqxedMRLa988S7gWDq8jVrswenlDKFgBE12BzNSwHp%2BD%2FwC%2FIVzGKqNUoJNjRTGIaRGA49ybYPz2efB37qV34hxoMR22MjhYuxHjBwuwlioNXaGUHrXKgN2cQQY8iFhUjFUsnfjxe9SSigIdBwBjc6GftcW4cw3zt%2FBjlNQSvYUAqpT%2BSdavsA91YqL1CstJuQvfimvrVsvpRzp9AaaHW1jd%2FTnQnWzvkvB%2FUI05fQu1J%2BOlnNtY0dpXo42Xmrd8ja69pPXLiVJ%2FXGlJ%2BW3RVNe9nKXY33uSFPe58608UJlu4Mm65PodhTHC7VRTo%2FnTO3RleptLtZuOV6Xl22P3qWWu1AbL0RT3iaWU1L7CHDMpB9k3kYpfZUYwhbHMrQfdPY6arGY7Ru2Nps4FuTlIzuTUsIsULPFdUNV3hJuYHCDipthDFI%2FeOhgsZHD8btcY7j%2F%2FcU4%2BsXXotqV%2BnjUq5w3iOXt6S3n9PrJuG1KUhDobgROr4lBZV7LZnx31%2Beu9OMttZhgtofSue63zyPWZbPcXdqdeyIfveIN19YLvq28toDtaDne29GyHS3XHTT7at3dgWVHaXYH5h2tuzPlWLYjqb3%2BtJfvSvNylyP93kCzo23syf50Rxu7oz8dbWdHy3VHG0lTSS0IcCzk4yHZEQpbymaGkOdkCIVTGaqOmi1CTZQqznKG0GQyC22dmPhYTJpqj0dIO0KqjVM9mFLC4qIWW2pqERzYc0D82CJKqqkRQukwNUh4pMaAaxtbWt%2F3zrR6K2JGO6tO9z0UlB5fKQRiUktQmUcNF0XcfKUw72o9vYIB7GonlfsVBBQEFAQUBBQEFAQuLwJkuCSVXTKEkoRQcixjsVqE%2BqjEEEp2g64MIZ010fkV7QhTms0wHHaE6VnClpDxCCWVYdJz2BEu%2FlIwflTdp4SQNtwjRycLVeS%2BzBCGDa2A1qPvODq6vDNbodZZBHxCmxAYX4eKbLuzr87er5S%2F8ggoDOCVx1ypUUFAQUBBQEFAQeCqQ8DBcDXbEWpsdqaQtsdt2hHKPI2SqZMziLRZ9fX3w9DhQwROdBZFz7GSt1EeJTtCMp6UHvJHh11M9N4tQk8kDxe267SXlewIrzrgXTqkVtsQOazCJbdn%2Fhwcmgq1SoOTxbu7tQGdqWdQ6Fh46LxxJH8LvHS%2BSAweiWOF2zEqajpOFu2CTq3HyKhpOFa4DTVN3Y%2Bjjz4QyZGTUVSbg%2FSyw044adUGzBl4D04U74a%2FRwiCPMOxKf1zxAUMQmzAIOzIWuFUvif%2FiE4pVRjAnhyATtbdKxhAujZ3DaXAfvIDIYVS4N%2B0Q6AjCVf33lQXoeMHaaeSHwt7cPkWJyESbl5eXk5OFajCUl%2Fv7B1T1K3XgQ4X%2BMG7UN28TkcGUjmWba8%2FbCNpSokfPDq7YHvliR9Ted28Rm%2BHruWYT9sJeb%2F5kXV1tsFyxJE4Se1sr9901ECaUjnWyTayrfLEcuyP3PFEe%2F2m0wy5ExnSdPXeSNqkyXbK%2B0Oarh4UWdZ1HNm%2BtvrNPssdy3AOca4RJ3linWynVDevcQ65lmM%2B2yjvN2m6OkJhOdbNshKWLEcseZQnXifm7P%2FlSKTf1nNC2nSuIbWHf7c3Zt0yV2XPHueANP9d%2B9yludrGfCGufJ7oEEZKHe033zUcW9dnr1NzVfaMsv7OzNW25kt3zFXOZ85%2FaW6w35xDrnOV7ef7Tj5X6QCE7XRNfI%2FJndVw8U%2FcXd%2FfrnUTa2LuWo706VxLGkeWa%2B99x%2FnLd47UH9e2KX9fHgSIrwNjDSAxhBwbiSEUxw54GuU8YPgIqn7SsQy9ijKEkMOO8Fymk3M0hovZsn6r%2BLE3Pj7eGNxsR0jGcDDjEcq%2B4Zenx%2B5BJSSpCjov5%2B9IT7UsJXoGtBpdtzOAHa3HW%2BeH%2BUN%2FhLf3%2FlpAcsPgH2JX9hrE%2BA9EQtBQHM7fhCDPCMwZfC9yKk9fEQZwTOwsTEtciNqmKvx76yPCA680XlqVBuPib0BZfSGi%2FRMREzBQMIB5Vedw8%2FAfI7fqLLIrnD1OS%2Fde6SOlgD6hDagtcXbWd6XbodTXMQRaVjwdK98jpXZu3SXclUvqH2wEY8rR5fS9D93raBNjdH3%2B8efCoNyRCQij8Ztum%2B%2BIw8aFw7v%2Fe69VTDt%2BqB75yY%2BECgnvZ7mc7By88tL%2FOcUyo7dRukqni3ouzJlY95KPlghVFXnd9Lj56z%2F%2FysHg8MP33Zr1Dm9nUlkumqbNmoobbrpeysLRQ8ewevlqJ1sIXpx%2B3VRcP%2F96J%2B%2BMf33hb6isdHa3z3hrjz%2F9mCNGGReWe3fuw7JPlznFR2OMsFvvvBWM6SR5FDxz6gw%2Beudj0P28PMXGx%2BDZ3zzj%2BKhzYUdX3ru2Oe%2FuUZ1n7s1zxRhJ9zM8w5YN21q78L%2FrVuGmXWKuqPrzl9%2B%2B6FQ3xyY6Nkp4hGWsRSaWW%2F3VGkfAYakeetFkSAzGcZMWHwwfsPiDxa28xtKxAMNDSInxC5d98gVOnTgtZYnjwCFJuPn2BYKmdOHT9z8VLuVpzyJP9z38A4cLf443Y6j9568vt4qPxpAldLfPsWcqKy3DZx8uESFB5PTosfaZXz%2Fl5MJffr2z52zPh29%2F3MqtP0ND%2FOkff3TMAS7uGR6BGMsTmcTp100TnhSl%2FKMHj4rwA66xHxkWgs8JmTYp%2FeNP%2F2wVr411P%2Fj4gw5vv1y47962G18uWe40Vzme99y%2FSIR7kebqubPpePe1d1HnEsaEXiGf%2FfXTDoaATMOKL1Zix5adUlPEkd4g594y16F6xkw%2Bo9s2bmtF8%2Bbbb8LM62c65hXn4Et%2F%2BAcqyp13iRn37p4H7hGeJkmvvbrJhPz05z8BnytprhLL99%2F80Imp5DuHC9ZHf%2FqIo%2B2Me%2FfV51%2Fj5HHnjz%2Fn6q3fu8XJOynn6rHDx1thyRASE64dL2hyrjIW6st%2Fe6XVXL1m8gTwHSrF8GQsvQ%2Ff%2FkjEYnU0CIC%2Fvx%2Be%2F91zjlA4pLlzyy4sW%2FyFvBj4bpo0dRJuvmOBI5%2F94PuOMVbliSFr2B%2FJ8ydtzF779%2Bti4S8vR4%2FPP%2FjRvY73N%2BsmlmynFIKA5YnlgtsXCNsz%2BYabnJZy3j0IcI5L85wB6rXQiu8smUCOF%2F%2FxvcMNSB75HhC%2F5qD0fNfa%2FzaJMY3rFw%2FJjpAt5vuHUsDM9ExkpWeL%2BLZST2pr60RYJCk0Ejfg%2BKxIoSdMDQ1Oz5x0X288hg1xjqnaG%2FvQXW2eOfBupJUcQGWD3TlOqE8sgr0iodd6wFvvD526ZRO%2Bu9ogp6uCCqOjZ2Bv9lpMSJiHgSFjcbpkr6NIo6Ue606%2FjwZzLVadfBv3jPmFuGaxWbAlYynmDX0Yr%2B34mXh2HDf14En40ErUblEYwB4cgg5X3SsYQLoQ52KeHwgpqRg6wcWFt96gQ3hkeKudYcYTk0tkSINu47mDLafJfMb9kycuEOjmXb7bzLq5KKc6iZSkul3pccHk%2BOA1F6axOoOSyxMXyAwvIU9c0NB1vFxCxet0ES8xS1J5LnblYQ6Yz7bLJWtsh4%2BvN2LiYmGztdgGcLdeWlxJ9IhDTGxMK%2BmnxHxJ5eh%2BnUHOXftDxpftlyf%2FgADBxLlKA5xcxIsFmka4dKeETZ44ZvxoS4kYtFW3kIC47OySyaKNiHx8iIeri3jOE7q7d5X6st9yLNkGhjNwnRvMlzYFpHbyPpajJESeqKIkl5Swb6zHFR%2BOjet4y%2Bl09pztobt9bqLIk5hnMvtt4sM56Tq2LNdqrjLIeXRkq75zHnCOyJNr6A5eI02GOpASP4revj6t5iqvC3xlJBmmg%2FOf0iN54nyRP3vEms%2Bta3%2FEXJWFxCANBqZuiyZDW8gTxywqJhJ%2B%2Fs7hTfgekr9zLjRXKY2SJ%2FaPgeDlie8c17nKceS7Lb7OOeC8mKsuNO0bTye6AAAgAElEQVRz1fm5J31p80Gqi21pa64SI%2FlcJfPNPrpKACl5l5cjXV9%2F31aY893kGuJDet9JEjypTQzV4DT%2FVfZwINJ16Uiacoki84llW8893znyuSHRUI5XHgExX5o%2FpXw%2Fc6xtOhvknkbJEPIb7MoM0rMoJcech2QOI6LCxft7zLjRoiPcwMzJYtiJbMEUMkaltJFMWiePnRI%2Fxq%2FkK8VXo0aoTguTqRw2D3%2BotM3PZi%2BKo%2BAZYAQlMe6WPLU%2BGBI%2BHh5ab5yvPI3zVWlOTTRoPDEgJAWBnqEwW81CspXrUibcJx5xQUOgVelQVJOJzPITrRifC9VDVctRUdPw3t7fOuomwzc4PFVI0QaGjoZW4%2Fw%2BlgqybqpgUirYaLa%2Fc%2Fl3Uuho6DUeKKzOQEb5cak4EoNHoaaxHMV1OY48niQEDUNdUxVK6nJFfr%2Bg4QjwDMX%2B3PWI9O%2BPcXGznRhAvdqAIeHjsPjQ3zEhYS4O5bXErD1ZuFtIMweGjMaZ0gNO9fTUH8H9a5C1MxwWU8v6uKfaotR7YQR6RRgIMmrcaXddvHOxIu1Is5v8ENTV1bVSCaTqkqtKYHVVtSgnp0kafgF%2BTgt90mRwZXk5LhwETZlaHsvV1taKNsghJ5PIRad8sUFpAH%2FypFKrxa64nHnggpbl%2BPGTJy6W%2BZMvtMrLyoX3NXk50uSOvLSgYh%2FIXLSFJReCchUvMitUw%2BRuuzyRlnzhRpos58q0cIHIvnBRJiX2pYFMt9WZJhkcuYSIH3oGX3ctx7p9fX0dEiqWI03OD3ki1lzAS%2F3mNQYGr6tpPYeohkaGXErEmnPIVeWY5RhTTE6TbstZTj43SIcLXnm%2FSZPSWdf%2BEG%2FiLo0jy3EOuaq0cg4Rc6mc1NZLPbKempqaVnOV84Xxt%2BSJ%2BPInTyzHxTrnoJTam6scV%2FZRPv%2Fbm6tkoiSmqb25yvp8%2FHycFvqUbFdX1bTCl2PFeSDVzfnCud%2BVucq%2ByPtNmpUVlW0%2BJ5c6V4llTZVzjFH2oTvmqiuWHZ6rFot47l3nKucGA6zL5yqfT1eVbpYj4048pcR3DseHbZAn1%2BeE14g537nyRJqUJMs3aohlbbWzejyx5LuJc1OaG3I6yrn7IMD3gPR%2BpZSQwenJ7PGcDBzPOV%2FMFrN4b7oyiFZet1odNIxNTTifnWuXEIqYhDmtNuaceq%2FRAXofqPS%2BUBl8AJ1ny5xxU6YwNrUE0aPKnbrRk3%2FcNep5UMpm0HmiqqEEZPRCfKKxIe1TbM38UjQtwrcffpD6WzSZ6lFcex6BnuEI843FlvRl2HjuM1FmQtyNmD3oB4J5tFhNSAgajoyy4%2Fjk4J8FE9iReib3uxXj4ubgX1secTCOtAG0Wi2gRM2g9USdsQpk9h6d9A%2B8tfuXIBNKZu7ulOex9%2Fw6fHPmA9Ee2gveNOxhlNUVoNZYKWzyyAB%2BdvglWKxmsD1k7F7f9YwDfl9DIJ6a%2BgaWHPo7TpfsE%2Fm3Jf8UEb4J%2BO%2BOn2J09EwsGP4oXt72OMrr7aEEWEir1sNsNTqODoIAvjfqWWjVOnxy8C%2Fy7B49P7shEmUZLeuqHm3MFa5cCQNxGQEvKizC10tXCLWrxKT%2BF6QsLfguWKj5onzRf6HypElJzcUSy8kZowuV5%2BJDzui1V5ZMhJyRaK8c8ykJu1jiYoeLHjmz1d49XER1lCaZcDkj3h7Njvabi0dXRqQtmixH5tFVetlWWUoGXKUDbZUj49rRudGRPrMO0uxIf1iODEt3JjJL69duEHNg%2FMRxF52HHR2znpyrZBo7gi%2FnS3fM1Y48J52ZqwLLsJaNk%2FbmQ4%2FOVU3H52pn3jn6oLZ3310x6Oi7VmAZenEsXekrf7sHAvxmOZh0NaC2qYUWCJlCvU1vVx%2B12RyhJ7ghQ0kgJYN2T6MtjmUsZjN0Wq2wI0wcmMjgluL%2BvPP5wtTj6PbdyCsqgalF0QiwmICGCtj4IyQqjZ0hNHhDZfAF9Nzckkk63IApDIp3Nttwh5EM9o7ARwf%2BhHOldgcnt498ChP73eRgAK8f9AOU1xfgnT2%2Fdti%2F3Tz8MUyIn%2BdgAGck3Y0NZz9xOD0hU3bXqGcEs1ZYmyW6ebF6EkNGIrvitIP54031ppbNNpOxteS0f9AI3J3yHHZmr8CGs4vt9XhF4KZhj2B75nJH%2B0K9Y%2FDQ%2BBcxKWEBtmZ8gUN5G3HX6OcR5h3nkAKOiJyMRlMtzpYeFHQoDR0aNh4bztnpnijciRuH3I%2BxsbPx7ZmPRBn%2BR%2BZPfnRcAJBdfgIzk%2B4WjnasNufNM3m5K3kelFDTZxnAK4lzV%2Btq0afrKqVuur%2BkqFTYovGFfTEGsJuaoJBVEOhRBCiBfuvVt5E6YSymzJzSsiC6hFZxUbTxm43Cu17yqBEXZQAvoQrlFgUBt0aATMK3q78DbSivv2kOwiPC3bq9SuNaEJCYQekoqQZzTCkhJ5fG0BNScHo7Q2gSUkJuflFCKNkRkiFk%2BImExHjE9YtDcH090jdtR73NhkPwhcnSBBV%2FVpmDMy6wm6pg4080SwXovAQzKCSEBh%2Bo1M3Lqh5gBnVeZngGOpsatKDXc2eF1VkO5o%2BtOFtyCMMjJoLqjUZrE748%2FqqdIW82TdGotcL5ikHrAZ5Toma0NGB45CTkV2cINUx6y%2FzThnucOnWxesJ945DTCYcpVM%2BcmngbduesdTB%2FrHBYxCRhRrMlY5mjfqp0nijaJbx5kgFMKz2IOmM1kqOnYH3ax6Ic1U%2BP5m8T0kZmjIiaLLQlmMfUZGnAyaLdoEObDWc%2FAyWdF0sldfnCfjHAM8RJanix%2B7rzekBsPVRqOnqS2Wp0Z4UK7UtCwO0ZQL6kqQ7lqu5zSb1VblIQ6IUIUH31uzXfCeng5BmTu8QAcuectpVcLHFxpCQFgb6IwMljJ3H2zFlcO22SwgBeBROAEnYpMR4h321CdVRiCJsD1FNlVK4mSgZQClDvodNBo1bBx6YCtD6wqpq1MawWqCyNUJkbobI0ABajLNS1DTDVwcafJHjTegAGX6ioOsrjFbQj9I9ytgeWMOnpI9Uq5clstUvaGB6Cqd5YgzExM0Q4BjpkCfSKkDE%2Fdibiq%2BP%2FBaWCP0z9HYzmRmSUHcOB3PVIk9m%2BXageFdSgfWCDSRooeYvaPp818G40mRsR4hXpVCDEO0p4Nv359Ped8jVqHaw2u2o6pXFH87diZORkbEj7REgqyYB%2BefQVxz1jomfCbDFhwbAW517%2BniEiNMWw8GtwtGCro2x7J5QoMnnr%2FFGOFrXR9spfiXyN3grPwCbUl7U4f7sS9Sp1dA4Bt2cAO9cdpbSCwNWHAH0fNTUalU2Qq29olR71EAJkAoxNJmUTpIfw7%2B5qXRlCMoNiw8uFIWSeYApNZvjQNEOjhYWOaLQ6kGEAJVIqNWxqLWy6ZntVGxlCo50hNDcCZA6b5YGiX8wzN8JWV2LPpVMRqoo2M4UOO8JukBD6RTo7TutunDtKn95dL5S%2BN%2FIpxAcOFTZ2h%2FM2o7A2E%2F2DkzF%2FaIuHbqqP0nYvLmAIBoSMwpCwcVg05hf4%2FPC%2FcKLI7tn5QvXYYBWSREoUO5pop8jYfHeP%2FjlGRFwrYgXyXjJ3NU3l%2BPTgXy9I6mDuRlyTMA9xgUMwOGwsKKGU1FVp9xjp1w%2FHCnagsrHEQaeo7rxgAFPj5nSIAWSIDSaTxb0kv77hDQoD6BhV9zzp%2BJPgnu1XWqUgoCCgIKAgoCCgIKAg0C4CVBmV1EVpR8hEplAKP0G1UW9PT3hotcI%2BTKPVg5JEMg1kArkJJ5x4kSHk%2FZT0aBkCihdsUFGiZW5ySAlVMi%2FblBiiwdhiR6jWADpKB%2B0SQugZV7dZgtlFptAryNkhWruAuNGFAI9QDAwbg9Wn3sbenHWOlo2Ps3tCJiPO8Awzk%2B7C7qzVyKo4IX50DvPUlNeRGJLsYAAdN7dzQmctPvqAdq62zqZTFzqBOV64E3OHPoDM8uPC4UthdbZQ06SKZ1VjqePGCXFzhWSQaqpM9ACaX52OoeETQA%2Bje7LXOsoy9AMlmV8ffw2mZomodNFkbsSMpDuF1LCoNlvKbvPopbM7W6kxOociarPwFcz0CmptT3kFq1eq6gACLXoTHSisFFEQUBBQEFAQUBBQEFAQ6K0IkBnkj1JCOlKiAzc6PdPzqFFBr1YJCaBaqwMZQbXWII4anQFq8dNDRQmhVguVWiN%2B0HrBZgiA1TscFt94mH1iYPEMhVXnI6SHTlhZm%2B0Iq%2FNgLTkNa94hWIpPwVKZC1t9BWx0PCM4zgtLzZxoij9s8Ay8uM1Y6%2Ft6NodOWGjjFxswSNj7qVVqJEdOQWrsbNEwnVqHBlMNkkJScP2Q%2B%2BBnCAbLDAgeBS%2B9PxgQvaOJQdPpcbOzac2pd%2BgByCGRPJK%2FRdj30ZlNsHe0cMCSHDkZswfdC4YwkqeDeZuQEjUd%2Fh6hOFZgt%2FWjqmhy1GScKt7TivnjvYfzN4sNitTYOXJSbZ5H%2BfdHRX2R8F7aZoEeylQYwB4CvhPVur0EcNDQQfhs1aciJlcn%2BtVnitpMjTh44DhMLq7TJQB0ej0GDBkKf9%2BuecJrqK7C8WNnoPbwxMiU4dC6xHaT6mvraDE2Iis9B6VlzZ7UmgvpDAZExsYhIowxxpxfmm3R6at53BRmnEl53MlLxYIeGZ974TkRDJvhSZTkjIDNakFOZhaKi8udgofLS8UkDUJMeMd3keX3Os5tNuRlZqGwqBShsXGIjgwVY%2BK4fsETG6orK3Dm%2BFnIfb4xwLlfYAhiYiPh7a3YXlwIQkqDxDMlsx27UHnl2tWNgGAIVWrBGEoMoiSVUwk%2BTApH0XyUwlMI6aBkb0jpoBAVAmoNbBoDbPrm%2BKBWc7MdIR3LtGFHaKwDjHWwSuZpWk%2BAEkIpBIVO5h23HSmhzsMCja732XUbLY1YceINzB3yAH410%2B4sJa%2FqLD4%2F%2FE%2FhRTMmIAlnSw9h8aGXcOuIH%2BPpaW%2BIyUjbud05q3Awd0OHJ%2BeZ4v0idAMZsI44WJEI07Zw7en3RP1k9I4WbMOH%2B%2F%2BIW4Y%2Fjievfbm5PUbszF6J7ZlfSbeJ47H87bhh0A9xtuQg6kzVIm9waCo8dT44kt%2B2jR%2BlihllR5EcNQXfpn0IYtReSggcijMl7hEDUN5GD9%2Fetxkhb39fOO8VcQCpqsGXspJaI2CpzcfUa25HZWWLK2N5qYCQEPx78WdIHRwmz%2B70%2BfnDu7BwwaPwTRyI5es%2Bg6%2B%2B48Lj2tJ8%2FOPXf8NXqzfBOXIX4OUfiId%2B8yvcd9vMVoHJO93Iq%2FQG2qhUlFWI%2BHPyuGlXaXd7tFs2cwP%2B8fsXsXTJatQ3tP0Be%2Frl13HfrZO61k6bBe%2F88S9479NVuOPpZ%2FDgPfPh5dlBps1mwaHtW%2FDju3%2BKSpdWaHV6TJy3AD996gEkJUS57EW7FO6jf%2FJ7wriEfK58fHycYnv2UUiUbgPY%2F%2F5iHP3ia4HFSn086lUu%2B%2BNk7qREBpDnzQyfUCeVzqlEShVQa%2FNRqI2yKO9opuGwI2wQaqOgt1HpmlSH%2FCjsCJudyugZj1AWw7J5beQV2ITkhfZwCPJbe8s5mTLGzWs01V1QmkUVTg%2BdN6oaStuUnl2ovwz6%2FtTU10GJ3rHCHRcq2uFrjO2n13qisqGkTabSoPHCc9PfxtIj%2F3EK8N7hCi5QMMAzDD%2BZ%2FCpe2%2FGUI7D8BYpf8Ut7302C1dLxteIVb2A3VKjEAbzMoCrMX%2FuA0rD8x8%2F%2BGE1NRsBmwpt%2FfhkVVuC2Hz6MAXG%2BMHh6ITaieReymYz9Q4R2meq2rvuFx%2BC%2BJx%2BCITBUqMnIW9RWefl1su7ig6jR44aFN2P4kP7QqCw4sXs71n23B2%2B9%2BB%2FMmX4NYsN8lQWrHLjmc0orQsJC2riiZF12BNQ6TL%2F%2BekT3HyS8BX73%2BZc4ciYT42bMw8TxA6HVqjF2lHM80ovNf7ZRlKHqmaPBaoycPBk%2FCAjFiNFDodPaDfkdZXniVN5xozghPZvFgrghw3D9LfMQ4q1FWX4ONnyzCZu%2F%2BAITrhmLmMhweBnsXvac7%2B7bf%2FF70tEYnn0bKaX3TgjIN6H5bJKhE3lqOEkJhXTQCuFDhhLCTtkR0tuoXUrY2o6wHLaGcjub2IYdodbQ9oaVUx%2Fc%2BA9K5Mrq8i%2FaQtrx8XcpibZ2OzK%2FxtjYOZeNAaxpqgD4c0latQEalRrTBtwuPI%2FKvZW6FL3kPxkv8EzxPrdk%2FtgpjZYxOi%2B5e8qN3YyAyxZXN9d2ieS52FGYwLbBU%2Bt88b1777RftNbg87%2F9F5VmC66%2FayEmDm2Jb9VYV4t927di9dffIr%2BoEqHRsbjx5vmYOCkFHhoL1n61BodOZCF5cAIO796P9JwCxA0djQcfW4TYiECYjQ0oLiyGoYnG8DZhB19yPh0fv%2F0xDp3IhM7gidHXTMRtd8xDZHjbQem1egMmTp2KG66fCINWjfLrxuPYgQeQ11CHhiblLdH2CF%2F%2B3I4wLJe%2F1t5BkTG8xk6aKH7cUMnduwcn0rIwZuY03HPnTOh1EkNlw%2Flzp7HkgyU4fioLKrUOKZMm4Y5FtyIi2AfnszKxfPGX8PANgpdOg13bd0Ll4Y8bFt6CqVPHwsdDi7qaSpQUlaCmuh5cJjbWVmL5hx%2Fh200HYDIDkf0H4J4f3oWRIxLbBS86Pg43f%2B92xIZ4wEo39cZG5GYtQ12DEWYL1cGk9rZLQrmgIKAgcCkIODGEJNDMFPLMxudOkhJKKqJ29VGxGSpUR5vVRZslh1B7wabxhM1gdywDq8keh9DcYFcftcr0ZyQ7QikeoUqFugYvIW2hPxllvdT%2BgO7KWS1UKxlInrEEuysNCh2DO0Y9JTb%2Flh75t%2FAcejnrouQxJWoa3tz988tJ9rLSUmmtQJPyDbqsoF5GYm7PABYWFGH5Z8tx3Y2zMGDQgMvY9b5DqrG%2BBuuWfIw%2F%2Fv512HSe8Pf3wenjJ7Bz80784PFHsOiuWTh84ACWfr4Oy6xAeHQEmmqqsH%2Fvfhw5chZvvf9nGMtLsfKz5fBJHIjHnnkEtefT8eD3foSMvApExsRAbavHoT0HcOZUBn73158j2K%2B1OhttAbd8sw6F6aegUllx8sBu5JbVYuTMBYgJ9ZJJR%2FrO2HS0p1RX40dd7t68o%2FfKyxmNRqxfux4GgwHXTL5GCQQvB6cT55nH9uHBux5DYZURIaHhUNkasW%2FPPuzYvAsvvvIX1JYW45uVq5CTX4mAgEB4eepRUVaGvXuP4vk%2F%2FhJzb5yEcwePYNXSlfCJH4RxKf3x%2ByeexLdbjyEgOAzhIZ745vMD2PLtRrzzxWcYMbBtFe7cjHR8%2Fu778PPSoKwwD9s2bYdXzBAMGRgPbw%2B3f713AvHLW1SKgclnSlksX15s%2BzQ1iSkUai9kCckNauxHh9qoM0NINVJKCckYqhxqo7bO2REyzIXFSp4Raq0artqrfXpMXDpPhzNLDv8dPoa2N6pdil%2Fyn%2Bmlh7Hk0D9QVl%2BAi3nyvJRKPLReoh9yL6SXQke5p%2B8i4PYrhKL8Qrzxypvon9RfYQAvaZ7aUF5ciA%2Fe%2FBReoVF46NnncOuNqdi08mu88vf%2FYdOGLRiVkiQo28xmzLhjEX721APQ1Rbix%2Fc%2FjZMHNmP3sWyM8mmpnBLAjV99gYy8cqTMuAGvvvpbVBfl4LWXXoFfdDAqq%2BvaYQCbsGHlKmwSwV%2Ft9hFmgwGDhycJqWJLDcqZHIHqqmq89u%2FXkXpNKmbMnt6lBavJaMKar9bCL8APySnJCgMoB7qD5zarCW%2F941UUVDZh6q0%2FwF%2F%2F%2FAQaKwvwx6efx%2B5jJ7Fk2TrMvba%2FUNUKj0%2FEI8%2F8BDdMHYHPXnsL77z7OXbu3I%2FU1KFOtZ3etRnb96XBKyIBn379PqJDvPHa717AyfwGFJeWAO0wgDnn0vHh62%2BCPpQo2bWobBg%2BaSR8%2FPjA0t6oRenUqcI%2B%2FAeZv7Ur1qEwvwBzb5mHiMgWTYk%2BDIvS9cuNgMQMSnQdaqMSQ8gLdqmgnQm0OewG21QbpWhPo4dVcvQi7AibQ0%2BYG6H1McBsNEKnZngLhi9Unn0JetdjWX0h%2BOvO1Gipx8ni3d1WRUldXrfRVgj3DQTcngHsG8PQfb1k7KK68hJkFdUhcXgSZl43AT6%2BXhgxajhGjEjEoXMlKCksazY%2F12Fs6iiEBPnDMzIQo5PjcTYnHznZZRg5TDZVbMDZzBxoNFqMSR0Hfx8v%2BHkPwh9ffQUqutbWtG30q%2FHwxr1PPoZJ1yRDYzMj4%2BRx%2FO%2FVd%2FHJv%2F6O6KhY3HP7ZMUbaBtTob6%2BAetWfAN%2Ff39Mv25alxjANsgrWZ1EwNpUj1PpOVCrdFh4103w9%2FWAtyESC26ahc173kLmyUyYJtFOUIXo6CgMHZoEb%2F8gDB05GNHRwSgpqUZ9vXOMpIzs88LraHLyWESH%2Bgv39I%2F%2B7k8iPtiFvL8OG5uKHz7%2BI0QG6lBZUowVS7%2FC5s0b8d6bIQh5%2FkEkxLYtOexkl6%2B64ieOnsCZk2mYMmOKwgBedaPrxh2SM4WSlLA5T9gRknlrdhYjjsKe0L5Zao9H2Kw2apXHI%2FQWzJ4mwARYSxx%2BZtwYBaVpfQQBm1XZhHDnoZat6t25mUrbuoKAWqeBVquCxWxFfUMjLBYDmhoaYWxohMagg1bfMg0a6puE8wuLWoVGo32RqjG0XJfaodPpBdNYU1MtvOk1NdTjzKnT8PAJQUK%2FaHh6yNxWN9%2Bk0WoR1z8Bw5KHCRvAYaOG4fTerVi29gBOHT0H28JrFYmFBLBydF8E1Gromp%2BZ2tp6WKxWmE1m1FTXig0QnacH%2FT%2BIZDJb0dhosj8jJvuzpdGpW%2B3O6%2FT2MC21tTUwms3wUKuQdeY4SuqAQQMTERTo7MhJAscvwB9DkociNsjT7myioQKZZ9JwPiMHdTX1UjHlqCCgIOCOCFyIIWR721UbpdUwJX1WhzMamgiqtCrhfEYR%2FLvjYPe9NlnN0pew7%2FW9N%2FS49cq%2BN7RaaWOHEaBEzi84EqMHReJIVhY%2BeXcpbr5xPLas3YBDJ7IxcupsxMdH4pCgaMKar9cgMSEC2rrz2H0oAyq9P0YOioLKUuCokzYzY1NGYPHSrdj2zTrsuDYZppJs%2FPMP%2F4A%2BIhHP%2FOm3uHZMa3tNi8WEE0ePwktlhMpmRl52BtbvToNNpUV0%2FyhFW82BsHLizgho9F6YPG4YzqRvxnuvvono4CdgrMjH%2B5%2BuQUCwP8ZNTIZGbHzakJ52Gt%2Bu%2FhaahlHYunkX8opqMHZuDAJ8vZ26OGLoIPj5euHUvh1Y%2B90uJCeG4u%2FP%2Fhq7ThXgvp%2B%2FgJ89cpNTeemPspJi7Nq8Ded8daipqsR3q9Yjp6ASKUPC4eHV2g5Xuk85KggoCLghAnKGkM27oNqoFTZ1c1gJAFaTGlqdSmwuKXatzmMb5BWO2IDBKKk9j%2FzqDKeLXjpfDAkfjwO5653yO%2FJHhG8%2F0AaPgeqV5IyAxaiGxaRIAJ1Rca%2B%2F3J4B1Ol1CIsIhYdH1wKZuxfs3dcaH38%2FBFis0DrUMFUIDA7DfY8%2FhL%2F%2F9Q18t%2BQjrFvyEf2VIWHoCCy49XoM6BfR3CAtSrPO4A%2FP%2FgoN9XVQa%2FW48Y47kTwwCtXppaC0wcfXByqNCuPn3IQ5Gw9gx%2B6jeO6hx6FVqeAZGIRZs2di9LB%2Bzh1Uq%2BHh5QVvgxZrPl2MNZ%2FaP2waqotqDUidNhG3zZ%2FUZQcnzpUqf7WFABcG%2FhxHP1%2BoNYp3rrYwkud5eHsLvDwMupZNdZUGi554AqfSinH07DE8fu%2FDUFst8PDxxcy5N%2BCmGyfj%2FBl6l1PDXN%2BA75Yuw%2BrFnwgpYL%2FhqZg%2BfQJCghiixRO%2B%2Fn7wMBgQM3wcFt0xF0uWfYO%2FPvtzGLRamKHC8HHjcdfCWfImiXOtVgffAH8UZGbgld%2F%2FSeRJ6tfRAwbitoVzRHD5VjcqGQoCCgK9CwE5U%2BikNtoSfoIdMps1oDGw2r771Lv62I2tjfYbgHvH%2FganivfguqRF2JL5JfblrHPUOLX%2FQmjUnV8KDwkbjztTnsXSI%2F%2FC8cKdDnrKiR2BpjpiqjCA7jwfOj%2Frr3Bv4vvF46VX%2FwYelXQRBFQGLPrZo6i12pAgi%2F2nNXggddYN%2BGfiIOzdfQhlZVUICA%2FHmAmpSEyIhspS20zYgHsf%2FhH8fDSoqKhEVL%2BBmDpjPLy9DFBFxOKRpx%2BDPiAUBo0KusAQvPDPF7Fzw2akZeVDb%2FBE0rDhSB2fDE8PZ8ZC7%2BWHGQvmIiF5VLOtIVVVNPD29kFIeBiGJw%2BDr4%2Bn8qpoZ3i1Gg1i4mMQEOjfTomOZxs8DLj%2F0ftAuzI%2F%2F7bVCjtO7WovqcGUBfMQnTIGySlJ0MgWVkExSXjp3VewY8tuZGXlwabWISk5GROvSYGnTo3zzdAMGZmCW2%2B%2FCbWVBVDpfZA6cRwGDIiFRq3CmOnT4RndDwPHJMPg4Yn7n30ao6%2BZgP2HTsGiUiE0Mg7TZ09GcKCXM9AqFSIT%2BuMhxv%2BUrqgAg6cHAgKD0H9gEqKjw2UhK6RCylFCICg4SNj%2B6Q2tVdWlMspRQcAtEXBlCKUvpw0w1hngGWB0y2b3VKOuSZiPw%2FlbsPb0uxgcmooFIx5zMIB%2BhmCMip6GV3f8tFPNYwiGBcMf6dQ9fa1wQ7nybnX3MXd7BtDbxxujxoxydxzdo30qPeZ%2F%2F3tttkWj0yNh4GDxcy3QEqjTBr%2FQcMyfPwUeemcmzjs0Arf%2F8C6nWz39%2FDHzlgWY6ZTb%2Bg%2BdhxfGT5uC8dNaX1NyLo5AYFAg%2Fv7q34T0tathIBhUPnFg%2B3HlLt6aPlRCpcbY6VMxtp0u%2BwSEYs6C%2Ba2v0gVfc9IZPDA8dSwG9g%2BRshzHIeNSwV9L0mD0tGni15LX1pkaoVExuO0%2B5%2BexrZJKXmsEKAW%2FfdFCYbdJabiSFASuFgTqy%2FUKA%2BgymIFeoThfeVrkMiQDVT4NGi80WeoxLXEhDuZthAjm7tDhmgEAACAASURBVHJfe39Se%2BqWET9GZvlJDA0f316xPp9fV66YILj7JFAsNN19hK5A%2B1SghCkOo8aOQHCwP80OlORGCGi0GkRGR8LXT5HYudGwXKApKnj7%2BGJo8jAkDUyAhxKP7wJYXflLkhp0cGgwtDq33wO98gApNfZaBOpKPHtt27ur4bWNVfDW2zd6vA3%2BMFuMMFoaEOgZjmERE7E9Y3mnqh4fdyOCPMOx9tS7nbqvrxWuL1EYQHcfc7f%2F%2BjFwdXlpOQICA%2BDhqUyo7phQKq0n7rj3Hsy%2F43siLpxeq%2BwLdAfO7kCTMdCqKquEvSXtOSkRVNJlRkClQsKAQXjhpT%2BLYM5eXi4qnJe5OoWcgoCCgIIAEajM80YcShQwZAgcytuI%2BcMfEc5aUqJnYH%2FueuFBdcaAO7D3%2FDrUmaplpS98GuYdh1lJd%2BHDA3%2BE0dxw4cJ9%2BCojmdQqDKDbzwC3X%2BkXFRTjrf%2B%2BjfSz6W4PZq9toEoFDy9vBAYFwGDQK3Hm3GwgGWIgMz0T5WXlXW6ZyWTCN6u%2BxaZvN6O%2BTgkT0GVA2yGg0eng6%2B8PX8Fku%2F1rtp1eXJ3ZjK9WWlyKvPN5aGpyWFFenZ1VetWnEKgv08PUqLxv5IN%2BumQfVhx7DZG%2B%2FXEkfwvWnX4fod4xSAodjR2ZK6BRaZAUkoKBIWMu6AxGo9Zh4cifYHfOWuRUnpFXoZy7IFBb5AGzUdlcdoHF7f50%2BzdFeWkZvvj0S%2BTm5LkdeEqDFASuBAK1tbV4%2B9V3sGfH3uYgwZdeK5nJ7Zu2Y%2B%2BuvWhsaLx0QsqdCgK9FAEygFs2bsWXS5ajrKSsl%2FZCabaCQFsIqFB13jnETFul%2BlremdIDWHXqTew7%2F42Ilzoj6S7szFqFRnMdFo3%2BBaYPuBMT%2B92EB8b9WTCEbeFDD6J8d2w691lbl5U8GQIV2Yq5igwOtz11ewbQbZFTGqYgcIUQaGxswo4tO5GVntVlBvAKNVmpRkHArRFIT0vH4f1HUFdb59btVBqnINBZBErP%2BXX2lj5VnpLA%2BMAh2J29GrH%2BAxEXOATv7f0tPtj3O3jr%2FTA4rLVjF63agGsS5sFT74MHJ%2FwFD1%2FzN9w37g8Ct1lJi3DP6F%2F1KQwv1tmyDJ%2BLFVGuuwECbm8D6AYYKU1QEFAQUBBQEFAQUBBQEHB7BKryvGGs10DvZXH7tvZEA2cm3Y1tGcthtDQi0CsC1Y0VMFntquD0EhrsJcVFbmmdzWbG5nOft2QA0Gj0iPBLQEFNJnIq7F5GnQr00T9qCj3QVKuEgOgNw68wgL1hlJQ2KggoCCgIKAgoCCgIKAhcBAGbTYWyc36ITK64SMm%2BdzkuYDAi%2FOLw2eG%2Fi87XGavgqfMCQzvYYIO3zq9NpzAWmwWb0p0ZQA%2BNFyb3uxknCncqgeBlU6noZKDsL%2BXUnRFwewbQP9Afs%2BdeJ4L2ujOQStsUBHoDAgwpkZI6CvRMyaDwSlIQUBBQEFAQuLoQKDwRgPDhFVArRj5OA0vp35aML2FulvhlVZyEydKE2YO%2Bj3pjDfw9g3GyaI%2FTPcofHUeADojKMhX7v44j1rMl3Z4BjIiKwKM%2FewShYaE9i5RSu4JADyHg7e2FW%2B%2B6BSNSRnTZQ6ter8fcW%2BZBo1bD21txFtBDQ6pU24MIMA7gmPFjEBsfK8IL9WBTlKoVBLoFAargUQoYOrDjIQ66pSFuRDTAIxTVjaU4mLve0SqL1YS39%2F4Gk%2BLnw88QhLd2%2FxINphrH9QudGK2NeG%2FvCyipPX%2BhYn3qWuGxINisSiDp3jLobs8Aenh4oF9iv96Cp9JOBYHLjoCXtxcW%2FfBueHp5dpkBVKvVijT9so%2BQQrA3IUAGcPzEcbBYLPDxUZwV9KaxU9racQQKjgYhJKkaKmU9LkCrbCzBF8deaQUgmcK1Z95rlX%2BxDKvNiqyKExcr1meumxvVKDyuqH%2F2pgF3ewawN4GptFVBoDsQYLD24NDg7iCt0FQQ6JMI%2BPgqjF%2BfHPg%2B1On6CgNK0vwQNkiRAvahYe%2BxruYeCoHFrOgc99gAXELFbs8ANtQ3ICsjC1ExUfAP8L%2BELnbtFqvVAmOTCVYrABWgVgG0o9JqtZcsjWEsGbEtZ7M1ByJWw%2BChJ3mReJ3nDNptsdqg0%2Bmg0VyuB8sGi9mCpiYjNDot9DrdJfeDjbWYzTA2mWFrbrtaA%2Bi0Oqg16k7TlXBh341NjVCpddDpGEzUBkLGIzHRqLViDJqr7PLBZrOiqcEIg6fHVb9bSqlHfm6BmE9h4WHQ6nruFcDxbqxvcswd7lRrdBroLuXZstGE3%2F5YNTU2QqPVQ6vVgBNHmpsWswlWmwp6va7Lc0bMRqsVDQ2NoFSV9pSULF1qspiMMJqszfPcKmhqtTqBx6VQlT9L7LfJaIFWr7NjwieJ7xiVCpz7jfVGqHUaGC4TLnIMTMYmGE0WeHh6QsOXp5IUBBQErhgC5%2FeHIrhfLTR6LmCUpCDQPQg01WhRfCqge4grVLsNgZ5b%2FXWwS9lZOfjVU7%2FB0796CpOmTuzgXZenGBdHpXk5ePFXLyK%2F3AiVygadVoXAsDBMmjEDc26YhgA%2Fj45XZrOhNC8bq1eux8333Q9NUyVeev4FNHkl4Pcv%2FRTVhXk4fvw0YgcNRUKYN5Yv%2FhK7Dxdg0QN3YEzKwI7X005J9qcgOx3LPlqCvQdOwz80GvNuXYBp08fB06PzU8FqMePYnm146a8fQmfwFAbner0KIZGRmHH9HEyZMgY6XccYV2N9Fb5asgrTb7sdwT4aLP7Pi9ANnoPbrx%2BNgzu3Qx%2BWiNggHdZ88QWiR83CzGuHtdPLzmVbTCYc2L4JSz%2Fbjd%2F%2F9zfw0rrfIrWxsRGH9h0SmyBxCXFdYjSMTUZ88OYHoATk3oe%2Bj6DgoM4BdhlLG2sK8aPv%2FwI2tYeYJ9w88PHzRsr48bj5jnkI8OnYs2WzmrFl1SoEDx2PYf3D8Oqvn8Xgm57ADRP7Y9OqlYgcORkDInywbeUynKjwxRMP34KOzcr2O9tYXY73%2F%2B9NHDyVBZ1Gh9GTZ2HRvfPhob80yltWLMOHn2xCQ5MJarUJWr0BIaEhmHHz7Zh7fWqn2ltfXYmt6zcjbvhIDEyMx9Ft6%2FHG%2F77Cjfc%2BiLmzU5B95gR2HjiDu%2B5ZiKbSbPzk8T8hcexUPPf8vdBcxulvbqzHy7%2F%2FEw5n1uLF%2F3sRsaHuYXNK5pdxABkDcMCgAfD2cY92tT%2FblCsKApeGgKlei7zDQYgbV3ppBJS7FAQ6gEDm9nBYLZfx49GBOpUiXUfg0lYrXa%2B3wxSaGhqRcTYDtTW1Hb7nchY0Ntbj1PHjKCwsQEJSAkJD%2FZBx%2FDA%2BeudTbN9xCNK%2BGhcVViEmbLt2XrNazfi%2FP%2F8NH36wFA1mG9QqDcJjIxAZGYja6iqsWboUH7y%2FFEVlVSA35R8UiMjoEHh6tEgsLlbPha7XVlVgw4qVWLV2B7SeXijNPYdPP1qGYycyHFKStlvfdi7rqq2pRHFlHe7%2B0T14%2BMkf4s7v3wJffRO%2B%2Fnw5Tp3Nb77RBpvVKn6ulEiDv%2FKibLz1zueobTALKVzKpBkYPjAGDbVVWPLJUmTllcLbxw%2Bjxl2DfrEhDjLi%2FnZwJ8N7oTFpqK7Eqo8%2FxB9%2B80%2BcPJUBiyQqclB3j5Oaqhr8%2B8X%2FYMuGrV0OBE88CvMLUVxULCTBPdlDm7kJp06dxMyFC%2FHwk%2FfhgUfvwbgxg7Bp1Sqs%2B2afY062N3coLhPPlbEWH7z3KXLyy0HZ%2BaQ58zAgNhiWpmq8%2FcbHyCuuhkarQ%2F9hozB%2BzGAnSTvv5xxyTcyztpFvL2fDuk8%2BwuYD6bjv8Ydx%2B8LZ2PTVEqzfdtSVTIf%2FLi8qxLEjBwGDTjAl4cGe2LFxE17%2Bw4tIO1%2FloCPadYE28%2FqWtWvx9n%2FfxrmsfJitNnj5%2BiCmfzR8fHSwGSvw62d%2Bh1VrNov5rtZqENsvBqGhzp7b7PW0xkXqv8D9As9dfuY5%2FON3f8LSZd%2Fg%2BNEzaDJJb0pHV3rshH37bu16fPzuJ%2BI56LGGKBUrCFwBBGgLWFemeHy%2BAlD3ySoY9L0yV1Gp742D33mxT2%2FsZRfbrNKoEZvYH4899xPoTTVYufgzvP%2FuOuTn5KO2ohzb132L9et3oKKmHpHxCbjtnu8heVgidq1Zjm170xAW4o1du44jMjYaO3ceQmllE%2F79wt%2Fw4JMPoKG%2BHg31Vcg%2BfRxfr9iAvMJqrFyyCr6L5oLqU3W19TCbLTA31WLrd5vw7dotKCqpQNzAobjz3tsxMDEGp%2FZsxrKvt2LE6NHY9d23KKs2YsyUa3H%2FjxbBS08VSnuqKq%2FAgV37ERwVi0ef%2BQmObVqHT5ZuQnp6JkaPGgDtJaqZevr7IGVcCoJ99LBaTdCjCZ9%2FuhqFBQUI9zbiu9XfYPfeYzCageGpqVh45wJYy7OxeuMBFGWeRXGFEQZbIwpyc%2FGfP%2F8LTz73ODJPnoQ12gPZe49g%2F%2B5jqLQtg6bxRqDqPELVAYgIMmD3pi1Yu3oTqurMSJk4EfNvmY3IMD%2Bs%2BPhT1JnVOLb%2FCEqq6zBm4iTc9%2BCd8DK0MNJWiwW7Nq7Fqo2HMG1yCjbsKJRgcrujxWpFcWEJ6mrq3K5tXW0Q1SeHjE5GalKwYMTiYkJx9shhZJ1LQ3FuAtavWI1de4%2FCZAGGjU3FgltuQLivCl9%2B9S2K87Jx7lwhAvy9cfJEJhb%2F7w146x5H9sGDiPNJxPG1K3H2TBaWvPUmDA%2FcD31lFs5VeWLMyERknDiBLz%2F%2FCucyCxHTPwlzb5uLEQOjsenbDcjPL0LG2UyUVNQidcoU3H7HPPj7eTsYR6upAWtWrcfEWx9BamoyjPX9cXTXDmzeuANzZ45ylOssNlRWnXTjHCy6eQZgNUH94x9jze50ZJ4tRL8gNVZ%2B%2BCk27ziIeosNsf0HYO5tC9AvzID1q9ahsKwGVZVVqKxpQlFeNjKy8vDZ6%2B8jICAEvo1G1NfVorHRgmUffIjTZzIBfTn%2B%2Fve38MR9c1BXU4v62ibAZkVFcQGWL1mOffuOAxoDxk%2BbihvnzUSwnx47NmzG4ROZ0FnNOJt2FiaVBxbcdTuunTQKHoaWwL9WUx1eeO43SMsph9pNvzA11TUoL6uA2WTu7DAp5RUEehUCjAuYsTUCw27KBrUslKQgcLkQMDVokLUj%2FHKRU%2BhcYQTcXgJ4hfFouzqbFXW11Ug7fgoH9hzAkSOnYNbroTNosW%2FzZnzw9ieoMakRGRWM3Zs34d23P0dlZTXOHdmLlcu%2BxqeL14CSRIvJBrPVIiQbJpMRZpMJR%2Fbux6H9J2Eym9HYZAJghcVmgrmpCdnn0nFg33FUlFfj2y%2B%2BwP%2B99CpOZRQgKMgHW1evwLOP%2FgJZBeXITT%2BLVctX49VX3kREv0TU5J7DJ2%2B8jY3bzzj1x9jUhPLySvj7haB%2FYj9ERYZAZ2lEZWUtzJco%2FqKMgAxqbV096urqUHg%2BFwf3HkKNSQMPvQarlq3AkVO5uOWeRVh4%2Byzs27QRe%2FaeRFF2OlYuXYZGj1CMmzQGs%2BZPg87DC9fffCPCAjxw9tg%2BpJ8vw6BRKYiIDsWoceOQEO2LtJPHkX2%2BELs2bMTiT9Zh2IRpWPT9%2BTh7aAcWL1mNotIKHN65DStWb8bEG%2Bfi9lumY8WH72H7vkxYrS0SDbVGg7FTrsPvX%2FwlJk%2B4POqkTmArf3QQAZtj7lRVVuDEoSNIyyqGt4cnNq9Zi12H03HL9%2B%2FBrbfOwrHde7Fz1xHUVldg9%2FpvcPhcKZLHjcbs%2BbPgH%2BCDCTNmYHD%2FUBzbux3ZBVVIuXaSUCmdMH0mEmMDkJ95FkdPZOB8Rjreevkt1KmDcf8jP0CgpxEfvfcJ9h46juN7dmL9lgMYOXkq5swci9WfLcPhY9lO0lJLUyOKSiuRlBQvbOpoO9ovPhJ5OYVdliKX5Ofj1InT2L9zJ46knRc2xx4%2BHji0%2BVu8%2FNrHqLPpkRAXgY2rVmHxe4tRUFSCfds247NPvsKhg8dhNpphpi2h1QqzxSjsZsuLi7B72x7k5pajrqZBBDyG1gZTowlU09y1fRdOHM9CXW0V3n7pJbz77lLUNNkAUy3ef%2Fm%2FeOeNT1FeUY2zJ09iyfsfY9ueI9Br1Ug7tB9v%2FPdTFBVVOKS1HHRqNky67nr8682XkTqoRVrfwQmhFFMQUBC4zAjUlXogd78SSusyw9qnyVFBJn1LBEyNbrrL16dHp2OdV0auAzhZLVacPXYcv3ziabtTCbUWk2bfiElTJiAmzAuR%2FQagqLAI6SePYf82C8rKS4SLcdqXNTUa8cPnf4bvLZgArdqKJzL24%2FjZcjz%2By58hUN0I2mSZDUBU4iBMvnYUdhzIwuybrsfgpBhsX2uG0WhEfUUhtm7bj3KzL%2F7wq6cxOjkJX77zX%2Fz3jeX47rtdiLIY0djYhLvveggP33cdBkR54Le%2FfxO5uRkAhjp6SPbHBjXUKq1wAqLRqqBWU42uhTFyFO7gic1qQe6pY3jg5rtAASIlOv%2FP3nnAR1llf%2F83fTItk94LARJq6L0jqKAiNgTF3iuWXev%2BdS37uq6ua3ddu2vvvbsiqPQWCIGQAum9Z3p5P%2BeGGWZCQklCMpOcy2eYZ57n1u%2B9z5N7nnPvOdGJSTjrgmWYMGE4BidHYEaLBbRPqyCnDA6LGZZWCxwaO%2BTyKFx0%2BQoMio9AVWEWpHI5hmQMhUatAAnIMhcQGRsPrU6FmIR4RITrhdDcWFON%2Bqo8JAwbgTPPOxV6lRSm2kr8vCEfVWVVYhI8Z8HpmDV7CrRK4LM3%2F4vK8nK4MaTNks%2FBtunDIqDV21HZh4ZQjhFzv41ms1jwwNVXQCWM%2FQAhOh1mLVyA81YsgsRuwuhpjZBK3CioK4bdbIaJNOJOJyxmCc44%2FywsnDcJKjRDHaJEQmoqIiMNcNpscDrdiE9NgUqlQHxKKiKMWtCeVYvZjPL8fag3ATdfch5GDopGlEGB%2F77%2BCQr25MFsA6bPmoV582dBKzHhhy9%2BQH1jA5xuNzwPS6fTDofdDa1ac7BfJNBqlXCYLUIA7M420q%2FeeBPfv%2FOOENJIO7VwxVWYNi4RsIbj%2BdcGobKqBnt27IDKbUNjQy3MNifsNhvSRo3DtTdfg%2FGZqfjo9VfwWnkJlly0AuNGp2FLyWbQyx8y%2FrTs4uV4%2BfUvEJqcilW3XwZZwwFhiIquN5QW4KufNmNw5gw8%2BsTdaKkqwkv%2FehZbN2xGzvQxcDgcUGojcPYFK7Bg1gg8cOdfsWPfAbRYLMJ4jccGjkQRguUXny8MOL0v%2BtXZb8cvN4wJBAuBsqxw6GLMCE%2Ftm%2B00wcKJ63lsBEq3RqChmJd%2BHhutwIzlmdMEZu0ARMdG45KrL0bq4NQ%2BqyNpi9IyhuPKG66AXqNEVHwckpMSoNWqsWnNL3jx6ZdRVtWM1EGJwtoe7THxBrkSg4ZnIDQsFHCSBUspJJBAo9VCZrUejCYRwg9ZJyTrmSqVCnL5IeWs3WSCxWSC0RiNqIgI6A16DBpKSzYlaGhqRJymrbzYlFRoNCHQ6tuMGpBwdliQOGF3mmC12WE1OWC3S6BQyYSF08PiHsMJqVSGpOGj8OQLjyJMIwexovqTVUS33YKN%2F%2FsF77%2F3FeR6IwalJMBispMUKoIyMhbhoTqQr0fpQQuBbdZDDxVMAiVZK6Rv6cEZptNqh8PsgtYYBoNWLQxXGIw6uGFt03pIJQiPiYZapYJCQVZJZbDaD18%2B2R2rjYdqGFxHCqUC80%2Bdj5AQtfAr2Ne1V6hUuO%2F5f2PsIKPoZ6VKBaVaCThs%2BPWrtUKbrjAYhdbL3EoarYNBo0dkhBEajRoSm1nsG6Wx6NunnvEiobF1cH%2B62%2BmCxWyDVBaCSKNBWJPVG7RQh0hgtZnhlisRGhEu2CidDshkgNXeJuB4ipYrlFCopWhobdubR3sF62vNUBkNOEabR56sDvs%2BedkyzJ8xDkq1CokpKUhMihV5Zm3bgL%2Fc%2BShsUCA5JQkSsZbrkIXTsMhoxCYniWeDWq0U9wpZ3qSx77s1n%2FqdGJFrEa0mBNaGg1Vwu2FqbobN6kJUVCIiI8OgdJsRmxiH7OI8tJrNIqJKZxB7k%2FVGPRQqBdxwdrCHUiLuabe7g%2BfPYS3mE0yACfQWgfzVcVAvKYIm3DP36K2SuZz%2BRKChWIuSbeyaKtj7NOAFwNj4WNz0pxuFYNRnsCUShMVEYdbCeTCoJJAcFEZoX97ODRtQWFaPG%2B%2B5A%2BOGGHH%2FLQ%2FC4SP%2FUZ2lkkPCHP2maVtLczPksnYRaQGo0wWTiTSDtBy0LYSEhiPUoEP51izk7CtEbKQG635aA7PJivjkNEjq2mZxypAQT5IOvzUaDRITYpBTUYXtG7dg%2F%2F4iuEN0iI4IFxPFDhMdw0m5QoGIyAhE6A%2FtA6JkFQcOYOeOHMxachYuuGgprLUl%2BOsdBbDa25ahSUDCsCdIvIKh58yhbzJXf%2BiXShsClUGK0opS1DSaEaWXo7y4Cm6nCkrVQQYedcTBZIemyofyCZYjvV6HVXfeLIyD%2BAo4Xam%2FUqnEmecsEUlJ2O7rIJFIYQyPQFSMvzXSivIi7NyWhUkLT8M111%2BAxtICPPn352B32A4aZ6EXA576t40i3zHi1y6fsUNGT3ShGtitdSgqqUR81CBUV9Sivt6KxAyDEJx8R6VfPgd%2FyNQ6ZAxKxMbftuP0ueNgt5qxY1cOMtLnHJe1zo7yHjxqFOafMk%2B8EPG8%2FLBZzVj79Seoa7Xj7icfR0aYC3%2B9%2Bc9tyQ%2B2jcYF%2FfMNYn%2BxhVxf%2BJ5tOyb3Lc3NLZB7oEml0EdGQ6t0Y9%2B%2B7diTVwJ3bRF2bc6CLjQexogIFNGzjFy8yAP%2Bz8bhDfY5Q6wWLFqASdMmiReMPpf4kAn0awJOuxS5P8Rj5JkHoAgJHMNM%2FRp6P2ucqU6FfT%2FHA27%2Fvzf9rJkDojkB%2F5ec%2Flj3pa8yzyigepAvPl9%2FfFKZAjrS7Jkb8fLj%2F4Lb6UR1ZRVCXUZYbG17%2FTzpxbdEiqhQPczN%2B3HduRfjtof%2B5r2skMkRptfgQN4%2BvPDYczBddp73mizEiCVLTsGenfvwtz%2FfjadDFGiob8TERWfhtHmjsfGz7SJuB%2FM8bx50EBEVhdkLFuK3h5%2FFfbfcJfYbTjtlMUZlDutR8%2B%2BeQhUhGkikLmxc8zsk1mbk7chC9u5CpM9rhV3vb3xBrw%2BDztaCf973d9x29ypPFpAplDBKgC%2FefAeu0%2BYJ5aHGGIn0tAlY%2F%2ByreOTehxAVqsTWDbux%2BIILkZQY503rOTgaF0%2B8QP0mM%2FVnnrdEaG5oHHY3kB%2FLQA8KlRpSmQSb1q3HW0o79mfnYOOGLMRmToaVrAn5BKlSg1itBu899wxC5avgOqhilqq0iFbJ8d6zz0F95WXirEyuQsqwEUhPCcWTDz6MCeNHYM%2F2nQiNH4rx40ajdE%2B2T850ePjoIf%2BUF1y6Ejfc8jgedjTC0XgAmwvq8fjdp7RLe%2Fw%2FSRNOgjmtFPAE0mxGJyShuf43PHXvvdDLXdhfUo9hUTbU1h6%2BnEsfEgKVXIFn7n8YLSYZEmWHNKcSpQYRIXIU7t6Jc5dcj1f%2F8ydRDL2MCYtOxmWXnI0nnnkHl5%2B1Akq4INMYcPH1pyBzWDKyVntqFNzfdA%2BNmzhWaC5JyObABAYSAUuzEnu%2FT8Tw04ohUxz%2BfBtILLitx0fA2iLHnu8SQC8SOAQ%2FAUlOWTY%2FATrrR3Jz0FSP1T%2BugS4sBjPmTYWinTNjc3MjNq3bgLy8EqSkD4fCbUZtfTNmLpiHqryd2J1XgWknn4KESJ14P19VlIcvv1wNuUqDmQsXomD7H3BIjViweBZqy0uw5qc1cCp0GDd%2BNGytdSgqa8LY8WMQHx%2BGqqIDWPfHZlTXNiFpaDpmzpgEvT4EB%2FZkY%2F2mXZh40qkYHB%2BK8oJ9WPPHdoyeNBEjMgb5tc5qNmHPjixs3rILxtgE8RY8KT6yne7AL0mnP8jQRGXxAWzPKcK8k2ZB1X79m9uNiuL92Lx%2BC6rqW5GemQmFrQWSkHDEG6XYXdyE2TPHCQuCtFx1w6%2BrkZtfjtmLTkHD%2Ft1wh6UiMyMR%2B3N3Y%2BOmHCSnDYJW4YI2JhVpiREoKcjD5g1b0GhxY%2BTYsRg9Kh0hSik2rlmL8NQMDEqOFfsSf%2F%2FpR0SmZCBjaIrfEkFqGJVbW1yI9dtLcMoZcw7r304bzxe6TcBpbcZnn3yPuaedgQiDv5ly4YOzrAwbf1%2BPinoTho4cjhA4IFFoMSg1Bruy92HoyBGIjQ4TWrv8nCysX5%2BFjLETYa3KR%2FjQSRg2KAr7srZh49Y9GDFuHEKVdlS2yDBt0gg01VZhy%2FqNKCyqQXxaGsZPGINwgwo7t%2B2ELiIGgwYlQQYHfv9lLeKHZiA1Kd7v5Q%2B5QSjctQP%2F%2B3UTFBo9Zi6Yj7SUmC5rAPOzd2Dr9lxkTp2O9LT4w8appbUZv%2F%2F4IwpKG5GYMgjR4WpU1dKy8yTUlh2AWxOJzHGjEapVwtRUh7W%2F%2FI6S0hqMnT4LEWo7tm7fjfTMyRg%2BLBH7tm%2FG2t%2B3QaWLxJIzZ%2BPn71YjPDYNc%2BaNh8Nmxr5du7Bp005IFWqMmjAOo0emQwYn9uzMRmFFA8ZMyERCVCg2U9%2FUNmPG3JkIM%2Bo7eIa4se6Hb1Bc78YpS05BaMghK7zdHjycARPoYQKbX38XWR9%2FLnL9UpkCkyTg3493i0BYcguGLiwV%2Fnu7lREnHhAE7GYpdn%2BZAnOj%2F0qvAdH442hkirMFUx2VIsXC%2B%2B5E0qRxx5G696KWZJch4AVAcoJdWlyG2LgYdtjbe2ODS%2BqnBEhwqa6qhkwqQ1h4mNgD10%2Bbys1iAkyACRwzgYEmABKY8EHNGDq%2FDN7V9MdMiyMOJAIOqxQ53ySBrMlyODKBYBIAA16Puzd7L845%2BVz8tvr3I1Pnq0ygnxKwWq3Y%2BMcmFO0v7sDgxvE12mwy46G7H8YTj%2FwLdbV1x5eYCMgqoAAAIABJREFUYzOBfkCAjHQV5BUia9tOmFpN%2FaBF3AQm0DUCdYV65P6YAJez%2B1sLulYDThXoBBwWFv4CvY%2B6Wr%2BAFwC72jBOxwT6C4H6ugbcceOd%2BPrTr7stAPYXJtwOJtBVAiQAfvTOR3jq0adRWlza1Ww4HRPoFwTqi3TI%2FT4BpOXhwAR8CVib5cj%2BIoU1f75Q%2BtFx%2F17k3gcdRUvs3B2Z3euDuniLJCv4B10peM%2F14oFgQtYGA2y3KbkHYCMQvTgQulAUTdZp%2FATa2KENb%2BRKoS8CM%2BkL6lwmE%2Bi%2FBBpKtWKiP2xRMVQ6fyNb%2FbfV3LIjETDVqpDzbSLsZhYTjsQpmK9xz%2FZg75HT9i0btqC6srpbztV7sEoiK7KiOmhwKkaMHnGYcYmeLqt9fuR8OndPLvJy84Uj6vbX%2B%2Bo3GdOMiYvF1JlT%2BqoKXO5RCJCgQxqaXTuyYTFbjhK7dy8bjAbMmT%2B7T%2FZQtjS3tBk%2Fqm%2FzQ9i7Le%2B8NLJWO3PujIDwL9l5LfkKE2ACHREwNyix6%2FMUpC8ohT4msJ63HdWXz504ArUFOhSsiWNrnycOcUDkHPACIPncU6qUfhb4AoJcB5XYn78f%2F3jgMRzYXwyFUklqtw5i9e4p0kba7VZMmT4ZT7%2F8JMgPXG8G2mf2xkv%2FxbdffC%2Bcw1N%2FBkKwmEzQaELwx67fel0o7uv2kzN4uVwe8O2mvY8%2FfP0jnnn8OcgUcshkgfG4stusIMeUn%2FzwEVLTUnu9Owvz92PVlbdAplBAqfK3ntrrlTlYoMNuB91Tb332X4wZn8ma9b7qCC6XCXSDgN0kR85XyUidWYHojKZu5MRJg5EALdQq3hyJsu3kl7fv56%2FByDCY6hwYM6ojEIuMisCKS5YjKTX5CLH69pLD7oDT5QQZ2HC6XFh60UpMnjsXSlXfWkwiB%2B2W1la888ILoAkaaVR6KzidTjgcDpjNFthtdkyePQunnncewiIje6sKHZZD2lDyefbBKy9h%2Fc8%2Fdxgn0E6SbzidXitehHS3biT8zZw3Uwi%2F6pC%2BHZ%2BdtYWWfNLYsVqsICFwUEYGFi9bhrRhwzpL0ivn5XIZyCffmu%2B%2BwwcvvdSrGm26d4kJ3VdWiwWGMCNOX7Eck%2BfM65W2d1aITEZ%2BCxXI2rgRrz7xT%2FGc6SxuIJ1XqVRCUynto2W8gcSC68IEfAm4XBKh%2FWmpDEHKtCr2FegLpx8f20wy5K%2BOQ2Opth%2B3kpvmSyDgBcD4xHjcevctvnUOqGNa9klL1A4UHEBxUTGaG5tQVlSMnO07QAJYXwUy8z9szBiER0UJzZvTYu%2B1qtAkdX%2FBAWTv2IWa6lqUlpTCASlys3dCpw%2FttXp0VBD5jksZPBghGk1HlwPynE6nw2XXXYb0Yend1tqRBvic5WcHZDupUiTo1NfWY%2BO6jWiob8Se7D1obWxE4b69MJv61mJjfHIyho8dA51B3%2Bv86Dnz2y%2B%2FoaG%2BAcUHSmCz2lC6vwjZ%2Bq29XhffAiOiozB87FgYjKGQBIktedoPTS9BRo0ZiYhIetPNgQkwgfYEqvYa0VyhwZCTyqCNsLa%2FzL%2F7EYH6Ii0Kfo2D3dI3%2B9r7EcqgakrAC4CBTrOqogqvPv8qNq7fAp3BAJkqBHk5OeLTd3V3o6q0HKetWI5zLrmk16tBptW%2F%2FeJbvPrvN2AINUKubBOEf%2F78y16vy6EC3agsLcO0%2BfNxy0MPHjodBEcarSaghbaeROhyupC1fSf%2B70%2F3Q63RQn1QUN%2Fwy689Wcxx51VXXQ0SAP%2FfKy8fd9qeSNDc2Iw%2F33QXlEo1dKEGGMLCkLNjh%2Fj0RP5dyaO5oVHU5c7H%2FgF3wFnp6bxFJABOmDy%2B8wh8hQkwAUGAnH7v%2BiwFieNqEDe2jp3G97Nx4bRLcWBdFKr20ot5XvLZz7r3qM0JeAGQNAK0JIysNdIf7kAJZNzE7rCLZZ92u10s%2BZx%2FxunQG%2FpWw0XCFk2i7778Cjhstl7FRf1ELMxms1i%2Bl5aRgSUrL0RcYlKv1qN9YbR%2FjEbOgzevgt3eu0za1yUQfgurmkBA7dOi%2B5zGDmm2yOALLRU%2B9bxlyJw0qU%2BR0RJBmVyGlx9%2FHHVVVaSj7NX6EBPSqNNSalp%2BOvf003DSGWf0ah3aF0ZLkmVyOb796CNkbdwEl9vVPgr%2FZgJMoJ8QcLskKN4SBXIXMXhuBUKM%2FDe0P3RtU1kI8n%2BNhbWld%2B1C9Ad2%2FaUNAS8ANjc1Y%2BvGbRiRORzRMdEBwZ32%2Bu3ZvRdk9KW6qhqkBdRanSjIyUGItm%2FXT6cOTUfykCHobWMrJBAf2F%2BErK1ZaGlpQV5uHlqbW7B%2F3z40NzT0ab%2FFJSVj6KhRUMgDfrh3yImEI9oPR4ZbaA9jdwL10%2B5dOVAo5EgbmtbrRoE6qju1r66mDn%2BsXSeEvz279wiBp6yoCH29T9EYHoGREydAHRLSUdVP6Dl6zvzy4y%2BCBWkAnXY7airKkbtr5wkt92iZa3Q6ZIweDa1eH1AvEY5Wb9%2FrJFjTixCFQhG0bfBtDx%2F3LAEJ7ZcPnPfNPdu4LubWUh2CnR%2BnIjazDglj6yBT8IufLqLs02R2sxRFG6NRnWtgrV%2Bf9kTfF9692WQv1L8wrxC3XnMb%2Fv70Izjl9JN7ocSjF1FeVoE3X3oTG9ZtRnhUNGQyhdj7t%2Fb7H46e%2BATG2L8vD5PnzMbNDzxwAkvpOGuTyYTvvvgOL7%2FwGuKSkoSwQtZbt6z9reMEvXLWLfZjkibyrif%2B2SslnohCSBD4%2FqsfMHTYUIzM7J4rD4vFghefehGhxlDcctcqRMVEnYgqH1eepLHesS0Lf7n9PsTGx0Ot1SIiKgp52dnic1yZ9WDk2upqYXjnvmee6W3Fn2hFWWk57rjxLkTHx0MfGipe7FSXV%2BCHTz7twVYeX1bNTU2wW624%2FE%2B3A%2BSfMQgDvXDYuX2X2E9JS0HpXuDABMgvrCcoelnT7yk30L%2FJQEzZ9gjU5umRPLka4WktgWDsPNCxBUT9XA4JKncbUbotEg5bYFhjDwgwA7gSAS8AUt%2FQH%2BxACi6nE06nC5mTp2Dh0qXQ9LHWz8Pm0TvuEBYCPb9785veppPFxrikRKy84QYYw%2FveuALV6Y0nnxJLC8lsf7CGpqZmPPXo0zj%2FomUYMXp4jyyFDqQ9Wx4Np0anxZKVK%2Fvc2qdnnPzwySfYuWWLWFLdFxKgzdpmeGHB0qUYN3Wqp1p9%2Br1j40as%2Fe5buByOgHsuHysYGm8%2FffsT9u7ORVJyIguAxwqun8dTaH0NgwXv34ve6CZaNrjvfwnQ7TQjZWoV9LHsN7A3uHe1jLpCHYo2RMHSzMs9u8rwWNPJfbZE%2BL5UOtb0vRkvKATA3gRyrGXRfsRQYxhShwyBtg%2BsAnZUz9728ddRHVQhIUgenIaI6L5frksCoEavRXNjYDnM7ogbnwPkcgVik5MxKCM9IHAYIyIh62u%2FlRIgOi4uYJiUl5S0%2BTgNiB7iSjCBniOg9LEMrUBward7jsax5UTLQrO%2FTIExqQVJk2rYWuixYeu1WA0lGpRsiURLVe9vYei1RgZYQQo4vTVS%2BDxTvCcD6IAFwADqDK4KE2ACTIAJMAEm0PsE1KG0J6otaNyHJnGec%2FzdOYGGYh0airUIT2lB3Jg66GNYI9g5rRN7hRY7NRTpUJYVJtx4nNjSOPf2BFQ%2BGkBNgG8vCHgBUKVWISEpXjjtbQ%2BafzMBJnB8BEhzHR4ZDkOoAewE%2B%2FjYcWwmwAT6LwFtZIS3cVp37%2FnN9RYa9AcS1B3Qi48%2B1oT4MXUwJrXyHsFe6leXU4KafQZUZIfBVKfqpVK5mPYE1D4vj0LCAnt%2FecALgLHxsbjxTzcgfdjQ9pz5NxMYEATIemn68KGIjI7s9v4%2FWia85JwzhPVDrc53z8uAQMmNZAKCQGxcDCwWK1RqNRNhAoKALuqQAKhhAbBbo4IcyO%2Bt0EBtsCFmeAOiMxohU%2FGy2m5B7SSxzSRDxa4wVO8Nhd0S8FP6TlrRf07rDz47QkJDIQ%2Fwvy8BP1qMYUYsWrKo%2F4wObgkTOE4COoMO19x8NaJjY7otAJIbiYlTJx5nDTg6E%2Bg%2FBEgLPvuk2ZjYakKkz6S%2F%2F7SQW9IVAmpjKGgfoM1kgsHFGsCuMGyfxtKkxIEN0WIfWsTgJkRlNPLy0PaQuvCbVhk2lGhRvScU9cU6kK9GDoFBQIc2P5na6L63sH40IgEvAB6tAXydCfR3AiqVChOmTOjvzeT2MYFeIUACYGpaaq%2BUxYUEDwEaF8bkJFTt2YtQ2EC%2BAN0Snlj3RA86HVJU7TWKj0pnQ%2BSQZkSlN0IdyoL28fBtqVYJTV9doQF2i%2Bx4knLcXiBAKwdUBw1IRQ4O%2FL8xLAD2wqDgIpgAE2ACTIAJMIHAJkCTNhIAlXCBlnI1Sdhsfk%2F3GLmQKN0eIT4aow1hqc2IHNqEEGOb5qSnywvm%2FMigS0uVGrX5BtQf0ILYcQhcAuGuNtdNVMNwFgC731FF%2B4vw3BMv4MJLVyBzfGb3M%2BQcmECQESC%2FZXa7HTKpDDJ59976ka%2FGd19%2FTxhVWrTkVGEMJshwcHWZQLcI0P3kdDjhcrvEXljS%2FHBgAkQgang68PX3Akaky4ImKU%2B4T%2BTIMDUoYTooDKr1NhiTW2FMboE%2B1gyZfGD6YnRYpWgs0aChRCesebKm70SOwJ7NO9pl9mYYM2KY9zhQDwJeA9hQ1yCc9p50ynyw%2BBeow4jrdSIJ1NfV44G7HsT8k%2BdhyblLurUP0GF3YOumrTCEhor8ENhGqk4kVs57gBIgAfDDtz9E0YFiXHjZBUhMThygJLjZ7QkkjBkFgF4IuJHgakUBDrmGaB%2BXf%2FcsAXJSXpFNnzBA4oY%2B2iysiOpiLNBFmSFT9E%2BB0GGRoqlcI3z1kSsNUz1b8OzZkdV7ucUdFADVBj2MSQm9V3AXSwp4AdDztpa%2BOTCBgUjAZrNjx5YsDBsxDHQfdFdj4XK64HKxn6uBOJa4zW0EiotKkJuzD2bToTe2zIYJkCGYiLQU1BbsR5TbAhlpi1lD3PsDwy1Bc6VGfEThEjdouag%2BzgRdlAWacCtCwmyQyoJrXui0SWGqUaG1XoXWajWaK0JAgi%2BH4Cegc9mgQ9ue1sSJ47s9T%2BsNIgEvAPYGBC6DCTABJsAEmAATYAKp06cIAVABF%2BJcrSiR6RhKXxNwS4RmjLRjld66uKEJtyHEaIUmwgpaQqrS26E22CFX953LCdJV2E0yWJuUsDQrYGlSwFSrhrmefrOw5%2B2%2BfnaQ4mr1tih58njvcSAfsAAYyL3DdWMCTIAJMAEmwAR6jUDytEnY8tb7orwUZwsLgL1G%2FngLkgiH5%2BT0vLbAP61M4YLKYIdKS8KgE4oQB5QaJ%2BQqJ2RKJ%2BRKl%2FBLKJW7IJG6QfE9QSp3g9ws%2BLpWcNikgFsCp10Kp1UKh00G0uY5LDLYzXLYTHLQ3j0S%2BqzNCrjYLYMH58D4druR7GwWbVWEqJE0aVxQtDvgBUCVWoXElERhtCIoiHIlmUAAE6Dlo%2BGR4dAb9JDKumdQJoCbyVVjAkyACXSJQFhyIiIHp6EmvwDx7lao3U5YJPys7BLMPkpEgpqpViU%2BfVQFLnYAEYhyW2E4uPwzdcZUyJTBoekNeAFwaMZQvPP5WywADqCbiZvqT0ChUCBz%2FGjEJcR1e115iCYEd%2F31TpEPvVzhwAQGIoGk5ERxD9D9wIEJtCeQfup81DxXACmAoY5G7FSEt4%2FCv5kAE2ACgkC6o8FLIv3k%2Bd7jQD8IeAGQzN4bQtkS1%2FEPJDcsZjNqq2tgsVigOP4M%2BmUKm9WKmqpqmFtNQdO%2B8Igw%2FOOZRyGXy7stAJIGUKPVBE3bA6miTqcTtVXVaG5sCqRq9WldXE4nmmrr0VTfADetmwqCIJVKce6F58LlanMDEQRV5ir2MoEh82Zh65vvw9LcjMGuJuxxG2GXkDjIgQkwASZwiIDBZUOCu23%2FX%2BSQNMSQK5kgCQEvAAYJx4CrptPpwOpvvsHa776HG25MmzW128JDwDWyCxXasWEjVp13Luw2O0KNweEDgYQ2dYi6C63lJD1JoOxAEW5bcQHsDjuUCgXkCn581tXU4P%2FddhtIOCZhUKEMjldNpFXnwAQ6IyBXqZCxeCF2vP8JVHBiqLMRu%2BVhnUXn80yACQxQAhnOBuE4hpo%2F%2BpwzgooCz2CCqruOvbJSiQyTpk7EOSvOFstnUwalCKfHx55D%2F4w5bEQGLrn6YqjVasTGx7JQ3D%2B7%2BYS0KjomCtffdh10Oh3CwsOQmMT%2B44yhBpx9zcVITk0WKzWGjRwG0rBxYALBTmDkkkXI%2FuIbOMwW0CRvnyyUtYA90KlqlQK3XX%2F2YTm5XG60tFpQsL8ca9btQktrz7toiQgzoLb%2B0AqOC8%2Bbh3CjHs%2B89IW3PpqDWyNMFqs4N3PqKMyeNhIvvPo16htbvPH4gAkYXTYMcrUZfwmNjwVZEA6mEPACYG5OLv7vT%2Fdh1Z03Y%2Frs6cHEtu%2Fq6naLSdiQ9MFYfOYiUY%2Fu%2Bo7ru8b0UMnkLsgNxCfG4bSli4XgNxCZkN%2BzJx99GnqDDhdcugLhEby35WgjjDToFAzGUDF2VCoVvzhwQ%2FikDNFqMG%2FhXAzJGDJg76mjjR%2B%2BHpwEyJlz5tlnYOvbH0IJF0Y66rBdERmcjQmgWstkMsyZkQmn0wWLxeatmVQmgVqlFM%2BRSy9YiLseeBUFByq817t7cMYpU7D87Dm48Jp%2FeLMaO2ow4mMjvALgqGEpuOe25bjnodexv7jN4cSg5BhR39ff%2BYkFQC85PiACYx3VXu3f%2BIvOhyTIXn4GvABIE9a9u3PR3MRvXo7lltv6x%2B%2B4cO5cmp1BKpPyRBXAvuzduHThybDbbRgxamjQTVSrKqtwxfKrcNaypbj0mku6pWGhfU%2BlRSUwGA1wOtgZ%2FNHuKVriSMs%2BHQ4HMoanB93YOVr7unLd1NKKp%2B7%2FK1xuJ%2BIT4sR4pJcpwfJChe6BZx57Fvn78rHqzlUYPDStKxg4zQAgMOqs05Hz7U8w19Uj3dWIAy496qVsPKsnun77zjzc8%2FAbflkp5HKcfcYMXH7hyVh1zVKsuufffte782PapGFi6b5vHv9%2B9SsoVYeWg48YloKIcH%2BbEz%2F8bwt27CpATV2jb1I%2BHuAEyEVMjNsiKEQPSw867R9VPOAFwAE%2Bxo67%2BckpyTh7%2BVnQ6rSYOXfmcafvjwkioyNx3opzoA%2FVY8r0yUEzUfX0BS2NaW5shvXgkhTPef4%2B8QQ0mhCcu%2BIsxMXHYsToEbyMGhD7%2FBYsOgkjM0dg8NDBiE%2BMD7p7ymq1orXFJPYtnvhRxCUEKwHaCzjliouw%2BrGnxZv%2BSfZq%2FKhMgFsiCdYmBXS97Q4H3v%2F0V8yZMRrD0pNgDNWhwWfZJb1kigjTI0StRFOTCY0tnRtzUykVCAvVoaq2AfQ3tKOQfwwaxsqaBtCnoxCiUiIiwiCWrvrWs6O4CpkMUZFGWKw21DW0LRvsKJ5eG4LQUC3qGlpgMrUJGB3Fk0oliIkKQ01tE4gbh94joHI7MdZRIwqUSGWYdu1lQaf9o8qzANh7Y6ZbJbndbrHkqu2bljO64XA6YLdaYbfZhBEGh8OOocOH4sobruhWWcGSmFgQBw8T%2BiathN1ihc1ug93mEEJTfHwsLrvuUrHvL1jaxvU88QTaxo2LhpAYQ6QZonuJPg67HabmZvEiZcUly5GUkhR0Qk5XCLYx8bmnXC44nHaQ9VyHzY7mhnphjXbh4gU4efFCkJVmDkygPxNImz0d%2BavXonjTNoTBilGOenYLcYI7vK6uGYNT46AJUQkBUCaV4sJz5%2BH0U6cg1KD1lp6%2FvxxPPPcJ8grLxLnxmYNx%2Fx0r8eS%2FP8N1ly9GqEGHnL1FQqsXGWEQqxU%2Bf%2Bt%2BfPPjJrz4xjf4272XIC42Apff9ATuXHUeZk8bLfJ55h%2FXY39RBW668wWxbHTF2XNx7e3PoLyyTlwnwfL6y0%2FHjKkjQEtaKVBdXnjlK%2BzM2S9%2B03%2BP3HcZrFYbNmzeiytWngK9vs0Cd25%2BCR596kOUlLUJERQ3OTEaN121BJkjB4n09Pdo49ZcPPOfz1FT17ZvkTSkH71%2BL975eDWmTxouhOTWVgsuv%2FlffoKytwJ80PME3G5MtldBjbYVVKOWnoaIwW191vOFndgcg0IADJalRT3ZVUKYcbngcrpgs1lRW1mF4oJ8FBcUoLy4GDWVlWiub4CNJqsOu1jOZzGZoB6f2ZPVCLi86KFIFgdpgt5YX4eSgv2CSWnRAdRUlKOhth5Ws0lcp3jkCmPM%2BDEB1w6uUO8ToHuKxgRZyDU1taCs6AD25%2Bej9MB%2BVJeWo76mBq2tLULQcTkd4g93REQYJP3Y%2FHsbExdcLidsZgvKS0pQlJ%2BPkv37UVFSgvrqarQ0NQkBkLjZrTaQVlTBFlB7fwBziX1GYObN1%2BDTG%2F4MS1MzhrvqUeNUoVx2SBDps4r1w4INuhAMG5oo9gdW17Qtu6Q9gcuWzsbXP27C6rU7xAu78ZlDsPycObj1uqW44Y7nBQkyQKVWK3Hd5aeh8EAlSsqyUV3biP1Flbh4%2BQLEx4bj8Wc%2FQXlFrYivVCpAmkIKX3y7HhJIMG%2FWGLz29g%2FePYAkdFGedI0Caf3%2B8eCVSIgNx%2FufrMHWnfmIjTKC6vjoXy%2FHn%2B97Bdl7D4i4KoUCQ9MSMDIjVWg29xdVYWxmGs5dMgs3XXUm7nzgFREvOtKIJx6%2BWvx9eurfn6GwqALpgxNw2YUn4%2FGHrsL1f3oWJnObURqqyzlnzEBTswmff7MOOl0IC3%2BCYu%2F8N8zZgHh3m%2BY5LCUZ41cu652CT0ApAS8AkrNqMtwRMhDM4IsJqkuYmSe%2FWvk5u7Fz4ybk7soS%2FsecDgf0Bj0SkhKQlpqA6KnjhCsDWu6pVqsglcowZkL%2FE3ZocuqwO2BqbUVJQQG2b9iInO3bUVlaIiamIcKiZ4xwlJ45KkNYaNTqtWKiKpPJMWxkBpRK5Qm4fXovS4lUAu9u424US38gwyLChREY6cE3l93ILuCTkm86u71NU15VVo7tGzZg99atKM7PF%2BNJqZQjIipSPGMGT8pERFQEDAaDcLtBbh4SEhMQHRvVr7R%2FJPTR%2FUQvjkjozdq0CdlbtqAgJwfNTc2QwN1m5TQ5ASNHDAEtoSZfrOQ%2FkiZMEZGRyBw%2FOqi1f%2FRSkZZQcWACx0IgxGjErFuvx48PPCoew1MdVfhRkoAWaXD%2FXTmWtp%2BoOKTJmzh2qDd7lUqB2KgwoeUjTdm7H6%2F2Lm2cNC4D2TkH8PSLn3njk6YtJTkaM6aMhFajRqvPcsnSshrc9eCrQlD0JFhy6hREhYfit%2FW7PKf8vnNyizF6xCAhAG7dkecVAP0iAVi8cBKSE6Lw%2FCtf4vNv14vLOwFkZRfilWduw7WXLxaaQ086vS4Ef77vZWTtLhSnNm3PRXJCDCZPSPfWe%2BV580HxbrrzeeTml4p4VJ%2FS8lr87S%2BX4vRTpuCDz9Z4shRC6233voimlp63lOothA8OIxDrNCHT2aYFliuVmHvHzZAF8cvQgBcA04en47OfP%2FWq2Q%2FrkX5wgvxn2Wx2tDY1ojA3Fxt%2B%2BRU5O7bB3NKC6NhoTJw0FuMnjcPIMaOE0QWlStmveVCXumk5nt0Gk8mM8qIibF6zBtvXb0B9TTVCQw1iP9a5552GUWNHI2VQMrRabb81ekM%2By0aNGYXYuNhuj3byJ3j%2FI%2F8n8umvy%2FdIwLHb7UKjVVtTha1r%2F8DmP9aifH8R1CEqkHXcFZcsw5jxmRiSPgTGMKMYO%2F3ZfYFH6LNZLWior8eOdeuwae1v2J%2BbC5lMiuSURJx25qniBRK5SqHnDi1tIkGpP67AIMGetMEhmpBu31OcwcAgkDRxHMgozK5PvxJWQefYy%2FGTMhFWCS%2BD7soIGJKWIISb9mmtNjs%2B%2FGwN%2Fvv%2Bz95L197%2BtPeYDmhJaGJCpFd7p1TI0eaKuy0aLZ2kZ96JCJMnDIPD4cQ3P2zyy572Ca7buBuzZ4z227totli9wp8nQUlZtZ8AOGViBopLq4XWkjSOnrBz935Q%2Bknj0%2F0EwN25RSz8eSD10je5fJjmqPS%2Bh59x41UISw5uV1CHRlovQTzeYmhSFqgTM1qOSNopetAc7ySJJh%2B014i0WlVlZdi%2Bbh22r1%2BH%2BqpqYVThjKWLMPuk2aDJWDBNUuiZS%2Badu8KEBGGauJvNJtTX1GLXps3YvHYtSg8UIiIiHBMnjcGcBXOEMEyT9oESIiLD8cwrT%2FVIc2mcBqoDc3K3QEsvSfg%2FXnPKdC%2BSRstqtqCpoQF7duzApl%2FXCC26RqPGyMyRuOjiZZgyYzJi4mIC9pnSUSc7XQ5Q%2B473OUj3oBCELVa0NDUiLzsHm9b%2Bipxt26FQyIQgfNPt12Pa7KkgP6HHm39HdQ2Gc9TOCy5bEQxV5ToGGIGJl6xAY0kZijdthQ4OzLaVY7Uynv0DdqGf8gvL8Ma7P3lTOpwuNDW34kBxFWx2f6MmcqlMCFazp49EYnwUYqPDxTOMBLGOQo2Pr7%2BOrnfnHO0lpGWldufhZZdWtGmHIsMN3mWZLR1o6RwH09IaBBJeydgNfb5674EOqxYVEep3nvZIcug9AjqXHbPsZeLFD5VKL4IGz5vVexU4QSUFvAB4gtrdrWxpckpGwKoryrFv927EJCQgRKMBqYTlcjnkcnpz3vb2nN5B0TI0mtTSvjW7zQ6LxYTaymrs252N3Vu2oqyoEDqNBmMnjsX8k%2BeJt%2FChRv8bvlsV7oXEJFiQxsDU3IR9O3fCYjYhRKMFaSvlCoXg0satzUk0TU7d7ralnSQI2ywWIfQV7NmD7G1bcSB3L%2BQyGYaPGoaVl5wrJu5R0f1rKV4vdEvQFEFjx2l3IH9PDnR6A7QGPZQqlbC6KZMrfLS7koOGf0jgc3g1fST0HcjLE8s783Znw2GzIm3IIFy76mrMnDtDGHEJNgGHluiSmgbzAAAgAElEQVTSfbV%2F7z7EJaUgNCwUSqW6jYlCLpZgSiCFeBiB7icXnA56ztjE0mjau1dSWIjd27djX9ZOtDY3ITE5HhdfeSHmLpiDQUMG9fuVBEFzA3BFg4IA3ZNzbr8RX99xP%2BqLihEOK%2BbYyvGrMo6FwOPsQbKauWHr3mNK9eebz8XcmZkg4ykbtuxBwf4K5OaVYMmiqViyaNphedBz8EQFehlHzuw7CiTMUSDDL57QmQVSz3WPojKvoBRvf%2FiL57Tft9XmLxB7BEi%2FSPzjhBAg4W%2BuvQyag0ZfBs%2BZgUmXXXhCyurtTANeACRz3ZXlVYiMihB7UHobUEfl6fRapA1Nw4%2Ff%2FIS3nn4SIToDwqOiEB4dhbCoaISGhUEdohGGEugx5LDa0NrSjLqqKlRXVKCqtAS0x4%2F2H9EStNPPuBJTZ05FQlJ80E7IaI9daloKNCoFPnr5P1BrtAgNj0B4TDTCo6JhjAiHRquDnBy9EhMb7elrEUs6q8vLUVlSgsa6OkglbqGNuOCS5ZgxZzrShqQFrMaqo7ER6Ofoj1dtdS1oImM0hgbEPi7a3xgbH4vklASs%2FuIL%2FP79d9AbwxARHdt2X0VFQKsPFS8T6CUCaYrNJhMaauvESxi6n8hYidNuF%2FmcvvRUzJo7E8NGDQM5bQ%2FWEBZuRObY0dj22xpkrV8HrcGAiJgYcT%2BFRUVCbzQKy7bUl%2FSCyWqxiOdKdWWleMbUVlTAajGLZ%2BfsedOEW5jMcaMD5jkarP3C9R7YBJRaDU5%2B8G58f98jaCgqRgQsmGsrwxplHC8HPQFDI2NIohD%2BflufjYcef8evhLCwNp99x7sCyy%2BT4%2FxRVlGHKRMyQO4amlv99%2BClpsSIFVC19ceuoSMXDuTKwaDXYt3mPYctXZ0xeQTqjiO%2F42wORz8CAYPLhtn2cmjRJoDHjx2NmauuO%2B4Vf0cook8vBbwAWFRYhIfu%2FRtuuO16oQXqU1oHC4%2BOicZVN1yJxUsWYd%2FePBTmFaLoQDEqDxSiMHun0PK5PK91DqaRSiRQhagRGRmByVPGC8Mko8eOEss9aY9XsAfaW7bozEUYN2k8CvblIy83H0X7i1BeWo7S%2FFzYrDaxjM3TThIC6aGtVKuEwYkxY0cgY0S6mPAmpSYF9cTd08ae%2BiaDHQV5BYJTVExUt7Klfnjz5f9Cp9dh2crzRJ7dyrAHEpP2j3zKPffasyjIK0R%2Bbh4K8%2FejrLQc%2B7YfgMVi9fprI426x3SHQqkQRpAGD0pE%2BqL5GD1utND6kbGS3pwQ9ACCDrMgjfcLbz6P%2Ffn7kbcvHwX7ClFWUoaivdnYu80sVhR4drkQEzqmFQh6g04YRJoxfRxGjRkt7isy4hJsGtAOofTQyYrySqElpb2OarW6h3LlbAYKAW1EOBY9fC%2B%2BufshNJaWCk3gAlsJ1iri0MSGYXp0GJArCAoey52ezJPiIzFpXJsRGZm8bWWR51pH37Tqkl66HynQizQKR4q3dt0uTJ04DCuXzccLr33tzW7MyDRMGDMEG7fkei12ei8e5YDyPOv06cLAzNc%2FbPTGnjdzDO66ZZnYE%2FnyWxXe83xw4glEO82Y4ajwLvuMyxyJBf%2F3p6A2%2BtKe2pHvhvax%2B%2BC3qdWErK1ZaKjv2BFnH1RJTC5pX96QjCHiQ8sZyV0D7bdpbGxEQ30jWltahSBIE1GVSgl9qEG8iad0NEnrDxPU9uxJkE1KSRQf2qsn9jna7cLhcmNDI5obm8TSCOJFS0P1eh3CI8OFMEJp%2ByOT9oy68pvG%2Fn13%2FBWnn3UaLrh0Rbcm8tQn9MLCYDQIS5Bdqc%2BJSENCIFmbpM%2Fk6ZPEywKqq9lkFvd%2BY0OT0HDR%2FlLaw0iWb0lDRkulSfvcH4Ubuh9IcMscnyk%2BnucMrYqgMUH3FD0faR8MGXKhZwvxCAunFQhqwYTvqcNHK2nBP%2FvgM%2FGS4bpbrkFqWurhkfgMEzgKgZAwI0577K%2F44b6%2FoyYvX%2BwJXGAvxQZ5FEpluqOk5svHSmBvXglq65qwZPE0mK02lJbVIjU5BmecOhVV1Q3Cf57RoIPHZURn%2BVbXNQp3Dv96%2BGqsXZ%2BNT776%2FbConjzuvvV8YdXzXy98elic%2F63djrkzMrH0tOlIiIvE9p35iIkJw6KTJqGxqQXPv%2FrlYWmOduKtD%2F%2BHieOG4uarz8ToEanYs69EWBo9Zf4EYRzmw8%2FWHi0Lvt5TBNxuDHE2YbyzxvuyedCs6Zh963WQ9QNljS%2BmgBcAfSsbqMc0ySKLivShiVdMbEygVrVX60WTevrQG3YyZMKhawRovX9FaQWaG499WUnXSgqcVCTQ0UcRqhBCUODUrO9q4nnOaOQasYwzPjG%2B7yoT5CU3NTahpqpGvKQL8qZw9fuQgFqvx%2BJH%2Fg%2BrH3sGRRu3QAEXZjoqkeuyIEseAScZC%2BDgR4BelpPLhIIDlX7nO%2FtB%2Fu%2FuevA1XHHhyTjt5ClQymXILSjD3%2F%2F1Piqr63HT1WciMT4S%2BwpK0dxiFnk3dPC38t2PfkFEuB5J8VEiPpVXsL8cjU2H7If%2BvmE3vvxuA8aOTkNqcqywNlpRVSfytNntooq0p%2B%2BBR98SGrv5s8fhwmXz0NRkwrc%2Fb8J7H%2F%2BKWh8DNPn7y1BT1%2BbL0Ld95RWePNuWFra0mnHrPS9ixTlzMW3ycLHEtKauWdTlvU9Wo7Glze8c3G5Rl5LSat%2Fs%2BLiHCCjdLkyyVyHRfWhMjD77DEy4eLnYNtNDxQRMNpKcsmzPKqKAqZRvRXZs2YFLzr0Mjz7zd5xy%2Bsm%2Bl%2FiYCQwIArRcbflpK3D%2BRctwzaqru6XtIs30nTfdJTSAt951C7q7pHRAdAA3sl8RIA3g4w%2F%2FE3t35%2BKuv96BocMO%2BSLrVw3lxvQaAdLOZ33wGba%2B%2FaEwxkQFN0CJbfJIVMnY1UivdQQXxAS6SCDZ2YJxjhqoDxp7kavVIFcPZPSlP4aS7DKwBrA%2F9iy3iQkwASbABJgAE%2BgVAqSdH3P%2BWYhMH4w1T74Ac109jLBhrqMMhS49dsnDYZbwdKtXOoMLYQLHQcDosgrBL9pt8aYKT03G7NtvQHhqivdcfzwI%2BCdSRFQEll9yvnD23R87gNvEBI6FAO17I2uZ3Q2UD%2FmXpKXKweRfsrvt5vRMwJeAVCoTe0lp4s6BCfQUgYRxmTjr6Uex4aU3kP%2Fr72IPUZqrGSm2FuRJDdgtD4ONHcf3FG7Ohwl0mYDOZcMoRz2S3S3evX4SqQyjlp6G8ReeC5lS2eW8gyVhwC8BpeU6NputzfeVTBYsXLmeTKDHCLQ0t%2BDTDz7DiNEjMH7SuG4by6H7iSa%2B%2FdUYUY%2BB54z6JQFarrfh9w2oranDtFlTER7B%2B5P7ZUf3caNKt2Vh3fOvoKni0F43ByQolOqRLwtFI1sL7eMe4uIHHAG3G1FuC4Y6mpDoI%2FgRh5gRGZh67eWIGNS%2FtX6ePqcloAEvAHoqy99MYCAToEkraysG8gjgtvc0Ab6nepoo59eegNPuQO73P2PHh5%2FDVFfnd7kaahTLdCiVaWHi5aF%2BbPgHE%2BhJAkaXDfGuVqQ4m2FAmzEfT%2F7G5CRMWLkMKdMmeU4NiG8WAAdEN3MjmQATYAJMgAkwgb4i4LBZse%2BH1dj91fdoLC3zqwZZ4SODMRVSDaqkIaiVqmGXHN2vnV8m%2FIMJMAEvAY3bgXCXBbEuM2JdJq8jd28EAFHpQzDqrNOROn0yJNKBd78FhQBYV1uH31b%2FjolTJgin6b4dyMdMgAkcHwFyKr910zaQE%2FXho4axE%2Bzjw8exmQATYAJdJkCOxku2ZSHnq%2B9Rti0LLvJO3kEwQYYmiVJoBi2QwyqRwgmpcCvh9O5Y6iAhn2ICA4SA3O0CiW1yOBHidkEJJ7QuO0JhgwquDinIQ9RInToZI844FZFD0zqMM1BOBoUV0KqKKvzn6f%2FAeP8dLAAOlJHJ7fQjQK4bPvvwcwwfNRzjJo7t1lJQu92Obz7%2FBjq9HsmpySwA%2BpHmHwOBgGcPIL1cnDqT9wAOhD4PlDaSpiFpwljxsTQ1o3jDFhT%2BsQEVu3LgsByyQqiBExq3GQhoJ12BQpXrwQQ6J6A26JEwfgwGzZiC%2BPGZkCtVnUceYFcC3gqo1WJFSVEpzCbzAOsabi4TaCPQ2tqKD9%2F6EEuXLcXYCWO6JQCSUSVygE2GYDp7%2B8zcmUB%2FJkAC4OYNW5Cfm49hI4ezEZj%2B3NkB3DaamA5dOFd8aK9gbV4BqnPzUJtXiIbiUjRXVsHa0hLALeCqMYHAIhASHgZ9dDTCByUjYsggRGekw5ic0K05U2C1sGdrE%2FACYM82l3NjAsFHwOVyo6G%2BkV%2BCBF%2FXcY0DlICp1YSmxmY4HY4ArSFXayARkCnkiB6eLj6%2B7babzGipqoG1tRUuu7%2FxCt94fMwEBioBuUoFpU4LfWw0ZArFQMXQpXYHrQBosVhQVVEN%2FzUSEmg0IQiPDIf04KZO0nTU19WDNIm%2BQaFQIJoGjI9rCVoSRCb3fYNEIkWo0QBDqMF72mK2gOI62k0edHodQo2h3jxJ21JRVnFYPECC2PgYKA%2F6GaE30jQhqa2p9ZbhOTCGGf3KJk0ole1st3dApVYhOiba%2B6aD8qyrqQNpj3wDmf6nOmp1Wu%2FppsYm0Ifq6xvCwsNAbfJYn3Q6nCgvKz8sHjGMiY0RfrUoPdWN8mtuavbNTvRJZFSk8EHnuUBxSLhxu%2F3LDgkJQVRMlCcaqOza2loQe99A7ab2qNVqcfpQu03txgZAZWu0Gm9y2g9X1m5DPl2kssn%2FpGcM0bLJhroGmM3%2BWmhiSczJt54nNDY0gj6%2BgcaQVqfx0zTQ%2BK2vrQfl7Ru0Wq1ojydP6pPqymo4nCd2onqksRoTFw2Vqm3ZBMWjMdjRWG0%2FXqivaqprDhsvNO5j4mK844ryrK9rQGu7t92djdXGhqbDxgvdJ3qD3psnjcHy0sPHavs%2Bo3jUX%2B3ve%2Bp7Gi80vjzjn%2BLQvdc%2BkE9FGgeeQOOKxmr7Z45SpUJYuNHLksZqbXUtTCYaq%2F4hIjLC7x49nrFKdWxfNrUnLj4OMvkhVzp0jzbUN%2FgXDAl0eq3%2FWDVbxDO0o7FK3D15Unvoedc%2BHhVAfIgTBYpHY4jGRvtA9zL1o%2Bfeo%2FuEGLV%2F3tEzJyEpwZuc8qTnfEf96MnTE5ni0LJqGnccmEAgE1BoQhCWmhTIVeS6MQEmEKQEDs1cA7QBZKyCHGB7JqBUTfrDXbCvAHfceCfs9kMTY7lchlnzZ%2BHmP9%2FknegXFRbhP8%2B8hB1bs%2FxamJSSiH%2B%2B8LiYbHsuvP%2FfD%2FDZB597fopvEijPueAcrLz8Qu95yuv5fz2PirJD%2Fn3o4tLzzsT5Fy%2FzTp5sVhvuufVeEY8mKJ5AE6F%2FvfgE0oYMEqdowrT%2Bt%2FX4x4OPe6KIb5rkXHrNJVi28jzv%2BbayX0BluX%2FZo8eOwqPP%2FN0rfJJw%2BtJzL%2BOXH1Z709JBXEIsLr7qYsw%2FeZ73%2FHdffo8P3vrwMIHt%2BluvxaIzF3kF1YaGRtxy9W2HxSNh9rHn%2FuGdBNME6%2BN3P8GHb3%2FkLYMODKF63Hn%2FHRg%2Febx3gvfrz2vw0rMv%2Bwl2NOGePnsa7nvk%2F7zpaVL7z7%2F9C9s3b%2Feeo4PMcaNxydWXYNSYkeI8jQ1qNxkOstv8hasH%2FnE%2FpsyYIib01B%2FVVdW46oJr%2FPKjH5OmTcK9D93tdZRO%2FfzSsy9hw%2B8b%2FeJSux995lHExB4SvL%2F4%2BEu89crbfvGovxctORXXrjpUVu7uXDz7z%2BdwoLDIL%2B7CxQuw8oqViI2LEefpBcZzTzwvhBSlqvtvt2hiTcIlCWEewYYKorH6l9vvQ1lJmZigeypF4%2F%2BRp%2F4fho0cJk7RuPpjzTo8%2FvA%2FPVHEN%2BV7zc1X44xzTveOwV07duGJ%2F%2Fcv4W%2FNN%2FLQjCF46uUnvfGojW%2F85w18%2F9UPvtHEnt%2BLr7oI8xbO9Z7%2F%2BtOv8fF7nx42Bq%2B%2B%2BSqcec4SrzBOE%2Fzbrr0dJCz6hsTkRPztiYcQGx8rTlM8Gvufvv%2BZbzQxVu956B4xvjwviX7%2F9Q8889gzfs8caveEKRPw8D8f9KancfXM489iy4at3nN0QPfoFddfLvZy0u%2B2sfoKfv%2F18LF6z4N3Yc6COSI9jVUSKDsaqzPmzsCtd60SQhNFpj3TNF7al02%2B7p597RlERB7yeUf3%2FSvPvyrK8PxHY%2FXU00%2FBdbde6zmF3btyxDO0MK%2FQe44OFiw6CZdefYn3RQ2158F7HkJh3n6%2FMUTP8Icef1DsX6V09DJn2%2BbteOS%2BR%2FxYUrzzL1qGc1ec4733aJnmYw89jvLSCr%2By6d577YNXvc8ReobS8%2BaT9z71ixcVHYkVl67AaUsXi%2FPEcvWPq7Fp3WZEx0Z50%2Fsl4h9MgAkwASbABPo5gYAXANOGpuGxZx%2F1TvCpP2jiGhMXi6tvvhpkVcsTaIN1QmK8V2Ch86RFOvO8MzFjznRPNPGtM%2Bi9b6Q9F2bOnYn4hDjPT%2FFNk5K0oYP9zqWkpWDl5SthaqddGzQkzSt4UgLSNlx42YUwm0x%2BEyKZXO43EaMJZvrwDJDA5RuoPcMPTrw951PTUnDRFYeXHREV6Tehp4npwkULDktPmr%2BhGUM92YlvMixCb%2F3bC0yjx2V6J%2BkUUavV4PLrLj0snkarhV6v9%2BZJk0hysEyTL9%2BgVCmRlJrkV8%2BRmSNw1Y1X%2Bi3Fov6NjffvB9JELjnnDEyfNdU3S0RGRyHOp8887R6ZOfKwPW6paanesqkM0uq2Z06Zk3aKNMSeYAwLxeIzF2PC5PGeU%2BKb2m3w0TrRyUlTJ4pzvhGpv6ls30Dai%2BWXLEdzo7%2BAkpSa7JdeIVdg%2BUXniwksCabUvu4E0mhdecOVkEol0Ice6jNq7wWXLheaaN%2BXFfKDmnJPmTRWM0Z0PFaJuW%2F9qK9JOLe005yGGo1%2B8aiN806eh8HtrHJRn5Ow6BtI2DKGG4XA6nt%2B1JhR4kWR5xyNwcuuvfSweHTf%2B2rziQfd93EHBUJPerrvE5MS%2FOpJVlOvWXWN37iiezTaR1NN6Sn%2FM84%2BHVOmT%2FZkJ75prNLY8gQagwsXnSSebe33Yw7xaTfFo%2Furo7EanxgvtJSePEnb1VHZKrVa3L%2BeePRN9337PKm%2FyTiQb0hMThCCWVM7zTaNVeojT6C%2BP3%2Fl%2BWhqJI3%2BoRdeUqGti%2FdEE%2F1EL7%2FaP78pHvW3771HzwF6%2BUaCum%2Bg55jvWKNxOWPODO%2BLE09cdUgIMkake36K71FjR2PVnTeLFSDEjwMTYAJMgAkwgYFGICgcwdPbXfoD7%2FsHn942t1%2BCSZ0nlbRpODwdSRMReuPsarfEkCZVJKDRtydQPKfrcLPMMqnMu8yJ4lLZtCTJd5JD5ymeVCb1y5Pq3j4exaVJjl%2FZTudhy5xEnjKZnxDWWdnt201padlYR%2B0mjsTTE6gt7ZdYdVQ2tYPa0z60Z0nxXE5XhyyJuW8%2FdlZ2%2B%2FZQnh31I8Uj5r55dtRuqnP7sjtrz7GW3b7dVEZ3xxCVTUvqfMeGZwy1HzPt%2B%2BFYf4u%2BduOYx2p7bp31GY0p33HV2ViltvlO8jvjRvF4rLb16pHGqu946ew%2BoVzaj59O%2B%2FEYn3dHGqvtx2L7MdTZ8%2FtYn7XdHUNUvufZ4Xuvta83%2F2YCTIAJMAEm0N8IBIUfwP4GndvDBJgAE2ACTIAJMAEmwASYABPoCwIkAHZvPVlf1JrLZAJMgAkwASbABJgAE2ACTIAJMIEuEWABsEvYOBETYAJMgAkwASbABJgAE2ACTCD4CLAAGHx9xjVmAkyACTABJsAEmAATYAJMgAl0iQALgF3CxomYABNgAkyACTABJsAEmAATYALBR4AFwODrM64xE2ACTIAJMAEmwASYABNgAkygSwRYAOwSNk7EBJgAE2ACTIAJMAEmwASYABMIPgIsAAZfn3GNmQATYAJMgAkwASbABJgAE2ACXSLAAmCXsHEiJsAEmAATYAJMgAkwASbABJhA8BFgATD4%2BoxrzASYABNgAkyACTABJsAEmAAT6BIBFgC7hI0TMQEmwASYABNgAkyACTABJsAEgo8AC4DB12dcYybABJgAE2ACTIAJMAEmwASYQJcIsADYJWyciAkwASbABJgAE2ACTIAJMAEmEHwEWAAMvj7jGjMBJsAEmAATYAJMgAkwASbABLpEgAXALmHjREyACTABJsAEmAATYAJMgAkwgeAjwAJg8PUZ15gJMAEmwASYABNgAkyACTABJtAlAiwAdgkbJ2ICTIAJMAEmwASYABNgAkyACQQfARYAg6%2FPuMZMgAkwASbABJgAE2ACTIAJMIEuEWABsEvYOBETYAJMgAkwASbABJgAE2ACTCD4CLAAGHx9xjVmAkyACTABJsAEmAATYAJMgAl0iQALgF3CxomYABNgAkyACTABJsAEmAATYALBR4AFwODrM64xE2ACTIAJMAEmwASYABNgAkygSwRYAOwSNk7EBJgAE2ACTIAJMAEmwASYABMIPgIsAAZfn3GNmQATYAJMgAkwASbABJgAE2ACXSLAAmCXsHEiJsAEmAATYAJMgAkwASbABJhA8BFgATD4%2BoxrzASYABNgAkyACTABJsAEmAAT6BIBFgC7hI0TMQEmwASYABNgAkyACTABJsAEgo8AC4DB12dcYybABJgAE2ACTIAJMAEmwASYQJcIsADYJWyciAkwASbABJgAE2ACTIAJMAEmEHwEWAAMvj7jGjMBJsAEmAATYAJMgAkwASbABLpEgAXALmHjREyACTABJsAEmAATYAJMgAkwgeAjwAJg8PUZ15gJMAEmwASYABNgAkyACTABJtAlAiwAdgkbJ2ICTIAJMAEmwASYABNgAkyACQQfARYAg6%2FPuMZMgAkwASbABJgAE2ACTIAJMIEuEWABsEvYOBETYAJMgAkwASbABJgAE2ACTCD4CLAAGHx9xjVmAkyACTABJsAEmAATYAJMgAl0iQALgF3CxomYABNgAkyACTABJsAEmAATYALBR4AFwODrM64xE2ACTIAJMAEmwASYABNgAkygSwRYAOwSNk7EBJgAE2ACTIAJMAEmwASYABMIPgLy4Ksy15gJMIHOCBRv2Y49X38Ph9XeWZQun3e7XGiprIJMpYImPKzL%2BXSW0FRbD6fNCn1sDCCRdBatS%2Beddjtaq6qhNhig1Ou6lMeRErVUVovLupioI0Xr0jVrczOsTS3QxURCKld0KY%2FOEvWHPp1x0zVInDAG5Tuysf2DTztrKhLGjELmsqXi%2BpY330PV3rxO4068%2BHxEZQzt9DpfYAJMgAkwASYQzARYAAzm3uO6M4F2BH57%2BkWY6%2Brbne35n40lpT2f6cEcW6prTljerbV1Jyxvyri5svKE5d9aW3vC8qaMg7VP1z36JE76802o3rkb5Vm7OmUkczmROChZXK%2FYloXKvIJO49ZszoCsqRnhk8Z3GocvMAEmwASYABMIVgKSnLJsd7BWnuvNBJiAP4FXz1juf4J%2FMYEBQGB0VAQaLFYUN7d02tpQlQrJhjbt7%2F7GJjTbOteSx%2Bu0kEulGHzdFYgZkXFCNN6dVpQvMAEmwASYABM4gQRKssvAGsATCJizZgJ9RcB3sttTdcirb4DZ4RTZZYSHQSnruS3EjRYrig5O3mM1GkRpQ3qq2iKfnJo6ONxt77pIWOjJUNbcilqLRWSZYtDDoFL2ZPbYWd2m%2BeM%2B9cfq26d0xahWiY9%2FrI5%2FpYYaOr5w8CwJk0VNzSh69EksvO9OFgCPSIsvMgEmwASYQLAR6LkZXLC1nOvLBJgAE2ACTIAJMAEmwASYABMYYARYABxgHc7NZQJMgAkwASbABJgAE2ACTGDgEmABcOD2PbecCTABJsAEmAATYAJMgAkwgQFGgAXAAdbh3FwmwASYABNgAkyACTABJsAEBi4BFgAHbt9zy5kAE2ACTIAJMAEmwASYABMYYATYCugA63BuLhNgAkygPxAgK7QqSHrcYmx%2FYMNtYAJMgAkwASZwJAIsAB6JDl%2FrMQIulwuvv%2FiGX34SiQQarQYZI9IxZvwY0O%2BeCBaLBWq1WmT11qtvI3PsaGSOz%2FRmfbTr3og9fLAnew82%2FL4REqkEcxfMRXJqUg%2BXwNkxgYFDQCaVQiqRQq%2FsWbcbRFAhkyJUqUTYpHHQhBsHDlRuKRNgAkyACQwIAiwADohu7vtGul1uPPbQ40Lg0%2BnanDG73C60NLfAYrZg6syp%2BPd%2Fn4dKpepWZf9y%2B31ITUvBlTdcIfJ56tGncfVNV3kFwKNd71bhR0j8yvOv4p9%2FewLjJ49HY0OjYPHki0%2FgpFNPOkIqvsQEmEBfENAqFNCGKjDprlv7ongukwkwASbABJjACSXAewBPKF7OvD2BS6%2B5BL9u%2B0V81m7%2FFVv2bcI9D92N9b%2Btx3tvvN8%2B%2BnH%2F%2Fv6r7%2BE%2B6PCbEn%2F47fs478Jzvfkc7bo3Yg8e5O8rwOMP%2FxP3%2F%2F0%2BvPXpm%2Fjif59h6XlLQcKo2WTuwZI4KyYwcAiY7Q40Wq3YWV07cBrNLWUCTIAJMAEm0AMEWADsAYicRdcJSKVSrLz8QkRGR2L97%2Bu9GZFm8NsvvsXLz72CN196Ezu27PAT7LK27UTe3jzs2pEtlpbm5uRizc9r4LA7kJebLwRKyqz4QAmaGptEvke77imc8nzntXfx5sv%2FBeXrGyi%2FTes2wWaz4bsvv8crz7%2BCH7%2F5CU6H0zea3%2FGXH3%2BJsPAwryBKS11v%2FNP1aKhvwG%2Brf%2FeLyz%2BYABPoewItNjsKG5rw7b0Po3rvvr6vENeACTABJsAEmEAPEuAloD0Ik7PqGgGX0yWWgRrD2vba7N65G5effyV0eh2GZAxBSVEJHrn%2FUVy76hqsuvNmUchzTzwPm9WKLRu2wm63C%2BEqd88%2BWK1WrFu7TiyzpGWlt117u1gCetWNV%2BL5J%2F99xOuUz10334PvvvwO4yaOhdlswSP3%2FR2XX3cZ%2FvSX26Sla9gAACAASURBVMUexV9%2B%2BB%2FeeOm%2FCI8IQ31dA6jO2VnZmDFnOl5%2B96UOAeTsysHwUcNBwq4nxMTGINQYil07dmHh4gWe0%2FzNBJhAABBwuFxosdvRkrULlqbTAqBGXAUmwASYABNgAj1HgAXAnmPJOR0DAdoL6NGWOZwOVJRV4N9PvSj2Ai5cvFDk8OgD%2F0DKoGS88%2FnbkMllQvN3721%2FwRsvvYmb77jJayxm%2FW8b8PTLT2HOgtlobWkVWrZJGVNw0RUrQQJf%2B%2FDel%2B%2FgSNfJSA1pHd%2F46DVMmjZJJH%2F39Xfx4D0PY%2Fykcd79emUlZTjz3CW46c83irq8%2Fdo7ePjev2Hfnn0YOmxo%2B2JRX1eP1LTUw86TVrC2pu6w83yCCTABJsAEmAATYAJMgAmcKAIsAJ4ospxvhwReePLfoI9vIM0YadnmnzxPnP77U48IwYqEPwqkmYuOiRb75ehYedDqX3xivFd7pgzvviXArz79GnMXzPEKf1T28kuW4%2FX%2FvIkvPv7SKwDS%2BcuuvdQriM6aN1PUs7y0vEMB0GKxQq44%2FFajc9QeDkyACTABJsAEmAATYAJMoLcIHD4r7a2SuZwBSYCWO556ximi7RKJFKFGg1geSdowT6Djj979WOyPO1BwAMUHiqFQKsRlXwMvPe1GgZaazpo3y1MN8U379YakDwZp%2FTyBBFO9Qe%2F5CeVBy6Uul9t7zvcgRBMCi9nqe0ocWy0W6PTaw8731gltWirCp0yE22aHqaQUdRs292jR%2BpHDkHDGIhS%2B%2Fg6sFZU9l7dUiqTzz0bElIlwtLSi%2BMPP0LhjZ4%2FlHzZxHBKWngaZWo3Sz75GzW%2Freixv34ySlp0Fh8mM8q%2B%2B8z3d7eO0ay6DKipC5FPy8Zdoztnb7Tx9M9CnD4Fh1AiYS0rRkJUNl8Xie7lLxzKtBum3XA%2F4eIJpLSxC0dsfdCm%2F9on0wzOgH5oGW10DQhLjUPbld3C2mtpH499MgAkwASbABAYEARYAB0Q3B04jaYnk4jMXd1ohEvBWXX0rNq%2FfjAsuXYGzli3F8FHD8MeadXjgrgf90nkEL7%2BT3fghl8vFvsL2WZhMZoRoNN7T5HvseEJCYgKq2glA5BexurIG8Qlxx5NVj8WlCXfaVRcj%2B%2F6%2Fw2WzYdhdt6G18ACsVdU9UoZUqYCjoQnatEF%2Bk%2FqeyDx88gS05Oah7MtvETN%2FNoZcfyWy7rgP9sbGbmevDAsD3G7s%2BsvDQjhOu%2FJi1G3cDJetZzW1%2BuHpIEGz5o8N3a6zbwaGkcNFP9Zt3CJOt%2BzL973c7eOoubNAdS948TXA5ep2fp4MjOMyUbtuIyyVVYQfoSOGwd7cZrzJE6fL31IpUleej51%2FeUj0LXGPX7IYxe9%2B1OUsOSETYAJMgAkwgWAmcHwz2WBuKdc9KAiQpo2sdd52z624%2Fd7bcMrpJyM5NRn5uW0TWdpDeLTgqyXsKG5n14eNzMDmDVv8rI3S3kIySkPGaLoaJkwZj%2Bys3WKfoiePXdt3gRzST5wy0XOqV78jZ0yBubRSCH9UcPPefYg9ped8EpLAZC4tg9PU81qW1gNFqN%2ByHc6WVpR98S0crS1Qx8f2CD9bfb3ImzJr2L4T9uZmuI5g4bUrhco0GoSOHIGGHbu6kvyIaWJPmQ9LRRWasnPQsC0LbofjiPGP56I%2BYwjiFp%2BM%2Fa%2B93aPCH9WhMSsbVf9bg6bsPWjevQfKcCPqN207nup1Glcql0MZGQF1XNsYkeu0cJm7r7XstEC%2BwASYABNgAkwgwAmwABjgHTTQqkdWNWmJ5bZN2%2F5%2Fe%2BcBHlW1teEvM5OZSS8QAgRC70Va6FWpKvYCVkQRwS6o13rvVX97vVbsig0VUHqTjoAgVYpIL6GkEFJnMu1%2F1k5mmAlpJCdhknzneYbT19773cPkrLOaKrUgCWNm%2FTwLP0zNqxEoSlNxS3BwMDZv3AwpE1HYUtz5O8bfAcnYKQXbM9IzkHQyCU8%2B%2FJSKPbzp9lGFiSvVscuuuhRGkxH%2FevBJpKak4vDBw3jm0X%2BjY%2BcOngL1pRKk4UWhzZv5WMxyU08jKL6Bhi1UnCjr8QLupC4g%2B%2FARzRuMSuiM%2FR9%2FpbmyU2%2FEECTOXaR5f43iRu1yodndt6P9%2Fz2L0GZNNW0j7torcXrTZsT07Ym6lw6FwcsNurwN2dMzPCICAg0whIVCvpPFLUGBBkSYTOiQ7%2B5a1LVi4T61dAVaTb4f0QldEBRXH4lztXW7LaptHicBEiABEiABfyRABdAfZ6UG9ykkNATPvfZf%2FLZwKbo074ZOzbpg2tQf8fbHbykq2zZtK5bONaOuxvLFK3DTFTermoAFLy7u%2FMAhA%2FDCm8%2Fj5%2B%2Bmo3vrnujfeSD%2B2b0Xn3z3cbksgKLUvvf5%2FyB979OhH4b1HgGz2YR3Pn3Hk0imYD8rej8wNAQOryL0TrsNxsiIim5Wc%2FkSi5a0YrXm8Vyxgweh0ajrEH%2FTddAFnXX%2FLe8ARAE589cOOHO0t4yKwrTnrQ%2Bw5ZEncXrTVjS%2F%2F27N%2Bi4uw2HNm8J6KgXJazdAvj9tnpwEcfXVeolo30ZZBLWUe%2BTHmcg5chRN7x6j3IddtuIto6GBgWgcEYbhzz%2BFmHJY%2F7UcA2WRAAmQAAmQgFYEGAOoFUnKKZaAWPV2Je4o9hr3yWtuvBpiNRN30PDwcNTKf8Pvff%2BUqR%2B6L%2FdZS53AOyeOVccky%2BaGv31jrEo6f%2B2oa3DVdVfi8KHDMJvNqFu%2Fro%2BSdtu42yAf76VuvdgSxyZlJZZuXIKD%2Bw8hJCQYsfVifeR6y6uMbXtWNgLys6xKe3qjEU7ruYlqKqMvZW1DZzIhokM7HJk2vawiirzv5JJlSNnwJ9o8ORm1eyfg1G8riry2tCcCoyIR2akjTi1fhdAWzZTCrTcZlWui5fiJ0oop8Tpxv5X4tpCGcQhr3gRntpfu%2F11xggMj8l4OpPyxEY6sLBz7ZQ5iBvZFWKuWmsj3bju6axccmf6r96FCt6VWXwBcOGPNRYSp%2BCzA9UcOx4lFS5H651alBLqcTo%2Brb2HCDXodwvRG1O%2FUobDTPEYCJEACJEACVZoAFcAqPX3Vt%2FMmkwlNmjUp0wClgHxxS0nnRVkta9vFtavX69GshbZuecW1V9y57GOJMNeJ8VwSGBmJ7ENHPft%2Bv6HTIXboIKWIaJmMxHvc9jPpSF23AbrA4pUL73uK2zZGhkOU1rrDBqvLguPjVIxeZKcOOKGhAujuQ8Y%2F%2B%2BHUKAbQnpHnomkIClKxl6JkWpNSAJ22TiTi%2FqkPDYHtdJp7GEWubQ4n7C4XDqdnFOsGKsprrV7dVbyoCNMbA1HvsqHFKoBFNlrEiaLiir0vl4zCXEiABEiABEjAHwhQAfSHWWAfSKCSCaSsWY%2BWk%2B4H5KHU5UJI00Y4Pk%2F7uDQZVoB3bn8txqnTod6IwUhasQbOnBzlhhjerjXSioj7LE%2BT4vqYsm5DeUR47pWyBnvfm%2BLZj7%2F5BtizsnBi%2FmLPsfJs6MxmFa8oMW%2BimOmDg5S7Y3lkuu%2B1Z2SqBC1iubQmJSv5AXodMvKTM7mvK%2B86ol0bzS2K0idRLN3f9ZQNmxDV%2BaJiu5pmseJIRia2jxyFIc8%2BjoYJnc%2B5XjL5Oh1OuOCCbLsXjzLoAqxWK2y5NmXtlzjg4JBgSN1TKoNuWlyTAAmQAAlcCAJUAC8EdbZJAheYgDzEn1y4BA2uvRKS%2BVKygGbs2qNdr3Q6RHXuCENIMKITOuPkkhWaZQSVOnfRqlbf5eqhPkCnw8Evv9Ok71FdO6Hh6GuRvHItXE6HqqGnpXumJp0sQkidgf0QO3QgUjdshiNH6gsuhMvhKOLq8z984PNv0HjszRBlMKRJPI78%2BIvmsYxRXTvj6M8lu3%2BeT%2B%2BlPMjJBb%2Bp73ra1u2QlwWHvv%2FpfEScc63D4VDJoZ546CmkJqfAbrfDYslzoRaFL1eU8AKLKH33PDReuZjr9FQCC%2BDhLgmQAAmQQCUSoAJYibDZFAn4E4FTy1ZBShKIgU7zotj5MVYbxz2g%2BZD3f%2FgZ9msuNU%2BglJfI3HtAxUeqLJRSlK6CFq2KnLu7d2LBYqSs3wCnzabcNN3HtVrLi4I9b74PY1Qk0nf%2FjZISqZSl3cRZ83yy05ZFRmH3nFyyXFkBDaGhSPx1nrJ6F3ZdaY6Jhc9djubioYPw%2FpsflOY2VV5m%2B%2BbtKr7ZqDPSClgqaryIBEiABEigIghQAawIqpRJAlWEQEXU6asiQy%2Bym1oUlC9SeAWfKE3sXLm64HKVWJ6hPPKVe2l5BBRzryisWvARS564fYoVUGp8Nm3eBPv3Hjin5QbxcagTWweSjEqn00MyHI%2B85vI8t9EKfLFwTkd4gARIgARIgAQKEKACWAAId0mABEiABEigOAIS15oXy6fD1TdehTdffFtZ%2BLzvOZF4Ek2bN8XAIQMRXSsaIaHBCAsLYwygNyRukwAJkAAJXBAC2qZwuyBDYKMkQAIkQAIkUHkEAnQBMBgMMJoCVcbgbj27ntO4xAWuXLoKr7%2FwBtauWgu93qCsgXIvFxIgARIgARK4kASoAF5I%2BmybBEiABEigTAR0AToYAnSIMGpTpuN8OiHWv8DAQFUrVDJ7imunrGXR63Xo3jsBQcFBaj87KxvTpv6Ipyc9g3Wr1ysXUJU9lG6g54Oc15IACZAACWhIgAqghjApigRIgARIoHIImAw6hBgDER8RVjkNerUicYCSyVPqlQYFBaFWTG0MvWyIusLhcCItNQ0PPnY%2F%2Bl%2FSX1kK5UTi0URlDXz8gX9h5%2FadsEmyHofjHNdRr2a4SQIkQAIkQAIVQoAKYIVgpVASIAESIIGqSiDSbFLF5cfO%2FqHQGoAyLrECihuoOciMkJBg9BvYF%2FUb1FdD3rP7H5w8cQqXXTkCk59%2BBF0SOnuyfu7cvguTJj6KF595CUcOHaEiWFW%2FJOw3CZAACVRhAlQAq%2FDkseskQAIkUFMJWO0OZOXacCAt%2FYIhECugu8B7WEQ4rr7hKk9f5s6cq5TDuIZxuGXszXjgsftVxlC5QEpJrF6%2BBhNuuxefvveZshhKzKAUlPcUkvdI4gYJkAAJkAAJaEuACqC2PCmNBEiABEigEgg4XS7YXU5k2myat5brcOKMNRcHVq9DdurpIuUrK6De4IkFbNO%2BNbp276KuP3UyCVmZ2QiPCEdEVARatG6B%2BybdizvuGYM6sTHqGnEDnTFtJu4aPQ4zfpgJiReU%2BEBRBLmQAAmQAAmQQEURYBmIiiJLuSRAAiRAAlWSQLbNhiMZmTj8ytsY8uzjCI6OKnIceoMeBqcBQUFm2EJDcf3N1ykrXp26sWjUNF4ph6LQiatoTnaOUhBbt2uN31f%2Bjt%2Fm%2F4bMzCxkZGTik%2Fc%2Bxbxf5%2BG2u25Fn4F9EGgIVHGGEm%2FIhQRIgARIgAS0JEAFUEualEUCJEACJFDjCEgsoCSECQl1oG79urh30kQYjUal%2FMlxcRU1281qPyfHApPZhEuGXYzuvbpjyfwlWLVsNcQF9NiRRLz071fQtkMb3HXvXWjdrhX0ej1rB9a4bxQHTAIkQAIVS4AKYMXypXQSIAESIIFqTkCVhTAGIhjBKjGMZPcUxU3iA6VchDthjFgLZd9kylcOzWZcdcOV6NW%2FFxbOXohNGzYr66FKFDNhMvoN6ovb774N9eLqURGs5t8hDo8ESIAEKpMAFcDKpM22SIAESIAEqiUBUfhghFIAnS6nyvrptt7JgMWVU6yCcswQaFCKoNFkQo7JqKyHt9x5C%2FoO6ovZ02dj%2F94DShGUQvJrV63DFdeOxKjbb0RYWJiyJopCyYUESIAESIAEykogYFfiDldZb%2BZ9JEAC%2FkXg85GjVIekQLbZoNe0cxIX5U5NEWwwQKdhbJLd6YTF4VD9Ner0MOq1fcDNstng%2FqELDQzUlIvFboc9v6i3WR7uNX44dyc54Zz6Tltp5jQkMBB1QvIKsp%2FIzEaO3e4rxGsvNiQYwYF570T%2FSU3zfB8lBrBhQmevK0velEyexcXuyXmJCxS3T1uuDZYcC7Kzc2DJkY8Ff23dgTkz50ASybiXsLBQjB4zGpdddalyJRW30uLacN%2FHNQmQAAmQAAl4Ezi6IxG0AHoT4TYJVHECOr0eTocjPzuiW13TflDZxTxIl7e1XKcD8qmoxa1QVYR8pcTmK7Jay8%2FLeMk59eaqQwCccBWZCTSodjSiOnVUtxzbuBmZScnet%2FtsN2rWBFF18rJzWuYvPntOd%2F5JWEpSzOS82zpo0BuU1VDcRS1BJpUJtHNCJ7Rq10olilm6YKlKEiOJYj5%2B9xPM%2FWUuxowfg979e6n7xBpYUntnB8MtEiABEiABEgD090269z8EQQIkUD0IWDOzkLxnn1Qaqx4D4ihIoBgCLhSvnNXt0gldHroH0QldcHjLdqQnnihSWqdxt6PJVZeqazd%2F%2F7O6LjK%2BIbrcdD30GluN3Z0QxU0UOLHmqfhAQ6ByDZU4QVEQGzZqgIReCcod9Ojho8pqmJGegVVLV2HLxi2IbxyP6NrRSgGkEuimyjUJkAAJkEBxBNKTMkAX0OII8RwJkAAJkAAJVBIBSR4jH3ELtVqtqmyElI6QzKGnTpzEonlLsOmPTUohlC6J0jfgkv64bdxtqB9Xj%2FGBlTRPbIYESIAEqjIBcQGlAliVZ5B9JwESIAESqFYEVHygwwm7w45cay6sFqtSAHOys1V84MH9BzFn5lyVKMY9cLEYXnHdSIy%2BfZQnUQwtgm46XJMACZAACXgToALoTYPbJEACJEACJOAnBNyKoM1mg3yys7OVRVCSxIhSuGPbznMSxYRHhCslUBLFSK1BcSPlQgIkQAIkQALeBKgAetPgNgmQAAmQAAn4GQHJFipuoXab3eMW6p0x9PdVa7F04TJIbKB7aRAfh7H33KHqC0qMIRVBNxmuSYAESIAEqADyO0ACJEACJEACfk7AXTZClEHlFmq15pWOyMqGxWJFRno6li1aDqkbKKUl3Eu7jm0x7r5xaN22FeMD3VC4JgESIIEaToAKYA3%2FAnD41Y%2FAnsXL8NeMOXDYbJoPTspLWDOyIKUmTGEhmsu3ZmTC6XDCHB6KAI1r6TlsduRmZcFgMiIwKK8unFYDkIdzS771JSg8HCUkpjzvZm3ZObDn5mLkm%2F%2BHqPgGOLx%2BI9Z%2F8nWRchr26Iqe425X51e98xFObN9Z5LV9HxiPeh3bFXmeJ%2FyLgFsRFCVPFEH5uK2Bkigm6VQSFs9bgj%2FX%2F%2BmTKGbQkIGQQvNMFONf88nekAAJkMCFIEAF8EJQZ5skUIEEpt5wB2w5ORXYAkVfKAJxDeLQ9uJ%2BOHHgELavWltkN%2Bo2jkeH%2Fr3V%2Bc2%2FrUDyseNFXtvp4v6o374N6g4ZVOQ1POF%2FBMQS6HK6YLPbPIXkc3JylDKYa7Hi4IFDmDtzLvb9s9%2FTeXeimFG33ehJFCPuoVxIgARIgARqFgEqgDVrvjnaGkDg85Gj1Cj1CIBRr%2B3DnRQ5d1cXNOulBe0WuzzMuvKKnBsCdAgsQ%2FHt4nqT41WcPUjjxBi5DifcZIw6PfRaggHg7nuEyYT48FBk5ObiZGZ2kcMNNRpRNzRYnU%2FMzEJ2btHW4EizCaaoKNS%2FcgSaDeiLwCBzkXJ5wr8IiDVQWQQlY6g9Pz4wxwJLTo5KFiPWwcISxURGReKGW67H5VdfBpPJpFxDmTHUv%2BaWvSEBEiCBiiRABbAi6VI2CVwAAm4F0K0saNmFvafTkGN3KJGtoqM0VTDPWKw4nJGpZNcNDkZMiLZumruSU2F35amvHWJqaYkFiRlZSLFYlMxG4WEINxk1lb89KUXJq4g5PZ6ZheScvL7f8Nl7CK1TW9O%2BU1jFE3ArgqIEuhPFSKZQt2uobK9bvR5LFvzmkygmrmF93DnxTvTs20MliRFrIBXBip8vtkACJEACF5qAKICGC90Jtk8CJEACJEACJFA2AqK0yUdcPCXbpyHQAKPRqMpA5GSbYDFbMGDwAHTt0UVlC3Unijl2JBHPPfE82nZooxLFtGrbkopg2aaAd5EACZBAlSNABbDKTRk7TAIkQAIkQAK%2BBEQJFAXQXfbBrQiazWYYTTkwmYwYee1IVRpi4ZxFnkQxO7fvwiP3TMLAwQNw6123oF5cPSWDFkFfvtwjARIggepEgApgdZpNjoUESIAESKBGE3Argmqty7cImoywmE2QTKGiCN58x03oM6A35kiimD37VCzhssXLsXr5Glxx7UiMup2JYmr0l4iDJwESqPYEqABW%2BynmAEmABEiABGoaAbHgqY9eB4PeoFxETWYTLEEmVUOwZZuWuLdxPHZs24HZM%2Bbg1Mkk2Gw2TP9hBn5buBQ33noDRlwxHEFBQQjQBShZNY0hx0sCJEAC1ZUAFcDqOrMcFwmQQLUhINlFjUzZX23mszIH4q0I6g36PEXQZMqLETQZ0TmhM1q1a411q9Zh8fwlKlFM2uk0TPnfx5gzcw7unDAWPfr2UEqk3M%2BFBEiABEig6hOgAlj155AjIAESqOYE6oUGa55dtJoj4%2FAKEHArgj6JYkx5SWKMJhMGDR2Ibj27Ycn8JfBJFPPkC2h%2FUTuMvecOtG7f2hNnKC6mXEiABEiABKomASqAVXPe2GsSIAESKDeBkMBABAQFIzqhMwxBpnLLowD%2FJ%2BBWBGXttggGGo2wWkwqe%2BiV11%2BB3v17Y8GchZ5EMX9t3YFJEx%2FNTxRzK%2BrF1VWKoCiBVAT9f87ZQxIgARIoSIAKYEEi3CcBEiABPyOQZrHC6QIizdrWGJSahbFx9dH%2BvnF%2BNmJ2p6IJeDKG5ieKkeQwqnxEviIoiWL6DuyjEsXs%2FXsvE8VU9IRQPgmQAAlUIgFdJbbFpkiABEiABMpA4ExuLtJzc8twJ28hgaIJqEyhBr1S%2FCTZS2h4KCIiIxAZFanWLVq3wMSHJ%2BDOCXegTmyMEuROFDPupvH49edfkZOdA4fdAafTWXRDPEMCJEACJOBXBKgA%2BtV0sDMkQAIkUHkEUnOs%2BHvvAcx%2F6gVY0s5UXsNsya8IFFQEw8LDEBklimAEIiLDVaKYyc9MxrWjroGck0USxXz49hRMHHMv1qz8XWUQdTgcfjUudoYESIAESKBwAnQBLZwLj5IACZBAtSdgddhxJseCM9v%2Bgj3XVu3HywEWT8ATH6g%2FGx9okoyhJhMkUczAIQPQtUfXcxPFPPE8OnbugDF33%2B5JFCMuplxIgARIgAT8kwAtgP45L%2BwVCZAACZAACVwQAqIIBgYGwmgyIiQ0RFn98qyBEagVUwuSKObJ5%2F6lsoa6k8Bs27xdJYp5%2Ffk3cPL4SeUW6nK5Lkj%2F2SgJkAAJkEDxBKgAFs%2BHZ0mABEiABEigRhJQJSMMBpjNZoSGhSI8IhyRkeIWGoF6cfUgiWIeeOx%2BNG%2FVXPERhW%2FpomX4XVxC7TaVOKZGguOgSYAESMDPCdAF1M8niN0jgYoiENK0MaJ7dIMr14bso8eQun6jpk2FtWuNuJEjcODL72A9cVI72TodGt54DWr16AZ7ZhaO%2FPQLzmzdrpn8qG6dEXfVZdCbzTj2y1wkr16rmWxvQQ1vuBr27Bwcn7PA%2B3C5t5uOvwOmmFpKztHps5Gx6%2B9yy6SAmkvAHR%2Boc%2Bmgz88YKpZBcQvNybGgZZuWaNQ4Hju27VAZQ01mM3r165VnATS4AL5mrrlfHo6cBEjAbwlQAfTbqaleHZPkABPH3OczKHmwCA4ORut2rXDt6GtRq3a0z%2Fmy7OTm5iLxaCIaN22sbn94%2FCMYdvkwDB85TO2XdL4sbZ7vPW%2B99DYku97lV192vrdqdr0%2BJBhNx92GHf9%2BGc7cXLT%2B1yPIOnAI1lNJmrShMwbCnpaOkKZNAI3rRUd374rMPXuROHs%2BYi%2Fuj%2BYT78K2x56F7Uz5k5gYo6IAlwt%2FPf2CUo6b3nUbUv%2FYCKfG8XFhbVpCFM3k39drwtstJLxdGzWPqX%2F8qQ5l%2FrPPfarC1253P7dLYIU3yAYqlYBbEQzQBcCgNygXUZPZBJPZiByTEZ27d0H7Th1gtVhUjUD396GsnTx04BBefPZl3H3%2FOHTt3sUjRuROmvAosrKy8Oq7LytrpPvk0cNH8fxT%2F4fxD9yNLgmd3Yd91h%2B%2B%2FRFsuTZluZQTBf8m%2BFzMHRIgARKopgT4bq6aTqzfDcsFrPxtJY4fO47w8DD1CQkJQVZmJt57%2FX1cNfhqJJ0sv%2FJxw4gbsXjeEs%2Fwd27fheSkZM9%2BSec9F1bAhjy4fP7hF%2Fj43U8UhwpootQia%2FfpgZxjJ5XyJzdl%2FP0P6g67pNT3l3ShKEw5xxLhyM4u6dLzPp916DBO%2F7kFjswsJM6aD3tWJsz16563nMJuyD19WsmWc2lbtsOWkQGnXdvMhvrgYES0a4u0rX8V1oVCj0WaTIg0lVwDsO6wi2E5cQrpO3YhbfM2uOz2QuVpdVC%2B0%2FJyZ%2FeO3Zg88TFcM%2BRabN64hSUBtALsh3IkPtAQaFDxgUHBQQgPD1dlI6KiIxFdKwpxDePUOYPBAFEWy7qIi%2Bkfa%2F7AskXLfUTs27MP82fNx5oVa5SrqffJdavXqb8zDeMbeB%2F22T504DAO7j%2FkOVbwb4LnBDdIgARIoBoToAWwGk%2BuPw5tyKWDcf9kX0vg1j%2B3YtTIm%2FDlx1%2Fh0Wcml6vbx44m%2Bty%2F8Pf5Pvslnfe5WMOd1JRUvPLf1zBnxhz4g4UktHkzH4tZbupphLVtpeGIK06U9XgBd1IXkH34iOYNRiV0xv6PvwI0rm9Wb8QQJM5dhAbXXF7qPkeYjJCi7cUtxug862Wzu2%2BHPceC%2FR99gcx9%2B4u7pcznRPGTum9pqWn4YspXWDxvERyOvDpwyxcvR%2FuL2qnvuT9818s8SN5YLAFPxtB8hVBcQt1lIET5kyQy5Zl%2FKUrfrWdXbN6wyacfq5atRnzjeNSLq4uVS1dhxBUjPOc3rN2oXFJj8msWek54bbz8zotee0DBvwk%2BJ7lDAiRAAtWU1r7cMgAAIABJREFUABXAajqxVWlYF3W9CPUb1Me%2Bf84%2BrG7asBmzfp6FY0eOqSLFnbp1wk1jRquMdDK26d9PR2R0FE4knsDq5avVQ8CeXf%2FAYrFAHkDlQeSeB8fj7ZffQc%2B%2BPdGzbw%2B8%2FsKbxZ4XuVLU%2BPuvfsDWTVtVDEuv%2Fr1w3U3XqngXOb9x3UZItrvBIwbjyylfQlyO5GFk7IQ71BiK4v7IPZNw8vgpfD39S9xz28SiLqu044GhIbB6WVyddhuMkRGV1r5WDYW3b4ukFavhyNLW0hg7eJCKA7SmpmLXS2%2FDmaON%2FOiELjjz1w7N5HlzFCV%2Bz1sfQNxv4669Es3vvxvbnniu2Laig8yoXb8eGo%2B5CUGR4d7iitwWxc9ut6t4r6mfTEVGRqbn2mYtmuLSqy6F3WaHKAgsBeBBU203ZI7dc%2B1y5mX9FMufHCvvIrGEb738NqxWq%2Bc3WJS%2B3v17KUujvDSU76O7rT%2FWbsCIK4Z7mn3zxbcw9LKh%2BPWnX3Hq5CncOfFO7N2zV%2F22X3%2FzdYX%2BTZCbxVNl6mffYO%2Ffe5WLqbjrDxg8wCM3JSkFX386FXt271GKbvfe3SHyRAnmQgIkQAJVgUD5f6GrwijZR78mIAWFxf1TlEBZ5v4yDzdfeYtSxnr3743YerHKTfSJh570jGPRvCWQdOPvvvYe0lLP4NjhY55z3hvffvEdtm8pOkGI9%2FnkU8m48pKr8PUnU9GsRTM0bNwQb%2Fzfmxh7w50qTkTk7ty%2BE5%2B%2B%2FxluvuoW5OTkqOx30t%2Fbrh3jefvt3b57%2B6F%2FPYg5y2epGlruYxdybc%2FKRoDhbJ0uvdEIp9V6Ibt03m3rTCZEdGiHxDkLz%2Fvekm44uWQZtj31HHQmM2r3Tijp8lKdD4yKRGSnjpCH5NAWzZTCbYqOgrleye6rxzKycDwzq1TtiPvtke9%2FhiXxOMKaNyn2HpNej%2FCwUNTv1AHyHShuUe6edge2bd6Ge8fchw%2Fe%2FNCj%2FElxcMkI%2BchTjyAiIlz9X5Bxyj1cqj8BsfQpJdCgh96QpxBqMWpR9ORlwo5tO5U4eUG3cf1G9Lu4H%2FoO7ANRxPbs2qPOSey3vBCU4%2B5FlLhH730MK5euVG6fcv9v83%2FDwmJ%2BM0TelZdcjfVr%2FlC%2F16LUTbj9XuW6L3LlJeOt19yOtavWoluPrmjUpJF60fj4%2Ff9yN8s1CZAACfg9AVoA%2FX6KqlcHjx46qv5wyqjsdof6g%2F3t59%2Bqt7ijbr1BDVYsf5dddSleefdlz%2BAl7bjEznm%2F7T1y6AjmrJilEr7Ig6Y8hEybOg0DhwzEuPvu8tzr3pj89CPFnv%2FgrQ%2BRkpyKhWvmo3ad2uq24ZcPU%2B6p06b%2BiFvvvEUdO516Gv%2F79B2IO6ssPfv0wPhbJ2Drpm1FJh7o1LWTutZf%2Fsk%2BlghznRhPdwIjI5F96Khn3%2B83dDrEDh2EY7%2FM0dxF0z12%2B5l0pK7bAF1g8YqR%2B%2FqS1sbIcIjSWndY3vcmOD5OxehFduqAE8dPFHu73eWELd%2B6UuyFXicz%2FtkPZwkxgE6XC3aHA9aMTBhDghFQhNVG%2Ft%2BdOnFKvfxYvmSFVytATJ0Y9BvUV%2F3%2F2%2FTHJgQHB0EyQQYGGoCAgHK5Afo0xB2%2FJ%2BB2%2BRw4eIAm8y4ZRiOjIpUbqCR1%2BeP3P9RLhR69u0PiDyVxmFgEW7drjQ1rNyhvESlU773Id3fWsl%2BVdU7%2BTnz9ydee04X9TXjh6RfRsFFD%2FDj3B6XMysXtLmqHF576P4y85nIkHjuOA%2FsOYNbSX1QyLznftkNbLJq7SFkWRQHmQgIkQAL%2BToAKoL%2FPUDXr36zpsyEf76VVm5b432fvqNgNOT7lm4%2FUafljLW94xTX04P6DSvmz2WweN5vGTRt5sn26Hzy85Z7vtjxIiGunW%2FmT%2B8U9VeKZJIGNWwGU4wMG9%2FeIb9aymdrOOJPuOebvGylr1qPlpPvVA7pkvQxp2gjH5y2qkG4HaJ0GVKdDvRGDkbRiDZw5OcrlMbxda6RtLtrSW9aBSbbUlHUbynq7z31ZBw5j73tTPMfib74B9qwsnJi%2F2HOsPBs6s1kpw5LVFeJ%2BGRyksqUWJ%2FNkVjaSt%2B%2FEppvuwg2fvYfQ%2FBcf3vdYciyYOW0mvv3ye8h2wSXpVBJmTJtZ8DD3azABsdxJHGB5XYDFqtirX09sXP%2Bnct%2BU%2BL8uCV08oQB9BvTB6uVrVKZQif9L6NXN8%2FfBjb%2FPgN6eYyX9ncjKzFKK5E13jMauHbvdItCoSbz6%2B7N29Tr0H9RPuX1KhukbbrkefQf1U1mmvV1PPTdygwRIgAT8lAAVQD%2BdmOrarTHjb8edE8aq4Ym1ISw8VL219R7v4YNH8Nrzr6ssb%2BKyUye2Dmrl1zXzvk6yxGm5pCSnoF4h2STr1q%2Fnk7VTZcDzcpfTG%2FL%2BG1UlbzdrUjJOLlyCBtdeCcl8KVlAM%2FJdqTRhqtMhqnNHGEKCEZ3QGSeXrNAsI6jUuYtWtfouz7Mw6XQ4%2BOV3mnQ7qmsnNBx9LZJXroXL6VA19CwlWOc0aVgDIXUG9kPs0IFI3bAZjhypL7gQLkf5MpiK9URcnU%2BnpinrhgbdpIgaQEBeFEiJCFG43PF5ZR22xAG%2B%2FsIbSgETBVBi7dxL30F98dTDT6sYwQ3rNmD07aPdpzxrd2iB50AxG%2FI3QJafvvkZM37wfalhDjKrpEfygvCT7z7Gu6%2B9i5f%2B%2FQrw71fQsFEDVXpCyhlxIQESIIGqQIAKYFWYpWrUx%2BCQYB8LW8GhSbzHuJvGIdBoVG6W7Tq2RVR0FCRWT1xwvBedXltXm9CwUEi2zoJLanIKwiPOJsjQ3KJVsMFK2j%2B1bBWkJIEY6LROoiKZM6VUw8ZxD2g%2Bmv0ffoaz6YK0FS99ztx7QMVHSlIVsY5W1HL42x81FX1iwWKkrN8Ap82mSmSUV7hY4J0Op7LkXHXDlejQuQN%2B%2FOYn7Pprl49oeREjcVfyf9ug1ys30vI%2B9Ps0wJ0qQSBP2QuA0WRScXJiAXQFlv%2F%2Fj1gA08%2BkK%2FfPwwcP%2B8T4SYy4eIVIqQh5cSjWvoLL%2BXwXpTSRLE%2B98CRuzA9JKChP9nv06Y4efaZCwgF%2BX7kWEiLw9KRn0aJ1S3Ts3KGwW3iMBEiABPyKABVAv5oOdkbiK%2BQP%2BfOv%2F9fnD%2F261XkFs%2BWBtLhFHkLEalHUUtx5CehfsWSlengxizsdoIrKb928DRMevKcokVX6eEXU6avSQACf8hhVbSy202madtmFvAd4UQYl3uqmMaNUIqRFcxereFlpTDImzv91PoZfMRwS62ow6DWJ%2F9J0IBRWsQTyYz3lBYDE5mmZAKhBfAPI57MPPlffQYkLdC%2FynWzTvg2%2B%2B%2FJ7SOmH5q2au0%2BVeu39NyG6djTiGzdUdQbFvVPOySK1LR%2B773G8%2Fv6rSE09jeeffAG%2F%2FjZTvZyUePVOXS%2FC4B5DIXHpVABLjZ4XkgAJXEACVAAvIHw2fS4Bqe0kf9S%2F%2F2oaGjaKh16vw8xpv0AK%2FMqSmZGpHjDOvTPviBQjlqyckrlN3E0LLsWdv%2FeRibj%2B0htx1%2Bi7ccc9Y1S8k2QZjYmpjZvH3lRQFPdJoFoTkIdfsZ6IJUdeiOQG56qMjPLAHd%2B4kSqJIiVYrNZcZGZm4efvpkPisO6ceAdqxdRWkZ%2FuB%2BhqDYqDUwTU90Wvh8lkPFsIPl%2BBKi8isQL%2B9O3PuOK6K85xKRXr8yfvfQqxUpfl%2B1bwb8KkpybhwXEPYdKEybjqhquQlnoab774NmJia6P9Re0hWaslVnDimPtU%2BR%2F5%2FzH106nKS0T6yYUESIAEqgIBKoBVYZaqQx8DgG49u6FBwwbFjkaKB0sSGIn5mDRxMsLDwzHs8qHqbevjDzyB%2FXsPqDe9LVu3KFSOFJL%2F8O0pmD1jDm4ZezO6dO8C71jB4s7L2%2BNpc77H%2F159F%2F9%2B7D%2FqoVdcih549H6ViU4ajK1XV43Du3GjMVAdi4wuXR29gn3ylsVtEvAnAqIAyv9JsepIRk%2BDIRCBxkD1gkXirzp26YgVS1YoC4lYCQ8dOIQVv63C2AljoNfREuhPc1mhfclX9HQ6%2BY7kFYGX7835uF8W1z%2Bp5Xdg30FcduXZou%2Fu6yVxl1joRow8W%2F%2FPfU68OuSlovfSonUL5TbqPlbwb8LQy4bg42%2BnKKXyiQefVIqdHLt30kSVFVTi0b%2F6%2BQtVgkjCEnJzc5Xl%2B9tfpiK6VrRbLNckQAIk4NcEAnYl7ii%2Fk75fD5GdI4GaQ%2BDzkaPUYCNMJsSHh2o68L2n05Bjz0sq0io6Cka9dmVEz1isOJxfULxucDBiQoI07fuu5FTY8%2BP5OhSSUKg8jSVmZCHFkpcds1F4GMJN2pSNcPdpe1IK4kJCEG4ywaDPc0lznyvvWmoLJudn9iwqC6iKBcwv%2Fp5rzUV2djays7KRlZkNS06Oepg%2BnngCC%2BcsgtTSvH%2FyfejSvbNK7iQFwctilSnvuHj%2FhSGgrIABOrjnnXN%2FYeaBrZIACZBAcQSO7kgELYDFEeI5EiABEvADAga9TnPlT4alE6ueTg9dkLnIGoDyEC%2Fp%2FMWaI1Y9sfAYjUZlIVeKYFa2Kscy4aHxCAoOVoXg3a6jrInmB1%2BeSuzCkUNHVUyoJEnhQgIkQAIk4L8EqAD679ywZyRAAiSgCOTaHcg1ODW1uorg2JBgNG7ZHO2ff6pE0koRlAQv4uYXmKcESsZHSfdvtVjhcDhU7Jcoi%2FJxW4FKFMwLqjQBsRBv2rAZM76fgT%2FWbkBkVAS%2Bnv4VpGwCLYBVemrZeRIggWpMgApgNZ5cDo0ESKB6EDgubpcOh%2BZuvedLx9saqAvQqZgoiYEV11CH0wE5JgqhKIhaxX%2Bdbx95feUQkNi35YtXYPr307Hvn7OFWaRm5NJFyyBxc2ItphJYOfPBVkiABEjgfAhQATwfWryWBEiABKoRgWybHRnJqdi9YAmaDeiLwKC88iclDdHHGqg3KMufpP6XRdw%2BlQVQowyQJfWF5yuPgFj7JBPz7Olz8OvPv3pKgbh7ENewPoZdNgxdEjqrjLH8HrjJcE0CJEAC%2FkWACqB%2FzQd7QwIkQAKVRuCM1YrktDM4%2BP6naNClU6kVQHcHxcqnYgNdeohyIIsoh7T6uAlVj7XM7dHDxzDjhxlYPG8xLBarz8CkNEj%2Fi%2FuhVdtWMJtNav7FJVi9FNAuV5RPm9whARIgARIoOwEqgGVnxztJgARIgASo9FXb74Aofts3b8fP30%2FH2lXrPEq%2BDFjcO6W0j5TKqVO3Tt6LAElWFBioLMBi%2FVPFIKstHQ6MBEiABKouASqAVXfu2HMSIAESIAES0JyAzWbDyqWrMP276diz%2Bx8f%2BWFhoegzsA%2B690pASFioUvyk5p%2FEgpqDghAcHKQSwDAO1Acbd0iABEjArwhQAfSr6WBnSIAESIAESODCEMhIz8C8X%2Bfjlx9%2FRdKpJJ9O1K0Xi%2F6X9FdFz%2FOUuwCI4mc2m1XiH1N%2BRlgpESLWQYkFpSuwD0LukAAJkIDfEKAC6DdTwY6QgHYEMqy5%2BDslTTuBAGzOvCLwInT%2F6TOaPtw5nU5PX5Oyc5BaIMbIc7KMG%2B4i8HK71lzsXlyOZWTheGZ2GXtZ%2FG3FzWlcWAhCjYFKQEnja1UrUl2Xbs3F6RzfWK7ie8Cz1ZGAuHmeSDyBGT%2FMxII5C5GTneMzzJatWyjFr0XrFvlunnoEBhpgMptVvJ8ofkaTEYHGPNdPFRMq7p9cSIAESIAE%2FJYAFUC%2FnRp2jATOn0BgUBBsOTlwwoVcL8Xk%2FCUVf4fN5QTycn4Uf2EZzjrgUiUFynBrqW6pSC72CuKiQ0CxcxrduwfqNI5X49%2F%2B4WfFcmhw3VXqfOKefTj023LPtYZ8BdJzgBvVmoC8dNn11y78%2FN10%2FL7ydzgcZ1%2FCSPxel%2B6dVWKXOnVjleInVj1R9Ewmo7L6ybZY%2B0TxM%2BgNqu4jS39U668MB0cCJFCNCFABrEaTyaGQQI9xt2H3vCVAfkZGLYk47HZkJSVDbzIiJDpaS9FKVlZKKhy5uQitEwOdxhYEm8WK7NRUmEJDYA4P17TvYkHJPJUM0Yil7xXh9pZz5gxEuTcYjYX2PXZgH9Rt21qdq71oWaHXuA%2FWu3SI2nTExqD2wcNqO65bJ5gjI9yXcF2NCTjsDqxevho%2Ffz9DKYDeQw0OCUbv%2Fr3Qu18vFd%2Bnl6QuhkCl9El9RynurpS%2BwMA8i59OD51eVyHfee9%2BcZsESIAESEBbAgG7EndU0Ht8bTtKaSRAAiRAAiRAAudPQF5SZGdlY8HsBZg57RecOH7SR0hMnRhl7euc0FlZ%2BfQ6nVLw3HF9EufntvhJbJ%2B7%2FEdFvOzw6Rh3SIAESIAENCdwdEciaAHUHCsFkgAJkAAJkMCFJyBunqdOJmHmtJlYMHshsjKzfDrVvFVz9B8k9ftaKqu7uH5KNk%2BjyeQb3yelHQx6Vd6Bbp4%2BCLlDAiRAAlWSABXAKjlt7DQJkAAJkAAJnEtArH3y2bNrj4rvW7VsNaQou3sRt86LulyEfhf3Q%2F0G9SH7en1efJ8UcXcndWF8n5sY1yRAAiRQ%2FQhQAax%2Bc8oRkQAJkAAJ1DACovRJfN%2Fa1euUxW%2Fb5u0%2BBCR%2Br1ffnujVvxciIiOU4ifxfaL0KYtfUJ7yJ6UdxNonSV%2FE2kc3Tx%2BM3CEBEiCBakGACmC1mEYOggRIgARIoCYSEMVPSjcsmrsYM3%2BciWNHEn0w1Kodjb6D%2BqJbj66qdINBr4fU8fMu4yAJXtyKH%2BP7fPBxhwRIgASqJQEqgNVyWjmomkpgwxffYues%2BZCMnVxIoCYQ6HDNSCTccTP2rViDFa%2B%2FW%2BSQm%2Fbvg4GP3q%2FOL%2FrvKzi6cXOR1w559nE0TOhc5Hl%2FOCGKnxRrn%2FXzbMz9ZR6kiLv30rhpI5XYpW2HttBLYXa9Pr9ge14Zh0BjXkkHUQaljIM7myctft4UuU0CJEAC1ZMAFcDqOa8cVQ0lsOPXeXB6xfvUUAwcdg0isPfXeQhLSUXSyaRiR52%2B62%2FszlcQs%2FYfLPbaozNmIWvFarSenKcwFntxJZ4UpU8%2B%2B%2Fbsw%2FQfZmD54hWwe73s0ekC0P6iDug3qC8aNW0E2T9bxsEMc5BJlXGQ%2BD7l5uml%2BFXiMNgUCZAACZDABSZABfACTwCbJwEtCbiVP6NOj1CNC3unW6yw51d%2FjzCZoA8I0KzruXY7MvMfZIMMegQZAjWTLYJOWyyeuvXRZrOmsrNybbA685JshAYGwqhxDcNUi0X1l3PqO23uOc1xOJCxczecNjuKm1tTjkVdJ1LM1txir007cBhH%2Ft6LA0%2B9gG633YiYVi18G6%2FkPVH6JKPnhrUbVGKXLX9u9emBFGfv0acH%2BgzojcjoKIibpxRol4QuEvvnLuNAN08fbNwhARIggRpLgApgjZ16Drw6EwgKNCAuLETTIebYbbDb8xSduiHBMOp1msk%2FY7EiMyNTyYswmhATEqSZbBGUbrXC7soreao1l8SMLFgteVxqBZkRbiq8WHtZB%2BRWADmnvgS951TOBAca1Mf3qsL3agcX%2FxIgTb6PNhsyt%2F0FS%2FplhQuphKOi9OVac7FkwW%2BY%2Fv0MHDl0xKfVqOhI9BnQB917J8AcFKQUP6nXp4q2q9p9ktjFqGL%2BAg2BCNAFqKQudPP0wcgdEiABEqhxBKgA1rgp54BJgARIgAT8mYBY%2FFJTTmP29NmYPWMOzqSd8eluw0YNlZtnh07tVXyfZOxUJRykjIPZrJQ%2BdxkHvU6vFD%2FW7%2FNByB0SIAESqNEEqADW6Onn4EmABEiABPyFgFj8Du4%2FhBk%2FzMBvC5bCZrN5uiZWu%2FYXtUPfgX3QuGljVbj9rOJnRlCQWVn%2B3G6ekvRFPlxIgARIgARIoCABKoAFiXCfBEiABEiABCqRgCh%2Bf67%2FE9N%2FmImN6zb6tCyWvIRe3ZSrp5R0kOQtckw%2B3vF9sq9q9%2Bl1qn6fjxDukAAJkAAJkIAXASqAXjC4SQIkQAIkQALlISDK3JoVv%2BO9N97H4OGX4K577yy0mLq4eVqtVixbtFxZ%2FA7s881MGh4RrpK6JPRKQEhoiFd8nyR1OevqKWUcJL7PXcahPH3nvSRAAiRAAjWDABXAmjHPHCUJkAAJkEAFE3A4HKoQ%2B%2BsvvIGszCzM%2B2Ue7hg%2FRlnt3IlXRPGTmD6J7ZMYP4n1817qN6iv6vd16NRBJW%2BRjJ4qqUt%2BNk930XbJ8in1%2BySxC%2BP7vAlymwRIgARIoCQCVABLIsTzJEACJEACfkdAsqLqAnSIDw%2F1i76J8me1WPHqc68p5U86NfyK4cjNzYURRqWoHTuSiOnfT8dvC36DxWL16Xeb9m1UYpdmLZoiQKdT7px52TzzrH1i9VNunoF5Rd1F6XMrlT6CuEMCJEACJEACJRCgAlgCIJ4mARIgARKoWQSknmPjiDC0nvwAops2LnHwYtWTguzff%2FU9du%2FYra4XRW74yGFKAdz11y7MnPYL1v%2F%2Bhyrk7hYoCVu6du%2BCvoP6onZMLZXYRY5J6QYV3yeJXUwmyDGx%2BInSR8XPTY9rEiABEiCBshKgAlhWcryPBEiABEjgghGwO52Ay4mUHAuk%2FqKWi0GvQ5jeiPqdOpRKrMPuwF9b%2FsK0qT%2Bq60V5u%2FG2G7F21Tpl7SsY3xcWHobe%2FXuhR%2B%2FuCA4JVqUcjAUKt4v1T5K6SIyfZPMUax8tfqWaDl5EAiRAAiRQAgEqgCUA4mkSIAESIAH%2FI2BzOGF3uZCTmaW5Ang%2BoxXlL%2B10Gt74vzfhdLrUrTF1YvD%2BGx%2BcU7%2Bvbv26ys3zoi4dlVXPndFTavfllXEwQxRBd3yfO7ELFb%2FzmRFeSwIkQAIkUBIBKoAlEeJ5EiABEiCBGkUgzWLFkYxMbB85CkOefRwNEzoXOn7J%2BCm1%2Bj54%2ByOcOpnkuebIoSOebdlo2boF%2Bl3cDy1aNVfxfeLSaTQZlatnUFBQ%2FrZJKX4s3O6DjjskQAIkQAIVQIAKYAVApUgSIAESIIHqTcAd97d00VKs%2FG3lOYMVt02x9El8X%2F24esrN07twuyiAktjFHd%2FndvNkRs9zUPIACZAACZCAxgSoAGoMlOJIgARIgASqPwFx%2FTx6%2BBg%2BeufjQgcrbpxJp5KwbNEyREVHoV5cPfS%2FpD8ioiJgNourp1GVh2Bil0Lx8SAJkAAJkEAFEqACWIFwKZoE%2FJ1AYEQEdGYjrF7ua1r2WR8cDJfdBmeuTUuxgE4Hc2ws7NlZsJ9J11Y2AGOtWiptvzUpWXPZboHCRmcywnY6zX1Ik3WAwQAE5ItyuuByODSR6y0kINAAc926sJ5KgtPqW87A%2B7rz2RaZPosLcNntPofKs2MID0NgeBgsJ0%2FBZSufXHH9lPIOb774FrKzsgvtliXHgiOHjqqP%2B4LDB4%2FgX%2F95TLl8ui1%2BjO9z0%2BGaBEiABEigsggU%2BItbWc2yHRIggQtNIGZgPwRGhiM3JRV1Lh6II9%2F%2FpFmXdMZAxPTvi7hrLseO51%2BF9fhJ7WQHBaHlgxNgCAmGKbYOTsxfjGMzZ2smv%2F5VlyG0SSOENG2C05u34ODn32om2yMoIADNJoxF5r4DSPxlrudweTdE%2Bevw8r9hio5Wona%2F%2Fi4yduaVJSivbHW%2FTod6IwZDF2hE8voNcNq0UexNsTHo%2BNJ%2FfLqYtmU7%2FvnfRz7HyroTO2wwXLlWZB08hMa3jcaJBb8h51hiWcXB6ciL%2FbvnwfE4fPAQTiSeVNa%2B9LR0ZGRkICszG5mZmchMz4DVmutpJyIyXGX0dFv9PCe4QQIkQAIkQAKVSIAKYCXCrslNibtUt1bdfRDIm29Jgd6qTSuMf%2BBudO%2Bd4HO%2BLDsH9x%2FE8WPH0atfL3V7%2F84Dccf4MbjjnjFqv6TzZWmzNPds%2FXMr3nr5bezYtlM9AHbq1gmPPjMZUivsQiymurGoO3QQtj%2F1POByocUD9yCsVQtk%2FP2PJt0Ri9%2FJpSsQd90VmsjzFhLdrRP2TflcWc7C2rREq8kPIGXdRliOH%2Fe%2BrEzbxqgoJUuUsqAG9dH%2Buadw%2BNvpcFotZZJX1E0x%2FftAZzIVdbrMx2v16o69734My6kUJcOZU7h1qkwNBASg6Z23IftYIo79MqdMIoq6KaxFc2x%2F%2BgVlUXQ5nRA%2BDo0si%2FIyou6Qgdg6%2BWnVfOrGLYgdOggHvyi7Yu%2BCS9Xji4qOhF6vQ53YOqqwu9PhgMPpRAACoNMFqLg%2FiRW0WixAQADatm8DsR5yIQESIAESIIELSUB3IRtn2zWLgLhE9ezbA089%2F4T6%2FOs%2FjyvlTBS2O24Yi7%2B27ig3kFGX3%2BQjp%2B%2FAPohvEu%2BRW9J5z4UabhzYdwBjrh%2BL8IhwTPnmI7z98VtITzuD2665HSlJeQ%2FqGjZXKlG1eyUgSzIVuvLS1mfu24%2BYi%2FuX6t5SX%2BR0wmnRxj3Qu83Tm7Z53CYzdu2BNSkFgWEh3peUeTv39GlYT%2BRZK3PTzigLndbKn7lePYhSkl0gU2SZO51%2Fo1j%2F6g67GLV6JsBUOwqaKn8AavfrDVPdGGVxLW9fC96fsvYPWBKP57l8Op2IvKg9xAJY3KLX6WDU6RFtLr4GoMvpgj4oCFHd8jJ5hjSJR8Y%2F%2B4oTXeI5XYBOvciRWL6Q0FBERkWiVu1oRNeuhVq1oiGKYVhEOEJCgxEWFgop%2F9C4aWMV81eicF5AAiRAAiRAAhVMgBbACgZM8b4E2nZoi%2Btuus7n4JXXXYGLEwbjh6%2Bn4YU3nvM5d747jgLxTi%2B%2B9X8%2BIko673OxRjs%2FfvOTUv7e%2BPB1lfFPxLZq%2Bx56t%2B%2BLRXMXYfSY0Rq1VHoxwQ0bwJqS6rnBlp6JqDoxnn1%2F3nBkZXm6p%2BLd4ELm%2FoOeY1psiIIWd9XlOPrTL1qI88iQ%2FsYM6I0jP85E%2FGjf%2Fweei8q4oQ8JRvKa9Qhv0xLtnn0ch779CUnLV5VR2rm31bt0KDL37EX9Ky9FSKN4nFiwGBl%2F7z33wjIc8Y5T1IeGwGlo94apAAAbrElEQVS3w5mTU6wko14HUcTiSlD%2BJY7w4Fffoem4MUhq1QI5RxORsnpdsbJLOin1%2BSTJiyyyttnsEOuf0%2BVU7qFi5XM4xNLnglgAAwJ0qr6fyWRSSiDj%2FkoizPMkQAIkQAIVSYAWwIqkS9mlIlC7Tm3IJzU5zxom7qJT%2FvcxLu13OS5q3BkJrXrgrtHj8M%2Fus%2B6JLz7zEj5571M8cNeD6NoiAW%2B99DZGjbwJWZlZmPrZN7jntomq7VuvuR0zp%2BU9xJd0Xm7YvfNvjL91Anq164PurXsq%2BZLIwb3MmTkXD49%2FBIvmLsblA0aiU5MuuOLiqwpNA%2B%2B%2BZ9CQQXj2pac9yp8cDw8PV%2FtJpyouyYi7%2FcLWepMJjhwvt0aXC4YSHqQLk3Ohj8X0762UNC2ThciYont2R0ijhmjx0ASYNFSMYwcPwsnFy4AKcAOUZDgSD7nnzfex94NP0HDUNTBGR2kyRYGRETDXqY2kFWtUzGLKmvVoIXGYEeGayPcWEtX5IpzeuNn7ULm307ZsQ%2Br6DajdtyeCGsYpd8zihEaaTegQUwtjZ%2F9QaA1AUeAkiYsodEHBQQgLD0V4ZDgiIiIQERmhLIJiBZTsn3mfSISFh8EcZIaUgmCph%2BLo8xwJkAAJkEBFE6ACWNGEKb9EAn%2Fv2qPi9lq2aamufe%2BN9%2FHhWx%2FhznvH4rtZ3%2BD515%2FDvn%2F244mHnvLIOnTwMD5%2B9xPlQnnL2JshlsWJD92jHsgk%2Fm%2FM3bepa3fv2I3k%2FEyOJZ3fuX0nbrx0lHKLfGvKm3j13Vdw6MBhjB45Gsn5ipooqcsXr1DZ%2F%2B669y6888lbCAoy4%2BF7Jinl09NBrw2Jbbxk%2BCVeR4Bffv5VFZDu1a%2Bnz%2FHK2slNT1cZKN3tSTZKe%2FpZy5r7uD%2BvTTG1VRzd6T%2B3aN7N5JVrsOvFN5B95Biiu3fRRL7EFEZ2bAuJ06t3%2BXCENG2E8BbNPa6JmjSSLyRt83akbdqK4MZn3Z%2FLI18fFKxuzzl%2BQq1T%2F9ysMruGNdc%2BhjXyog5I2%2FJXid212p3IyrXh8JmMEq9tevcdSJy9ALtfegu1Erqg3uXDSrynpAtEidMb9OpFjpR0kI%2FJbFJKniiFEt8cHByMkJAQtRblT2r%2BieLIhQRIgARIgAQuJAG6gF5I%2BjWw7fWr10MsfLLY7Q6cSDyO3xYsVW%2FJb89X2sSd6pGnHsa1o65R17Xr2A4nEk%2Fglf%2B%2Bqu6Vh668%2B%2B34aOqH6s26OgDAEGhA85bN0LPvuYqV1OAq7vyHb09BTGwM3vviXY%2B1rm3HNhjaczi%2B%2FnQqHnnyYdWMxWLB6x%2B8hvYXtVP78ob%2FxstHY%2FuW7YW26%2B6be719y1%2F4v6dfxIgrhiOhV%2FkT37jlns868599CG%2FXxnOLKFPljYvyCKuEDUNYKKISulRIPJqn%2By4XzmzfCUd28a6InutL2HBac3F68zbPVS67A06HXfsSGfkt5KacVhlePQ2WYyM3NRVOmx3G6EjkZGerlyS2tDOwy7aGiz4kBC5hUoqkO%2BJuaZc5yj2bZbOwrkimWHPdOnCX9Nj78RdodOO1OD57QWGXq2NWhwOZuTbsXrAEDbp0Qmid2kVe6z7hdut0r93HuSYBEiABEiABfyNABdDfZqSa92fvnn1ISc6LPZMseeEREbj%2B5usgyp8oUrJMfvoRZR3bsW0HDh04BLln6YKl6pzdYfckUmjavKmP8ldedJs3bsaQEYM9yp%2FIk%2Bx%2BHbt0xOaNvlamNu1be5oTpVEWS07JCU%2FWr%2FkD995xH7okdMZL77zokVHZG5I1M3boxdCZzHDmWhHavAn2f%2FKV5t0I0AWo%2BCctBUs9N4mfS1q%2BGmKBChA3vPqxOLloWbmb0QUFq4QyUt9Oag0G1auLQ99pUx5DFBDl%2FpnfS3EttWdl4cy2kq1dpRlYcHxDdVn24SMQl03JpqlVohmp9Ze8%2BndEduqgYujU98Zu0ywG0D2%2BqC4dobVF13YmHTqjCTqjEc7cXOSeSlaWXXebha1zbHYkZmYh8f1PMeTZx0ulABYmh8dIgARIgARIwB8JUAH0x1mpxn26eexNuH%2FyfcWOcOVvK%2FHkI08jLTUNjZs1Rpt2rdGsZXOIq6j3UjumlvduubclflAydRZc5Nip%2FMyQcq6gG1eArnSe1L%2F8%2BCuenvQMLrvqUrzw5vM%2BimbBNit635GdjQOffI24qy9TSsjRGXO0LQav0yGqc0elLES0bwOxFkmbWixxV14KY0QE4q68zCPu2JyirTmei0qxIRkiG99yAzL37lcFw4%2FNng%2FvpDOlEFHqS6wnk2DXsEyDqU5tNLj2CmTtP4TMvftw7Fft6gvKoA7%2FMB0NrrsKMQP7whAagv1TvtQ8ljG8VUscnPpDqRmW5kKnxYL9H3%2BJ%2BiOHK8VPlOND3%2F1Ymlt5DQmQAAmQAAlUSwJUAKvltFbdQWVnZeOh8Y%2BgV9%2BeeO39V1UcjYzm8w%2B%2FwLxf56mMep7RBQR4NrXYiKlTG4lHzy0OfezwUdSLq1euJr76%2BGu8%2FJ9XMPGRCbhv0r3wBzcxKf0gnwpZnE5lydHamiN9PTR1WoV0WYRK0fTtT5YvE21pO3dySfktlt5tSeIUrZOneMt32ew48v3P3oc0397%2FqfZWaOmkKMTy4UICJEACJEACJACUznRBUiRQSQTSTqchJzsH%2FS7u51H%2BcnNzMfeXeaoH7vjBorojCRZsubaiTqsEDEWdHzh4IBbPW%2BKjBIrLpmQGHTB4QJEySzqxcukqpfxNfnqSsn76g%2FJXUp95ngRIgARIgARIgARIoHoSoAWwes5rlR2VWNok6cs7r%2FwPp06egkFvwNxf5qqiyjIoyegZElp00e%2B4hnH4YsqX%2BGvrX%2Fjgq%2FfP4VDc%2BXsnTcSaFWtw3fAbMPKay5GTk4Nff5qFfoP64rrR154jq7QH3n75HXWp1DmcVsB6dfWNV2PCQ%2FeUVhSvIwESIAESIAESIAESIIFyEdDfN%2Bne%2F5RLAm8mgfMg0KN3D4gSVtQi1jHJjinJQ%2Fb%2FcwB2ux13ThyLex4ar6x3DRs1REydGOVC2apNS7hLR7jlSckFKbwsyWXEjVQsgl26d0H9fBfO4s6bzWZcfcNVCA4NVm1LseexE8bgwccf9CSekXbq1q%2BLhJ7d3E2qtRSD7tGnu6r%2F5X1C%2BnI65TS69uyKVm1bnfPp2LkjGjXRJlW%2FtLs530XPbDAgwmT07kq5t1MtFtidLiWndlAQ9DrtXHCtdocnm2NoYCBC8otsl7vT%2BQKSs3MgZblliQ3JK2mQv1vuVUauDTl2u5ITaTLBlJ%2BlttyC8wWcys9Cyjn1JVqRc2qxO5Cen1202YC%2BiCinC7hvz7lHAiRAAiRAAheOQHpSBgJ2Je7Ie6K7cP1gyyRAAhoR%2BHzkKCUpwmRCfHioRlLzxOwV99z8Eh6toqNg1GvnQX7GYsXhjEzVUN3gYMSEBGna913JqapkgAiVAt9aLokZWUixWJTIRuFhCNdY8d6elKJkc059Z02%2BjwEIQO3gIM1fdqRZrDiS%2F32ULKANEzr7Ns49EiABEiABEqiiBI7uSARdQKvo5LHbJEACJFCTCRh0OugCdJorf8LUqNcj2mxGzIA%2BCNH4hUFNnjOOnQRIgARIwD8IUAH0j3lgL0iABEiABPyEQHCgAfJJuG%2Bcn%2FSI3SABEiABEiAB7Qho58OlXZ8oiQRIgARIgASKJSDF2s9YrXC7yBZ7MU%2BSAAmQAAmQAAl4CFAB9KDgBgmQAAmQAAkAWTYbDp%2FJwNKX30LKvgNEQgIkQAIkQALVigAVwGo1nRwMCZAACZBAeQnYHE6VlfbgmvXITk0rrzjeTwIkQAIkQAJ%2BRYAKoF9NBztDAiRAAiRAAiRAAiRAAiRAAhVHgApgxbGlZBIgARIgARIgARIgARIgARLwKwJUAP1qOtgZEiABEiABEiABEiABEiABEqg4AiwDUXFsKZkELhiBvOyI1gpr%2F%2B%2FU0xUm%2B0R2NuRTUUtFZo08lJ5RUd3Oz3jJOS0McFFzGmEyIT48VN1y8Ew6MnJthd2ujjUKD0O4yai23UXgi7yYJ0iABEiABEigChOgAliFJ49dJ4GCBIIiIpBz5kzBw9wngWpJQFxYnMWMLKxFUzS7ZqS64tR3PyNj7%2F4ir65%2F6VDEtmymzm9%2F7lXPdYEhQZ5tbpAACZAACZBAdSBABbA6zCLHQAL5BPpPuheHfv8DLpdLcyYOmx1ph44gMNiM8Pr1NJeffuw4bDkWRDWOh86g11S%2ByE07fBTBtaMRUitaU9nCOvXAYSUzukk8AgICNJWflZyK7JQURDVqCIPZrKnsqjynAsJyJh0Ou73IOY1p1RzRCV0Us6YnkxDZrEmR%2FGL79EB043h1vtWwS9Q6rF4sYlu3LPIeniABEiABEiCBqkggYFfiDu2fFKsiCfaZBEiABEiABEiABEiABEiABKoxgaM7EsEkMNV4gjk0EiABEiABEiABEiABEiABEvAmQAXQmwa3SYAESIAESIAESIAESIAESKAaE6ACWI0nl0MjARIgARIgARIgARIgARIgAW8CVAC9aXCbBEiABEiABEiABEiABEiABKoxASqA1XhyOTQSIAESIAESIAESIAESIAES8CZABdCbBrdJgARIgARIgARIgARIgARIoBoTYB3Aajy5NWlo27f8hW8%2B%2BwbbNm9Hbm4u4hrGYcTIYbh61NUwe9VOWzB7IRbOWYi3prxZJJ5P3%2F8MZ9LOYNJTjxR5TWWccDqdqqac1nXlKqPvbIMESEBbAlJvUj7ye8DfBG3ZUhoJkAAJ1DQCtADWtBmvhuP9cspXuOHSG7Fn1x5cef0VGDP%2BdtRvUB8v%2FfsVjL78Jpw8cdIz6iOHjmD18jWe%2FcI2dm7fiS1%2Fbi3sVIUfkwc8h92B06mn8cFbH2LkwCvw7uvvQZRBLiRAAjWPgPwm2Gw2TJowGdePuBE%2FfD0NOdk5mv0m7Ni2A%2BNvnYBZP88qFO77b3yAN%2F6v6Bdmhd7EgyRAAiRAAn5NgBZAv54edq4kAqLMvfLfV3H73bfhsWcfhU539p2GKIJjrrsDj977OL786XOfcyXJrezz8pAnSp7dbsfC2Qvx9affIO10murGyt9W4p4Hx%2FPNf2VPCtsjAT8gIL8LyaeSlXeDdOezDz7HgtkLMO6%2BcejZpwd0el25fttSU05DfmP%2BWPMHOid0QcNGDXxGvW3LdmRnZfsc4w4JkAAJkEDVJnD2ablqj4O9r6EEPnjzAzRt3uQc5U9wtG7bCpOffgQb1m7AhrUbCyUkipe4hT48%2FhHcN%2FYBLF%2B8otDrKvKgW%2FHbsXUHHrr7Yfzvtfc8yl9oaAjGP3C3sgrSCliRs0DZJOCfBFxOF0LDQnHTmNEIDAxUnTx2JBH%2Fefy%2FeObRZ3Fw%2FyH1%2ByC%2FZeVZxMr45MNPaWZZLE9feC8JkAAJkEDFEqACWLF8Kb0CCWSkZ2Dzxi0YPGJwkW%2FAR1wxAnq9HksXLi20J%2B%2B98b5S%2FkJCQtCqbUs89%2BTzWLd6faHXan1QFDpx90xOSsbrL7yJSRMfxT%2B796pmdLoA9L%2B4H%2F7z6r%2FRoXOHvIcyF1QMkNb9oDwSIAH%2FJCC%2FEU6XU%2F3%2Fl9%2B5J59%2FAh07d%2FR0Vl5s3TvmPnzy%2FqeQ30OHw1Hm34i7HxiHjes24rsvv%2FfIL2pjy59b8PQjz2DcTXfjv%2F96Dv%2Fs%2Fsdz6ZT%2FfYwl85d49uU37tXnXsPieWeP2W12dUzc7bmQAAmQAAlUPgG6gFY%2Bc7aoEYHjx44rSfFN4ouUGBIagpjYGBw7mnjONUknkzDlnY9x%2F%2BT7MPGRCer89Tdfj2G9hp9zrdYH5MHOarFi9ow5%2BObzb31crPR6Hbr37qH6vemPzQgK2gWj2QSDXo8ALxdXrftEeSRAAn5GQGKCHXmu4RaLRcX%2BNWvRFIDL4xIqlrufv5uOZYuX447xY3DJ8IthMBjOO1HMiJHDcWDvAbzxwpvq5VN848J%2FVyVW8PEHnsAlwy9BQq8ErF%2FzB64ddj0%2B%2FnYKevbtgX179ikFUBRWWbZv3Y4vPvoSf3b%2BE0MuzTu2acNmdey2u271M%2BDsDgmQAAnUDAJUAGvGPFfLUTrzXZ5EMSpukYchFOIetWHdBvXG%2FIrrRnpur1svFv0u7qeygHoOarwhb8T%2F%2FGMTPnpnCg4fPHyOdHngW7tq7TnHeYAESIAEiiKQkpSC1194A%2FNnzVcxw63atirSM6IoGc%2B8%2BLRS6J586Cl8PeOrc%2B7PzMjEf594HrfeeYuyRoqccffdhUfumaRcUuevnqsUQ3Fll0RWUdFR%2BH3FWtSKqQXJ1CxWyrDwMCxbvAxtO7RF3fp1i%2BoKj5MACZAACVQgAbqAViBciq5YAnEN6qsGJB6mqEVKQpw4fgL14uqdc0lyUoo6JhZC76VeBT6UiIuWvLFPSU6BJSfHu1lukwAJkEC5CWSkZ6oXWJJQ6nzjAqNrReM%2Fr%2FxbvaASz4SCy5%2Fr%2F1TeCm3at8FfW3eoz45tO5Uyd%2BjAIRw7cgx9B%2FaBIdCA31fmvcRavXw1bh93G%2FQGPf5cv0mJlFjrwSMuKSie%2ByRAAiRAApVEgBbASgLNZrQnIG%2BSu%2FXshnmz5mP8g3erWL%2BCrUgsisSbXDxsUMFTiIgIV8dOp6ZBLH%2FuJT09w72p6dqd6VMUwI6dO%2BBf%2F3lc9X3FkpVKKXQ3JokeevXvBVFEJX5Ran55Zzd1X8c1CZBAzSAgvx15vx8O2O0O5WYpcXhO59nEL0HBQbj0ihFKsRLLm3galMUVdOhlQzDiiuF48%2F%2FewoBL%2BvsATjqVpPafe%2BJ5IMDnFMxBZqQmp6JBfAOVnXTVstXq%2Fq2btimlcuXSVVi3Zh2aNG%2BMg%2FsPYvBwKoC%2BBLlHAiRAApVHgApg5bFmSxVAQOL3br9ujHJ9kjIQ3gWS5SHjxWdfxkVdL0L33t3PaV3iV2QRJfGWsTerbavVinWr1qG4uMJzBJ3nAffDnE6vVw9Ibdq1xqK5i%2FH3rj1KkiiIq5etUnGAQy8djOCQ4LxxBRR44jrPdnk5CZBAFSWQXyYmJTkV836dh53bd3kGIgmjpHzDwMEDUCffm0F%2BY8qzuF1Bn3jwSUgctXtxb89Y%2FDOaNGviPnzOWuID33%2FzA%2FyxdgMioyLRonUL9O7fS5W4qR9XT5WaaN6q%2BTn38QAJkAAJkEDlEKACWDmc2UoFEejeO0HForz07MvY9McmDLt8GMIjwrDzr92Y%2BcNM1G9QD2988Fqh1kEpFj96zGi8%2FvwbykrYpFljfPXJVFWCoSIUQLclTyx8ZrMZIaE2OB0OlezlmtHX4ND%2BQ0oZPXUySb3ZX7d6HbZv2Y5b77wZHTp3hI4KYAV9iyiWBPyXgLL8uVxYPG8x5s6cp2qFunvbuGkjXDLsYshvmbwocn%2BMJqNyufR%2BIea%2BpzRrsSCKK%2BgDdz2o5HTu1lnd1qlrJ7VeMGshJjx8j0fU5x9%2BoQrJfz%2F7O4glctDQgSo76DeffYsefXqoF1i9%2BvXE%2F159FzOn%2FaLiBMvaN0%2Bj3CABEiABEigzASqAZUbHG%2F2FgCQkkAeTrz7%2BCtOmToPEwDSIj8MDj92PG2%2B9QT0UufsqsYBdundx7%2BKp559QrpbTpv6IrKwsDL10CPoN6gt3hlHPhRptiCunKIDKqqfTKcU00BgIY2aWekveqEm8SpawdNEyFWuTlZmF77%2BaphLT6HV57qAadYViSIAEqgAByRgspWJ%2B%2FWmWp7fRtaJU%2BZuWrVvCZDYqpSs0NFRZ6%2BS3xWQ2edzHPTed54Zk7JQyOpJUxr3I76d4S4h1T7wlevTprqyRb738Nm6%2B42bVD7k2tm4s2nVsp5JZPf%2F6f9XtHS7qoH73du%2F8G0%2B%2F%2BLRbJNckQAIkQAIXgAAVwAsAnU1qT6BDp%2FZ4%2FYPXShR8%2BdWXQT7uRWLsJIudfCpjkbfekgzBFGCCTi%2FKoAFGkwkmsxmi7EliGHmoErfVVUtXqWQMklo9KCgIRqMRAboAHzfXyugz2yABErgwBMT6J7F88rshiVcSjyaiz4DeqvyC%2B7dDWf2CgxGSr%2FiJ9U9i%2F0obNxwRGaFiqcVyV3B59qWnlUdE85bNPKeeeO5faNi4ofKw%2BPGbnxBbtw4ee2YybrnzFs81siEv32ZNn43e%2FXur4%2FK7d8Mt16v4xU5dL%2FK5ljskQAIkQAKVSyBgV%2BKO8gULVG5%2F2RoJVBsCqsizw6kSwLhrfGVnZSM7O0cdk3qAwcHBiIiKgLzdN5lMSnmsNgA4EBIggWIJiAIo2TzldyH9TDrSz2RAMhuLQmgyGT0un%2BoFkZfiR%2FfKYrHyJAmQAAnUaAJHdySCFsAa%2FRXg4C8kAXlDLw9qYtWTt%2BPiGipWPrEGWi0WiIKoYnl0evU2n9a%2FCzlbbJsEKp%2BA%2FD7oAvJdxVXssAlGYyDEbVziiMVqJy%2BG5LdDPApKa%2FWr%2FJGwRRIgARIgAX8iQAXQn2aDfalxBOQBT9xQ5cFNYvykfpbE7%2BRag2B32NUx2ZfjfLircV8PDpgE1AsilTgqyOzxAHC%2FLBJFUH4%2F5MOFBEiABEiABEpLgApgaUnxOhKoQAJKETTo1cOeQS9xgUY4HU5lIRTroDzgyTVcSIAEahYBefEjCp94ALh%2FE8Ta535xxN%2BFmvV94GhJgARIQAsCVAC1oEgZJKARAXnYU9ZAl14Vfhax8oDHhzyNAFMMCVQxAvJ%2FX14CiQKIwLzO8zehik0iu0sCJEACfkaACqCfTQi7QwJCgA94%2FB6QAAl4E6ALuDcNbpMACZAACZSHgK48N%2FNeEiABEiABEiABEiABEiABEiCBqkOACmDVmSv2lARIgARIgARIgARIgARIgATKRYAKYLnw8WYSIAESIAESIAESIAESIAESqDoEqABWnbliT0mABEiABEiABEiABEiABEigXASoAJYLH28mARIgARIgARIgARIgARIggapDgApg1Zkr9pQESIAESIAESIAESIAESIAEykWACmC58PFmEiABEiABEiABEiABEiABEqg6BKgAVp25Yk9JgARIgARIgARIgARIgARIoFwEqACWCx9vJgESIAESIAESIAESIAESIIGqQ4AKYNWZK%2FaUBEiABEiABEiABEiABEiABMpFgApgufDxZhIgARIgARIgARIgARIgARKoOgSoAFaduWJPSYAESIAESIAESIAESIAESKBcBKgAlgsfbyYBEiABEiABEiABEiABEiCBqkOACmDVmSv2lARIgARIgARIgARIgARIgATKTCAgIABUAMuMjzeSAAmQAAmQAAmQAAmQAAmQQNUhoNPpqABWneliT0mABEiABEiABEiABEiABEig7ASoAJadHe8kARIgARIgARIgARIgARIggSpFwGAw0AJYpWaMnSUBEiABEiABEiABEiABEiCBMhKgAlhGcLyNBEiABEiABEiABEiABEiABKoaASqAVW3G2F8SIAESIAESIAESIAESIAESKCMBo9GI%2Fwc8SrsDdCe%2BsgAAAABJRU5ErkJggg%3D%3D)%0A%0A%23%23%23%23%23%20Topic%0A%0A%3E%20%E7%94%A8%E6%88%B7%E5%88%92%E5%88%86message%E7%9A%84%E9%80%BB%E8%BE%91%E6%A6%82%E5%BF%B5%EF%BC%8C%E4%B8%80%E4%B8%AAtopic%E5%8F%AF%E4%BB%A5%E5%88%86%E5%B8%83%E5%88%B0%E4%B8%8D%E5%90%8Cbroker%E4%B8%8A%0A%0A%23%23%23%23%23%20Partition%0A%0A%3E%20Kafka%E6%A8%AA%E5%90%91%E6%89%A9%E5%B1%95%E5%92%8C%E4%B8%80%E5%88%87%E5%B9%B6%E8%A1%8C%E5%8C%96%E7%9A%84%E5%9F%BA%E7%A1%80%EF%BC%8C%E6%AF%8F%E4%B8%AAtopic%E8%87%B3%E5%B0%91%E8%A2%AB%E5%88%87%E5%88%86%E6%88%901%E4%B8%AApartition%E6%B6%88%E6%81%AF%E5%9C%A8Partition%E4%B8%AD%E6%98%AF%E6%9C%89%E7%BC%96%E5%8F%B7%E7%9A%84%EF%BC%8C%E7%A7%B0%E4%B8%BA%E2%80%9Coffset%E2%80%9D%0A%3E%20Kafka%E4%BB%A5Partition%E4%B8%BA%E5%8D%95%E4%BD%8D%E5%AF%B9%E6%B6%88%E6%81%AF%E8%BF%9B%E8%A1%8C%E5%A4%87%E4%BB%BD%EF%BC%88replica%EF%BC%89%EF%BC%8C%E6%AF%8F%E4%B8%AApartition%E5%8F%AF%E4%BB%A5%E9%85%8D%E7%BD%AE%E8%87%B3%E5%B0%91%E6%9C%891%E4%B8%AAreplica%0A%0A%23%23%23%23%23%20consumer%0A%0A%3E%20%E7%94%A8%E6%88%B7%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%EF%BC%8C%E8%B4%9F%E8%B4%A3%E4%BB%8Ekafka%E4%B8%AD%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%B9%B6%E8%BF%9B%E8%A1%8C%E5%A4%84%E7%90%86%3B%0A%0A%23%23%23%23%23%20Consumer%20group%0A%0A%3E%20%E5%A4%9A%E4%B8%AAconsumer%E5%8F%AF%E5%BD%A2%E6%88%90%E4%B8%80%E4%B8%AAgroup%EF%BC%8C%E5%90%8C%E6%97%B6%E8%AF%BB%E5%8F%96%E6%9F%90%E4%B8%AAtopic%3B%20%0A%3E%20%E6%AF%8F%E4%B8%AAconsumer%E8%AF%BB%E5%8F%96%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AApartition%0A%0A%23%23%23%23%23%20Consumer%20position%0A%0A%3E%20%E6%AF%8F%E4%B8%AAconsumer%E8%87%AA%E5%B7%B1%E7%BB%B4%E6%8A%A4%E8%AF%BB%E5%8F%96%E7%9A%84%E4%BD%8D%E7%BD%AE%EF%BC%88offset%EF%BC%8C%E4%B8%80%E6%97%A6%E6%8C%82%E6%8E%89%E5%90%8E%EF%BC%8C%E9%87%8D%E5%90%AF%E5%8F%AF%E7%BB%A7%E7%BB%AD%E8%AF%BB%E5%8F%96%EF%BC%89%0A%3E%20Message%20%E8%A2%AB%E8%BF%BD%E5%8A%A0%E5%88%B0append-only%E6%96%87%E4%BB%B6%E4%B8%AD%0A%3E%20Producer%E5%90%91%E6%96%87%E4%BB%B6%E4%B8%AD%E8%BF%BD%E5%8A%A0%E6%B6%88%E6%81%AF(%E9%A1%BA%E5%BA%8F%E5%86%99)%0A%3E%20Consumer%E4%BB%8E%E6%96%87%E4%BB%B6%E4%B8%AD%E8%AF%BB%E5%8F%96%E4%B8%80%E5%AE%9A%E8%8C%83%E5%9B%B4%E7%9A%84%E6%B6%88%E6%81%AF%20(%E9%A1%BA%E5%BA%8F%E8%AF%BB)%0A%0A!%5B350cba450682ac89df16c9e31f34dd46.png%5D(en-resource%3A%2F%2Fdatabase%2F1063%3A0)%0A%0A%23%23%23%23%23%20Kafka%20producer%20%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%0A%0A%60%60%60%0AKafkaProducer%20-%3E%20%E9%80%9A%E8%BF%87%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%94%9F%E6%88%90Producer%20Bean%20producer%0AProducerRecord%20-%3E%20%E5%B0%81%E8%A3%85%E4%BA%86%20topic%2C%20key%2C%20value%2C%20partition%20%E5%92%8C%20timestamp%0ARecordMetadata%20-%3E%20Broker%E7%A1%AE%E8%AE%A4%E6%94%B6%E5%88%B0%E4%B8%80%E6%9D%A1%E6%B6%88%E6%81%AF%E5%90%8E%EF%BC%8C%E5%BA%94%E7%AD%94%E7%9A%84%E5%85%83%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%8C%85%E6%8B%AC%0Aoffset%2Cchecksum%E5%92%8Cpartition%E7%AD%89%E4%BF%A1%E6%81%AF%0A%60%60%60%0A%0A%60%60%60java%0AProperties%20props%20%3D%20new%20Properties()%3B%0Aprops.put(%22bootstrap.servers%22%2C%20%22localhost%3A9092%22)%3B%0Aprops.put(%22acks%22%2C%20%22all%22)%3B%0Aprops.put(%22retries%22%2C%200)%3B%0Aprops.put(%22batch.size%22%2C%2016384)%3B%0Aprops.put(%22linger.ms%22%2C%201)%3B%0Aprops.put(%22buffer.memory%22%2C%2033554432)%3B%0Aprops.put(%22key.serializer%22%2C%22org.apache.kafka.common.serialization.StringSerializer%22)%3B%0Aprops.put(%22value.serializer%22%2C%22org.apache.kafka.common.serialization.StringSerializer%22)%3B%0AKafkaProducer%3CInteger%2C%20String%3E%20producer%20%3D%20newKafkaProducer%3C%3E(props)%0A%60%60%60%0A%0A%23%23%23%23%23%20Kafka%20producer%E9%87%8D%E8%A6%81%E5%8F%82%E6%95%B0%0A%0A%60%60%60%0Abootstrap.servers%20-%3E%20%E5%88%9D%E5%A7%8B%E5%8C%96Broker%E5%88%97%E8%A1%A8%0Akey.serializer%2Fvalue.serializer%20%20-%3E%20Key%E5%92%8Cvalue%E5%BA%8F%E5%88%97%E5%8C%96%E5%99%A8%0Aacks%20-%3E%20%E5%8F%AF%E9%9D%A0%E6%80%A7%E7%BA%A7%E5%88%AB%EF%BC%9A%E5%8F%AF%E9%80%89%E5%80%BC%EF%BC%9A0%EF%BC%8C1(default)%EF%BC%8Call%0Abuffer.memory%20-%3E%20Producer%E6%95%B0%E6%8D%AE%E7%BC%93%E5%AD%98%E5%A4%A7%E5%B0%8F%EF%BC%88%E7%AD%89%E5%88%B0%E6%BB%A1%E5%90%8E%E4%BC%9A%E5%8F%91%E7%BB%99broker%EF%BC%89%0Acompression.type%20-%3E%20%E6%95%B0%E6%8D%AE%E5%8E%8B%E7%BC%A9%E6%96%B9%E5%BC%8F%EF%BC%9Anone%2C%20gzip%2C%20snappy%2C%20%E6%88%96lz4.%0Amax.request.size%2Fbatch.size%20%20-%3E%20%E6%AF%8F%E4%B8%AAbatch%E6%95%B0%E6%8D%AE%E9%87%8F%0A%60%60%60%0A%0A%23%23%23%23%23%20%E5%8F%91%E9%80%81%E4%BF%A1%E6%81%AF%E5%88%B0kafka%20broker%0A%0A%60producer.send(new%20ProducerRecord%3CString%2C%20String%3E(%22test%22%2C%20Integer.toString(i)%2C%20Integer.toString(i)))%3B%60%0A%0A%23%23%23%23%23%20producer%20configuration%20doc%0A%0Ahttp%3A%2F%2Fkafka.apache.org%2F0100%2Fdocumentation.html%23producerconfigs%0A%0A%23%23%23%23%23%20Kafka%20consumer%E7%A8%8B%E5%BA%8F%0A%0A%60%60%60%0AKafkaConsumer%20-%3E%20%E4%B8%8EKafka%20broker%E9%80%9A%E4%BF%A1%E7%9A%84%E7%B1%BB%EF%BC%8C%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95%E6%98%AFsubscribe%E5%92%8Cpoll%0AConsumerRecord%20-%3E%20%E4%B8%80%E4%B8%AA%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%8C%85%E5%90%ABtopic%EF%BC%8Coffset%EF%BC%8Ckey%2Fvalue%EF%BC%8Ctimestamp%E7%AD%89%E4%BF%A1%E6%81%AF%0AConsumerRecords%20-%3E%20%E4%B8%80%E7%BB%84%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%EF%BC%8C%E4%BF%9D%E5%AD%98%E6%AF%8F%E4%B8%AApartition%E5%AF%B9%E5%BA%94%E7%9A%84%E7%BB%93%E6%9E%9C%E9%9B%86%0AConsumerConfig%20-%3E%20%E5%8F%82%E6%95%B0%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%8F%AF%E9%80%9A%E8%BF%87%E8%AF%A5%E5%AF%B9%E8%B1%A1%E8%AE%BE%E7%BD%AE%E7%A8%8B%E5%BA%8F%E5%8F%82%E6%95%B0%0A%60%60%60%0A%0A%60%60%60java%0AProperties%20props%20%3D%20new%20Properties()%3B%0Aprops.put(%E2%80%9Cbootstrap.servers%E2%80%9D%2C%20%E2%80%9Ctest1%2Ctest2%2Ctest3%E2%80%9D)%3B%0Aprops.put(%22groupid%22%2C%20%E2%80%9C123%E2%80%9D)%3B%0Aprops.put(%22enable.auto.commit%22%2C%20%E2%80%9Dtrue%22)%3B%0Aprops.put(%22key.deserializer%22%2C%20%22org.apache.kafka.common.serialization.StringDeserializer%22)%3B%0Aprops.put(%22value.deserializer%22%2C%20%22org.apache.kafka.common.serialization.StringDeserializer%22%0Aconsumer%20%3D%20new%20KafkaConsumer%3C%3E(props)%3B%0A%60%60%60%0A%0A%23%23%23%23%23%20Kafka%20consumer%E9%87%8D%E8%A6%81%E5%8F%82%E6%95%B0%0A%0A%60%60%60%0Abootstrap.servers%20-%3E%20%E5%88%9D%E5%A7%8B%E5%8C%96Broker%E5%88%97%E8%A1%A8%0Akey.deserializer%2Fvalue.deserializer%20-%3E%20Key%E5%92%8Cvalue%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%99%A8%0Afetch.min.bytes%20-%3E%20%E6%AF%8F%E6%AC%A1%E8%AF%B7%E6%B1%82%E8%87%B3%E5%B0%91%E8%BF%94%E5%9B%9E%E7%9A%84%E6%95%B0%E6%8D%AE%E5%A4%A7%E5%B0%8F%EF%BC%88%E9%BB%98%E8%AE%A4%E6%98%AF1%E5%AD%97%E8%8A%82%EF%BC%89%0Agroup.id%20-%3E%20Consumer%E6%89%80%E5%9C%A8%E7%9A%84group%0Asession.timeout.ms%20%20-%3E%20Session%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%EF%BC%8C%E4%B8%80%E6%97%A6%E8%B6%85%E6%97%B6%EF%BC%8C%E8%AF%A5consuemer%E5%B0%86%E8%A2%AB%E7%A7%BB%E9%99%A4%E6%89%80%E5%9C%A8group%0Aenable.auto.commit%20%20-%3E%20%E6%98%AF%E5%90%A6%E8%87%AA%E5%8A%A8%E6%8F%90%E4%BA%A4offset%0A%60%60%60%0A%0A%60%60%60java%0A%2F%2F%20subscribe%20topics%0Aconsumer.subscribe(Arrays.asList(topic))%3B%0A%2F%2F%20read%20data%20from%20subscribed%20topics%0AConsumerRecords%3CString%2C%20String%3E%20records%20%3D%20consumer.poll(10000)%3B%0A%60%60%60%0A%0A%23%23%23%23%23%20consumer%20configuration%20doc%0A%0Ahttp%3A%2F%2Fkafka.apache.org%2F0100%2Fdocumentation.html%23consumerconfigs%0A%0A%23%23%23%23%23%20Kafka%20consumer%E7%A8%8B%E5%BA%8F%E8%AF%B4%E6%98%8E%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E6%9F%90%E4%B8%AAtopic%E7%9A%84%E5%88%86%E5%8C%BA%E6%95%B0%E5%B0%8F%E4%BA%8E%E6%8E%A5%E6%94%B6%E7%BA%BF%E7%A8%8B%E6%95%B0%EF%BC%8C%E5%88%99%E9%83%A8%E5%88%86%E7%BA%BF%E7%A8%8B%E7%A9%BA%E9%97%B2%0A%3E%20%E5%A6%82%E6%9E%9Ctopic%E7%9A%84%E5%88%86%E5%8C%BA%E6%95%B0%E5%A4%A7%E4%BA%8E%E6%8E%A5%E6%94%B6%E7%BA%BF%E7%A8%8B%E6%95%B0%EF%BC%8C%E5%88%99%E9%83%A8%E5%88%86%E6%8E%A5%E6%94%B6%E7%BA%BF%E7%A8%8B%E4%BC%9A%E5%90%8C%E6%97%B6%E8%AF%BB%E5%8F%96%E5%A4%9A%E4%B8%AA%E5%88%86%E5%8C%BA%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%0A%3E%20%E5%90%8C%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%94%B6%E5%88%B0%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%83%BD%E6%9D%A5%E8%87%AA%E5%A4%9A%E4%B8%AAPartition%EF%BC%8C%E4%B8%8D%E4%BF%9D%E8%AF%81%E6%95%B0%E6%8D%AE%E7%9A%84%E9%A1%BA%E5%BA%8F%E6%80%A7%0A%0A%23%23%23%23%23%20%E5%90%AF%E5%8A%A8zookeeper%0A%0A%60bin%2Fzookeeper-server-start.sh%C2%A0%20config%2Fzookeeper.properties%20%26%60%0A%0A%23%23%23%23%23%20%E5%90%AF%E5%8A%A8Kafka%20Broker%0A%0A%60%60%60%0Abin%2Fkafka-server-start.sh%20-daemon%20config%2Fserver.properties%0Ajps%20%7C%20grep%20Kafka%0A%E5%A6%82%E6%9E%9C%E5%90%AF%E5%8A%A8%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%9F%A5%E7%9C%8Bkafka%E5%AE%89%E8%A3%85%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84logs%2FkafkaServer.out%E6%96%87%E4%BB%B6%EF%BC%8C%E5%AF%BB%E6%89%BE%E5%A4%B1%E8%B4%A5%E5%8E%9F%E5%9B%A0%0A%60%60%60%0A%0A%23%23%23%23%23%20%E5%88%9B%E5%BB%BAtopic%EF%BC%8C%E5%90%8D%E5%AD%97%E4%B8%BAtest%EF%BC%8C%E5%8C%85%E5%90%AB5%E4%B8%AA%E5%88%86%E5%8C%BA%EF%BC%8C%E5%89%AF%E6%9C%AC%E6%95%B0%E4%B8%BA1%EF%BC%8C%E6%95%B0%E6%8D%AE%E4%BF%9D%E7%95%99%E6%97%B6%E9%95%BF%E4%B8%BA2%E5%A4%A9%EF%BC%88%E9%BB%98%E8%AE%A4%E6%98%AF1%E5%A4%A9%EF%BC%89%0A%0A%60%60%60%0Abin%2Fkafka-topics.sh%20--create%20--zookeeper%20localhost%3A2181%20--replication-factor%201%20--partitions%205%20--topic%20test%20--config%20delete.retention.ms%3D172800000%0A%60%60%60%0A%0A%23%23%23%23%23%20%E7%94%9F%E4%BA%A7%E6%95%B0%E6%8D%AE%0A%0A%60bin%2Fkafka-console-producer.sh%20--broker-list%20localhost%3A9092%20--topic%20test%60%0A%0A%23%23%23%23%23%20%E5%90%AF%E5%8A%A8%E4%B8%80%E4%B8%AA%E7%BB%88%E7%AB%AF%E6%B6%88%E8%B4%B9%E6%95%B0%E6%8D%AE%0A%0A%60%60%60%0Abin%2Fkafka-console-consumer.sh%20--bootstrap-server%20localhost%3A9092%20--topic%20test%20--from-beginning%0A%60%60%60%0A%0A%23%23%23%23%23%20open%20issues%0A%0A%3E%20%E4%B8%BA%E4%BB%80%E4%B9%88%E8%AF%B4Partition%E6%98%AFKafka%E6%A8%AA%E5%90%91%E6%89%A9%E5%B1%95%E5%92%8C%E4%B8%80%E5%88%87%E5%B9%B6%E8%A1%8C%E5%8C%96%E7%9A%84%E5%9F%BA%E7%A1%80%EF%BC%8C%E6%AF%8F%E4%B8%AAtopic%E8%87%B3%E5%B0%91%E8%A2%AB%E5%88%87%E5%88%86%E6%88%901%E4%B8%AApartition%20%3F%0A%0A

rocketmq links

创建时间:2020/9/2 14:11
更新时间:2020/9/2 14:31
作者:Chris

https://www.jianshu.com/p/2838890f3284
https://www.cnblogs.com/520playboy/p/6750023.html
https://www.cnblogs.com/SimpleWu/p/12112351.html
https://www.cnblogs.com/xiaobaoTribe/p/11381675.html

rocketMq-Console

https://www.jianshu.com/p/5b0cde62b3fc

rocketMq-Topic创建过程

https://www.jianshu.com/p/345aaa18f71d

RocketMQ进击

https://blog.csdn.net/itanping/article/details/100919270

https%3A%2F%2Fwww.jianshu.com%2Fp%2F2838890f3284%0Ahttps%3A%2F%2Fwww.cnblogs.com%2F520playboy%2Fp%2F6750023.html%0Ahttps%3A%2F%2Fwww.cnblogs.com%2FSimpleWu%2Fp%2F12112351.html%0Ahttps%3A%2F%2Fwww.cnblogs.com%2FxiaobaoTribe%2Fp%2F11381675.html%0A%0A%23%23%23%23%23%20rocketMq-Console%0A%0A%3E%20https%3A%2F%2Fwww.jianshu.com%2Fp%2F5b0cde62b3fc%0A%0A%23%23%23%23%23%20rocketMq-Topic%E5%88%9B%E5%BB%BA%E8%BF%87%E7%A8%8B%0A%0A%3E%20https%3A%2F%2Fwww.jianshu.com%2Fp%2F345aaa18f71d%0A%0A%23%23%23%23%23%20RocketMQ%E8%BF%9B%E5%87%BB%0A%0A%3E%20https%3A%2F%2Fblog.csdn.net%2Fitanping%2Farticle%2Fdetails%2F100919270

easypoi

创建时间:2020/11/3 9:19
更新时间:2020/11/3 9:19
作者:Chris

http://easypoi.mydoc.io/

http%3A%2F%2Feasypoi.mydoc.io%2F%0A

node.js installment

创建时间:2020/10/23 12:51
更新时间:2020/10/24 6:57
作者:Chris
来源:https://www.cnblogs.com/zhi-leaf/p/10979629.html

Centos7

1.下载

https://nodejs.org/en/download/

cd /usr/local/
scp node-v12.19.0-linux-x64.tar.xz root@master:/usr/local

2.安装

tar -xvf node-v12.19.0-linux-x64.tar.xz       // 解压
mv node-v12.19.0-linux-x64 nodejs

3.让npm和node命令全局生效

ln -s /usr/local/nodejs/bin/npm  /usr/local/bin/
ln -s /usr/local/nodejs/bin/node /usr/local/bin/

4.查看nodejs是否安装成功

node -v
npm -v

Win10

1.下载

https://nodejs.org/en/download/

2.安装

默认安装,点击下一步

3. 校验版本

Win + R , 输入cmd ,打开dos命令行,输入 node -v 查看NodeJS版本号

4.环境变量配置

环境配置主要配置的是npm安装的全局模块所在的路径,以及缓存cache的路径.

之所以要配置,是因为以后在执行类似:npm install express [-g] (后面的可选参数-g,g代表global全局安装的意思)的安装语句时,会将安装的模块安装到【C:\Users\用户名\AppData\Roaming\npm】路径中,占C盘空间

4.1 新建目录

node_global
node_cache

4.2 设置

在当前文件夹,长按Shift + 鼠标右键 打开cmd命令行

npm config set prefix "F:\Program Files\nodejs\node_global"
npm config set cache  "F:\Program Files\nodejs\node_cache"
4.3 设置环境变量
4.3.1 设置系统环境变量

在【系统变量】下新建【NODE_PATH】
NODE_PATH
F:\Program Files\nodejs\node_global\node_modules

4.3.2 设置用户环境变量

将【用户变量】下的【Path】追加
Path
F:\Program Files\nodejs\node_global

4.4 测试

npm install express -g # -g是全局安装的意思

npm install express -g

%5Btoc%5D%0A%23%23%23%20Centos7%0A%23%23%23%23%201.%E4%B8%8B%E8%BD%BD%0A%0Ahttps%3A%2F%2Fnodejs.org%2Fen%2Fdownload%2F%0A%0A%60%60%60%0Acd%20%2Fusr%2Flocal%2F%0Ascp%20node-v12.19.0-linux-x64.tar.xz%20root%40master%3A%2Fusr%2Flocal%0A%60%60%60%0A%0A%23%23%23%23%202.%E5%AE%89%E8%A3%85%0A%60%60%60%0Atar%20-xvf%20node-v12.19.0-linux-x64.tar.xz%20%20%20%20%20%20%20%2F%2F%20%E8%A7%A3%E5%8E%8B%0Amv%20node-v12.19.0-linux-x64%20nodejs%0A%60%60%60%0A%0A%23%23%23%23%203.%E8%AE%A9npm%E5%92%8Cnode%E5%91%BD%E4%BB%A4%E5%85%A8%E5%B1%80%E7%94%9F%E6%95%88%0A%60%60%60%0Aln%20-s%20%2Fusr%2Flocal%2Fnodejs%2Fbin%2Fnpm%20%20%2Fusr%2Flocal%2Fbin%2F%0Aln%20-s%20%2Fusr%2Flocal%2Fnodejs%2Fbin%2Fnode%20%2Fusr%2Flocal%2Fbin%2F%0A%60%60%60%0A%0A%0A%23%23%23%23%204.%E6%9F%A5%E7%9C%8Bnodejs%E6%98%AF%E5%90%A6%E5%AE%89%E8%A3%85%E6%88%90%E5%8A%9F%0A%0A%60%60%60%0Anode%20-v%0Anpm%20-v%0A%60%60%60%0A!%5Bdc4136c178015130672d95c64894a595.png%5D(en-resource%3A%2F%2Fdatabase%2F924%3A1)%0A%0A%23%23%23%20Win10%0A%0A%23%23%23%23%201.%E4%B8%8B%E8%BD%BD%0Ahttps%3A%2F%2Fnodejs.org%2Fen%2Fdownload%2F%0A!%5B942c1bd5e407598054e3265071ce1af1.png%5D(en-resource%3A%2F%2Fdatabase%2F928%3A0)%0A%0A%23%23%23%23%202.%E5%AE%89%E8%A3%85%0A%3E%20%E9%BB%98%E8%AE%A4%E5%AE%89%E8%A3%85%EF%BC%8C%E7%82%B9%E5%87%BB%E4%B8%8B%E4%B8%80%E6%AD%A5%0A%0A%23%23%23%23%203.%20%E6%A0%A1%E9%AA%8C%E7%89%88%E6%9C%AC%0A%3E%20Win%20%2B%20R%20%2C%20%E8%BE%93%E5%85%A5cmd%20%EF%BC%8C%E6%89%93%E5%BC%80dos%E5%91%BD%E4%BB%A4%E8%A1%8C%EF%BC%8C%E8%BE%93%E5%85%A5%C2%A0node%20-v%C2%A0%E6%9F%A5%E7%9C%8BNodeJS%E7%89%88%E6%9C%AC%E5%8F%B7%0A%0A%23%23%23%23%204.%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E9%85%8D%E7%BD%AE%0A%0A%3E%20%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E4%B8%BB%E8%A6%81%E9%85%8D%E7%BD%AE%E7%9A%84%E6%98%AFnpm%E5%AE%89%E8%A3%85%E7%9A%84%E5%85%A8%E5%B1%80%E6%A8%A1%E5%9D%97%E6%89%80%E5%9C%A8%E7%9A%84%E8%B7%AF%E5%BE%84%EF%BC%8C%E4%BB%A5%E5%8F%8A%E7%BC%93%E5%AD%98cache%E7%9A%84%E8%B7%AF%E5%BE%84.%0A%3E%0A%3E%20%E4%B9%8B%E6%89%80%E4%BB%A5%E8%A6%81%E9%85%8D%E7%BD%AE%EF%BC%8C%E6%98%AF%E5%9B%A0%E4%B8%BA%E4%BB%A5%E5%90%8E%E5%9C%A8%E6%89%A7%E8%A1%8C%E7%B1%BB%E4%BC%BC%EF%BC%9Anpm%20install%20express%20%5B-g%5D%20%EF%BC%88%E5%90%8E%E9%9D%A2%E7%9A%84%E5%8F%AF%E9%80%89%E5%8F%82%E6%95%B0-g%EF%BC%8Cg%E4%BB%A3%E8%A1%A8global%E5%85%A8%E5%B1%80%E5%AE%89%E8%A3%85%E7%9A%84%E6%84%8F%E6%80%9D%EF%BC%89%E7%9A%84%E5%AE%89%E8%A3%85%E8%AF%AD%E5%8F%A5%E6%97%B6%EF%BC%8C%E4%BC%9A%E5%B0%86%E5%AE%89%E8%A3%85%E7%9A%84%E6%A8%A1%E5%9D%97%E5%AE%89%E8%A3%85%E5%88%B0%E3%80%90C%3A%5CUsers%5C%E7%94%A8%E6%88%B7%E5%90%8D%5CAppData%5CRoaming%5Cnpm%E3%80%91%E8%B7%AF%E5%BE%84%E4%B8%AD%EF%BC%8C%E5%8D%A0C%E7%9B%98%E7%A9%BA%E9%97%B4%0A%0A%23%23%23%23%23%204.1%20%E6%96%B0%E5%BB%BA%E7%9B%AE%E5%BD%95%0Anode_global%0Anode_cache%0A%0A!%5B376871c96cafc72e229971a2d29daadf.png%5D(en-resource%3A%2F%2Fdatabase%2F930%3A0)%0A%0A%23%23%23%23%23%204.2%20%E8%AE%BE%E7%BD%AE%0A%0A%3E%20%E5%9C%A8%E5%BD%93%E5%89%8D%E6%96%87%E4%BB%B6%E5%A4%B9%EF%BC%8C%E9%95%BF%E6%8C%89Shift%20%2B%20%E9%BC%A0%E6%A0%87%E5%8F%B3%E9%94%AE%20%E6%89%93%E5%BC%80cmd%E5%91%BD%E4%BB%A4%E8%A1%8C%0A%0A!%5Bf7afb87d972ffc17386706ac09a80e06.png%5D(en-resource%3A%2F%2Fdatabase%2F932%3A0)%0A%0A%60%60%60%0Anpm%20config%20set%20prefix%20%22F%3A%5CProgram%20Files%5Cnodejs%5Cnode_global%22%0Anpm%20config%20set%20cache%20%20%22F%3A%5CProgram%20Files%5Cnodejs%5Cnode_cache%22%0A%60%60%60%0A%0A%0A%23%23%23%23%23%204.3%20%E8%AE%BE%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%0A%23%23%23%23%23%23%204.3.1%20%E8%AE%BE%E7%BD%AE%E7%B3%BB%E7%BB%9F%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%0A%3E%20%E5%9C%A8%E3%80%90%E7%B3%BB%E7%BB%9F%E5%8F%98%E9%87%8F%E3%80%91%E4%B8%8B%E6%96%B0%E5%BB%BA%E3%80%90NODE_PATH%E3%80%91%0ANODE_PATH%0AF%3A%5CProgram%20Files%5Cnodejs%5Cnode_global%5Cnode_modules%0A%0A%23%23%23%23%23%23%204.3.2%20%E8%AE%BE%E7%BD%AE%E7%94%A8%E6%88%B7%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%0A%3E%20%E5%B0%86%E3%80%90%E7%94%A8%E6%88%B7%E5%8F%98%E9%87%8F%E3%80%91%E4%B8%8B%E7%9A%84%E3%80%90Path%E3%80%91%E8%BF%BD%E5%8A%A0%0A%3E%20Path%0A%3E%20F%3A%5CProgram%20Files%5Cnodejs%5Cnode_global%0A%0A%23%23%23%23%23%204.4%20%E6%B5%8B%E8%AF%95%0A%3E%20npm%20install%20express%20-g%20%23%20-g%E6%98%AF%E5%85%A8%E5%B1%80%E5%AE%89%E8%A3%85%E7%9A%84%E6%84%8F%E6%80%9D%0A%60%60%60%0Anpm%20install%20express%20-g%0A%60%60%60%0A!%5B34512f79d9c3772a57323a6518edef2d.png%5D(en-resource%3A%2F%2Fdatabase%2F934%3A0)%0A

zk installment

创建时间:2020/9/2 22:06
更新时间:2020/10/23 11:44
作者:Chris

1. 安装

  1. root@master:/usr/local/zookeeper# wget https://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz

  2. tar -zxvf apache-zookeeper-3.6.2-bin.tar.gz

  3. mv apache-zookeeper-3.6.2-bin zookeeper

  4. cd zookeeper/conf

  5. 更改默认配置文件名称
    mv zoo_sample.cfg zoo.cfg

  6. 编辑配置文件,自定义dataDir
    vi zoo.cfg

    dataDir=/usr/local/zookeeper/data

2. 启动关闭

cd /bin
./zkServer.sh start

./zkServer.sh stop

使用 zkCli.sh 连接测试

root@master:/usr/local/zookeeper/bin# ./zkCli.sh -server 127.0.0.1:2181
[zk: 127.0.0.1:2181(CONNECTED) 7] ls /
[zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 8] ls /zookeeper
[config, quota]
   
%23%23%23%23%201.%20%E5%AE%89%E8%A3%85%0A%0A1.%20root%40master%3A%2Fusr%2Flocal%2Fzookeeper%23%20wget%20https%3A%2F%2Fmirror.bit.edu.cn%2Fapache%2Fzookeeper%2Fzookeeper-3.6.2%2Fapache-zookeeper-3.6.2-bin.tar.gz%0A%0A2.%20tar%20-zxvf%20apache-zookeeper-3.6.2-bin.tar.gz%0A3.%20%20mv%20apache-zookeeper-3.6.2-bin%20zookeeper%0A4.%20cd%20zookeeper%2Fconf%0A%0A5.%20%20%E6%9B%B4%E6%94%B9%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%90%8D%E7%A7%B0%0A%20%20%20mv%20zoo_sample.cfg%20%20zoo.cfg%0A%0A6.%20%E7%BC%96%E8%BE%91%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%EF%BC%8C%E8%87%AA%E5%AE%9A%E4%B9%89dataDir%0A%20%20%20vi%20zoo.cfg%20%0A%0A%20%20%20dataDir%3D%2Fusr%2Flocal%2Fzookeeper%2Fdata%0A%0A%23%23%23%23%202.%20%E5%90%AF%E5%8A%A8%E5%85%B3%E9%97%AD%0A%0A%60%60%60%0Acd%20%2Fbin%0A.%2FzkServer.sh%20start%0A%0A.%2FzkServer.sh%20stop%0A%60%60%60%0A!%5Bef4a0874524a40c9d8fb36dce99870df.png%5D(en-resource%3A%2F%2Fdatabase%2F659%3A1)%0A%0A%0A%E4%BD%BF%E7%94%A8%20zkCli.sh%20%E8%BF%9E%E6%8E%A5%E6%B5%8B%E8%AF%95%0A%0A%60%60%60shell%0Aroot%40master%3A%2Fusr%2Flocal%2Fzookeeper%2Fbin%23%20.%2FzkCli.sh%20-server%20127.0.0.1%3A2181%0A%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%207%5D%20ls%20%2F%0A%5Bzookeeper%5D%0A%5Bzk%3A%20127.0.0.1%3A2181(CONNECTED)%208%5D%20ls%20%2Fzookeeper%0A%5Bconfig%2C%20quota%5D%0A%20%20%20%0A%60%60%60

对象与垃圾回收

创建时间:2020/10/14 23:38
更新时间:2020/10/14 23:50
作者:Chris

1. 对象在内存中的状态

1.1 可达状态

当一个对象被创建后,有一个以上的引用变量引用它。那么它就出于可达状态,程序可以通过引用变量来调用该对象的属性和方法。

1.2 可恢复状态

如果程序中某个对象不再有任何引用变量引用它,他将进入可恢复状态,
在这种状态下,系统的垃圾回收机制准备回收该对象所占用的内存。在回收该对象之前,系统会调用可恢复状态的对象的finalize方法进行资源清理,如果系统调用finalize方法重新让一个以上的引用变量引用该对象,则该对象会再次编程可达状态;否则,该对象将进入不可达状态。

1.3 不可达状态

当对象的所有关联都被切断,且系统调用所有对象的finalize方法依然没有使该对象变成可达状态后,这个对象将永久性地失去引用,最后变成不可达状态。只有当一个对象出于不可达状态,系统才会真正回收该对象所占用的资源。

2. 触发GC的方法

调用 System 类的 gc() 静态方法:System.gc()
调用 Runtime 对象的 gc() 实例方法:Runtime.getRuntime().gc()

这种强制只是建议系统立即进行垃圾回收,系统完全有可能建议完全置之不理,垃圾回收机制会在收到通知后,尽快进行垃圾回收。

3 finalize 方法

永远不要主动调用某个对象的finalize 方法
该方法应交给垃圾回收机制调用。finalize 方法何时被调用,是否被调用具有不确定性,不要把finalize 方法当成一定会被执行的方法。

在JVM的规范中,只规定了JVM必须要有垃圾回收机制,但是什么时候回收却没有明确说明。也就是说,对象成为了垃圾对象之后, 并不一定会马上就被垃圾回收。

由于 Sun 公司的 JVM 采用的是“最少”回收的机制,因此不应当把释放资源的代码写在 finalize 方法中。

%5Btoc%5D%0A%23%23%23%23%201.%20%E5%AF%B9%E8%B1%A1%E5%9C%A8%E5%86%85%E5%AD%98%E4%B8%AD%E7%9A%84%E7%8A%B6%E6%80%81%0A%23%23%23%23%23%201.1%20%E5%8F%AF%E8%BE%BE%E7%8A%B6%E6%80%81%0A%3E%20%E5%BD%93%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E8%A2%AB%E5%88%9B%E5%BB%BA%E5%90%8E%EF%BC%8C%E6%9C%89%E4%B8%80%E4%B8%AA%E4%BB%A5%E4%B8%8A%E7%9A%84%E5%BC%95%E7%94%A8%E5%8F%98%E9%87%8F%E5%BC%95%E7%94%A8%E5%AE%83%E3%80%82%E9%82%A3%E4%B9%88%E5%AE%83%E5%B0%B1%E5%87%BA%E4%BA%8E%E5%8F%AF%E8%BE%BE%E7%8A%B6%E6%80%81%EF%BC%8C%E7%A8%8B%E5%BA%8F%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%BC%95%E7%94%A8%E5%8F%98%E9%87%8F%E6%9D%A5%E8%B0%83%E7%94%A8%E8%AF%A5%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%B1%9E%E6%80%A7%E5%92%8C%E6%96%B9%E6%B3%95%E3%80%82%0A%0A%23%23%23%23%23%201.2%20%E5%8F%AF%E6%81%A2%E5%A4%8D%E7%8A%B6%E6%80%81%0A%3E%20%E5%A6%82%E6%9E%9C%E7%A8%8B%E5%BA%8F%E4%B8%AD%E6%9F%90%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%B8%8D%E5%86%8D%E6%9C%89%E4%BB%BB%E4%BD%95%E5%BC%95%E7%94%A8%E5%8F%98%E9%87%8F%E5%BC%95%E7%94%A8%E5%AE%83%EF%BC%8C%E4%BB%96%E5%B0%86%E8%BF%9B%E5%85%A5%E5%8F%AF%E6%81%A2%E5%A4%8D%E7%8A%B6%E6%80%81%EF%BC%8C%0A%E5%9C%A8%E8%BF%99%E7%A7%8D%E7%8A%B6%E6%80%81%E4%B8%8B%EF%BC%8C%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E5%87%86%E5%A4%87%E5%9B%9E%E6%94%B6%E8%AF%A5%E5%AF%B9%E8%B1%A1%E6%89%80%E5%8D%A0%E7%94%A8%E7%9A%84%E5%86%85%E5%AD%98%E3%80%82%E5%9C%A8%E5%9B%9E%E6%94%B6%E8%AF%A5%E5%AF%B9%E8%B1%A1%E4%B9%8B%E5%89%8D%EF%BC%8C%E7%B3%BB%E7%BB%9F%E4%BC%9A%E8%B0%83%E7%94%A8%E5%8F%AF%E6%81%A2%E5%A4%8D%E7%8A%B6%E6%80%81%E7%9A%84%E5%AF%B9%E8%B1%A1%E7%9A%84finalize%E6%96%B9%E6%B3%95%E8%BF%9B%E8%A1%8C%E8%B5%84%E6%BA%90%E6%B8%85%E7%90%86%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8finalize%E6%96%B9%E6%B3%95%E9%87%8D%E6%96%B0%E8%AE%A9%E4%B8%80%E4%B8%AA%E4%BB%A5%E4%B8%8A%E7%9A%84%E5%BC%95%E7%94%A8%E5%8F%98%E9%87%8F%E5%BC%95%E7%94%A8%E8%AF%A5%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%88%99%E8%AF%A5%E5%AF%B9%E8%B1%A1%E4%BC%9A%E5%86%8D%E6%AC%A1%E7%BC%96%E7%A8%8B%E5%8F%AF%E8%BE%BE%E7%8A%B6%E6%80%81%EF%BC%9B%E5%90%A6%E5%88%99%EF%BC%8C%E8%AF%A5%E5%AF%B9%E8%B1%A1%E5%B0%86%E8%BF%9B%E5%85%A5%E4%B8%8D%E5%8F%AF%E8%BE%BE%E7%8A%B6%E6%80%81%E3%80%82%0A%0A%23%23%23%23%23%201.3%20%E4%B8%8D%E5%8F%AF%E8%BE%BE%E7%8A%B6%E6%80%81%0A%3E%20%E5%BD%93%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%89%80%E6%9C%89%E5%85%B3%E8%81%94%E9%83%BD%E8%A2%AB%E5%88%87%E6%96%AD%EF%BC%8C%E4%B8%94%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E6%89%80%E6%9C%89%E5%AF%B9%E8%B1%A1%E7%9A%84finalize%E6%96%B9%E6%B3%95%E4%BE%9D%E7%84%B6%E6%B2%A1%E6%9C%89%E4%BD%BF%E8%AF%A5%E5%AF%B9%E8%B1%A1%E5%8F%98%E6%88%90%E5%8F%AF%E8%BE%BE%E7%8A%B6%E6%80%81%E5%90%8E%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%B0%86%E6%B0%B8%E4%B9%85%E6%80%A7%E5%9C%B0%E5%A4%B1%E5%8E%BB%E5%BC%95%E7%94%A8%EF%BC%8C%E6%9C%80%E5%90%8E%E5%8F%98%E6%88%90%E4%B8%8D%E5%8F%AF%E8%BE%BE%E7%8A%B6%E6%80%81%E3%80%82%E5%8F%AA%E6%9C%89%E5%BD%93%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%87%BA%E4%BA%8E%E4%B8%8D%E5%8F%AF%E8%BE%BE%E7%8A%B6%E6%80%81%EF%BC%8C%E7%B3%BB%E7%BB%9F%E6%89%8D%E4%BC%9A%E7%9C%9F%E6%AD%A3%E5%9B%9E%E6%94%B6%E8%AF%A5%E5%AF%B9%E8%B1%A1%E6%89%80%E5%8D%A0%E7%94%A8%E7%9A%84%E8%B5%84%E6%BA%90%E3%80%82%0A%0A!%5B940779050c738ff4df7b709b5c887cf4.png%5D(en-resource%3A%2F%2Fdatabase%2F916%3A0)%0A%0A%23%23%23%23%202.%20%E8%A7%A6%E5%8F%91GC%E7%9A%84%E6%96%B9%E6%B3%95%0A%0A%60%60%60%0A%E8%B0%83%E7%94%A8%20System%20%E7%B1%BB%E7%9A%84%20gc()%20%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%EF%BC%9ASystem.gc()%0A%E8%B0%83%E7%94%A8%20Runtime%20%E5%AF%B9%E8%B1%A1%E7%9A%84%20gc()%20%E5%AE%9E%E4%BE%8B%E6%96%B9%E6%B3%95%EF%BC%9ARuntime.getRuntime().gc()%0A%60%60%60%0A%0A%3E%20%E8%BF%99%E7%A7%8D%E5%BC%BA%E5%88%B6%E5%8F%AA%E6%98%AF%E5%BB%BA%E8%AE%AE%E7%B3%BB%E7%BB%9F%E7%AB%8B%E5%8D%B3%E8%BF%9B%E8%A1%8C%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%EF%BC%8C%E7%B3%BB%E7%BB%9F%E5%AE%8C%E5%85%A8%E6%9C%89%E5%8F%AF%E8%83%BD%E5%BB%BA%E8%AE%AE%E5%AE%8C%E5%85%A8%E7%BD%AE%E4%B9%8B%E4%B8%8D%E7%90%86%EF%BC%8C%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%BC%9A%E5%9C%A8%E6%94%B6%E5%88%B0%E9%80%9A%E7%9F%A5%E5%90%8E%EF%BC%8C%E5%B0%BD%E5%BF%AB%E8%BF%9B%E8%A1%8C%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E3%80%82%0A%0A%0A%23%23%23%23%203%20finalize%20%E6%96%B9%E6%B3%95%0A%0A%3E%20%E6%B0%B8%E8%BF%9C%E4%B8%8D%E8%A6%81%E4%B8%BB%E5%8A%A8%E8%B0%83%E7%94%A8%E6%9F%90%E4%B8%AA%E5%AF%B9%E8%B1%A1%E7%9A%84finalize%20%E6%96%B9%E6%B3%95%0A%E8%AF%A5%E6%96%B9%E6%B3%95%E5%BA%94%E4%BA%A4%E7%BB%99%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E8%B0%83%E7%94%A8%E3%80%82finalize%20%E6%96%B9%E6%B3%95%E4%BD%95%E6%97%B6%E8%A2%AB%E8%B0%83%E7%94%A8%EF%BC%8C%E6%98%AF%E5%90%A6%E8%A2%AB%E8%B0%83%E7%94%A8%E5%85%B7%E6%9C%89%E4%B8%8D%E7%A1%AE%E5%AE%9A%E6%80%A7%EF%BC%8C%E4%B8%8D%E8%A6%81%E6%8A%8Afinalize%20%E6%96%B9%E6%B3%95%E5%BD%93%E6%88%90%E4%B8%80%E5%AE%9A%E4%BC%9A%E8%A2%AB%E6%89%A7%E8%A1%8C%E7%9A%84%E6%96%B9%E6%B3%95%E3%80%82%0A%0A%3E%20%E5%9C%A8JVM%E7%9A%84%E8%A7%84%E8%8C%83%E4%B8%AD%EF%BC%8C%E5%8F%AA%E8%A7%84%E5%AE%9A%E4%BA%86JVM%E5%BF%85%E9%A1%BB%E8%A6%81%E6%9C%89%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%EF%BC%8C%E4%BD%86%E6%98%AF%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E5%9B%9E%E6%94%B6%E5%8D%B4%E6%B2%A1%E6%9C%89%E6%98%8E%E7%A1%AE%E8%AF%B4%E6%98%8E%E3%80%82%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E5%AF%B9%E8%B1%A1%E6%88%90%E4%B8%BA%E4%BA%86%E5%9E%83%E5%9C%BE%E5%AF%B9%E8%B1%A1%E4%B9%8B%E5%90%8E%EF%BC%8C%20%E5%B9%B6%E4%B8%8D%E4%B8%80%E5%AE%9A%E4%BC%9A%E9%A9%AC%E4%B8%8A%E5%B0%B1%E8%A2%AB%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E3%80%82%0A%0A%3E%20%E7%94%B1%E4%BA%8E%20Sun%20%E5%85%AC%E5%8F%B8%E7%9A%84%20JVM%20%E9%87%87%E7%94%A8%E7%9A%84%E6%98%AF%E2%80%9C%E6%9C%80%E5%B0%91%E2%80%9D%E5%9B%9E%E6%94%B6%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%B8%8D%E5%BA%94%E5%BD%93%E6%8A%8A%E9%87%8A%E6%94%BE%E8%B5%84%E6%BA%90%E7%9A%84%E4%BB%A3%E7%A0%81%E5%86%99%E5%9C%A8%20finalize%20%E6%96%B9%E6%B3%95%E4%B8%AD%E3%80%82%0A

引用类型

创建时间:2020/10/14 23:34
更新时间:2020/10/14 23:38
作者:Chris

1. 强引用

被强引用指向的对象,绝对不会被垃圾收集器回收。
Integer prime = 1; 这个语句中prime对象就有一个强引用。

2. 软引用

被SoftReference指向的对象可能会被垃圾收集器回收,但是只有在JVM内存不够的情况下才会回收;
如下代码可以创建一个软引用:

Integer prime = 1; 
SoftReference<Integer> soft = new SoftReference<Integer>(prime);
prime = null;

3. 弱引用

当一个对象仅仅被WeakReference引用时,在下个垃圾收集周期时候该对象就会被回收。
我们通过下面代码创建一个WeakReference:

Integer prime = 1; 
WeakReference<Integer> soft = new WeakReference<Integer>(prime);
prime = null;

当把prime赋值为null的时候,原prime对象会在下一个垃圾收集周期中被回收,因为已经没有强引用指向它。

%5Btoc%5D%0A%23%23%23%23%201.%20%E5%BC%BA%E5%BC%95%E7%94%A8%0A%3E%20%E8%A2%AB%E5%BC%BA%E5%BC%95%E7%94%A8%E6%8C%87%E5%90%91%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E7%BB%9D%E5%AF%B9%E4%B8%8D%E4%BC%9A%E8%A2%AB%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E5%9B%9E%E6%94%B6%E3%80%82%0A%3E%20Integer%20prime%20%3D%201%3B%20%E8%BF%99%E4%B8%AA%E8%AF%AD%E5%8F%A5%E4%B8%ADprime%E5%AF%B9%E8%B1%A1%E5%B0%B1%E6%9C%89%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%BC%95%E7%94%A8%E3%80%82%0A%0A%23%23%23%23%202.%20%E8%BD%AF%E5%BC%95%E7%94%A8%0A%3E%20%E8%A2%ABSoftReference%E6%8C%87%E5%90%91%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%8F%AF%E8%83%BD%E4%BC%9A%E8%A2%AB%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E5%9B%9E%E6%94%B6%EF%BC%8C%E4%BD%86%E6%98%AF%E5%8F%AA%E6%9C%89%E5%9C%A8JVM%E5%86%85%E5%AD%98%E4%B8%8D%E5%A4%9F%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E6%89%8D%E4%BC%9A%E5%9B%9E%E6%94%B6%EF%BC%9B%0A%3E%20%E5%A6%82%E4%B8%8B%E4%BB%A3%E7%A0%81%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%BD%AF%E5%BC%95%E7%94%A8%EF%BC%9A%0A%60%60%60%0AInteger%20prime%20%3D%201%3B%C2%A0%0ASoftReference%3CInteger%3E%20soft%20%3D%20new%20SoftReference%3CInteger%3E(prime)%3B%0Aprime%20%3D%20null%3B%0A%60%60%60%0A%0A%23%23%23%23%203.%20%E5%BC%B1%E5%BC%95%E7%94%A8%0A%3E%20%E5%BD%93%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%BB%85%E4%BB%85%E8%A2%ABWeakReference%E5%BC%95%E7%94%A8%E6%97%B6%EF%BC%8C%E5%9C%A8%E4%B8%8B%E4%B8%AA%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%91%A8%E6%9C%9F%E6%97%B6%E5%80%99%E8%AF%A5%E5%AF%B9%E8%B1%A1%E5%B0%B1%E4%BC%9A%E8%A2%AB%E5%9B%9E%E6%94%B6%E3%80%82%0A%3E%20%E6%88%91%E4%BB%AC%E9%80%9A%E8%BF%87%E4%B8%8B%E9%9D%A2%E4%BB%A3%E7%A0%81%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAWeakReference%EF%BC%9A%0A%60%60%60%0AInteger%20prime%20%3D%201%3B%C2%A0%0AWeakReference%3CInteger%3E%20soft%20%3D%20new%20WeakReference%3CInteger%3E(prime)%3B%0Aprime%20%3D%20null%3B%0A%60%60%60%0A%E5%BD%93%E6%8A%8Aprime%E8%B5%8B%E5%80%BC%E4%B8%BAnull%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%8E%9Fprime%E5%AF%B9%E8%B1%A1%E4%BC%9A%E5%9C%A8%E4%B8%8B%E4%B8%80%E4%B8%AA%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%91%A8%E6%9C%9F%E4%B8%AD%E8%A2%AB%E5%9B%9E%E6%94%B6%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%B7%B2%E7%BB%8F%E6%B2%A1%E6%9C%89%E5%BC%BA%E5%BC%95%E7%94%A8%E6%8C%87%E5%90%91%E5%AE%83%E3%80%82%0A

Comparable和Comparator

创建时间:2020/10/14 23:29
更新时间:2020/10/14 23:33
作者:Chris

Comparable 简介

Comparable 是排序接口。
若一个类实现了Comparable接口,就意味着“该类支持排序”。此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。
接口中通过 x.compareTo(y) 来比较x和y的大小。若返回负数,意味着x比y小;返回零,意味着x等于y;返回正数,意味着x大于y。

Comparator 简介

Comparator 是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。
int compare(T o1, T o2) 和上面的 x.compareTo(y) 类似,定义排序规则后返回正数,零和负数分别代表大于,等于和小于。

代码

https://blog.csdn.net/u010859650/article/details/85009595

%5Btoc%5D%0A%0A%23%23%23%23%20Comparable%20%E7%AE%80%E4%BB%8B%0A%3E%20Comparable%20%E6%98%AF%E6%8E%92%E5%BA%8F%E6%8E%A5%E5%8F%A3%E3%80%82%0A%E8%8B%A5%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%AE%9E%E7%8E%B0%E4%BA%86Comparable%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%B0%B1%E6%84%8F%E5%91%B3%E7%9D%80%E2%80%9C%E8%AF%A5%E7%B1%BB%E6%94%AF%E6%8C%81%E6%8E%92%E5%BA%8F%E2%80%9D%E3%80%82%E6%AD%A4%E5%A4%96%EF%BC%8C%E2%80%9C%E5%AE%9E%E7%8E%B0Comparable%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%E7%9A%84%E5%AF%B9%E8%B1%A1%E2%80%9D%E5%8F%AF%E4%BB%A5%E7%94%A8%E4%BD%9C%E2%80%9C%E6%9C%89%E5%BA%8F%E6%98%A0%E5%B0%84(%E5%A6%82TreeMap)%E2%80%9D%E4%B8%AD%E7%9A%84%E9%94%AE%E6%88%96%E2%80%9C%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88(TreeSet)%E2%80%9D%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%EF%BC%8C%E8%80%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E6%8C%87%E5%AE%9A%E6%AF%94%E8%BE%83%E5%99%A8%E3%80%82%0A%E6%8E%A5%E5%8F%A3%E4%B8%AD%E9%80%9A%E8%BF%87%20x.compareTo(y)%20%E6%9D%A5%E6%AF%94%E8%BE%83x%E5%92%8Cy%E7%9A%84%E5%A4%A7%E5%B0%8F%E3%80%82%E8%8B%A5%E8%BF%94%E5%9B%9E%E8%B4%9F%E6%95%B0%EF%BC%8C%E6%84%8F%E5%91%B3%E7%9D%80x%E6%AF%94y%E5%B0%8F%EF%BC%9B%E8%BF%94%E5%9B%9E%E9%9B%B6%EF%BC%8C%E6%84%8F%E5%91%B3%E7%9D%80x%E7%AD%89%E4%BA%8Ey%EF%BC%9B%E8%BF%94%E5%9B%9E%E6%AD%A3%E6%95%B0%EF%BC%8C%E6%84%8F%E5%91%B3%E7%9D%80x%E5%A4%A7%E4%BA%8Ey%E3%80%82%0A%0A%23%23%23%23%20Comparator%20%E7%AE%80%E4%BB%8B%0A%3E%20Comparator%20%E6%98%AF%E6%AF%94%E8%BE%83%E5%99%A8%E6%8E%A5%E5%8F%A3%E3%80%82%0A%E6%88%91%E4%BB%AC%E8%8B%A5%E9%9C%80%E8%A6%81%E6%8E%A7%E5%88%B6%E6%9F%90%E4%B8%AA%E7%B1%BB%E7%9A%84%E6%AC%A1%E5%BA%8F%EF%BC%8C%E8%80%8C%E8%AF%A5%E7%B1%BB%E6%9C%AC%E8%BA%AB%E4%B8%8D%E6%94%AF%E6%8C%81%E6%8E%92%E5%BA%8F(%E5%8D%B3%E6%B2%A1%E6%9C%89%E5%AE%9E%E7%8E%B0Comparable%E6%8E%A5%E5%8F%A3)%EF%BC%9B%E9%82%A3%E4%B9%88%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E5%BB%BA%E7%AB%8B%E4%B8%80%E4%B8%AA%E2%80%9C%E8%AF%A5%E7%B1%BB%E7%9A%84%E6%AF%94%E8%BE%83%E5%99%A8%E2%80%9D%E6%9D%A5%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%E3%80%82%E8%BF%99%E4%B8%AA%E2%80%9C%E6%AF%94%E8%BE%83%E5%99%A8%E2%80%9D%E5%8F%AA%E9%9C%80%E8%A6%81%E5%AE%9E%E7%8E%B0Comparator%E6%8E%A5%E5%8F%A3%E5%8D%B3%E5%8F%AF%E3%80%82%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E2%80%9C%E5%AE%9E%E7%8E%B0Comparator%E7%B1%BB%E6%9D%A5%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%AF%94%E8%BE%83%E5%99%A8%E2%80%9D%EF%BC%8C%E7%84%B6%E5%90%8E%E9%80%9A%E8%BF%87%E8%AF%A5%E6%AF%94%E8%BE%83%E5%99%A8%E5%AF%B9%E7%B1%BB%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%E3%80%82%0Aint%20compare(T%20o1%2C%20T%20o2)%20%E5%92%8C%E4%B8%8A%E9%9D%A2%E7%9A%84%20x.compareTo(y)%20%E7%B1%BB%E4%BC%BC%EF%BC%8C%E5%AE%9A%E4%B9%89%E6%8E%92%E5%BA%8F%E8%A7%84%E5%88%99%E5%90%8E%E8%BF%94%E5%9B%9E%E6%AD%A3%E6%95%B0%EF%BC%8C%E9%9B%B6%E5%92%8C%E8%B4%9F%E6%95%B0%E5%88%86%E5%88%AB%E4%BB%A3%E8%A1%A8%E5%A4%A7%E4%BA%8E%EF%BC%8C%E7%AD%89%E4%BA%8E%E5%92%8C%E5%B0%8F%E4%BA%8E%E3%80%82%0A%0A%0A%23%23%23%23%20%E4%BB%A3%E7%A0%81%0Ahttps%3A%2F%2Fblog.csdn.net%2Fu010859650%2Farticle%2Fdetails%2F85009595

tomcat性能优化

创建时间:2020/9/2 15:02
更新时间:2020/10/13 11:23
作者:Chris

1. tomcat 的工作原理

1.1 目录结构
bin:   启停脚本
conf:  配置文件 server.xml和web.xml
lib:   运行相关的jar文件
logs: 日志文件
temp:  临时文件
webapps: 要发布的程序文件
work:  编译后产生的class文件
doc:   存在tomcat文档
1.2 请求处理原理

  1. 客户端向服务器server发请求

  2. 连接器connector,默认端口号为8080,连接器为两种一种是http,一种是ajp

  3. 连接器请求发给engine

  4. 将访问的资源解释到虚拟主机host

  5. 匹配到需要的虚拟主机host

  6. 通过context获取请求,并通过mapping table 找到对应的servlet

  7. servlet封装request和response,并将结果返回给engine

  8. engine再将结果返回给connector

  9. connector再将结果返回到客户端

注: **servlet 是以servlet编码方式写的一个tomcat服务器端
​ tomcat是一个web服务器只能处理静态内容,所以需要通过
servlet **的方式进行请求处理
mapping table 在tomcat中的./conf/web.xml

2. tomcat的监控

2.1 status监控
2.1.1 配置用户及角色,

​ 目的是为了配置登录监控界面的用户

文件目录: ./conf/tomcat-users.xml

配置的用户名可以随便起名,但是角色
​admin-gui: 是用来访问Server Status
​manager-gui:是用来访问Host Manager

    <user username="test" password="test" roles="admin-gui, manager-gui"/>

2.1.2 重启服务器
/usr/local/apache-tomcat-8.5.31/bin/shutdown.sh
/usr/local/apache-tomcat-8.5.31/bin/startup.sh
2.1.3 进入监控页面
1. http://ip:8080
2. http://ip:8080/manager/status
3. http://ip:8080/host-manager/html
2.1.4 修改权限

如果进入监控页面提示403,表示没有权限去访问服务器资源,需要修改如下文件的内容

1. /usr/local/apache-tomcat-8.5.31/webapps/manager/META-INF/context.xml
2. /usr/local/apache-tomcat-8.5.31/webapps/host-manager/META-INF/context.xml

将allow修改为对应的网段也可以全部修改为 *

2.2 probe [探针] 监控
2.2.1 安装
https://github.com/psi-probe/psi-probe/releases
下载probe.war包,放到\apache-tomcat-8.5.47\webapps下

2.2.2 配置权限

使用probe监控工具需要使用权限为manager-gui

文件目录: ./conf/tomcat-users.xml
<role rolename="manager-gui"/>
<user username="test" password="test" roles="manager-gui"/>
2.2.3 配置后重启tomcat
2.2.4 进入监控页面

http://localhost:8080/probe

3. 连接器

3.1 连接器种类

tomcat里面有两种连接器,HTTPAJP

<Connector port="8080" protocol="HTTP/1.1" --连接的协议及版本号,表示只能处理此协议的请求
               connectionTimeout="20000"   --连接超时时间,单位ms
               maxThreads="300"            --最大线程数,表示同时可以并发处理的线程数,一个http请求对应一个线程
               accountCount="150"          --最大排队数,若并发的请求数超过maxThreads,就需要排队,超过排队数的请求就被kill掉
               redirectPort="8443"         --重置端口号,http重置为https后端口号就变成了8443
               URIEncoding="UTF-8"
               />
3.2 日志文件分析
3.2.1 日志文件配置

/usr/local/tomcat/conf/logging.properties

#日志文件被记录下来的级别
1catalina.org.apache.juli.AsyncFileHandler.level = FINE
#日志文件保存的目录
1catalina.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
#日志文件的前缀
1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.
3.2.2 日志文件的级别

从高到低分别为:

SEVERE > WARNING > INFO > CONFIG > FINE > FINER > FINEST
3.2.3 日志文件开启和关闭
1catalina.org.apache.juli.AsyncFileHandler.level = OFF --表示不记录日志
1catalina.org.apache.juli.AsyncFileHandler.level = ON
3.2.4 日志文件种类
  1. localhost_access_log.2020-08-04.txt
192.168.140.1 - test [04/Aug/2020:09:06:06 +0000] "GET /probe/js/Tooltip.js HTTP/1.1" 200 20051
192.168.140.1 --访问tomcat的客户端IP
test -- 用户名
+0000 -- 时区偏移
200  -- 最后结果的状态码
20051 -- 最后处理的字节数
  1. catalina.outcatalina.2020-08-04.log 类似

    主要记录tomcat服务器启停相关的线程信息

  2. localhost.2020-08-04.log

    主要记录线程运行时调用的方法和属性以及JAVA线程号

%0A%0A%23%23%23%23%201.%20tomcat%20%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%0A%0A%23%23%23%23%23%20%20%20%20%20%20%20%20%20%20%201.1%20%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84%0A%60%60%60%0Abin%3A%20%20%20%E5%90%AF%E5%81%9C%E8%84%9A%E6%9C%AC%0Aconf%3A%20%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%20server.xml%E5%92%8Cweb.xml%0Alib%3A%20%20%20%E8%BF%90%E8%A1%8C%E7%9B%B8%E5%85%B3%E7%9A%84jar%E6%96%87%E4%BB%B6%0Alogs%EF%BC%9A%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%0Atemp%3A%20%20%E4%B8%B4%E6%97%B6%E6%96%87%E4%BB%B6%0Awebapps%3A%20%E8%A6%81%E5%8F%91%E5%B8%83%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%96%87%E4%BB%B6%0Awork%EF%BC%9A%20%20%E7%BC%96%E8%AF%91%E5%90%8E%E4%BA%A7%E7%94%9F%E7%9A%84class%E6%96%87%E4%BB%B6%0Adoc%3A%20%20%20%E5%AD%98%E5%9C%A8tomcat%E6%96%87%E6%A1%A3%0A%60%60%60%0A%0A%23%23%23%23%23%20%20%20%20%20%20%20%20%20%20%201.2%20%E8%AF%B7%E6%B1%82%E5%A4%84%E7%90%86%E5%8E%9F%E7%90%86%0A%0A!%5B698befd3ea0c673f1610780e479ce131.png%5D(en-resource%3A%2F%2Fdatabase%2F902%3A0)%0A%0A%0A%20%201.%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%91%E6%9C%8D%E5%8A%A1%E5%99%A8**server**%E5%8F%91%E8%AF%B7%E6%B1%82%0A%0A%20%202.%20%E8%BF%9E%E6%8E%A5%E5%99%A8**connector**%EF%BC%8C%E9%BB%98%E8%AE%A4%E7%AB%AF%E5%8F%A3%E5%8F%B7%E4%B8%BA8080%2C%E8%BF%9E%E6%8E%A5%E5%99%A8%E4%B8%BA%E4%B8%A4%E7%A7%8D%E4%B8%80%E7%A7%8D%E6%98%AFhttp%2C%E4%B8%80%E7%A7%8D%E6%98%AFajp%0A%0A%20%203.%20%E8%BF%9E%E6%8E%A5%E5%99%A8%E8%AF%B7%E6%B1%82%E5%8F%91%E7%BB%99**engine**%0A%0A%20%204.%20%E5%B0%86%E8%AE%BF%E9%97%AE%E7%9A%84%E8%B5%84%E6%BA%90%E8%A7%A3%E9%87%8A%E5%88%B0%E8%99%9A%E6%8B%9F%E4%B8%BB%E6%9C%BA**host**%0A%0A%20%205.%20%E5%8C%B9%E9%85%8D%E5%88%B0%E9%9C%80%E8%A6%81%E7%9A%84%E8%99%9A%E6%8B%9F%E4%B8%BB%E6%9C%BA**host**%0A%0A%20%206.%20%E9%80%9A%E8%BF%87**context**%E8%8E%B7%E5%8F%96%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%B9%B6%E9%80%9A%E8%BF%87**mapping%20table**%20%E6%89%BE%E5%88%B0%E5%AF%B9%E5%BA%94%E7%9A%84**servlet**%0A%0A%20%207.%20servlet%E5%B0%81%E8%A3%85request%E5%92%8Cresponse%EF%BC%8C%E5%B9%B6%E5%B0%86%E7%BB%93%E6%9E%9C%E8%BF%94%E5%9B%9E%E7%BB%99engine%0A%0A%20%208.%20engine%E5%86%8D%E5%B0%86%E7%BB%93%E6%9E%9C%E8%BF%94%E5%9B%9E%E7%BB%99connector%0A%0A%20%209.%20connector%E5%86%8D%E5%B0%86%E7%BB%93%E6%9E%9C%E8%BF%94%E5%9B%9E%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A%3E%20%20%E6%B3%A8%EF%BC%9A%20**servlet%20**%E6%98%AF%E4%BB%A5servlet%E7%BC%96%E7%A0%81%E6%96%B9%E5%BC%8F%E5%86%99%E7%9A%84%E4%B8%80%E4%B8%AAtomcat%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%0A%3E%20%20%E2%80%8B%20%20%20%20tomcat%E6%98%AF%E4%B8%80%E4%B8%AAweb%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8F%AA%E8%83%BD%E5%A4%84%E7%90%86%E9%9D%99%E6%80%81%E5%86%85%E5%AE%B9%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E9%80%9A%E8%BF%87**servlet%20**%E7%9A%84%E6%96%B9%E5%BC%8F%E8%BF%9B%E8%A1%8C%E8%AF%B7%E6%B1%82%E5%A4%84%E7%90%86%0A%3E%20%20%E2%80%8B%20%20%20%20**mapping%20table**%20%E5%9C%A8tomcat%E4%B8%AD%E7%9A%84.%2Fconf%2Fweb.xml%0A%0A%0A%0A%0A%0A%23%23%23%23%202.%20tomcat%E7%9A%84%E7%9B%91%E6%8E%A7%0A%0A%23%23%23%23%23%20%20%20%20%20%20%202.1%20status%E7%9B%91%E6%8E%A7%0A%0A%23%23%23%23%23%23%20%202.1.1%20%E9%85%8D%E7%BD%AE%E7%94%A8%E6%88%B7%E5%8F%8A%E8%A7%92%E8%89%B2%EF%BC%8C%0A%0A%E2%80%8B%20%20%20%E7%9B%AE%E7%9A%84%E6%98%AF%E4%B8%BA%E4%BA%86%E9%85%8D%E7%BD%AE%E7%99%BB%E5%BD%95%E7%9B%91%E6%8E%A7%E7%95%8C%E9%9D%A2%E7%9A%84%E7%94%A8%E6%88%B7%0A%0A%60%60%60%0A%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%EF%BC%9A%20.%2Fconf%2Ftomcat-users.xml%0A%60%60%60%0A%0A%3E%20%E9%85%8D%E7%BD%AE%E7%9A%84%E7%94%A8%E6%88%B7%E5%90%8D%E5%8F%AF%E4%BB%A5%E9%9A%8F%E4%BE%BF%E8%B5%B7%E5%90%8D%EF%BC%8C%E4%BD%86%E6%98%AF%E8%A7%92%E8%89%B2%0A%3E%20%E2%80%8Badmin-gui%3A%20%E6%98%AF%E7%94%A8%E6%9D%A5%E8%AE%BF%E9%97%AEServer%20Status%0A%3E%20%E2%80%8Bmanager-gui%3A%E6%98%AF%E7%94%A8%E6%9D%A5%E8%AE%BF%E9%97%AEHost%20Manager%0A%0A%60%60%60%0A%20%20%20%20%3Cuser%20username%3D%22test%22%20password%3D%22test%22%20roles%3D%22admin-gui%2C%20manager-gui%22%2F%3E%0A%60%60%60%0A%0A!%5Bb234fc82e4991d42535f657bb124c757.png%5D(en-resource%3A%2F%2Fdatabase%2F528%3A1)%0A%0A%0A%23%23%23%23%23%23%20%202.1.2%20%E9%87%8D%E5%90%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%0A%0A%60%60%60shell%0A%2Fusr%2Flocal%2Fapache-tomcat-8.5.31%2Fbin%2Fshutdown.sh%0A%2Fusr%2Flocal%2Fapache-tomcat-8.5.31%2Fbin%2Fstartup.sh%0A%60%60%60%0A%0A%23%23%23%23%23%23%20%202.1.3%20%E8%BF%9B%E5%85%A5%E7%9B%91%E6%8E%A7%E9%A1%B5%E9%9D%A2%0A%0A%60%60%60%0A1.%20http%3A%2F%2Fip%3A8080%0A2.%20http%3A%2F%2Fip%3A8080%2Fmanager%2Fstatus%0A3.%20http%3A%2F%2Fip%3A8080%2Fhost-manager%2Fhtml%0A%60%60%60%0A%0A%23%23%23%23%23%23%20%202.1.4%20%E4%BF%AE%E6%94%B9%E6%9D%83%E9%99%90%0A%0A%E5%A6%82%E6%9E%9C%E8%BF%9B%E5%85%A5%E7%9B%91%E6%8E%A7%E9%A1%B5%E9%9D%A2%E6%8F%90%E7%A4%BA403%EF%BC%8C%E8%A1%A8%E7%A4%BA%E6%B2%A1%E6%9C%89%E6%9D%83%E9%99%90%E5%8E%BB%E8%AE%BF%E9%97%AE%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%B5%84%E6%BA%90%EF%BC%8C%E9%9C%80%E8%A6%81%E4%BF%AE%E6%94%B9%E5%A6%82%E4%B8%8B%E6%96%87%E4%BB%B6%E7%9A%84%E5%86%85%E5%AE%B9%0A%0A%60%60%60%0A1.%20%2Fusr%2Flocal%2Fapache-tomcat-8.5.31%2Fwebapps%2Fmanager%2FMETA-INF%2Fcontext.xml%0A2.%20%2Fusr%2Flocal%2Fapache-tomcat-8.5.31%2Fwebapps%2Fhost-manager%2FMETA-INF%2Fcontext.xml%0A%60%60%60%0A%0A%E5%B0%86allow%E4%BF%AE%E6%94%B9%E4%B8%BA%E5%AF%B9%E5%BA%94%E7%9A%84%E7%BD%91%E6%AE%B5%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%85%A8%E9%83%A8%E4%BF%AE%E6%94%B9%E4%B8%BA%20*%0A%0A!%5Bfa7f10998d34b65572d5174f3d417c84.png%5D(en-resource%3A%2F%2Fdatabase%2F529%3A1)%0A%0A%0A%0A%0A%23%23%23%23%23%20%20%20%20%20%20%202.2%20probe%20%5B%E6%8E%A2%E9%92%88%5D%20%E7%9B%91%E6%8E%A7%0A%0A%23%23%23%23%23%23%202.2.1%20%E5%AE%89%E8%A3%85%0A%0A%60%60%60%0Ahttps%3A%2F%2Fgithub.com%2Fpsi-probe%2Fpsi-probe%2Freleases%0A%E4%B8%8B%E8%BD%BDprobe.war%E5%8C%85%EF%BC%8C%E6%94%BE%E5%88%B0%5Capache-tomcat-8.5.47%5Cwebapps%E4%B8%8B%0A%60%60%60%0A%0A!%5B405f9ac8953e276c9865338bc020d10d.png%5D(en-resource%3A%2F%2Fdatabase%2F527%3A1)%0A%0A%0A%0A%23%23%23%23%23%23%202.2.2%20%E9%85%8D%E7%BD%AE%E6%9D%83%E9%99%90%0A%0A%E4%BD%BF%E7%94%A8probe%E7%9B%91%E6%8E%A7%E5%B7%A5%E5%85%B7%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E6%9D%83%E9%99%90%E4%B8%BAmanager-gui%0A%0A%60%60%60%0A%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%EF%BC%9A%20.%2Fconf%2Ftomcat-users.xml%0A%3Crole%20rolename%3D%22manager-gui%22%2F%3E%0A%3Cuser%20username%3D%22test%22%20password%3D%22test%22%20roles%3D%22manager-gui%22%2F%3E%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.2.3%20%E9%85%8D%E7%BD%AE%E5%90%8E%E9%87%8D%E5%90%AFtomcat%0A%0A%23%23%23%23%23%23%202.2.4%20%E8%BF%9B%E5%85%A5%E7%9B%91%E6%8E%A7%E9%A1%B5%E9%9D%A2%0A%0Ahttp%3A%2F%2Flocalhost%3A8080%2Fprobe%0A%0A%0A%0A%23%23%23%23%203.%20%E8%BF%9E%E6%8E%A5%E5%99%A8%0A%0A%23%23%23%23%23%203.1%20%E8%BF%9E%E6%8E%A5%E5%99%A8%E7%A7%8D%E7%B1%BB%0A%0Atomcat%E9%87%8C%E9%9D%A2%E6%9C%89%E4%B8%A4%E7%A7%8D%E8%BF%9E%E6%8E%A5%E5%99%A8%EF%BC%8C**HTTP**%20%E5%92%8C%20**AJP**%0A%0A%60%60%60%0A%3CConnector%20port%3D%228080%22%20protocol%3D%22HTTP%2F1.1%22%20--%E8%BF%9E%E6%8E%A5%E7%9A%84%E5%8D%8F%E8%AE%AE%E5%8F%8A%E7%89%88%E6%9C%AC%E5%8F%B7%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%8F%AA%E8%83%BD%E5%A4%84%E7%90%86%E6%AD%A4%E5%8D%8F%E8%AE%AE%E7%9A%84%E8%AF%B7%E6%B1%82%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20connectionTimeout%3D%2220000%22%20%20%20--%E8%BF%9E%E6%8E%A5%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%EF%BC%8C%E5%8D%95%E4%BD%8Dms%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20maxThreads%3D%22300%22%20%20%20%20%20%20%20%20%20%20%20%20--%E6%9C%80%E5%A4%A7%E7%BA%BF%E7%A8%8B%E6%95%B0%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%90%8C%E6%97%B6%E5%8F%AF%E4%BB%A5%E5%B9%B6%E5%8F%91%E5%A4%84%E7%90%86%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%95%B0%EF%BC%8C%E4%B8%80%E4%B8%AAhttp%E8%AF%B7%E6%B1%82%E5%AF%B9%E5%BA%94%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20accountCount%3D%22150%22%20%20%20%20%20%20%20%20%20%20--%E6%9C%80%E5%A4%A7%E6%8E%92%E9%98%9F%E6%95%B0%EF%BC%8C%E8%8B%A5%E5%B9%B6%E5%8F%91%E7%9A%84%E8%AF%B7%E6%B1%82%E6%95%B0%E8%B6%85%E8%BF%87maxThreads%EF%BC%8C%E5%B0%B1%E9%9C%80%E8%A6%81%E6%8E%92%E9%98%9F%EF%BC%8C%E8%B6%85%E8%BF%87%E6%8E%92%E9%98%9F%E6%95%B0%E7%9A%84%E8%AF%B7%E6%B1%82%E5%B0%B1%E8%A2%ABkill%E6%8E%89%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20redirectPort%3D%228443%22%20%20%20%20%20%20%20%20%20--%E9%87%8D%E7%BD%AE%E7%AB%AF%E5%8F%A3%E5%8F%B7%EF%BC%8Chttp%E9%87%8D%E7%BD%AE%E4%B8%BAhttps%E5%90%8E%E7%AB%AF%E5%8F%A3%E5%8F%B7%E5%B0%B1%E5%8F%98%E6%88%90%E4%BA%868443%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20URIEncoding%3D%22UTF-8%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%3E%0A%60%60%60%0A%0A%23%23%23%23%23%203.2%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E5%88%86%E6%9E%90%0A%0A%23%23%23%23%23%23%203.2.1%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E9%85%8D%E7%BD%AE%0A%0A**%2Fusr%2Flocal%2Ftomcat%2Fconf%2Flogging.properties**%0A%0A%60%60%60%0A%23%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E8%A2%AB%E8%AE%B0%E5%BD%95%E4%B8%8B%E6%9D%A5%E7%9A%84%E7%BA%A7%E5%88%AB%0A1catalina.org.apache.juli.AsyncFileHandler.level%20%3D%20FINE%0A%23%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E4%BF%9D%E5%AD%98%E7%9A%84%E7%9B%AE%E5%BD%95%0A1catalina.org.apache.juli.AsyncFileHandler.directory%20%3D%20%24%7Bcatalina.base%7D%2Flogs%0A%23%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E7%9A%84%E5%89%8D%E7%BC%80%0A1catalina.org.apache.juli.AsyncFileHandler.prefix%20%3D%20catalina.%0A%60%60%60%0A%0A%23%23%23%23%23%23%203.2.2%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E7%9A%84%E7%BA%A7%E5%88%AB%0A%0A%E4%BB%8E%E9%AB%98%E5%88%B0%E4%BD%8E%E5%88%86%E5%88%AB%E4%B8%BA%EF%BC%9A%0A%0A%60%60%60%0ASEVERE%20%3E%20WARNING%20%3E%20INFO%20%3E%20CONFIG%20%3E%20FINE%20%3E%20FINER%20%3E%20FINEST%0A%60%60%60%0A%0A%23%23%23%23%23%23%203.2.3%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E5%BC%80%E5%90%AF%E5%92%8C%E5%85%B3%E9%97%AD%0A%0A%60%60%60%0A1catalina.org.apache.juli.AsyncFileHandler.level%20%3D%20OFF%20--%E8%A1%A8%E7%A4%BA%E4%B8%8D%E8%AE%B0%E5%BD%95%E6%97%A5%E5%BF%97%0A1catalina.org.apache.juli.AsyncFileHandler.level%20%3D%20ON%0A%60%60%60%0A%0A%23%23%23%23%23%23%203.2.4%20%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E7%A7%8D%E7%B1%BB%0A%0A1.%20**localhost_access_log.2020-08-04.txt**%0A%0A%60%60%60%0A192.168.140.1%20-%20test%20%5B04%2FAug%2F2020%3A09%3A06%3A06%20%2B0000%5D%20%22GET%20%2Fprobe%2Fjs%2FTooltip.js%20HTTP%2F1.1%22%20200%2020051%0A192.168.140.1%20--%E8%AE%BF%E9%97%AEtomcat%E7%9A%84%E5%AE%A2%E6%88%B7%E7%AB%AFIP%0Atest%20--%20%E7%94%A8%E6%88%B7%E5%90%8D%0A%2B0000%20--%20%E6%97%B6%E5%8C%BA%E5%81%8F%E7%A7%BB%0A200%20%20--%20%E6%9C%80%E5%90%8E%E7%BB%93%E6%9E%9C%E7%9A%84%E7%8A%B6%E6%80%81%E7%A0%81%0A20051%20--%20%E6%9C%80%E5%90%8E%E5%A4%84%E7%90%86%E7%9A%84%E5%AD%97%E8%8A%82%E6%95%B0%0A%60%60%60%0A%0A2.%20**catalina.out**%20%E4%B8%8E%20**catalina.2020-08-04.log**%20%E7%B1%BB%E4%BC%BC%0A%0A%20%20%20%E4%B8%BB%E8%A6%81%E8%AE%B0%E5%BD%95tomcat%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%90%AF%E5%81%9C%E7%9B%B8%E5%85%B3%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%BF%A1%E6%81%AF%0A%0A3.%20**localhost.2020-08-04.log**%0A%0A%20%20%20%E4%B8%BB%E8%A6%81%E8%AE%B0%E5%BD%95%E7%BA%BF%E7%A8%8B%E8%BF%90%E8%A1%8C%E6%97%B6%E8%B0%83%E7%94%A8%E7%9A%84%E6%96%B9%E6%B3%95%E5%92%8C%E5%B1%9E%E6%80%A7%E4%BB%A5%E5%8F%8AJAVA%E7%BA%BF%E7%A8%8B%E5%8F%B7%0A%0A%0A%0A

nginx

创建时间:2020/10/7 17:31
更新时间:2020/10/8 14:55
作者:Chris

1. Nginx基本概念

1.1 是什么

Nginx是什么?Nginx介绍及Nginx的优点

一个高性能的http和反向代理服务器软件,特点:

  1. 用内存少,并发量高.

    专为性能优化而开发,能经受高负载,可以支持高达50000个并发连接数。

  2. Nginx支持热部署。

    它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。

1.2 能干什么

反向代理
负载均衡
动静分离

2. 代理

2.1 正向代理

局域网中的客户端要访问internet,则需要能过代理服务器来访问,一般在客户端【浏览器】中配置代理服务器,这种代理服务就称为正向代理。

2.2 反向代理

客户端不需要做任何配置,对代理无感知,只需要将请求发送给反射代理服务器,再由返现代理服务器去生选择目标服务器获取数据后返回给客户端。

此时代理服务器和目标服务器对外是同一个服务器,暴露的是代理服务器的地址,隐藏的是真实服务器的地址。

3. 负载均衡

将请求平均分配到多个服务器上从而达到系统的可高用

常见的负载均衡组件有,Nginx, LVS, 硬件F5等

4. 动静分离

4.1 是什么

为了加快网站的解析速度,可以把动态资源和静态资源由不同的服务器来解析,加快解析的速度,降低单个服务器的压力。

将动态请求和静态请求分开,不能单纯的理解为将动态页面和静态页面分开,可以使用Nginx处理静态页面,Tomcat处理动态页面。

4.2 实现方式
  1. 将静态资源独立成单独的域名,存放在独立的服务器上,这是目前的主流方式。

  2. 将动态文件和静态文件混合存放在一起,通过Nginx将资源分开。

  3. 通过location指定不同的后缀名实现不同的请求转发

  4. 通过expire设置可以使浏览器缓存过期时间,减少与服务器之间的请求和流量,这种做法适合静态资源

    给一个静态资源设置一个过期时间,例如设置为3d,表示3天内请求同一资源,比对服务器该文件最后更新时间是否发生变化,如果没有发生变化,则不会从服务器获取,并返回状态码304,如果资源发生变化,则从服务器获取最新文件并返回状态码200.

    expires 30s;   #缓存30秒
    expires 30m;   #缓存30分钟   
    expires 2h;    #缓存2小时
    expires 30d;   #缓存30天
    

5. Nginx安装

5.1 安装gcc

查看是否已安装gcc

gcc -v

安装

yum -y install gcc
5.2 pcre、pcre-devel安装

pcre是一个perl库,包括perl兼容的正则表达式库,Nginx的http模块使用pcre来解析正则表达式,所以需要安装pcre库。

yum install -y pcre pcre-devel
pcre-config --version
5.3 zlib安装

zlib库提供了很多种压缩和解压缩方式Nginx使用zlib对http包的内容进行gzip,所以需要安装

yum install -y zlib zlib-devel
5.4 安装openssl
yum install -y openssl openssl-devel
5.5 安装Nginx
3.5.1 下载

http://nginx.org/

cd /opt/
curl -OL http://nginx.org/download/nginx-1.19.3.tar.gz
5.5.2 安装
tar -zxvf nginx-1.19.3.tar.gz
mv nginx-1.19.3 nginx
cd nginx
###运行下面三个命令
    ./configure
    make
    make install
    
也可以同时进行 make && make install
5.5.3 配置
cd /usr/local/nginx/conf
cp nginx.conf nginx.conf.bak
vi nginx.conf

修改为你需要的端口号

server {
        listen       1111;  
        server_name  localhost;
5.5.4 启动
cd /usr/local/nginx/sbin
./nginx

验证nginx配置文件是否正确

[root@master sbin]# ./nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

5.5.5 查看

http://master:1111/

5.5.6 常用命令

使用Nginx的命令时必须先进入到目录/usr/local/nginx/sbin

  1. 启动

    ./nginx
    
  2. 查看版本号

    ./nginx -v
    
  3. 停用

    ./nginx -s stop
    
  4. 重加载配置文件

    ./nginx -s reload
    

6. 配置文件

cd /usr/local/nginx/conf
vi nginx.conf
6.1 由三部分组成
6.1.1 全局块

从配置文件开始到events块之间的内容,主要设置一些影响Nginx服务器整体运行的配置指令

worker_processes 1; 值越大,表示处理并发量越大,但是需要考虑硬件和软件及网络因素的制约

6.1.2 events块

主要设置一些影响Nginx服务器与用户网络连接的配置指令

worker_connections 1024; 支持用户的连接数

6.1.3 http块
  1. 全局块

    配置的指令如文件引入,MIME-TYPE, 日志定义, 连接超时时间,单连接请求数上限等

  2. server块

    虚拟机相关的配置,每个http块可以配置多个server块,每个server块相当于一个虚拟主机

    每个server块可以包含多个location块

7. 反向代理

7.1 实例1

通过在windows中访问 www.123.com:1111 访问vmware中linux中的tomcat

  1. 配置window中的host文件

    ######## Nginx ###########
    192.168.101.127 www.123.com
    
  2. 配置nginx.conf文件

     server {
            listen       1111;
            server_name  192.168.101.127;
    
    location / {
              #  root   html;
              #  index  index.html index.htm;
              #  proxy_pass http://cluster;
                 proxy_pass http://127.0.0.1:8080;
            }
    
  3. 测试

    http://www.123.com:1111/

7.2 实例2

如果是www.123.com:9001/edu/a.html 防问vmware中linux中的tomcat8080

如果是www.123.com:9001/vod/a.html 防问vmware中linux中的tomcat8081

  1. 准备两个tomcat

    tomcat 8080
    tomcat 8081

    在tomcat 8080 的/opt/tomcat8081/webapps/ 下新增edu/ 目录, 并在此目录中新增文件a.html, 文件内容如下:

    <h4>tomcat 8080!</h4>
    

    在tomcat 8080 的/opt/tomcat8081/webapps/ 下新增vod/ 目录, 并在此目录中新增文件a.html, 文件内容如下:

    <h4>tomcat 8081!</h4>
    

    注: 最好重新启动tomcat, 尤其是8080

  2. 配置nginx.conf 新增server节点

    server {
        listen       9001;
        server_name  192.128.101.127;
    
        location ~ /edu/ {
            proxy_pass http://127.0.0.1:8080;
        }
    
        location ~ /vod/ {
            proxy_pass http://127.0.0.1:8081;
        }
    }
    
  3. 启动加载nginx.conf

    cd /opt/nginx/sbin
    ./nginx -s reload
    
  4. 测试

    www.123.com:9001/edu/a.html 访问vmware中linux中的tomcat8080
    www.123.com:9001/vod/a.html 访问vmware中linux中的tomcat8081

8. 负载均衡

8.1 实例1

通过访问 http://www.123.com:9002/edu/a.html 来将请求转发到两个不同的 tomcat8080 和 tomcat8081上

  1. 准备tomcat测试环境

    在tomcat 8080 的/opt/tomcat8080/webapps/ 下新增edu/ 目录, 并在此目录中新增文件a.html, 文件内容如下:

    <h4>tomcat 8080!</h4>
    

    在tomcat 8081 的/opt/tomcat8081/webapps/ 下新增edu/ 目录, 并在此目录中新增文件a.html, 文件内容如下:

    <h4>tomcat 8081!</h4>
    
  2. 配置nginx.conf

        # config loadbalance nodes
        upstream loadbalancer {
           server 127.0.0.1:8080;
           server 127.0.0.1:8081;
        }
    
    server {
        listen       9002;
        server_name  192.128.101.127;
    
        location ~ /edu/ {
            proxy_pass http://loadbalancer;
        }
    }
    
  3. 启动tomcat和nginx

  4. 测试

    http://www.123.com:9002/edu/a.html

8.2 负载均衡策略
8.2.1 轮询

轮询 为默认策略,请每个请求平均分配到后端的服务器,如果服务器down掉会自动剔除

8.2.2 weigh

权重策略,默认为1, 权重越高,被分配到的客户端数量越多,一般用于后端服务器性能不均匀的情况下。

# config loadbalance nodes
upstream loadbalancer {
   server 127.0.0.1:8080 weight=5;
   server 127.0.0.1:8081 weight=10;
}

8081的权重是8080的两倍,因此三次请求会有两次分配到8081,一次分配到8080。

8.2.3 ip_hash

将请求按照ip的hash结果分配,这样一个客户端可以固定访问一个后端服务器,这样可以解决session共享的问题。

sample:

当你服务端的一个特定url路径会被同一个用户连续访问时,如果负载均衡策略还是轮询的话,那该用户的多次访问会被打到各台服务器上,这显然并不高效(会建立多次http链接等问题)。甚至考虑一种极端情况,用户需要分片上传文件到服务器下,然后再由服务器将分片合并,这时如果用户的请求到达了不同的服务器,那么分片将存储于不同的服务器目录中,导致无法将分片合并。所以,此类场景可以考虑采用nginx提供的ip_hash策略。既能满足每个用户请求到同一台服务器,又能满足不同用户之间负载均衡。

# config loadbalance nodes
upstream loadbalancer {
   ip_hash;
   server 127.0.0.1:8080 weight=5;
   server 127.0.0.1:8081 weight=10;
   server 127.0.0.1:8083 weight=10 down;
}

server {
        listen       9002;
        server_name  192.128.101.127;

        location ~ /upload/ {
            proxy_pass http://loadbalancer;
        }
    }

down关键字,表示下线的意思

8.2.4 url_hash

将不同资源的请求按照url的hash结果分配,相关的资源只会被请求一次.

要用到urlhash,是要配合缓存命中来使用

sample

有一个服务器集群A,需要对外提供文件下载,由于文件上传量巨大,没法存储到服务器磁盘中,所以用到了第三方云存储来做文件存储。服务器集群A收到客户端请求之后,需要从云存储中下载文件然后返回,为了省去不必要的网络带宽和下载耗时,在服务器集群A上做了一层临时缓存(缓存一个月)。由于是服务器集群,所以同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。在此类场景下,为了使得缓存命中率提高,很适合使用url_hash策略,同一个url(也就是同一个资源请求)会到达同一台机器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取,既减少了带宽,也减少的下载时间。

upstream somestream {
    hash $request_uri;
    server 192.168.244.1:8080;
    server 192.168.244.2:8080;
    server 192.168.244.3:8080;
    server 192.168.244.4:8080;
 
}
server {
    listen 8081 default;
    server_name test.csdn.net;
    charset utf-8;
    location /get {
    proxy_pass http://somestream;
 
    }  
}
8.2.5 fair

根据服务器的响应时间来分配,谁的响应时间短就优先分配

需要单独第三方fair模块

# config loadbalance nodes
upstream loadbalancer {
   server 127.0.0.1:8080 weight=5;
   server 127.0.0.1:8081 weight=10;
   fair;
}

9. 动静分离

通过访问 http://www.123.com:9003/www/a.html 直接获取服务器www/a.html

通过访问 http://www.123.com:9003/images/ 直接获取服务器images/目录下的图片文件

9.1 准备静态资源
cd /usr/local
mkdir nginx-test
cd nginx-test
mkdir www
mkdir images
cd www
vi a.html

存放如下内容
<h4>test static resource!!!</h4>
cd images
上传若干张图片到images
9.2 配置nginx.conf文件
server {
    listen       9003;
    server_name  192.128.101.127;

    location /www/ {
        root /usr/local/nginx-test/;
        expires 20s;
    }       

    location /images/ {
        root /usr/local/nginx-test/;
        expires 20s;        
        autoindex on; #列出当前文件夹中的内容
    }       
}   
9.3 测试

http://www.123.com:9003/images/

http://www.123.com:9003/www/a.html

10. 高可用配置

先通过主Nginx发送请求,如果主Nginx宕机,则通过备份Nginx发送请求。
keepalived 相当于路由,通过脚本来检测主节点是否可用,如果不可用,则自动切换到另外一台备用节点上。
虚拟IP ,通过虚拟IP来绑定到可用的Nginx节点, 先是绑定到master节点上,如果master节点宕机,会自动绑定到slave节点上

10.1 配置备机slave01
  1. 安装nginx
  2. 安装tomcat
10.2 keepalived
10.2.1 安装keepalived
yum -y install keepalived
cd /etc/keepalived
echo > keepalived.conf
10.2.2 配置keepalived

将如下内容粘贴到keepalived.conf

! Configuration File for keepalived

# 全局定义
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id 192.168.101.127  # 局域网keppalived主机标识,可以为主机名或IP
   script_user root           # 添加运行健康检查脚本的用户
   enable_script_security     # 添加运行健康检查脚本的组
}

# 检测脚本相关配置
vrrp_script chk_http_port {
  script "/ect/keepalived/nginxchk/nginx_check.sh"  # 检测脚本位置
  interval 2  # 检测脚本执行的时间间隔  
  weight -20   #监测失败,则相应的 vrrp_instance 的优先级会减少20个点
}

# 虚拟IP相关配置
vrrp_instance VI_1 {
    state MASTER  # 备机上需要将 MASTER 改为 BACKUP
    interface eth0 # 服务器使用的网卡名称,可以通过ifconfig查到
    virtual_router_id 51  # 主机和备机的此配置项的值必须相同
    priority 100 # 主机和备机的优先级,主机的值大于备机的值
    advert_int 1 # 发送心跳时间间隔,默认为1秒
    authentication {   # 主备主机之间的认证表示信息
        auth_type PASS #采用明文认证机制
        auth_pass 1111 #编写明文密码
    }
    virtual_ipaddress {
        192.168.101.150 # 虚拟IP地址,此参数备节点设置和主节点相同,此处可以绑定多个虚拟IP.
    }

    track_script {
        chk_http_port       #调用执行脚本
    }
}

备机中配置keepalived.conf

! Configuration File for keepalived

# 全局定义
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server SMTP.163.com
   smtp_connect_timeout 30
   router_id 192.168.101.128  # 局域网keppalived主机标识,可以为主机名或IP
   script_user root           # 添加运行健康检查脚本的用户
   enable_script_security     # 添加运行健康检查脚本的组
}

# 检测脚本相关配置
vrrp_script chk_http_port {
  script "/etc/keepalived/nginx-chk/nginx_check.sh"  # 检测脚本位置
  interval 2  # 检测脚本执行的时间间隔
  weight -20  # 监测失败,则相应的 vrrp_instance 的优先级会减少20个点
}

# 虚拟IP相关配置
vrrp_instance VI_1 {
    state BACKUP  # 备机上需要将 MASTER 改为 BACKUP
    interface ens33 # 服务器使用的网卡名称,可以通过ifconfig查到
    virtual_router_id 51  # 主机和备机的此配置项的值必须相同
    priority 90  # 主机和备机的优先级,主机的值大于备机的值
    advert_int 1 # 发送心跳时间间隔,默认为1秒
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.101.150 # 虚拟IP地址,此处可以绑定多个虚拟IP
    }

    track_script {
        chk_http_port       #调用执行脚本
    }
}

10.2.3 启动keepalived
  1. 启动主机和备机的keepalived

    systemctl start keepalived.service
    
  2. 启动后,虚拟IP会先绑定到master节点上

    ip a 
    

10.2.4 配置宿主机host

C:\Windows\System32\drivers\etc\hosts

######## keepalived 虚拟IP ###########
192.168.101.150	vip
10.2.5 测试
  1. http://vip

  2. 关闭master节点

    systemctl stop keepalived.service
    cd /usr/local/nginx/sbin
    ./nginx -s stop
    

    在备机slave01可以看到虚拟IP绑定到了slave01上

    ip a
    

    http://vip

11 工作机制

11.1 原理

一个master,可以有多个worker

客户端发送请求到master中,master收到请求任务后,worker通过争抢的机制从master处获取任务,然后worker负责具体的反向代理,负载均衡等具体的操作。

11.2 这种机制的好处
  1. 每个worker都是独立的一个进程,不需要单独加锁,从来避免了加锁带来的开销。
    同时进程之间相互不影响,一个进程退出后不影响另外进程的正常工作。

  2. 一个master多个worker,可以方便线上做热部署

    例如一个master对应四个worker,其中一个worker-1正在处理上一轮中争抢到的任务,此时nginx重新加载,则除过这个正在执行任务的worker外,其它三个worker都会加载最新的nginx配置内容并参与到新一轮的任务争抢中,worker-1在执行完手头的任务后也会自动加载最新的nginx配置,并参与到下一轮的任务争抢中去。

11.3 设置多少个worker最好

Nginx 同Redis类似都是采用io多路复用机制,每个worker都是一个进程,但每个进程里面只有一个主线程,通过异步非阻塞的方式处理请求,即使成千上万个请求也可以高效处理。每个worker可以将一个cpu的性能发挥到极致,所以worker数和cpu数保持一致最好,例如8核cpu设置8个worker,设置少了会浪费cpu资源,设置多了会造成cpu在上下文频繁切换造成的损耗。

11.4 连接数worker_connection

问题1:客户端发送一个清求,占用几个worker连接数?
要么2个要么4个
如果客户端访问的是静态资源,占用两个worker连接数,如果客户端访问的是动态资源则会占用4个连接数。

问题2:nginx有一个master,有四个worker,每个worker支持的最大并发数为1024,那么支持的最大并发数为多少个 ?
如果客户端访问的是静态资源则会占用两个连接数,所以并发数为,1024x4/2
如果客户端访问的是动态资源则会占用4个连接数,所以并发数为, 1024x4/4

%5Btoc%5D%0A%0A%23%23%23%23%201.%20Nginx%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%0A%0A%23%23%23%23%23%201.1%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%5BNginx%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9FNginx%E4%BB%8B%E7%BB%8D%E5%8F%8ANginx%E7%9A%84%E4%BC%98%E7%82%B9%5D(https%3A%2F%2Flnmp.org%2Fnginx.html)%0A%0A%E4%B8%80%E4%B8%AA%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84http%E5%92%8C%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BD%AF%E4%BB%B6%EF%BC%8C%E7%89%B9%E7%82%B9%3A%0A%0A1.%20%E7%94%A8%E5%86%85%E5%AD%98%E5%B0%91%EF%BC%8C%E5%B9%B6%E5%8F%91%E9%87%8F%E9%AB%98.%0A%0A%20%20%20%3E%20%E4%B8%93%E4%B8%BA%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E8%80%8C%E5%BC%80%E5%8F%91%EF%BC%8C%E8%83%BD%E7%BB%8F%E5%8F%97%E9%AB%98%E8%B4%9F%E8%BD%BD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%94%AF%E6%8C%81%E9%AB%98%E8%BE%BE50000%E4%B8%AA%E5%B9%B6%E5%8F%91%E8%BF%9E%E6%8E%A5%E6%95%B0%E3%80%82%0A%0A2.%20Nginx%E6%94%AF%E6%8C%81%E7%83%AD%E9%83%A8%E7%BD%B2%E3%80%82%0A%0A%20%20%20%3E%20%E5%AE%83%E7%9A%84%E5%90%AF%E5%8A%A8%E7%89%B9%E5%88%AB%E5%AE%B9%E6%98%93%2C%20%E5%B9%B6%E4%B8%94%E5%87%A0%E4%B9%8E%E5%8F%AF%E4%BB%A5%E5%81%9A%E5%88%B07%5C*24%E4%B8%8D%E9%97%B4%E6%96%AD%E8%BF%90%E8%A1%8C%EF%BC%8C%E5%8D%B3%E4%BD%BF%E8%BF%90%E8%A1%8C%E6%95%B0%E4%B8%AA%E6%9C%88%E4%B9%9F%E4%B8%8D%E9%9C%80%E8%A6%81%E9%87%8D%E6%96%B0%E5%90%AF%E5%8A%A8%E3%80%82%0A%0A%20%20%20%0A%0A%23%23%23%23%23%201.2%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%20%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%0A%3E%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%3E%20%E5%8A%A8%E9%9D%99%E5%88%86%E7%A6%BB%0A%0A%0A%23%23%23%23%202.%20%E4%BB%A3%E7%90%86%0A%0A%23%23%23%23%23%202.1%20%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%0A%0A%3E%20%E5%B1%80%E5%9F%9F%E7%BD%91%E4%B8%AD%E7%9A%84%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%A6%81%E8%AE%BF%E9%97%AEinternet%EF%BC%8C%E5%88%99%E9%9C%80%E8%A6%81%E8%83%BD%E8%BF%87%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%9D%A5%E8%AE%BF%E9%97%AE%EF%BC%8C%E4%B8%80%E8%88%AC%E5%9C%A8%E5%AE%A2%E6%88%B7%E7%AB%AF%E3%80%90%E6%B5%8F%E8%A7%88%E5%99%A8%E3%80%91%E4%B8%AD%E9%85%8D%E7%BD%AE%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E8%BF%99%E7%A7%8D%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%B0%B1%E7%A7%B0%E4%B8%BA%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E3%80%82%0A%0A%20!%5B721a6e54c417611479445df3ea4f67b3.png%5D(en-resource%3A%2F%2Fdatabase%2F594%3A1)%0A%20%0A%0A%0A%23%23%23%23%23%202.2%20%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%0A%0A%3E%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%B8%8D%E9%9C%80%E8%A6%81%E5%81%9A%E4%BB%BB%E4%BD%95%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%AF%B9%E4%BB%A3%E7%90%86%E6%97%A0%E6%84%9F%E7%9F%A5%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E5%B0%86%E8%AF%B7%E6%B1%82%E5%8F%91%E9%80%81%E7%BB%99%E5%8F%8D%E5%B0%84%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%86%8D%E7%94%B1%E8%BF%94%E7%8E%B0%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8E%BB%E7%94%9F%E9%80%89%E6%8B%A9%E7%9B%AE%E6%A0%87%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE%E5%90%8E%E8%BF%94%E5%9B%9E%E7%BB%99%E5%AE%A2%E6%88%B7%E7%AB%AF%E3%80%82%0A%3E%0A%3E%20%E6%AD%A4%E6%97%B6%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E7%9B%AE%E6%A0%87%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AF%B9%E5%A4%96%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E6%9A%B4%E9%9C%B2%E7%9A%84%E6%98%AF%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E5%9C%B0%E5%9D%80%EF%BC%8C%E9%9A%90%E8%97%8F%E7%9A%84%E6%98%AF%E7%9C%9F%E5%AE%9E%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E5%9C%B0%E5%9D%80%E3%80%82%0A%20%0A%20!%5B274e446af9e604b711049ce94cc97469.png%5D(en-resource%3A%2F%2Fdatabase%2F593%3A1)%0A%20%0A%0A%0A%0A%23%23%23%23%203.%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%0A%3E%20%E5%B0%86%E8%AF%B7%E6%B1%82%E5%B9%B3%E5%9D%87%E5%88%86%E9%85%8D%E5%88%B0%E5%A4%9A%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E4%BB%8E%E8%80%8C%E8%BE%BE%E5%88%B0%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%8F%AF%E9%AB%98%E7%94%A8%0A%3E%0A%3E%20%E5%B8%B8%E8%A7%81%E7%9A%84%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%BB%84%E4%BB%B6%E6%9C%89%EF%BC%8CNginx%2C%20LVS%2C%20%E7%A1%AC%E4%BB%B6F5%E7%AD%89%0A%20%0A%20!%5B78c3bb074a4a59a26370fcda4efff395.png%5D(en-resource%3A%2F%2Fdatabase%2F596%3A1)%0A%20%0A%0A%0A%0A%0A%0A%23%23%23%23%204.%20%E5%8A%A8%E9%9D%99%E5%88%86%E7%A6%BB%0A%0A%23%23%23%23%23%204.1%20%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20%E4%B8%BA%E4%BA%86%E5%8A%A0%E5%BF%AB%E7%BD%91%E7%AB%99%E7%9A%84%E8%A7%A3%E6%9E%90%E9%80%9F%E5%BA%A6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%8A%8A%E5%8A%A8%E6%80%81%E8%B5%84%E6%BA%90%E5%92%8C%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E7%94%B1%E4%B8%8D%E5%90%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%9D%A5%E8%A7%A3%E6%9E%90%EF%BC%8C%E5%8A%A0%E5%BF%AB%E8%A7%A3%E6%9E%90%E7%9A%84%E9%80%9F%E5%BA%A6%EF%BC%8C%E9%99%8D%E4%BD%8E%E5%8D%95%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E5%8E%8B%E5%8A%9B%E3%80%82%0A%3E%0A%3E%20%E5%B0%86%E5%8A%A8%E6%80%81%E8%AF%B7%E6%B1%82%E5%92%8C%E9%9D%99%E6%80%81%E8%AF%B7%E6%B1%82%E5%88%86%E5%BC%80%EF%BC%8C%E4%B8%8D%E8%83%BD%E5%8D%95%E7%BA%AF%E7%9A%84%E7%90%86%E8%A7%A3%E4%B8%BA%E5%B0%86%E5%8A%A8%E6%80%81%E9%A1%B5%E9%9D%A2%E5%92%8C%E9%9D%99%E6%80%81%E9%A1%B5%E9%9D%A2%E5%88%86%E5%BC%80%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8Nginx%E5%A4%84%E7%90%86%E9%9D%99%E6%80%81%E9%A1%B5%E9%9D%A2%EF%BC%8CTomcat%E5%A4%84%E7%90%86%E5%8A%A8%E6%80%81%E9%A1%B5%E9%9D%A2%E3%80%82%0A%0A!%5Ba0bcd09d62b187f3d001ae4955373766.png%5D(en-resource%3A%2F%2Fdatabase%2F597%3A1)%0A%0A%0A%23%23%23%23%23%204.2%20%20%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F%0A%0A1.%20%E5%B0%86%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E7%8B%AC%E7%AB%8B%E6%88%90%E5%8D%95%E7%8B%AC%E7%9A%84%E5%9F%9F%E5%90%8D%EF%BC%8C%E5%AD%98%E6%94%BE%E5%9C%A8%E7%8B%AC%E7%AB%8B%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%EF%BC%8C%E8%BF%99%E6%98%AF%E7%9B%AE%E5%89%8D%E7%9A%84%E4%B8%BB%E6%B5%81%E6%96%B9%E5%BC%8F%E3%80%82%0A%0A2.%20%E5%B0%86%E5%8A%A8%E6%80%81%E6%96%87%E4%BB%B6%E5%92%8C%E9%9D%99%E6%80%81%E6%96%87%E4%BB%B6%E6%B7%B7%E5%90%88%E5%AD%98%E6%94%BE%E5%9C%A8%E4%B8%80%E8%B5%B7%EF%BC%8C%E9%80%9A%E8%BF%87Nginx%E5%B0%86%E8%B5%84%E6%BA%90%E5%88%86%E5%BC%80%E3%80%82%0A%0A3.%20%E9%80%9A%E8%BF%87location%E6%8C%87%E5%AE%9A%E4%B8%8D%E5%90%8C%E7%9A%84%E5%90%8E%E7%BC%80%E5%90%8D%E5%AE%9E%E7%8E%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E8%AF%B7%E6%B1%82%E8%BD%AC%E5%8F%91%0A%0A4.%20%E9%80%9A%E8%BF%87expire%E8%AE%BE%E7%BD%AE%E5%8F%AF%E4%BB%A5%E4%BD%BF%E6%B5%8F%E8%A7%88%E5%99%A8%E7%BC%93%E5%AD%98%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%EF%BC%8C%E5%87%8F%E5%B0%91%E4%B8%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B9%8B%E9%97%B4%E7%9A%84%E8%AF%B7%E6%B1%82%E5%92%8C%E6%B5%81%E9%87%8F%EF%BC%8C%E8%BF%99%E7%A7%8D%E5%81%9A%E6%B3%95%E9%80%82%E5%90%88%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%0A%0A%20%20%20%3E%20%E7%BB%99%E4%B8%80%E4%B8%AA%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E8%AE%BE%E7%BD%AE%E4%B8%80%E4%B8%AA%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%EF%BC%8C%E4%BE%8B%E5%A6%82%E8%AE%BE%E7%BD%AE%E4%B8%BA3d%EF%BC%8C%E8%A1%A8%E7%A4%BA3%E5%A4%A9%E5%86%85%E8%AF%B7%E6%B1%82%E5%90%8C%E4%B8%80%E8%B5%84%E6%BA%90%EF%BC%8C%E6%AF%94%E5%AF%B9%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%AF%A5%E6%96%87%E4%BB%B6%E6%9C%80%E5%90%8E%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4%E6%98%AF%E5%90%A6%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%EF%BC%8C%E5%88%99%E4%B8%8D%E4%BC%9A%E4%BB%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%8E%B7%E5%8F%96%EF%BC%8C%E5%B9%B6%E8%BF%94%E5%9B%9E%E7%8A%B6%E6%80%81%E7%A0%81304%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%B5%84%E6%BA%90%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%EF%BC%8C%E5%88%99%E4%BB%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%8E%B7%E5%8F%96%E6%9C%80%E6%96%B0%E6%96%87%E4%BB%B6%E5%B9%B6%E8%BF%94%E5%9B%9E%E7%8A%B6%E6%80%81%E7%A0%81200.%0A%20%20%20%3E%0A%20%20%20%3E%20%0A%0A%20%20%20%60%60%60%0A%20%20%20expires%2030s%3B%20%20%20%23%E7%BC%93%E5%AD%9830%E7%A7%92%0A%20%20%20expires%2030m%3B%20%20%20%23%E7%BC%93%E5%AD%9830%E5%88%86%E9%92%9F%20%20%20%0A%20%20%20expires%202h%3B%20%20%20%20%23%E7%BC%93%E5%AD%982%E5%B0%8F%E6%97%B6%0A%20%20%20expires%2030d%3B%20%20%20%23%E7%BC%93%E5%AD%9830%E5%A4%A9%0A%20%20%20%60%60%60%0A%0A%23%23%23%23%205.%20Nginx%E5%AE%89%E8%A3%85%0A%0A%23%23%23%23%23%205.1%20%E5%AE%89%E8%A3%85gcc%0A%0A%3E%20%E6%9F%A5%E7%9C%8B%E6%98%AF%E5%90%A6%E5%B7%B2%E5%AE%89%E8%A3%85gcc%0A%0A%60%60%60%0Agcc%20-v%0A%60%60%60%0A%0A%3E%20%E5%AE%89%E8%A3%85%0A%0A%60%60%60%0Ayum%20-y%20install%20gcc%0A%60%60%60%0A%0A%23%23%23%23%23%205.2%20pcre%E3%80%81pcre-devel%E5%AE%89%E8%A3%85%0A%0A%3E%20pcre%E6%98%AF%E4%B8%80%E4%B8%AAperl%E5%BA%93%EF%BC%8C%E5%8C%85%E6%8B%ACperl%E5%85%BC%E5%AE%B9%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BA%93%EF%BC%8CNginx%E7%9A%84http%E6%A8%A1%E5%9D%97%E4%BD%BF%E7%94%A8pcre%E6%9D%A5%E8%A7%A3%E6%9E%90%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E5%AE%89%E8%A3%85pcre%E5%BA%93%E3%80%82%0A%0A%60%60%60%0Ayum%20install%20-y%20pcre%20pcre-devel%0Apcre-config%20--version%0A%60%60%60%0A%0A%23%23%23%23%23%205.3%20zlib%E5%AE%89%E8%A3%85%0A%0A%3E%20zlib%E5%BA%93%E6%8F%90%E4%BE%9B%E4%BA%86%E5%BE%88%E5%A4%9A%E7%A7%8D%E5%8E%8B%E7%BC%A9%E5%92%8C%E8%A7%A3%E5%8E%8B%E7%BC%A9%E6%96%B9%E5%BC%8FNginx%E4%BD%BF%E7%94%A8zlib%E5%AF%B9http%E5%8C%85%E7%9A%84%E5%86%85%E5%AE%B9%E8%BF%9B%E8%A1%8Cgzip%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E5%AE%89%E8%A3%85%0A%0A%60%60%60%0Ayum%20install%20-y%20zlib%20zlib-devel%0A%60%60%60%0A%0A%23%23%23%23%23%205.4%20%E5%AE%89%E8%A3%85openssl%0A%0A%60%60%60%0Ayum%20install%20-y%20openssl%20openssl-devel%0A%60%60%60%0A%0A%23%23%23%23%23%205.5%20%E5%AE%89%E8%A3%85Nginx%0A%0A%23%23%23%23%23%23%203.5.1%20%E4%B8%8B%E8%BD%BD%0A%0Ahttp%3A%2F%2Fnginx.org%2F%0A%0A%60%60%60%0Acd%20%2Fopt%2F%0Acurl%20-OL%20http%3A%2F%2Fnginx.org%2Fdownload%2Fnginx-1.19.3.tar.gz%0A%60%60%60%0A%0A%23%23%23%23%23%23%205.5.2%20%E5%AE%89%E8%A3%85%0A%0A%60%60%60%0Atar%20-zxvf%20nginx-1.19.3.tar.gz%0Amv%20nginx-1.19.3%20nginx%0Acd%20nginx%0A%23%23%23%E8%BF%90%E8%A1%8C%E4%B8%8B%E9%9D%A2%E4%B8%89%E4%B8%AA%E5%91%BD%E4%BB%A4%0A%20%20%20%20.%2Fconfigure%0A%20%20%20%20make%0A%20%20%20%20make%20install%0A%20%20%20%20%0A%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E8%BF%9B%E8%A1%8C%20make%20%26%26%20make%20install%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%23%23%205.5.3%20%E9%85%8D%E7%BD%AE%0A%0A%60%60%60%0Acd%20%2Fusr%2Flocal%2Fnginx%2Fconf%0Acp%20nginx.conf%20nginx.conf.bak%0Avi%20nginx.conf%0A%60%60%60%0A%0A%E4%BF%AE%E6%94%B9%E4%B8%BA%E4%BD%A0%E9%9C%80%E8%A6%81%E7%9A%84%E7%AB%AF%E5%8F%A3%E5%8F%B7%0A%0A%60%60%60%0Aserver%20%7B%0A%20%20%20%20%20%20%20%20listen%20%20%20%20%20%20%201111%3B%20%20%0A%20%20%20%20%20%20%20%20server_name%20%20localhost%3B%0A%60%60%60%0A%0A%23%23%23%23%23%23%205.5.4%20%E5%90%AF%E5%8A%A8%0A%0A%60%60%60%0Acd%20%2Fusr%2Flocal%2Fnginx%2Fsbin%0A.%2Fnginx%0A%60%60%60%0A%0A%0A%0A%E9%AA%8C%E8%AF%81nginx%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E6%98%AF%E5%90%A6%E6%AD%A3%E7%A1%AE%0A%0A%60%60%60%0A%5Broot%40master%20sbin%5D%23%20.%2Fnginx%20-t%0Anginx%3A%20the%20configuration%20file%20%2Fusr%2Flocal%2Fnginx%2Fconf%2Fnginx.conf%20syntax%20is%20ok%0Anginx%3A%20configuration%20file%20%2Fusr%2Flocal%2Fnginx%2Fconf%2Fnginx.conf%20test%20is%20successful%0A%0A%60%60%60%0A%0A%23%23%23%23%23%23%205.5.5%20%E6%9F%A5%E7%9C%8B%0A%0Ahttp%3A%2F%2Fmaster%3A1111%2F%0A%0A!%5B76fda5e64235c218760b978c6d8cc2af.png%5D(en-resource%3A%2F%2Fdatabase%2F595%3A1)%0A%0A%0A%0A%0A%0A%0A%23%23%23%23%23%205.5.6%20%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%0A%0A%3E%20%E4%BD%BF%E7%94%A8Nginx%E7%9A%84%E5%91%BD%E4%BB%A4%E6%97%B6%E5%BF%85%E9%A1%BB%E5%85%88%E8%BF%9B%E5%85%A5%E5%88%B0%E7%9B%AE%E5%BD%95%2Fusr%2Flocal%2Fnginx%2Fsbin%0A%0A1.%20%E5%90%AF%E5%8A%A8%0A%0A%20%20%20%60%60%60%0A%20%20%20.%2Fnginx%0A%20%20%20%60%60%60%0A%0A2.%20%E6%9F%A5%E7%9C%8B%E7%89%88%E6%9C%AC%E5%8F%B7%0A%0A%20%20%20%60%60%60%0A%20%20%20.%2Fnginx%20-v%0A%20%20%20%60%60%60%0A%0A3.%20%E5%81%9C%E7%94%A8%0A%0A%20%20%20%60%60%60%0A%20%20%20.%2Fnginx%20-s%20stop%0A%20%20%20%60%60%60%0A%0A4.%20%E9%87%8D%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60%0A%20%20%20.%2Fnginx%20-s%20reload%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%206.%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%0A%0A%60%60%60%0Acd%20%2Fusr%2Flocal%2Fnginx%2Fconf%0Avi%20nginx.conf%0A%60%60%60%0A%0A%23%23%23%23%23%206.1%20%E7%94%B1%E4%B8%89%E9%83%A8%E5%88%86%E7%BB%84%E6%88%90%0A%0A%23%23%23%23%23%23%206.1.1%20%E5%85%A8%E5%B1%80%E5%9D%97%0A%0A%3E%20%E4%BB%8E%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%BC%80%E5%A7%8B%E5%88%B0events%E5%9D%97%E4%B9%8B%E9%97%B4%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8C%E4%B8%BB%E8%A6%81%E8%AE%BE%E7%BD%AE%E4%B8%80%E4%BA%9B%E5%BD%B1%E5%93%8DNginx%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%95%B4%E4%BD%93%E8%BF%90%E8%A1%8C%E7%9A%84%E9%85%8D%E7%BD%AE%E6%8C%87%E4%BB%A4%0A%3E%0A%3E%20worker_processes%20%201%3B%20%E5%80%BC%E8%B6%8A%E5%A4%A7%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%A4%84%E7%90%86%E5%B9%B6%E5%8F%91%E9%87%8F%E8%B6%8A%E5%A4%A7%EF%BC%8C%E4%BD%86%E6%98%AF%E9%9C%80%E8%A6%81%E8%80%83%E8%99%91%E7%A1%AC%E4%BB%B6%E5%92%8C%E8%BD%AF%E4%BB%B6%E5%8F%8A%E7%BD%91%E7%BB%9C%E5%9B%A0%E7%B4%A0%E7%9A%84%E5%88%B6%E7%BA%A6%0A%0A%23%23%23%23%23%23%206.1.2%20events%E5%9D%97%0A%0A%3E%20%E4%B8%BB%E8%A6%81%E8%AE%BE%E7%BD%AE%E4%B8%80%E4%BA%9B%E5%BD%B1%E5%93%8DNginx%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8E%E7%94%A8%E6%88%B7%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5%E7%9A%84%E9%85%8D%E7%BD%AE%E6%8C%87%E4%BB%A4%0A%3E%0A%3E%20worker_connections%20%201024%3B%20%E6%94%AF%E6%8C%81%E7%94%A8%E6%88%B7%E7%9A%84%E8%BF%9E%E6%8E%A5%E6%95%B0%0A%0A%23%23%23%23%23%23%206.1.3%20http%E5%9D%97%0A%0A1.%20%E5%85%A8%E5%B1%80%E5%9D%97%0A%0A%20%20%20%3E%20%E9%85%8D%E7%BD%AE%E7%9A%84%E6%8C%87%E4%BB%A4%E5%A6%82%E6%96%87%E4%BB%B6%E5%BC%95%E5%85%A5%EF%BC%8CMIME-TYPE%2C%20%E6%97%A5%E5%BF%97%E5%AE%9A%E4%B9%89%EF%BC%8C%20%E8%BF%9E%E6%8E%A5%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%EF%BC%8C%E5%8D%95%E8%BF%9E%E6%8E%A5%E8%AF%B7%E6%B1%82%E6%95%B0%E4%B8%8A%E9%99%90%E7%AD%89%0A%0A2.%20server%E5%9D%97%0A%0A%20%20%20%3E%20%E8%99%9A%E6%8B%9F%E6%9C%BA%E7%9B%B8%E5%85%B3%E7%9A%84%E9%85%8D%E7%BD%AE%EF%BC%8C%E6%AF%8F%E4%B8%AAhttp%E5%9D%97%E5%8F%AF%E4%BB%A5%E9%85%8D%E7%BD%AE%E5%A4%9A%E4%B8%AAserver%E5%9D%97%EF%BC%8C%E6%AF%8F%E4%B8%AAserver%E5%9D%97%E7%9B%B8%E5%BD%93%E4%BA%8E%E4%B8%80%E4%B8%AA%E8%99%9A%E6%8B%9F%E4%B8%BB%E6%9C%BA%0A%20%20%20%3E%0A%20%20%20%3E%20%E6%AF%8F%E4%B8%AAserver%E5%9D%97%E5%8F%AF%E4%BB%A5%E5%8C%85%E5%90%AB%E5%A4%9A%E4%B8%AAlocation%E5%9D%97%0A%0A%0A%0A%23%23%23%23%207.%20%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%0A%0A%23%23%23%23%23%207.1%20%E5%AE%9E%E4%BE%8B1%0A%0A%3E%20%E9%80%9A%E8%BF%87%E5%9C%A8windows%E4%B8%AD%E8%AE%BF%E9%97%AE%20www.123.com%3A1111%20%E8%AE%BF%E9%97%AEvmware%E4%B8%ADlinux%E4%B8%AD%E7%9A%84tomcat%0A%0A!%5B47471b465a6b715686dcb5c16e3db51d.png%5D(en-resource%3A%2F%2Fdatabase%2F587%3A1)%0A%0A%0A1.%20%E9%85%8D%E7%BD%AEwindow%E4%B8%AD%E7%9A%84host%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60%0A%20%20%20%23%23%23%23%23%23%23%23%20Nginx%20%23%23%23%23%23%23%23%23%23%23%23%0A%20%20%20192.168.101.127%20www.123.com%0A%20%20%20%60%60%60%0A%0A2.%20%E9%85%8D%E7%BD%AEnginx.conf%E6%96%87%E4%BB%B6%0A%0A%20%20%20%60%60%60%0A%20%20%20%20server%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20listen%20%20%20%20%20%20%201111%3B%0A%20%20%20%20%20%20%20%20%20%20%20server_name%20%20192.168.101.127%3B%0A%20%20%20%60%60%60%0A%0A%20%20%20%60%60%60%0A%20%20%20location%20%2F%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%20root%20%20%20html%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%20index%20%20index.html%20index.htm%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%20proxy_pass%20http%3A%2F%2Fcluster%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proxy_pass%20http%3A%2F%2F127.0.0.1%3A8080%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A3.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20http%3A%2F%2Fwww.123.com%3A1111%2F%0A%20%20%20%0A%20%20%20%20!%5B0cf4106981e3920ffc84c1d82deb7094.png%5D(en-resource%3A%2F%2Fdatabase%2F583%3A1)%0A%20%20%20%20%0A%0A%0A%0A%23%23%23%23%23%207.2%20%E5%AE%9E%E4%BE%8B2%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E6%98%AFwww.123.com%3A9001%2Fedu%2Fa.html%20%E9%98%B2%E9%97%AEvmware%E4%B8%ADlinux%E4%B8%AD%E7%9A%84tomcat8080%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E6%98%AFwww.123.com%3A9001%2Fvod%2Fa.html%20%E9%98%B2%E9%97%AEvmware%E4%B8%ADlinux%E4%B8%AD%E7%9A%84tomcat8081%0A%0A1.%20%E5%87%86%E5%A4%87%E4%B8%A4%E4%B8%AAtomcat%0A%0A%20%20%20%3E%20tomcat%208080%0A%20%20%20%3E%20tomcat%208081%0A%20%20%20%0A%20%20%20%20!%5Bb6214c93afdb0abf42cc648b0d74eb0f.png%5D(en-resource%3A%2F%2Fdatabase%2F589%3A1)%0A%20%20%20%20%0A%0A%20%20%20%E5%9C%A8tomcat%208080%20%E7%9A%84%2Fopt%2Ftomcat8081%2Fwebapps%2F%20%E4%B8%8B%E6%96%B0%E5%A2%9Eedu%2F%20%E7%9B%AE%E5%BD%95%2C%20%E5%B9%B6%E5%9C%A8%E6%AD%A4%E7%9B%AE%E5%BD%95%E4%B8%AD%E6%96%B0%E5%A2%9E%E6%96%87%E4%BB%B6a.html%2C%20%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Ch4%3Etomcat%208080!%3C%2Fh4%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%E5%9C%A8tomcat%208080%20%E7%9A%84%2Fopt%2Ftomcat8081%2Fwebapps%2F%20%E4%B8%8B%E6%96%B0%E5%A2%9Evod%2F%20%E7%9B%AE%E5%BD%95%2C%20%E5%B9%B6%E5%9C%A8%E6%AD%A4%E7%9B%AE%E5%BD%95%E4%B8%AD%E6%96%B0%E5%A2%9E%E6%96%87%E4%BB%B6a.html%2C%20%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Ch4%3Etomcat%208081!%3C%2Fh4%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E6%B3%A8%EF%BC%9A%20%E6%9C%80%E5%A5%BD%E9%87%8D%E6%96%B0%E5%90%AF%E5%8A%A8tomcat%EF%BC%8C%20%E5%B0%A4%E5%85%B6%E6%98%AF8080%0A%0A2.%20%E9%85%8D%E7%BD%AEnginx.conf%20%E6%96%B0%E5%A2%9Eserver%E8%8A%82%E7%82%B9%0A%0A%20%20%20%60%60%60%0A%20%20%20server%20%7B%0A%20%20%20%20%20%20%20listen%20%20%20%20%20%20%209001%3B%0A%20%20%20%20%20%20%20server_name%20%20192.128.101.127%3B%0A%20%20%20%0A%20%20%20%20%20%20%20location%20~%20%2Fedu%2F%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20proxy_pass%20http%3A%2F%2F127.0.0.1%3A8080%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%0A%20%20%20%20%20%20%20location%20~%20%2Fvod%2F%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20proxy_pass%20http%3A%2F%2F127.0.0.1%3A8081%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A3.%20%E5%90%AF%E5%8A%A8%E5%8A%A0%E8%BD%BDnginx.conf%0A%0A%20%20%20%60%60%60%0A%20%20%20cd%20%2Fopt%2Fnginx%2Fsbin%0A%20%20%20.%2Fnginx%20-s%20reload%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A4.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%3E%20www.123.com%3A9001%2Fedu%2Fa.html%20%E8%AE%BF%E9%97%AEvmware%E4%B8%ADlinux%E4%B8%AD%E7%9A%84tomcat8080%0A%20%20%20%3E%20www.123.com%3A9001%2Fvod%2Fa.html%20%E8%AE%BF%E9%97%AEvmware%E4%B8%ADlinux%E4%B8%AD%E7%9A%84tomcat8081%0A%0A%20%20%20%0A%0A%23%23%23%23%208.%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%0A%0A%0A%0A%23%23%23%23%23%208.1%20%E5%AE%9E%E4%BE%8B1%0A%0A%E9%80%9A%E8%BF%87%E8%AE%BF%E9%97%AE%20http%3A%2F%2Fwww.123.com%3A9002%2Fedu%2Fa.html%20%E6%9D%A5%E5%B0%86%E8%AF%B7%E6%B1%82%E8%BD%AC%E5%8F%91%E5%88%B0%E4%B8%A4%E4%B8%AA%E4%B8%8D%E5%90%8C%E7%9A%84%20tomcat8080%20%E5%92%8C%20tomcat8081%E4%B8%8A%0A%0A1.%20%E5%87%86%E5%A4%87tomcat%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%0A%0A%20%20%20%E5%9C%A8tomcat%208080%20%E7%9A%84%2Fopt%2Ftomcat8080%2Fwebapps%2F%20%E4%B8%8B%E6%96%B0%E5%A2%9Eedu%2F%20%E7%9B%AE%E5%BD%95%2C%20%E5%B9%B6%E5%9C%A8%E6%AD%A4%E7%9B%AE%E5%BD%95%E4%B8%AD%E6%96%B0%E5%A2%9E%E6%96%87%E4%BB%B6a.html%2C%20%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Ch4%3Etomcat%208080!%3C%2Fh4%3E%0A%20%20%20%60%60%60%0A%0A%20%20%20%E5%9C%A8tomcat%208081%20%E7%9A%84%2Fopt%2Ftomcat8081%2Fwebapps%2F%20%E4%B8%8B%E6%96%B0%E5%A2%9Eedu%2F%20%E7%9B%AE%E5%BD%95%2C%20%E5%B9%B6%E5%9C%A8%E6%AD%A4%E7%9B%AE%E5%BD%95%E4%B8%AD%E6%96%B0%E5%A2%9E%E6%96%87%E4%BB%B6a.html%2C%20%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%20%20%20%60%60%60%0A%20%20%20%3Ch4%3Etomcat%208081!%3C%2Fh4%3E%0A%20%20%20%60%60%60%0A%0A2.%20%E9%85%8D%E7%BD%AEnginx.conf%0A%0A%20%20%20%60%60%60%0A%20%20%20%20%20%20%20%23%20config%20loadbalance%20nodes%0A%20%20%20%20%20%20%20upstream%20loadbalancer%20%7B%0A%20%20%20%20%20%20%20%20%20%20server%20127.0.0.1%3A8080%3B%0A%20%20%20%20%20%20%20%20%20%20server%20127.0.0.1%3A8081%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%60%60%60%0A%0A%20%20%20%20%20%20%20server%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20listen%20%20%20%20%20%20%209002%3B%0A%20%20%20%20%20%20%20%20%20%20%20server_name%20%20192.128.101.127%3B%0A%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20location%20~%20%2Fedu%2F%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proxy_pass%20http%3A%2F%2Floadbalancer%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%0A3.%20%E5%90%AF%E5%8A%A8tomcat%E5%92%8Cnginx%0A%0A4.%20%E6%B5%8B%E8%AF%95%0A%0A%20%20%20%20http%3A%2F%2Fwww.123.com%3A9002%2Fedu%2Fa.html%0A%0A%0A%0A%23%23%23%23%23%208.2%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%0A%0A%23%23%23%23%23%23%208.2.1%20%E8%BD%AE%E8%AF%A2%20%0A%0A%3E%20%E8%BD%AE%E8%AF%A2%20%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AD%96%E7%95%A5%EF%BC%8C%E8%AF%B7%E6%AF%8F%E4%B8%AA%E8%AF%B7%E6%B1%82%E5%B9%B3%E5%9D%87%E5%88%86%E9%85%8D%E5%88%B0%E5%90%8E%E7%AB%AF%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9C%8D%E5%8A%A1%E5%99%A8down%E6%8E%89%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%89%94%E9%99%A4%0A%0A%23%23%23%23%23%23%208.2.2%20weigh%0A%0A%3E%20%E6%9D%83%E9%87%8D%E7%AD%96%E7%95%A5%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA1%EF%BC%8C%20%E6%9D%83%E9%87%8D%E8%B6%8A%E9%AB%98%EF%BC%8C%E8%A2%AB%E5%88%86%E9%85%8D%E5%88%B0%E7%9A%84%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%95%B0%E9%87%8F%E8%B6%8A%E5%A4%9A%EF%BC%8C%E4%B8%80%E8%88%AC%E7%94%A8%E4%BA%8E%E5%90%8E%E7%AB%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%80%A7%E8%83%BD%E4%B8%8D%E5%9D%87%E5%8C%80%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E3%80%82%0A%0A%20%20%20%20%23%20config%20loadbalance%20nodes%0A%20%20%20%20upstream%20loadbalancer%20%7B%0A%20%20%20%20%20%20%20server%20127.0.0.1%3A8080%20weight%3D5%3B%0A%20%20%20%20%20%20%20server%20127.0.0.1%3A8081%20weight%3D10%3B%0A%20%20%20%20%7D%0A%3E%208081%E7%9A%84%E6%9D%83%E9%87%8D%E6%98%AF8080%E7%9A%84%E4%B8%A4%E5%80%8D%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%B8%89%E6%AC%A1%E8%AF%B7%E6%B1%82%E4%BC%9A%E6%9C%89%E4%B8%A4%E6%AC%A1%E5%88%86%E9%85%8D%E5%88%B08081%EF%BC%8C%E4%B8%80%E6%AC%A1%E5%88%86%E9%85%8D%E5%88%B08080%E3%80%82%0A%0A%0A%0A%23%23%23%23%23%23%208.2.3%20ip_hash%0A%0A%3E%20%E5%B0%86%E8%AF%B7%E6%B1%82%E6%8C%89%E7%85%A7ip%E7%9A%84hash%E7%BB%93%E6%9E%9C%E5%88%86%E9%85%8D%EF%BC%8C%E8%BF%99%E6%A0%B7%E4%B8%80%E4%B8%AA%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%8F%AF%E4%BB%A5%E5%9B%BA%E5%AE%9A%E8%AE%BF%E9%97%AE%E4%B8%80%E4%B8%AA%E5%90%8E%E7%AB%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%8F%AF%E4%BB%A5%E8%A7%A3%E5%86%B3session%E5%85%B1%E4%BA%AB%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%0A%0A%3E%20sample%3A%0A%3E%0A%3E%20%E5%BD%93%E4%BD%A0%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84%E4%B8%80%E4%B8%AA%E7%89%B9%E5%AE%9Aurl%E8%B7%AF%E5%BE%84%E4%BC%9A%E8%A2%AB%E5%90%8C%E4%B8%80%E4%B8%AA%E7%94%A8%E6%88%B7%E8%BF%9E%E7%BB%AD%E8%AE%BF%E9%97%AE%E6%97%B6%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%E8%BF%98%E6%98%AF%E8%BD%AE%E8%AF%A2%E7%9A%84%E8%AF%9D%EF%BC%8C%E9%82%A3%E8%AF%A5%E7%94%A8%E6%88%B7%E7%9A%84%E5%A4%9A%E6%AC%A1%E8%AE%BF%E9%97%AE%E4%BC%9A%E8%A2%AB%E6%89%93%E5%88%B0%E5%90%84%E5%8F%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%EF%BC%8C%E8%BF%99%E6%98%BE%E7%84%B6%E5%B9%B6%E4%B8%8D%E9%AB%98%E6%95%88%EF%BC%88%E4%BC%9A%E5%BB%BA%E7%AB%8B%E5%A4%9A%E6%AC%A1http%E9%93%BE%E6%8E%A5%E7%AD%89%E9%97%AE%E9%A2%98%EF%BC%89%E3%80%82%E7%94%9A%E8%87%B3%E8%80%83%E8%99%91%E4%B8%80%E7%A7%8D%E6%9E%81%E7%AB%AF%E6%83%85%E5%86%B5%EF%BC%8C%E7%94%A8%E6%88%B7%E9%9C%80%E8%A6%81%E5%88%86%E7%89%87%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6%E5%88%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8B%EF%BC%8C%E7%84%B6%E5%90%8E%E5%86%8D%E7%94%B1%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%B0%86%E5%88%86%E7%89%87%E5%90%88%E5%B9%B6%EF%BC%8C%E8%BF%99%E6%97%B6%E5%A6%82%E6%9E%9C%E7%94%A8%E6%88%B7%E7%9A%84%E8%AF%B7%E6%B1%82%E5%88%B0%E8%BE%BE%E4%BA%86%E4%B8%8D%E5%90%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E9%82%A3%E4%B9%88%E5%88%86%E7%89%87%E5%B0%86%E5%AD%98%E5%82%A8%E4%BA%8E%E4%B8%8D%E5%90%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9B%AE%E5%BD%95%E4%B8%AD%EF%BC%8C%E5%AF%BC%E8%87%B4%E6%97%A0%E6%B3%95%E5%B0%86%E5%88%86%E7%89%87%E5%90%88%E5%B9%B6%E3%80%82%E6%89%80%E4%BB%A5%EF%BC%8C%E6%AD%A4%E7%B1%BB%E5%9C%BA%E6%99%AF%E5%8F%AF%E4%BB%A5%E8%80%83%E8%99%91%E9%87%87%E7%94%A8nginx%E6%8F%90%E4%BE%9B%E7%9A%84ip_hash%E7%AD%96%E7%95%A5%E3%80%82%E6%97%A2%E8%83%BD%E6%BB%A1%E8%B6%B3%E6%AF%8F%E4%B8%AA%E7%94%A8%E6%88%B7%E8%AF%B7%E6%B1%82%E5%88%B0%E5%90%8C%E4%B8%80%E5%8F%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%8F%88%E8%83%BD%E6%BB%A1%E8%B6%B3%E4%B8%8D%E5%90%8C%E7%94%A8%E6%88%B7%E4%B9%8B%E9%97%B4%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E3%80%82%0A%0A%20%20%20%20%23%20config%20loadbalance%20nodes%0A%20%20%20%20upstream%20loadbalancer%20%7B%0A%20%20%20%20%20%20%20ip_hash%3B%0A%20%20%20%20%20%20%20server%20127.0.0.1%3A8080%20weight%3D5%3B%0A%20%20%20%20%20%20%20server%20127.0.0.1%3A8081%20weight%3D10%3B%0A%20%20%20%20%20%20%20server%20127.0.0.1%3A8083%20weight%3D10%20down%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20server%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20listen%20%20%20%20%20%20%209002%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20server_name%20%20192.128.101.127%3B%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20location%20~%20%2Fupload%2F%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proxy_pass%20http%3A%2F%2Floadbalancer%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%3E%20down%E5%85%B3%E9%94%AE%E5%AD%97%EF%BC%8C%E8%A1%A8%E7%A4%BA%E4%B8%8B%E7%BA%BF%E7%9A%84%E6%84%8F%E6%80%9D%0A%0A%23%23%23%23%23%23%208.2.4%20url_hash%0A%0A%3E%20%E5%B0%86%E4%B8%8D%E5%90%8C%E8%B5%84%E6%BA%90%E7%9A%84%E8%AF%B7%E6%B1%82%E6%8C%89%E7%85%A7url%E7%9A%84hash%E7%BB%93%E6%9E%9C%E5%88%86%E9%85%8D%EF%BC%8C%E7%9B%B8%E5%85%B3%E7%9A%84%E8%B5%84%E6%BA%90%E5%8F%AA%E4%BC%9A%E8%A2%AB%E8%AF%B7%E6%B1%82%E4%B8%80%E6%AC%A1.%0A%3E%0A%3E%20%E8%A6%81%E7%94%A8%E5%88%B0urlhash%EF%BC%8C%E6%98%AF%E8%A6%81%E9%85%8D%E5%90%88%E7%BC%93%E5%AD%98%E5%91%BD%E4%B8%AD%E6%9D%A5%E4%BD%BF%E7%94%A8%0A%0A%3E%20sample%0A%3E%0A%3E%20%E6%9C%89%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%86%E7%BE%A4A%EF%BC%8C%E9%9C%80%E8%A6%81%E5%AF%B9%E5%A4%96%E6%8F%90%E4%BE%9B%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%EF%BC%8C%E7%94%B1%E4%BA%8E%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E9%87%8F%E5%B7%A8%E5%A4%A7%EF%BC%8C%E6%B2%A1%E6%B3%95%E5%AD%98%E5%82%A8%E5%88%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%A3%81%E7%9B%98%E4%B8%AD%EF%BC%8C%E6%89%80%E4%BB%A5%E7%94%A8%E5%88%B0%E4%BA%86%E7%AC%AC%E4%B8%89%E6%96%B9%E4%BA%91%E5%AD%98%E5%82%A8%E6%9D%A5%E5%81%9A%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8%E3%80%82%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%86%E7%BE%A4A%E6%94%B6%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AF%B7%E6%B1%82%E4%B9%8B%E5%90%8E%EF%BC%8C%E9%9C%80%E8%A6%81%E4%BB%8E%E4%BA%91%E5%AD%98%E5%82%A8%E4%B8%AD%E4%B8%8B%E8%BD%BD%E6%96%87%E4%BB%B6%E7%84%B6%E5%90%8E%E8%BF%94%E5%9B%9E%EF%BC%8C%E4%B8%BA%E4%BA%86%E7%9C%81%E5%8E%BB%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E7%BD%91%E7%BB%9C%E5%B8%A6%E5%AE%BD%E5%92%8C%E4%B8%8B%E8%BD%BD%E8%80%97%E6%97%B6%EF%BC%8C%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%86%E7%BE%A4A%E4%B8%8A%E5%81%9A%E4%BA%86%E4%B8%80%E5%B1%82%E4%B8%B4%E6%97%B6%E7%BC%93%E5%AD%98%EF%BC%88%E7%BC%93%E5%AD%98%E4%B8%80%E4%B8%AA%E6%9C%88%EF%BC%89%E3%80%82%E7%94%B1%E4%BA%8E%E6%98%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%9B%86%E7%BE%A4%EF%BC%8C%E6%89%80%E4%BB%A5%E5%90%8C%E4%B8%80%E4%B8%AA%E8%B5%84%E6%BA%90%E5%A4%9A%E6%AC%A1%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%88%B0%E8%BE%BE%E4%B8%8D%E5%90%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%EF%BC%8C%E5%AF%BC%E8%87%B4%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E5%A4%9A%E6%AC%A1%E4%B8%8B%E8%BD%BD%EF%BC%8C%E7%BC%93%E5%AD%98%E5%91%BD%E4%B8%AD%E7%8E%87%E4%B8%8D%E9%AB%98%EF%BC%8C%E4%BB%A5%E5%8F%8A%E4%B8%80%E4%BA%9B%E8%B5%84%E6%BA%90%E6%97%B6%E9%97%B4%E7%9A%84%E6%B5%AA%E8%B4%B9%E3%80%82%E5%9C%A8%E6%AD%A4%E7%B1%BB%E5%9C%BA%E6%99%AF%E4%B8%8B%EF%BC%8C%E4%B8%BA%E4%BA%86%E4%BD%BF%E5%BE%97%E7%BC%93%E5%AD%98%E5%91%BD%E4%B8%AD%E7%8E%87%E6%8F%90%E9%AB%98%EF%BC%8C%E5%BE%88%E9%80%82%E5%90%88%E4%BD%BF%E7%94%A8url_hash%E7%AD%96%E7%95%A5%EF%BC%8C%E5%90%8C%E4%B8%80%E4%B8%AAurl%EF%BC%88%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%90%8C%E4%B8%80%E4%B8%AA%E8%B5%84%E6%BA%90%E8%AF%B7%E6%B1%82%EF%BC%89%E4%BC%9A%E5%88%B0%E8%BE%BE%E5%90%8C%E4%B8%80%E5%8F%B0%E6%9C%BA%E5%99%A8%EF%BC%8C%E4%B8%80%E6%97%A6%E7%BC%93%E5%AD%98%E4%BD%8F%E4%BA%86%E8%B5%84%E6%BA%90%EF%BC%8C%E5%86%8D%E6%AD%A4%E6%94%B6%E5%88%B0%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BB%8E%E7%BC%93%E5%AD%98%E4%B8%AD%E8%AF%BB%E5%8F%96%EF%BC%8C%E6%97%A2%E5%87%8F%E5%B0%91%E4%BA%86%E5%B8%A6%E5%AE%BD%EF%BC%8C%E4%B9%9F%E5%87%8F%E5%B0%91%E7%9A%84%E4%B8%8B%E8%BD%BD%E6%97%B6%E9%97%B4%E3%80%82%0A%0A%60%60%60%0Aupstream%20somestream%20%7B%0A%20%20%20%20hash%20%24request_uri%3B%0A%20%20%20%20server%20192.168.244.1%3A8080%3B%0A%20%20%20%20server%20192.168.244.2%3A8080%3B%0A%20%20%20%20server%20192.168.244.3%3A8080%3B%0A%20%20%20%20server%20192.168.244.4%3A8080%3B%0A%20%0A%7D%0Aserver%20%7B%0A%20%20%20%20listen%208081%20default%3B%0A%20%20%20%20server_name%20test.csdn.net%3B%0A%20%20%20%20charset%20utf-8%3B%0A%20%20%20%20location%20%2Fget%20%7B%0A%20%20%20%20proxy_pass%20http%3A%2F%2Fsomestream%3B%0A%20%0A%20%20%20%20%7D%20%20%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%208.2.5%20fair%0A%0A%3E%20%E6%A0%B9%E6%8D%AE%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E5%93%8D%E5%BA%94%E6%97%B6%E9%97%B4%E6%9D%A5%E5%88%86%E9%85%8D%EF%BC%8C%E8%B0%81%E7%9A%84%E5%93%8D%E5%BA%94%E6%97%B6%E9%97%B4%E7%9F%AD%E5%B0%B1%E4%BC%98%E5%85%88%E5%88%86%E9%85%8D%0A%3E%0A%3E%20%E9%9C%80%E8%A6%81%E5%8D%95%E7%8B%AC%E7%AC%AC%E4%B8%89%E6%96%B9fair%E6%A8%A1%E5%9D%97%0A%0A%20%20%20%20%23%20config%20loadbalance%20nodes%0A%20%20%20%20upstream%20loadbalancer%20%7B%0A%20%20%20%20%20%20%20server%20127.0.0.1%3A8080%20weight%3D5%3B%0A%20%20%20%20%20%20%20server%20127.0.0.1%3A8081%20weight%3D10%3B%0A%20%20%20%20%20%20%20fair%3B%0A%20%20%20%20%7D%0A%0A%0A%0A%23%23%23%23%209.%20%E5%8A%A8%E9%9D%99%E5%88%86%E7%A6%BB%0A%0A%3E%20%E9%80%9A%E8%BF%87%E8%AE%BF%E9%97%AE%20http%3A%2F%2Fwww.123.com%3A9003%2Fwww%2Fa.html%20%E7%9B%B4%E6%8E%A5%E8%8E%B7%E5%8F%96%E6%9C%8D%E5%8A%A1%E5%99%A8www%2Fa.html%0A%3E%0A%3E%20%E9%80%9A%E8%BF%87%E8%AE%BF%E9%97%AE%20http%3A%2F%2Fwww.123.com%3A9003%2Fimages%2F%20%E7%9B%B4%E6%8E%A5%E8%8E%B7%E5%8F%96%E6%9C%8D%E5%8A%A1%E5%99%A8images%2F%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E5%9B%BE%E7%89%87%E6%96%87%E4%BB%B6%0A%0A%0A%0A%23%23%23%23%23%209.1%20%E5%87%86%E5%A4%87%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%0A%0A%60%60%60%0Acd%20%2Fusr%2Flocal%0Amkdir%20nginx-test%0Acd%20nginx-test%0Amkdir%20www%0Amkdir%20images%0A%60%60%60%0A%0A%60%60%60%0Acd%20www%0Avi%20a.html%0A%0A%E5%AD%98%E6%94%BE%E5%A6%82%E4%B8%8B%E5%86%85%E5%AE%B9%0A%3Ch4%3Etest%20static%20resource!!!%3C%2Fh4%3E%0A%60%60%60%0A%0A%60%60%60%0Acd%20images%0A%E4%B8%8A%E4%BC%A0%E8%8B%A5%E5%B9%B2%E5%BC%A0%E5%9B%BE%E7%89%87%E5%88%B0images%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%209.2%20%20%E9%85%8D%E7%BD%AEnginx.conf%E6%96%87%E4%BB%B6%0A%0A%20%20%20%20server%20%7B%0A%20%20%20%20%20%20%20%20listen%20%20%20%20%20%20%209003%3B%0A%20%20%20%20%20%20%20%20server_name%20%20192.128.101.127%3B%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20location%20%2Fwww%2F%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20root%20%2Fusr%2Flocal%2Fnginx-test%2F%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20expires%2020s%3B%0A%20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%20%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20location%20%2Fimages%2F%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20root%20%2Fusr%2Flocal%2Fnginx-test%2F%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20expires%2020s%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20autoindex%20on%3B%20%23%E5%88%97%E5%87%BA%E5%BD%93%E5%89%8D%E6%96%87%E4%BB%B6%E5%A4%B9%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%0A%20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%20%0A%20%20%20%20%7D%20%20%20%0A%0A%0A%23%23%23%23%23%209.3%20%E6%B5%8B%E8%AF%95%0A%0Ahttp%3A%2F%2Fwww.123.com%3A9003%2Fimages%2F%0A%20!%5Bcabc513d793ea5fb4fdab40b6d9f1f96.png%5D(en-resource%3A%2F%2Fdatabase%2F590%3A1)%0A%20%0A%0Ahttp%3A%2F%2Fwww.123.com%3A9003%2Fwww%2Fa.html%0A%20!%5Befc69efccf22680b7d570c1967787984.png%5D(en-resource%3A%2F%2Fdatabase%2F591%3A1)%0A%20%0A%0A%0A%23%23%23%23%2010.%20%E9%AB%98%E5%8F%AF%E7%94%A8%E9%85%8D%E7%BD%AE%0A%0A%3E%20%E5%85%88%E9%80%9A%E8%BF%87%E4%B8%BBNginx%E5%8F%91%E9%80%81%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%BBNginx%E5%AE%95%E6%9C%BA%EF%BC%8C%E5%88%99%E9%80%9A%E8%BF%87%E5%A4%87%E4%BB%BDNginx%E5%8F%91%E9%80%81%E8%AF%B7%E6%B1%82%E3%80%82%0A%3E%20keepalived%20%E7%9B%B8%E5%BD%93%E4%BA%8E%E8%B7%AF%E7%94%B1%EF%BC%8C%E9%80%9A%E8%BF%87%E8%84%9A%E6%9C%AC%E6%9D%A5%E6%A3%80%E6%B5%8B%E4%B8%BB%E8%8A%82%E7%82%B9%E6%98%AF%E5%90%A6%E5%8F%AF%E7%94%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%8F%AF%E7%94%A8%EF%BC%8C%E5%88%99%E8%87%AA%E5%8A%A8%E5%88%87%E6%8D%A2%E5%88%B0%E5%8F%A6%E5%A4%96%E4%B8%80%E5%8F%B0%E5%A4%87%E7%94%A8%E8%8A%82%E7%82%B9%E4%B8%8A%E3%80%82%0A%3E%20%E8%99%9A%E6%8B%9FIP%20%EF%BC%8C%E9%80%9A%E8%BF%87%E8%99%9A%E6%8B%9FIP%E6%9D%A5%E7%BB%91%E5%AE%9A%E5%88%B0%E5%8F%AF%E7%94%A8%E7%9A%84Nginx%E8%8A%82%E7%82%B9%2C%20%E5%85%88%E6%98%AF%E7%BB%91%E5%AE%9A%E5%88%B0master%E8%8A%82%E7%82%B9%E4%B8%8A%EF%BC%8C%E5%A6%82%E6%9E%9Cmaster%E8%8A%82%E7%82%B9%E5%AE%95%E6%9C%BA%EF%BC%8C%E4%BC%9A%E8%87%AA%E5%8A%A8%E7%BB%91%E5%AE%9A%E5%88%B0slave%E8%8A%82%E7%82%B9%E4%B8%8A%0A%0A!%5B575eca9ce7503cda8673058f740c1d86.png%5D(en-resource%3A%2F%2Fdatabase%2F588%3A1)%0A%0A%0A%23%23%23%23%23%2010.1%20%E9%85%8D%E7%BD%AE%E5%A4%87%E6%9C%BAslave01%0A%0A1.%20%E5%AE%89%E8%A3%85nginx%0A2.%20%E5%AE%89%E8%A3%85tomcat%0A%0A%23%23%23%23%23%2010.2%20keepalived%0A%0A%23%23%23%23%23%23%2010.2.1%20%E5%AE%89%E8%A3%85keepalived%0A%0A%60%60%60%0Ayum%20-y%20install%20keepalived%0Acd%20%2Fetc%2Fkeepalived%0Aecho%20%3E%20keepalived.conf%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%2010.2.2%20%E9%85%8D%E7%BD%AEkeepalived%0A%0A%3E%20%E5%B0%86%E5%A6%82%E4%B8%8B%E5%86%85%E5%AE%B9%E7%B2%98%E8%B4%B4%E5%88%B0keepalived.conf%0A%0A%60%60%60%0A!%20Configuration%20File%20for%20keepalived%0A%0A%23%20%E5%85%A8%E5%B1%80%E5%AE%9A%E4%B9%89%0Aglobal_defs%20%7B%0A%20%20%20notification_email%20%7B%0A%20%20%20%20%20acassen%40firewall.loc%0A%20%20%20%20%20failover%40firewall.loc%0A%20%20%20%20%20sysadmin%40firewall.loc%0A%20%20%20%7D%0A%20%20%20notification_email_from%20Alexandre.Cassen%40firewall.loc%0A%20%20%20smtp_server%20192.168.200.1%0A%20%20%20smtp_connect_timeout%2030%0A%20%20%20router_id%20192.168.101.127%20%20%23%20%E5%B1%80%E5%9F%9F%E7%BD%91keppalived%E4%B8%BB%E6%9C%BA%E6%A0%87%E8%AF%86%2C%E5%8F%AF%E4%BB%A5%E4%B8%BA%E4%B8%BB%E6%9C%BA%E5%90%8D%E6%88%96IP%0A%20%20%20script_user%20root%20%20%20%20%20%20%20%20%20%20%20%23%20%E6%B7%BB%E5%8A%A0%E8%BF%90%E8%A1%8C%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5%E8%84%9A%E6%9C%AC%E7%9A%84%E7%94%A8%E6%88%B7%0A%20%20%20enable_script_security%20%20%20%20%20%23%20%E6%B7%BB%E5%8A%A0%E8%BF%90%E8%A1%8C%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5%E8%84%9A%E6%9C%AC%E7%9A%84%E7%BB%84%0A%7D%0A%0A%23%20%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%0Avrrp_script%20chk_http_port%20%7B%0A%20%20script%20%22%2Fect%2Fkeepalived%2Fnginxchk%2Fnginx_check.sh%22%20%20%23%20%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC%E4%BD%8D%E7%BD%AE%0A%20%20interval%202%20%20%23%20%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC%E6%89%A7%E8%A1%8C%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%20%20%0A%20%20weight%20-20%20%20%20%23%E7%9B%91%E6%B5%8B%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%88%99%E7%9B%B8%E5%BA%94%E7%9A%84%20vrrp_instance%20%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%E4%BC%9A%E5%87%8F%E5%B0%9120%E4%B8%AA%E7%82%B9%0A%7D%0A%0A%23%20%E8%99%9A%E6%8B%9FIP%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%0Avrrp_instance%20VI_1%20%7B%0A%20%20%20%20state%20MASTER%20%20%23%20%E5%A4%87%E6%9C%BA%E4%B8%8A%E9%9C%80%E8%A6%81%E5%B0%86%20MASTER%20%E6%94%B9%E4%B8%BA%20BACKUP%0A%20%20%20%20interface%20eth0%20%23%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E7%9A%84%E7%BD%91%E5%8D%A1%E5%90%8D%E7%A7%B0%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87ifconfig%E6%9F%A5%E5%88%B0%0A%20%20%20%20virtual_router_id%2051%20%20%23%20%E4%B8%BB%E6%9C%BA%E5%92%8C%E5%A4%87%E6%9C%BA%E7%9A%84%E6%AD%A4%E9%85%8D%E7%BD%AE%E9%A1%B9%E7%9A%84%E5%80%BC%E5%BF%85%E9%A1%BB%E7%9B%B8%E5%90%8C%0A%20%20%20%20priority%20100%20%23%20%E4%B8%BB%E6%9C%BA%E5%92%8C%E5%A4%87%E6%9C%BA%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E4%B8%BB%E6%9C%BA%E7%9A%84%E5%80%BC%E5%A4%A7%E4%BA%8E%E5%A4%87%E6%9C%BA%E7%9A%84%E5%80%BC%0A%20%20%20%20advert_int%201%20%23%20%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%0A%20%20%20%20authentication%20%7B%20%20%20%23%20%E4%B8%BB%E5%A4%87%E4%B8%BB%E6%9C%BA%E4%B9%8B%E9%97%B4%E7%9A%84%E8%AE%A4%E8%AF%81%E8%A1%A8%E7%A4%BA%E4%BF%A1%E6%81%AF%0A%20%20%20%20%20%20%20%20auth_type%20PASS%20%23%E9%87%87%E7%94%A8%E6%98%8E%E6%96%87%E8%AE%A4%E8%AF%81%E6%9C%BA%E5%88%B6%0A%20%20%20%20%20%20%20%20auth_pass%201111%20%23%E7%BC%96%E5%86%99%E6%98%8E%E6%96%87%E5%AF%86%E7%A0%81%0A%20%20%20%20%7D%0A%20%20%20%20virtual_ipaddress%20%7B%0A%20%20%20%20%20%20%20%20192.168.101.150%20%23%20%E8%99%9A%E6%8B%9FIP%E5%9C%B0%E5%9D%80%2C%E6%AD%A4%E5%8F%82%E6%95%B0%E5%A4%87%E8%8A%82%E7%82%B9%E8%AE%BE%E7%BD%AE%E5%92%8C%E4%B8%BB%E8%8A%82%E7%82%B9%E7%9B%B8%E5%90%8C%EF%BC%8C%E6%AD%A4%E5%A4%84%E5%8F%AF%E4%BB%A5%E7%BB%91%E5%AE%9A%E5%A4%9A%E4%B8%AA%E8%99%9A%E6%8B%9FIP.%0A%20%20%20%20%7D%0A%0A%20%20%20%20track_script%20%7B%0A%20%20%20%20%20%20%20%20chk_http_port%20%20%20%20%20%20%20%23%E8%B0%83%E7%94%A8%E6%89%A7%E8%A1%8C%E8%84%9A%E6%9C%AC%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E5%A4%87%E6%9C%BA%E4%B8%AD%E9%85%8D%E7%BD%AEkeepalived.conf%0A%0A%60%60%60%0A!%20Configuration%20File%20for%20keepalived%0A%0A%23%20%E5%85%A8%E5%B1%80%E5%AE%9A%E4%B9%89%0Aglobal_defs%20%7B%0A%20%20%20notification_email%20%7B%0A%20%20%20%20%20acassen%40firewall.loc%0A%20%20%20%20%20failover%40firewall.loc%0A%20%20%20%20%20sysadmin%40firewall.loc%0A%20%20%20%7D%0A%20%20%20notification_email_from%20Alexandre.Cassen%40firewall.loc%0A%20%20%20smtp_server%20SMTP.163.com%0A%20%20%20smtp_connect_timeout%2030%0A%20%20%20router_id%20192.168.101.128%20%20%23%20%E5%B1%80%E5%9F%9F%E7%BD%91keppalived%E4%B8%BB%E6%9C%BA%E6%A0%87%E8%AF%86%2C%E5%8F%AF%E4%BB%A5%E4%B8%BA%E4%B8%BB%E6%9C%BA%E5%90%8D%E6%88%96IP%0A%20%20%20script_user%20root%20%20%20%20%20%20%20%20%20%20%20%23%20%E6%B7%BB%E5%8A%A0%E8%BF%90%E8%A1%8C%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5%E8%84%9A%E6%9C%AC%E7%9A%84%E7%94%A8%E6%88%B7%0A%20%20%20enable_script_security%20%20%20%20%20%23%20%E6%B7%BB%E5%8A%A0%E8%BF%90%E8%A1%8C%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5%E8%84%9A%E6%9C%AC%E7%9A%84%E7%BB%84%0A%7D%0A%0A%23%20%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%0Avrrp_script%20chk_http_port%20%7B%0A%20%20script%20%22%2Fetc%2Fkeepalived%2Fnginx-chk%2Fnginx_check.sh%22%20%20%23%20%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC%E4%BD%8D%E7%BD%AE%0A%20%20interval%202%20%20%23%20%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC%E6%89%A7%E8%A1%8C%E7%9A%84%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%0A%20%20weight%20-20%20%20%23%20%E7%9B%91%E6%B5%8B%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%88%99%E7%9B%B8%E5%BA%94%E7%9A%84%20vrrp_instance%20%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%E4%BC%9A%E5%87%8F%E5%B0%9120%E4%B8%AA%E7%82%B9%0A%7D%0A%0A%23%20%E8%99%9A%E6%8B%9FIP%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%0Avrrp_instance%20VI_1%20%7B%0A%20%20%20%20state%20BACKUP%20%20%23%20%E5%A4%87%E6%9C%BA%E4%B8%8A%E9%9C%80%E8%A6%81%E5%B0%86%20MASTER%20%E6%94%B9%E4%B8%BA%20BACKUP%0A%20%20%20%20interface%20ens33%20%23%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E7%9A%84%E7%BD%91%E5%8D%A1%E5%90%8D%E7%A7%B0%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87ifconfig%E6%9F%A5%E5%88%B0%0A%20%20%20%20virtual_router_id%2051%20%20%23%20%E4%B8%BB%E6%9C%BA%E5%92%8C%E5%A4%87%E6%9C%BA%E7%9A%84%E6%AD%A4%E9%85%8D%E7%BD%AE%E9%A1%B9%E7%9A%84%E5%80%BC%E5%BF%85%E9%A1%BB%E7%9B%B8%E5%90%8C%0A%20%20%20%20priority%2090%20%20%23%20%E4%B8%BB%E6%9C%BA%E5%92%8C%E5%A4%87%E6%9C%BA%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E4%B8%BB%E6%9C%BA%E7%9A%84%E5%80%BC%E5%A4%A7%E4%BA%8E%E5%A4%87%E6%9C%BA%E7%9A%84%E5%80%BC%0A%20%20%20%20advert_int%201%20%23%20%E5%8F%91%E9%80%81%E5%BF%83%E8%B7%B3%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA1%E7%A7%92%0A%20%20%20%20authentication%20%7B%0A%20%20%20%20%20%20%20%20auth_type%20PASS%0A%20%20%20%20%20%20%20%20auth_pass%201111%0A%20%20%20%20%7D%0A%20%20%20%20virtual_ipaddress%20%7B%0A%20%20%20%20%20%20%20%20192.168.101.150%20%23%20%E8%99%9A%E6%8B%9FIP%E5%9C%B0%E5%9D%80%EF%BC%8C%E6%AD%A4%E5%A4%84%E5%8F%AF%E4%BB%A5%E7%BB%91%E5%AE%9A%E5%A4%9A%E4%B8%AA%E8%99%9A%E6%8B%9FIP%0A%20%20%20%20%7D%0A%0A%20%20%20%20track_script%20%7B%0A%20%20%20%20%20%20%20%20chk_http_port%20%20%20%20%20%20%20%23%E8%B0%83%E7%94%A8%E6%89%A7%E8%A1%8C%E8%84%9A%E6%9C%AC%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%2010.2.3%20%E5%90%AF%E5%8A%A8keepalived%0A%0A1.%20%E5%90%AF%E5%8A%A8%E4%B8%BB%E6%9C%BA%E5%92%8C%E5%A4%87%E6%9C%BA%E7%9A%84keepalived%0A%0A%20%20%20%60%60%60%0A%20%20%20systemctl%20start%20keepalived.service%0A%20%20%20%60%60%60%0A%0A%0A2.%20%E5%90%AF%E5%8A%A8%E5%90%8E%EF%BC%8C%E8%99%9A%E6%8B%9FIP%E4%BC%9A%E5%85%88%E7%BB%91%E5%AE%9A%E5%88%B0master%E8%8A%82%E7%82%B9%E4%B8%8A%0A%0A%20%20%20%60%60%60%0A%20%20%20ip%20a%20%0A%20%20%20%60%60%60%0A%20%20%20!%5B3e2e0a99625e105fdcd0a9d659c1632d.png%5D(en-resource%3A%2F%2Fdatabase%2F586%3A1)%0A%20%20%0A%0A%23%23%23%23%23%23%2010.2.4%20%E9%85%8D%E7%BD%AE%E5%AE%BF%E4%B8%BB%E6%9C%BAhost%0A%0A%3E%20C%3A%5CWindows%5CSystem32%5Cdrivers%5Cetc%5Chosts%0A%0A%60%60%60%0A%23%23%23%23%23%23%23%23%20keepalived%20%E8%99%9A%E6%8B%9FIP%20%23%23%23%23%23%23%23%23%23%23%23%0A192.168.101.150%09vip%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%2010.2.5%20%E6%B5%8B%E8%AF%95%0A%0A1.%20http%3A%2F%2Fvip%0A!%5Bfe2668cb86ff11aeb4ebd57ee875e8af.png%5D(en-resource%3A%2F%2Fdatabase%2F592%3A1)%0A%0A%0A2.%20%E5%85%B3%E9%97%ADmaster%E8%8A%82%E7%82%B9%0A%0A%20%20%20%60%60%60%0A%20%20%20systemctl%20stop%20keepalived.service%0A%20%20%20cd%20%2Fusr%2Flocal%2Fnginx%2Fsbin%0A%20%20%20.%2Fnginx%20-s%20stop%0A%20%20%20%60%60%60%0A%0A%20%20%20%3E%20%E5%9C%A8%E5%A4%87%E6%9C%BAslave01%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E8%99%9A%E6%8B%9FIP%E7%BB%91%E5%AE%9A%E5%88%B0%E4%BA%86slave01%E4%B8%8A%0A%0A%20%20%20%60%60%60%0A%20%20%20ip%20a%0A%20%20%20%60%60%60%0A%20%20%20%20!%5B3141ca0d35b386ab3110962c4377c3ea.png%5D(en-resource%3A%2F%2Fdatabase%2F584%3A1)%0A%0A%0A%0A%20%20%20%20http%3A%2F%2Fvip%20%0A%20%20%20%20!%5B3c893dba05d2a8b9ff100d180e9a70f5.png%5D(en-resource%3A%2F%2Fdatabase%2F585%3A1)%0A%0A%23%23%23%23%2011%20%E5%B7%A5%E4%BD%9C%E6%9C%BA%E5%88%B6%0A%0A%23%23%23%23%23%2011.1%20%E5%8E%9F%E7%90%86%0A%3E%20%E4%B8%80%E4%B8%AAmaster%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%9C%89%E5%A4%9A%E4%B8%AAworker%0A%0A!%5Bdf2481cbb71ff3a731917f44fba6ccbd.png%5D(en-resource%3A%2F%2Fdatabase%2F800%3A0)%0A%0A%0A%3E%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%8F%91%E9%80%81%E8%AF%B7%E6%B1%82%E5%88%B0master%E4%B8%AD%EF%BC%8Cmaster%E6%94%B6%E5%88%B0%E8%AF%B7%E6%B1%82%E4%BB%BB%E5%8A%A1%E5%90%8E%EF%BC%8Cworker%E9%80%9A%E8%BF%87%E4%BA%89%E6%8A%A2%E7%9A%84%E6%9C%BA%E5%88%B6%E4%BB%8Emaster%E5%A4%84%E8%8E%B7%E5%8F%96%E4%BB%BB%E5%8A%A1%EF%BC%8C%E7%84%B6%E5%90%8Eworker%E8%B4%9F%E8%B4%A3%E5%85%B7%E4%BD%93%E7%9A%84%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%EF%BC%8C%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%89%E5%85%B7%E4%BD%93%E7%9A%84%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A!%5B97fa14b8aab06751966c01e734674bce.png%5D(en-resource%3A%2F%2Fdatabase%2F798%3A0)%0A%0A%23%23%23%23%23%2011.2%20%E8%BF%99%E7%A7%8D%E6%9C%BA%E5%88%B6%E7%9A%84%E5%A5%BD%E5%A4%84%0A1.%20%E6%AF%8F%E4%B8%AAworker%E9%83%BD%E6%98%AF%E7%8B%AC%E7%AB%8B%E7%9A%84%E4%B8%80%E4%B8%AA%E8%BF%9B%E7%A8%8B%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E5%8D%95%E7%8B%AC%E5%8A%A0%E9%94%81%EF%BC%8C%E4%BB%8E%E6%9D%A5%E9%81%BF%E5%85%8D%E4%BA%86%E5%8A%A0%E9%94%81%E5%B8%A6%E6%9D%A5%E7%9A%84%E5%BC%80%E9%94%80%E3%80%82%0A%E5%90%8C%E6%97%B6%E8%BF%9B%E7%A8%8B%E4%B9%8B%E9%97%B4%E7%9B%B8%E4%BA%92%E4%B8%8D%E5%BD%B1%E5%93%8D%EF%BC%8C%E4%B8%80%E4%B8%AA%E8%BF%9B%E7%A8%8B%E9%80%80%E5%87%BA%E5%90%8E%E4%B8%8D%E5%BD%B1%E5%93%8D%E5%8F%A6%E5%A4%96%E8%BF%9B%E7%A8%8B%E7%9A%84%E6%AD%A3%E5%B8%B8%E5%B7%A5%E4%BD%9C%E3%80%82%0A%0A2.%20%E4%B8%80%E4%B8%AAmaster%E5%A4%9A%E4%B8%AAworker%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%96%B9%E4%BE%BF%E7%BA%BF%E4%B8%8A%E5%81%9A%E7%83%AD%E9%83%A8%E7%BD%B2%0A%20%20%20%3E%20%E4%BE%8B%E5%A6%82%E4%B8%80%E4%B8%AAmaster%E5%AF%B9%E5%BA%94%E5%9B%9B%E4%B8%AAworker%EF%BC%8C%E5%85%B6%E4%B8%AD%E4%B8%80%E4%B8%AAworker-1%E6%AD%A3%E5%9C%A8%E5%A4%84%E7%90%86%E4%B8%8A%E4%B8%80%E8%BD%AE%E4%B8%AD%E4%BA%89%E6%8A%A2%E5%88%B0%E7%9A%84%E4%BB%BB%E5%8A%A1%EF%BC%8C%E6%AD%A4%E6%97%B6nginx%E9%87%8D%E6%96%B0%E5%8A%A0%E8%BD%BD%EF%BC%8C%E5%88%99%E9%99%A4%E8%BF%87%E8%BF%99%E4%B8%AA%E6%AD%A3%E5%9C%A8%E6%89%A7%E8%A1%8C%E4%BB%BB%E5%8A%A1%E7%9A%84worker%E5%A4%96%EF%BC%8C%E5%85%B6%E5%AE%83%E4%B8%89%E4%B8%AAworker%E9%83%BD%E4%BC%9A%E5%8A%A0%E8%BD%BD%E6%9C%80%E6%96%B0%E7%9A%84nginx%E9%85%8D%E7%BD%AE%E5%86%85%E5%AE%B9%E5%B9%B6%E5%8F%82%E4%B8%8E%E5%88%B0%E6%96%B0%E4%B8%80%E8%BD%AE%E7%9A%84%E4%BB%BB%E5%8A%A1%E4%BA%89%E6%8A%A2%E4%B8%AD%EF%BC%8Cworker-1%E5%9C%A8%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%89%8B%E5%A4%B4%E7%9A%84%E4%BB%BB%E5%8A%A1%E5%90%8E%E4%B9%9F%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%8A%A0%E8%BD%BD%E6%9C%80%E6%96%B0%E7%9A%84nginx%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%B9%B6%E5%8F%82%E4%B8%8E%E5%88%B0%E4%B8%8B%E4%B8%80%E8%BD%AE%E7%9A%84%E4%BB%BB%E5%8A%A1%E4%BA%89%E6%8A%A2%E4%B8%AD%E5%8E%BB%E3%80%82%0A%20%20%20%0A%23%23%23%23%23%2011.3%20%E8%AE%BE%E7%BD%AE%E5%A4%9A%E5%B0%91%E4%B8%AAworker%E6%9C%80%E5%A5%BD%0A%20%20%20%3E%20Nginx%20%E5%90%8CRedis%E7%B1%BB%E4%BC%BC%E9%83%BD%E6%98%AF%E9%87%87%E7%94%A8io%E5%A4%9A%E8%B7%AF%E5%A4%8D%E7%94%A8%E6%9C%BA%E5%88%B6%EF%BC%8C%E6%AF%8F%E4%B8%AAworker%E9%83%BD%E6%98%AF%E4%B8%80%E4%B8%AA%E8%BF%9B%E7%A8%8B%EF%BC%8C%E4%BD%86%E6%AF%8F%E4%B8%AA%E8%BF%9B%E7%A8%8B%E9%87%8C%E9%9D%A2%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E4%B8%BB%E7%BA%BF%E7%A8%8B%EF%BC%8C%E9%80%9A%E8%BF%87%E5%BC%82%E6%AD%A5%E9%9D%9E%E9%98%BB%E5%A1%9E%E7%9A%84%E6%96%B9%E5%BC%8F%E5%A4%84%E7%90%86%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%8D%B3%E4%BD%BF%E6%88%90%E5%8D%83%E4%B8%8A%E4%B8%87%E4%B8%AA%E8%AF%B7%E6%B1%82%E4%B9%9F%E5%8F%AF%E4%BB%A5%E9%AB%98%E6%95%88%E5%A4%84%E7%90%86%E3%80%82%E6%AF%8F%E4%B8%AAworker%E5%8F%AF%E4%BB%A5%E5%B0%86%E4%B8%80%E4%B8%AAcpu%E7%9A%84%E6%80%A7%E8%83%BD%E5%8F%91%E6%8C%A5%E5%88%B0%E6%9E%81%E8%87%B4%EF%BC%8C%E6%89%80%E4%BB%A5worker%E6%95%B0%E5%92%8Ccpu%E6%95%B0%E4%BF%9D%E6%8C%81%E4%B8%80%E8%87%B4%E6%9C%80%E5%A5%BD%2C%E4%BE%8B%E5%A6%828%E6%A0%B8cpu%E8%AE%BE%E7%BD%AE8%E4%B8%AAworker%EF%BC%8C%E8%AE%BE%E7%BD%AE%E5%B0%91%E4%BA%86%E4%BC%9A%E6%B5%AA%E8%B4%B9cpu%E8%B5%84%E6%BA%90%EF%BC%8C%E8%AE%BE%E7%BD%AE%E5%A4%9A%E4%BA%86%E4%BC%9A%E9%80%A0%E6%88%90cpu%E5%9C%A8%E4%B8%8A%E4%B8%8B%E6%96%87%E9%A2%91%E7%B9%81%E5%88%87%E6%8D%A2%E9%80%A0%E6%88%90%E7%9A%84%E6%8D%9F%E8%80%97%E3%80%82%0A%20%20%20%0A%20%23%23%23%23%23%2011.4%20%E8%BF%9E%E6%8E%A5%E6%95%B0worker_connection%0A%20%3E%20%E9%97%AE%E9%A2%981%EF%BC%9A%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%8F%91%E9%80%81%E4%B8%80%E4%B8%AA%E6%B8%85%E6%B1%82%EF%BC%8C%E5%8D%A0%E7%94%A8%E5%87%A0%E4%B8%AAworker%E8%BF%9E%E6%8E%A5%E6%95%B0%EF%BC%9F%0A%20%E8%A6%81%E4%B9%882%E4%B8%AA%E8%A6%81%E4%B9%884%E4%B8%AA%0A%20%E5%A6%82%E6%9E%9C%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%BF%E9%97%AE%E7%9A%84%E6%98%AF%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%EF%BC%8C%E5%8D%A0%E7%94%A8%E4%B8%A4%E4%B8%AAworker%E8%BF%9E%E6%8E%A5%E6%95%B0%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%BF%E9%97%AE%E7%9A%84%E6%98%AF%E5%8A%A8%E6%80%81%E8%B5%84%E6%BA%90%E5%88%99%E4%BC%9A%E5%8D%A0%E7%94%A84%E4%B8%AA%E8%BF%9E%E6%8E%A5%E6%95%B0%E3%80%82%0A%20%0A%20%3E%20%E9%97%AE%E9%A2%982%EF%BC%9Anginx%E6%9C%89%E4%B8%80%E4%B8%AAmaster%EF%BC%8C%E6%9C%89%E5%9B%9B%E4%B8%AAworker%EF%BC%8C%E6%AF%8F%E4%B8%AAworker%E6%94%AF%E6%8C%81%E7%9A%84%E6%9C%80%E5%A4%A7%E5%B9%B6%E5%8F%91%E6%95%B0%E4%B8%BA1024%2C%E9%82%A3%E4%B9%88%E6%94%AF%E6%8C%81%E7%9A%84%E6%9C%80%E5%A4%A7%E5%B9%B6%E5%8F%91%E6%95%B0%E4%B8%BA%E5%A4%9A%E5%B0%91%E4%B8%AA%20%EF%BC%9F%0A%20%E5%A6%82%E6%9E%9C%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%BF%E9%97%AE%E7%9A%84%E6%98%AF%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E5%88%99%E4%BC%9A%E5%8D%A0%E7%94%A8%E4%B8%A4%E4%B8%AA%E8%BF%9E%E6%8E%A5%E6%95%B0%EF%BC%8C%E6%89%80%E4%BB%A5%E5%B9%B6%E5%8F%91%E6%95%B0%E4%B8%BA%EF%BC%8C1024x4%2F2%0A%20%E5%A6%82%E6%9E%9C%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%BF%E9%97%AE%E7%9A%84%E6%98%AF%E5%8A%A8%E6%80%81%E8%B5%84%E6%BA%90%E5%88%99%E4%BC%9A%E5%8D%A0%E7%94%A84%E4%B8%AA%E8%BF%9E%E6%8E%A5%E6%95%B0%EF%BC%8C%E6%89%80%E4%BB%A5%E5%B9%B6%E5%8F%91%E6%95%B0%E4%B8%BA%EF%BC%8C%201024x4%2F4

linux快捷方式

创建时间:2020/10/7 15:06
更新时间:2020/10/7 15:07
作者:Chris
来源:https://blog.csdn.net/vitaminc4/article/details/76566720

ctrl + w 往回删除一个单词,光标放在最末尾
ctrl + u 删除光标以前的字符
ctrl + k 删除光标以后的字符
ctrl + a 移动光标至的字符头
ctrl + e 移动光标至的字符尾
ctrl + l 清屏
%60%60%60%0Actrl%20%2B%20w%20%E5%BE%80%E5%9B%9E%E5%88%A0%E9%99%A4%E4%B8%80%E4%B8%AA%E5%8D%95%E8%AF%8D%EF%BC%8C%E5%85%89%E6%A0%87%E6%94%BE%E5%9C%A8%E6%9C%80%E6%9C%AB%E5%B0%BE%0Actrl%20%2B%20u%20%E5%88%A0%E9%99%A4%E5%85%89%E6%A0%87%E4%BB%A5%E5%89%8D%E7%9A%84%E5%AD%97%E7%AC%A6%0Actrl%20%2B%20k%20%E5%88%A0%E9%99%A4%E5%85%89%E6%A0%87%E4%BB%A5%E5%90%8E%E7%9A%84%E5%AD%97%E7%AC%A6%0Actrl%20%2B%20a%20%E7%A7%BB%E5%8A%A8%E5%85%89%E6%A0%87%E8%87%B3%E7%9A%84%E5%AD%97%E7%AC%A6%E5%A4%B4%0Actrl%20%2B%20e%20%E7%A7%BB%E5%8A%A8%E5%85%89%E6%A0%87%E8%87%B3%E7%9A%84%E5%AD%97%E7%AC%A6%E5%B0%BE%0Actrl%20%2B%20l%20%E6%B8%85%E5%B1%8F%0A%60%60%60

centos7 issues

创建时间:2020/9/15 16:07
更新时间:2020/10/7 14:36
作者:Chris
来源:https://blog.csdn.net/to_be_thebest/article/details/108082791

1. Couldn‘t open file /etc/pki/rpm-gpg/RPM-GPG-KEY-7
rpm --import /etc/pki/rpm-gpg/RPM* 
yum makecache
%0A%23%23%23%23%23%23%201.%20Couldn%E2%80%98t%20open%20file%20%2Fetc%2Fpki%2Frpm-gpg%2FRPM-GPG-KEY-7%0A%60%60%60%0Arpm%20--import%20%2Fetc%2Fpki%2Frpm-gpg%2FRPM*%20%0Ayum%20makecache%0A%60%60%60

CentOS配置

创建时间:2020/10/7 14:13
更新时间:2020/10/7 14:15
作者:Chris

1.配置ssh免登录

在整个hadoop的整个处理过程中都是利用ssh进行通讯的,就算是本机也知必须配置ssh免登录处理:
由于电脑上可能出现过ssh的相关配置,因此必须删除根目录下的".ssh"的文件夹

rm -rf ~/.ssh

在hadoopmaster 主机上生成ssh key

ssh-keygen -t rsa

把生成的共钥拷贝到授权的文件之中

root@hadoopmaster:~/.ssh# cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

测试免登录处理

root@hadoopmaster:~/.ssh# ssh root@hadoopmaster

使用exit退出运程登录

%0A%5BTOC%5D%0A%23%23%23%23%201.%E9%85%8D%E7%BD%AEssh%E5%85%8D%E7%99%BB%E5%BD%95%0A%0A%E5%9C%A8%E6%95%B4%E4%B8%AAhadoop%E7%9A%84%E6%95%B4%E4%B8%AA%E5%A4%84%E7%90%86%E8%BF%87%E7%A8%8B%E4%B8%AD%E9%83%BD%E6%98%AF%E5%88%A9%E7%94%A8ssh%E8%BF%9B%E8%A1%8C%E9%80%9A%E8%AE%AF%E7%9A%84%EF%BC%8C%E5%B0%B1%E7%AE%97%E6%98%AF%E6%9C%AC%E6%9C%BA%E4%B9%9F%E7%9F%A5%E5%BF%85%E9%A1%BB%E9%85%8D%E7%BD%AEssh%E5%85%8D%E7%99%BB%E5%BD%95%E5%A4%84%E7%90%86%EF%BC%9A%0A%E7%94%B1%E4%BA%8E%E7%94%B5%E8%84%91%E4%B8%8A%E5%8F%AF%E8%83%BD%E5%87%BA%E7%8E%B0%E8%BF%87ssh%E7%9A%84%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%BF%85%E9%A1%BB%E5%88%A0%E9%99%A4%E6%A0%B9%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%22.ssh%22%E7%9A%84%E6%96%87%E4%BB%B6%E5%A4%B9%0A%60%60%60%0Arm%20-rf%20~%2F.ssh%0A%60%60%60%0A%0A%E5%9C%A8hadoopmaster%20%E4%B8%BB%E6%9C%BA%E4%B8%8A%E7%94%9F%E6%88%90ssh%20key%0A%60%60%60%0Assh-keygen%20-t%20rsa%0A%60%60%60%0A!%5Bf21ad42e486bc950270606d911e8dc6a.png%5D(en-resource%3A%2F%2Fdatabase%2F841%3A1)%0A%0A%0A%E6%8A%8A%E7%94%9F%E6%88%90%E7%9A%84%E5%85%B1%E9%92%A5%E6%8B%B7%E8%B4%9D%E5%88%B0%E6%8E%88%E6%9D%83%E7%9A%84%E6%96%87%E4%BB%B6%E4%B9%8B%E4%B8%AD%0A%60%60%60%0Aroot%40hadoopmaster%3A~%2F.ssh%23%20cat%20~%2F.ssh%2Fid_rsa.pub%20%3E%3E%20~%2F.ssh%2Fauthorized_keys%0A%60%60%60%0A%0A%E6%B5%8B%E8%AF%95%E5%85%8D%E7%99%BB%E5%BD%95%E5%A4%84%E7%90%86%0A%60%60%60%0Aroot%40hadoopmaster%3A~%2F.ssh%23%20ssh%20root%40hadoopmaster%0A%60%60%60%0A%E4%BD%BF%E7%94%A8exit%E9%80%80%E5%87%BA%E8%BF%90%E7%A8%8B%E7%99%BB%E5%BD%95%0A

nginx 相关网站

创建时间:2020/10/4 12:07
更新时间:2020/10/4 12:09
作者:Chris
来源:http://chao58.top/blog/read/92

OSS反向代理使用内网流量

%0A%5BOSS%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E4%BD%BF%E7%94%A8%E5%86%85%E7%BD%91%E6%B5%81%E9%87%8F%5D(http%3A%2F%2Fchao58.top%2Fblog%2Fread%2F92)

RabbitMQ

创建时间:2020/9/15 14:57
更新时间:2020/9/25 20:58
作者:Chris

1.是什么

RabbitMQ是Erlang语言编写的,实现了高级消息队列协议(AMQP)的开源的消息中间件

2.能干什么

  1. 同步变异步
  2. 解耦,高内聚低耦合,对新增开放,对修改关闭
  3. 流量削峰,一般用在秒杀服务

3.基本原理

3.1 Message

Message 包含

  1. routing key 路由键
  2. priority 相对于其它消息的优先级
  3. delivery mode 指出该消息可能需要持久化存储
3.2 Exchange

用来接收消息并把消息路由给队列
三种常用的交换器

  1. direct 发布与订阅,完全匹配,默认
  2. fanout 广播
  3. topic 主题,规则匹配
3.3 Routing key 路由键

RabbitMQ决定消息发送到哪个queue的规则队列通过路由键绑定到交换器
当消息发送到RabbitMQ时,RabbitMQ会将消息中和绑定中使用的路由键进行匹配
如果匹配则发送到该队列,如果不匹配则将消息发进黑洞,黑洞是指这个消息没有一个消费者

3.4 Binding

基于路由键将消息队列和交换器之间关联起来的路由规则,可以将交换器理解为一个由绑定构成的路由表。

3.5 Queue

队列可以存储很多的消息,基本上它是一个没有限制的缓冲区,前提是你的机器有足够的存储空间
多个生产者可以将信息发给同一个队列,多个消费者也可以从同一队列读取数据。

3.6 Connections

消息的生产者与消费者同RabbitMQ建立的TCP连接

3.7 Channels
  1. TCP中的虚拟连接,电缆相当于TCP连接,电缆中的光纤则为一个信道,一个TCP连接可以创建多个信道是没有限制的。
  2. TCP一旦打开就会建立AMQP信道
  3. 消息的生产,消费都是通过信道完成的。
3.8 Virtual Host
  1. 表示一批交换器,队列和相关对象
  2. 虚拟主机是共享相同的身份认证和加密环境的独立服务器域
  3. 每个vhost是一个mini版本的RabbitMQ服务器,拥有自己的交换器,队列,绑定和权限机制。
  4. vhost是AMQP概念的基础,必须在连接时指定,RabbitMQ默认的vhost是/
3.9 Broker

表示消息队列服务器实体

4.安装

4.1安装 erlang 组件

下载: wget http://www.rabbitmq.com/releases/erlang/erlang-18.3-1.el7.centos.x86_64.rpm
安装: rpm -ivh erlang-18.3-1.el7.centos.x86_64.rpm

检验erl

[root@iZ25sabz8p5Z sbin]# erl
Erlang/OTP 19 [erts-8.0] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

退出用 `halt().`
4.2 安装socat

下载: wget http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm
安装: rpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpm

4.3 安装 rabbitmq 组件

下载: wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.5/rabbitmq-server-3.6.5-1.noarch.rpm
安装: rpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm

Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again
处理很简单,修改文件“/etc/yum.repos.d/epel.repo”, 将baseurl的注释取消, mirrorlist注释掉。即可。
安装问题参考:
https://blog.csdn.net/yunfeng482/article/details/72853983
https://www.cnblogs.com/mcgrady/p/7614417.html

开启rabbitmq

sudo service rabbitmq-server start
Error epmd error for host xxx: address (cannot connect to host/port)
vi /etc/rabbitmq/rabbitmq-env.conf文件,添加NODENAME=rabbit@localhost

开启管理页面插件

sudo rabbitmq-plugins enable rabbitmq_management

添加管理员账号

sudo rabbitmqctl add_user chris 123456

分配用户标签

sudo rabbitmqctl set_user_tags chris administrator

创建和赋角色完成后查看并确认

sudo rabbitmqctl list_users

设置用户权限

sudo rabbitmqctl set_permissions -p "/" chris ".*" ".*" ".*"

web页面访问rabbitmq

http://master:15672/
4.3 Java连接RabbitMq
4.3.1 建queue
package com.springboot.chris.demo;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SenderConfig {
    @Bean
    public Queue queue() {
    return new Queue("hello-chris-queue");
    }
}
4.3.2 定义生产者
package com.springboot.chris.demo;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class Sender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
    String msg = "hello" + new Date();
    rabbitTemplate.convertAndSend("hello-chris-queue", msg);
    }
}
4.3.3 定义消费者
package com.springboot.chris.demo;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class Receiver {
    @RabbitListener(queues = "hello-chris-queue")
    public void process(String msg) {
    System.out.println("reciver:" + msg);
    }
 }
4.3.4 配置信息

application.properties

spring.application.name=springboot-amqp
server.port=8080
spring.rabbitmq.host=hadoop
spring.rabbitmq.port=5672
spring.rabbitmq.username=chris
spring.rabbitmq.password=123456
4.4 RabbitMQ为什么是信道通信而不是TCP通信?
  1. TCP开启和销毁开销大,开启需要3次握手,销毁需要4次分手。
  2. 如果不用信道,client会使用TCP与RabbitMQ server建立连接,高峰时大量的TCP连接会造成资源的巨大浪费,而且操作系统每秒处理TCP连接的数据也是有限制的,必定会造成性能瓶颈,使并发量不高。
  3. 信道的原理是一个线程一个信道,多个信道共用同一个TCP连接,一个TCP连接可以创建信道的个数是没有限制的,即使突发的大量请求也不会造成性能瓶颈。
%5Btoc%5D%0A%0A%23%23%23%23%201.%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20RabbitMQ%E6%98%AFErlang%E8%AF%AD%E8%A8%80%E7%BC%96%E5%86%99%E7%9A%84%EF%BC%8C%E5%AE%9E%E7%8E%B0%E4%BA%86%E9%AB%98%E7%BA%A7%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E5%8D%8F%E8%AE%AE%EF%BC%88AMQP%EF%BC%89%E7%9A%84%E5%BC%80%E6%BA%90%E7%9A%84%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6%0A%0A%23%23%23%23%202.%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%20%3E%201.%20%E5%90%8C%E6%AD%A5%E5%8F%98%E5%BC%82%E6%AD%A5%0A%20%3E%202.%20%E8%A7%A3%E8%80%A6%EF%BC%8C%E9%AB%98%E5%86%85%E8%81%9A%E4%BD%8E%E8%80%A6%E5%90%88%EF%BC%8C%E5%AF%B9%E6%96%B0%E5%A2%9E%E5%BC%80%E6%94%BE%EF%BC%8C%E5%AF%B9%E4%BF%AE%E6%94%B9%E5%85%B3%E9%97%AD%0A%20%3E%203.%20%E6%B5%81%E9%87%8F%E5%89%8A%E5%B3%B0%EF%BC%8C%E4%B8%80%E8%88%AC%E7%94%A8%E5%9C%A8%E7%A7%92%E6%9D%80%E6%9C%8D%E5%8A%A1%0A%0A%20%0A%20!%5Bf5c849c13f4c96298ea11074187be727.png%5D(en-resource%3A%2F%2Fdatabase%2F761%3A1)%0A%20%0A%20!%5B874253d97d73adb40c8f284644557eec.png%5D(en-resource%3A%2F%2Fdatabase%2F760%3A1)%0A%20%0A%20%0A%20%0A%23%23%23%23%203.%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86%0A%0A%20!%5Bebb0a10081e3cd214c877f2017f99bd0.png%5D(en-resource%3A%2F%2Fdatabase%2F762%3A1)%0A%20%20%0A%23%23%23%23%23%203.1%20Message%0AMessage%20%E5%8C%85%E5%90%AB%0A1.%20routing%20key%20%E8%B7%AF%E7%94%B1%E9%94%AE%0A2.%20priority%20%E7%9B%B8%E5%AF%B9%E4%BA%8E%E5%85%B6%E5%AE%83%E6%B6%88%E6%81%AF%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%0A3.%20delivery%20mode%20%E6%8C%87%E5%87%BA%E8%AF%A5%E6%B6%88%E6%81%AF%E5%8F%AF%E8%83%BD%E9%9C%80%E8%A6%81%E6%8C%81%E4%B9%85%E5%8C%96%E5%AD%98%E5%82%A8%0A%0A%23%23%23%23%23%203.2%20Exchange%0A%3E%20%E7%94%A8%E6%9D%A5%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%E5%B9%B6%E6%8A%8A%E6%B6%88%E6%81%AF%E8%B7%AF%E7%94%B1%E7%BB%99%E9%98%9F%E5%88%97%0A%3E%20%E4%B8%89%E7%A7%8D%E5%B8%B8%E7%94%A8%E7%9A%84%E4%BA%A4%E6%8D%A2%E5%99%A8%0A%20%20%20%20%3E%201.%20direct%20%E5%8F%91%E5%B8%83%E4%B8%8E%E8%AE%A2%E9%98%85%EF%BC%8C%E5%AE%8C%E5%85%A8%E5%8C%B9%E9%85%8D%EF%BC%8C%E9%BB%98%E8%AE%A4%0A%20%20%20%20%3E%202.%20fanout%20%E5%B9%BF%E6%92%AD%0A%20%20%20%20%3E%203.%20topic%20%E4%B8%BB%E9%A2%98%EF%BC%8C%E8%A7%84%E5%88%99%E5%8C%B9%E9%85%8D%0A%0A%0A%23%23%23%23%23%203.3%20Routing%20key%20%E8%B7%AF%E7%94%B1%E9%94%AE%0A%3E%20RabbitMQ%E5%86%B3%E5%AE%9A%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E5%88%B0%E5%93%AA%E4%B8%AAqueue%E7%9A%84%E8%A7%84%E5%88%99%E9%98%9F%E5%88%97%E9%80%9A%E8%BF%87%E8%B7%AF%E7%94%B1%E9%94%AE%E7%BB%91%E5%AE%9A%E5%88%B0%E4%BA%A4%E6%8D%A2%E5%99%A8%0A%E5%BD%93%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E5%88%B0RabbitMQ%E6%97%B6%EF%BC%8CRabbitMQ%E4%BC%9A%E5%B0%86%E6%B6%88%E6%81%AF%E4%B8%AD%E5%92%8C%E7%BB%91%E5%AE%9A%E4%B8%AD%E4%BD%BF%E7%94%A8%E7%9A%84%E8%B7%AF%E7%94%B1%E9%94%AE%E8%BF%9B%E8%A1%8C%E5%8C%B9%E9%85%8D%0A%E5%A6%82%E6%9E%9C%E5%8C%B9%E9%85%8D%E5%88%99%E5%8F%91%E9%80%81%E5%88%B0%E8%AF%A5%E9%98%9F%E5%88%97%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%8C%B9%E9%85%8D%E5%88%99%E5%B0%86%E6%B6%88%E6%81%AF%E5%8F%91%E8%BF%9B%E9%BB%91%E6%B4%9E%EF%BC%8C%E9%BB%91%E6%B4%9E%E6%98%AF%E6%8C%87%E8%BF%99%E4%B8%AA%E6%B6%88%E6%81%AF%E6%B2%A1%E6%9C%89%E4%B8%80%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A%0A%23%23%23%23%23%203.4%20Binding%0A%3E%20%E5%9F%BA%E4%BA%8E%E8%B7%AF%E7%94%B1%E9%94%AE%E5%B0%86%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E5%92%8C%E4%BA%A4%E6%8D%A2%E5%99%A8%E4%B9%8B%E9%97%B4%E5%85%B3%E8%81%94%E8%B5%B7%E6%9D%A5%E7%9A%84%E8%B7%AF%E7%94%B1%E8%A7%84%E5%88%99%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%B0%86%E4%BA%A4%E6%8D%A2%E5%99%A8%E7%90%86%E8%A7%A3%E4%B8%BA%E4%B8%80%E4%B8%AA%E7%94%B1%E7%BB%91%E5%AE%9A%E6%9E%84%E6%88%90%E7%9A%84%E8%B7%AF%E7%94%B1%E8%A1%A8%E3%80%82%0A%0A%0A%23%23%23%23%23%203.5%20Queue%0A%E9%98%9F%E5%88%97%E5%8F%AF%E4%BB%A5%E5%AD%98%E5%82%A8%E5%BE%88%E5%A4%9A%E7%9A%84%E6%B6%88%E6%81%AF%EF%BC%8C%E5%9F%BA%E6%9C%AC%E4%B8%8A%E5%AE%83%E6%98%AF%E4%B8%80%E4%B8%AA%E6%B2%A1%E6%9C%89%E9%99%90%E5%88%B6%E7%9A%84%E7%BC%93%E5%86%B2%E5%8C%BA%EF%BC%8C%E5%89%8D%E6%8F%90%E6%98%AF%E4%BD%A0%E7%9A%84%E6%9C%BA%E5%99%A8%E6%9C%89%E8%B6%B3%E5%A4%9F%E7%9A%84%E5%AD%98%E5%82%A8%E7%A9%BA%E9%97%B4%0A%E5%A4%9A%E4%B8%AA%E7%94%9F%E4%BA%A7%E8%80%85%E5%8F%AF%E4%BB%A5%E5%B0%86%E4%BF%A1%E6%81%AF%E5%8F%91%E7%BB%99%E5%90%8C%E4%B8%80%E4%B8%AA%E9%98%9F%E5%88%97%EF%BC%8C%E5%A4%9A%E4%B8%AA%E6%B6%88%E8%B4%B9%E8%80%85%E4%B9%9F%E5%8F%AF%E4%BB%A5%E4%BB%8E%E5%90%8C%E4%B8%80%E9%98%9F%E5%88%97%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A%0A%23%23%23%23%23%203.6%20Connections%0A%3E%20%E6%B6%88%E6%81%AF%E7%9A%84%E7%94%9F%E4%BA%A7%E8%80%85%E4%B8%8E%E6%B6%88%E8%B4%B9%E8%80%85%E5%90%8CRabbitMQ%E5%BB%BA%E7%AB%8B%E7%9A%84TCP%E8%BF%9E%E6%8E%A5%0A%0A%23%23%23%23%23%203.7%20Channels%0A%0A1.%20TCP%E4%B8%AD%E7%9A%84%E8%99%9A%E6%8B%9F%E8%BF%9E%E6%8E%A5%EF%BC%8C%E7%94%B5%E7%BC%86%E7%9B%B8%E5%BD%93%E4%BA%8ETCP%E8%BF%9E%E6%8E%A5%EF%BC%8C%E7%94%B5%E7%BC%86%E4%B8%AD%E7%9A%84%E5%85%89%E7%BA%A4%E5%88%99%E4%B8%BA%E4%B8%80%E4%B8%AA%E4%BF%A1%E9%81%93%EF%BC%8C%E4%B8%80%E4%B8%AATCP%E8%BF%9E%E6%8E%A5%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E5%A4%9A%E4%B8%AA%E4%BF%A1%E9%81%93%E6%98%AF%E6%B2%A1%E6%9C%89%E9%99%90%E5%88%B6%E7%9A%84%E3%80%82%0A2.%20TCP%E4%B8%80%E6%97%A6%E6%89%93%E5%BC%80%E5%B0%B1%E4%BC%9A%E5%BB%BA%E7%AB%8BAMQP%E4%BF%A1%E9%81%93%0A3.%20%E6%B6%88%E6%81%AF%E7%9A%84%E7%94%9F%E4%BA%A7%EF%BC%8C%E6%B6%88%E8%B4%B9%E9%83%BD%E6%98%AF%E9%80%9A%E8%BF%87%E4%BF%A1%E9%81%93%E5%AE%8C%E6%88%90%E7%9A%84%E3%80%82%0A%0A%23%23%23%23%23%203.8%20Virtual%20Host%0A%0A1.%20%E8%A1%A8%E7%A4%BA%E4%B8%80%E6%89%B9%E4%BA%A4%E6%8D%A2%E5%99%A8%EF%BC%8C%E9%98%9F%E5%88%97%E5%92%8C%E7%9B%B8%E5%85%B3%E5%AF%B9%E8%B1%A1%0A2.%20%E8%99%9A%E6%8B%9F%E4%B8%BB%E6%9C%BA%E6%98%AF%E5%85%B1%E4%BA%AB%E7%9B%B8%E5%90%8C%E7%9A%84%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81%E5%92%8C%E5%8A%A0%E5%AF%86%E7%8E%AF%E5%A2%83%E7%9A%84%E7%8B%AC%E7%AB%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%9F%9F%0A3.%20%E6%AF%8F%E4%B8%AAvhost%E6%98%AF%E4%B8%80%E4%B8%AAmini%E7%89%88%E6%9C%AC%E7%9A%84RabbitMQ%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E6%8B%A5%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E4%BA%A4%E6%8D%A2%E5%99%A8%EF%BC%8C%E9%98%9F%E5%88%97%EF%BC%8C%E7%BB%91%E5%AE%9A%E5%92%8C%E6%9D%83%E9%99%90%E6%9C%BA%E5%88%B6%E3%80%82%0A4.%20vhost%E6%98%AFAMQP%E6%A6%82%E5%BF%B5%E7%9A%84%E5%9F%BA%E7%A1%80%EF%BC%8C%E5%BF%85%E9%A1%BB%E5%9C%A8%E8%BF%9E%E6%8E%A5%E6%97%B6%E6%8C%87%E5%AE%9A%EF%BC%8CRabbitMQ%E9%BB%98%E8%AE%A4%E7%9A%84vhost%E6%98%AF%2F%0A%0A%0A%23%23%23%23%23%203.9%20Broker%0A%3E%20%E8%A1%A8%E7%A4%BA%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E4%BD%93%0A%0A%0A%0A%23%23%23%23%204.%E5%AE%89%E8%A3%85%0A%0A%23%23%23%23%23%204.1%E5%AE%89%E8%A3%85%20erlang%20%E7%BB%84%E4%BB%B6%0A%0A%3E%20%E4%B8%8B%E8%BD%BD%3A%20wget%20http%3A%2F%2Fwww.rabbitmq.com%2Freleases%2Ferlang%2Ferlang-18.3-1.el7.centos.x86_64.rpm%0A%3E%20%E5%AE%89%E8%A3%85%3A%20rpm%20-ivh%20erlang-18.3-1.el7.centos.x86_64.rpm%0A%0A%E6%A3%80%E9%AA%8Cerl%0A%60%60%60%0A%5Broot%40iZ25sabz8p5Z%20sbin%5D%23%20erl%0AErlang%2FOTP%2019%20%5Berts-8.0%5D%20%5Bsource%5D%20%5B64-bit%5D%20%5Basync-threads%3A10%5D%20%5Bhipe%5D%20%5Bkernel-poll%3Afalse%5D%0A%0A%E9%80%80%E5%87%BA%E7%94%A8%20%60halt().%60%0A%60%60%60%0A%0A%0A%23%23%23%23%23%204.2%20%E5%AE%89%E8%A3%85socat%0A%3E%20%E4%B8%8B%E8%BD%BD%3A%20wget%20http%3A%2F%2Frepo.iotti.biz%2FCentOS%2F7%2Fx86_64%2Fsocat-1.7.3.2-5.el7.lux.x86_64.rpm%0A%3E%20%E5%AE%89%E8%A3%85%3A%20rpm%20-ivh%20socat-1.7.3.2-5.el7.lux.x86_64.rpm%0A%0A%23%23%23%23%23%204.3%20%E5%AE%89%E8%A3%85%20rabbitmq%20%E7%BB%84%E4%BB%B6%0A%0A%3E%20%E4%B8%8B%E8%BD%BD%3A%20wget%20http%3A%2F%2Fwww.rabbitmq.com%2Freleases%2Frabbitmq-server%2Fv3.6.5%2Frabbitmq-server-3.6.5-1.noarch.rpm%0A%3E%20%E5%AE%89%E8%A3%85%3A%20rpm%20-ivh%20rabbitmq-server-3.6.5-1.noarch.rpm%0A%0A%60%60%60%0AError%3A%20Cannot%20retrieve%20metalink%20for%20repository%3A%20epel.%20Please%20verify%20its%20path%20and%20try%20again%0A%E5%A4%84%E7%90%86%E5%BE%88%E7%AE%80%E5%8D%95%EF%BC%8C%E4%BF%AE%E6%94%B9%E6%96%87%E4%BB%B6%E2%80%9C%2Fetc%2Fyum.repos.d%2Fepel.repo%E2%80%9D%EF%BC%8C%20%E5%B0%86baseurl%E7%9A%84%E6%B3%A8%E9%87%8A%E5%8F%96%E6%B6%88%EF%BC%8C%20mirrorlist%E6%B3%A8%E9%87%8A%E6%8E%89%E3%80%82%E5%8D%B3%E5%8F%AF%E3%80%82%0A%E5%AE%89%E8%A3%85%E9%97%AE%E9%A2%98%E5%8F%82%E8%80%83%EF%BC%9A%0Ahttps%3A%2F%2Fblog.csdn.net%2Fyunfeng482%2Farticle%2Fdetails%2F72853983%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fmcgrady%2Fp%2F7614417.html%0A%60%60%60%0A%0A%E5%BC%80%E5%90%AFrabbitmq%0A%60%60%60%0Asudo%20service%20rabbitmq-server%20start%0A%60%60%60%0A%60%60%60%0AError%20epmd%20error%20for%20host%20xxx%3A%20address%20(cannot%20connect%20to%20host%2Fport)%0Avi%20%2Fetc%2Frabbitmq%2Frabbitmq-env.conf%E6%96%87%E4%BB%B6%EF%BC%8C%E6%B7%BB%E5%8A%A0NODENAME%3Drabbit%40localhost%0A%60%60%60%0A%E5%BC%80%E5%90%AF%E7%AE%A1%E7%90%86%E9%A1%B5%E9%9D%A2%E6%8F%92%E4%BB%B6%0A%60%60%60%0Asudo%20rabbitmq-plugins%20enable%20rabbitmq_management%0A%60%60%60%0A%E6%B7%BB%E5%8A%A0%E7%AE%A1%E7%90%86%E5%91%98%E8%B4%A6%E5%8F%B7%0A%60%60%60%0Asudo%20rabbitmqctl%20add_user%20chris%20123456%0A%60%60%60%0A%E5%88%86%E9%85%8D%E7%94%A8%E6%88%B7%E6%A0%87%E7%AD%BE%0A%60%60%60%0Asudo%20rabbitmqctl%20set_user_tags%20chris%20administrator%0A%60%60%60%0A%E5%88%9B%E5%BB%BA%E5%92%8C%E8%B5%8B%E8%A7%92%E8%89%B2%E5%AE%8C%E6%88%90%E5%90%8E%E6%9F%A5%E7%9C%8B%E5%B9%B6%E7%A1%AE%E8%AE%A4%0A%60%60%60%0Asudo%20rabbitmqctl%20list_users%0A%60%60%60%0A%E8%AE%BE%E7%BD%AE%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%0A%60%60%60%0Asudo%20rabbitmqctl%20set_permissions%20-p%20%22%2F%22%20chris%20%22.*%22%20%22.*%22%20%22.*%22%0A%60%60%60%0Aweb%E9%A1%B5%E9%9D%A2%E8%AE%BF%E9%97%AErabbitmq%0A%60%60%60%0Ahttp%3A%2F%2Fmaster%3A15672%2F%0A%60%60%60%0A%0A%23%23%23%23%23%204.3%20Java%E8%BF%9E%E6%8E%A5RabbitMq%0A%0A%23%23%23%23%23%23%204.3.1%20%E5%BB%BAqueue%0A%60%60%60java%0Apackage%20com.springboot.chris.demo%3B%0A%0Aimport%20org.springframework.amqp.core.Queue%3B%0Aimport%20org.springframework.context.annotation.Bean%3B%0Aimport%20org.springframework.context.annotation.Configuration%3B%0A%0A%40Configuration%0Apublic%20class%20SenderConfig%20%7B%0A%20%20%20%20%40Bean%0A%20%20%20%20public%20Queue%20queue()%20%7B%0A%20%20%20%20return%20new%20Queue(%22hello-chris-queue%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%204.3.2%20%E5%AE%9A%E4%B9%89%E7%94%9F%E4%BA%A7%E8%80%85%0A%60%60%60java%0Apackage%20com.springboot.chris.demo%3B%0A%0Aimport%20org.springframework.amqp.core.AmqpTemplate%3B%0Aimport%20org.springframework.beans.factory.annotation.Autowired%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0Aimport%20java.util.Date%3B%0A%0A%40Component%0Apublic%20class%20Sender%20%7B%0A%0A%20%20%20%20%40Autowired%0A%20%20%20%20private%20AmqpTemplate%20rabbitTemplate%3B%0A%0A%20%20%20%20public%20void%20send()%20%7B%0A%20%20%20%20String%20msg%20%3D%20%22hello%22%20%2B%20new%20Date()%3B%0A%20%20%20%20rabbitTemplate.convertAndSend(%22hello-chris-queue%22%2C%20msg)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%204.3.3%20%E5%AE%9A%E4%B9%89%E6%B6%88%E8%B4%B9%E8%80%85%0A%0A%60%60%60java%0Apackage%20com.springboot.chris.demo%3B%0A%0Aimport%20org.springframework.amqp.rabbit.annotation.RabbitListener%3B%0Aimport%20org.springframework.stereotype.Component%3B%0A%0A%40Component%0Apublic%20class%20Receiver%20%7B%0A%20%20%20%20%40RabbitListener(queues%20%3D%20%22hello-chris-queue%22)%0A%20%20%20%20public%20void%20process(String%20msg)%20%7B%0A%20%20%20%20System.out.println(%22reciver%3A%22%20%2B%20msg)%3B%0A%20%20%20%20%7D%0A%20%7D%0A%60%60%60%0A%0A%23%23%23%23%23%23%204.3.4%20%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%0Aapplication.properties%0A%0A%60%60%60%0Aspring.application.name%3Dspringboot-amqp%0Aserver.port%3D8080%0Aspring.rabbitmq.host%3Dhadoop%0Aspring.rabbitmq.port%3D5672%0Aspring.rabbitmq.username%3Dchris%0Aspring.rabbitmq.password%3D123456%0A%60%60%60%0A%0A%0A%23%23%23%23%23%204.4%20RabbitMQ%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E4%BF%A1%E9%81%93%E9%80%9A%E4%BF%A1%E8%80%8C%E4%B8%8D%E6%98%AFTCP%E9%80%9A%E4%BF%A1%EF%BC%9F%0A%0A1.%20TCP%E5%BC%80%E5%90%AF%E5%92%8C%E9%94%80%E6%AF%81%E5%BC%80%E9%94%80%E5%A4%A7%EF%BC%8C%E5%BC%80%E5%90%AF%E9%9C%80%E8%A6%813%E6%AC%A1%E6%8F%A1%E6%89%8B%EF%BC%8C%E9%94%80%E6%AF%81%E9%9C%80%E8%A6%814%E6%AC%A1%E5%88%86%E6%89%8B%E3%80%82%0A2.%20%E5%A6%82%E6%9E%9C%E4%B8%8D%E7%94%A8%E4%BF%A1%E9%81%93%EF%BC%8Cclient%E4%BC%9A%E4%BD%BF%E7%94%A8TCP%E4%B8%8ERabbitMQ%20server%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5%EF%BC%8C%E9%AB%98%E5%B3%B0%E6%97%B6%E5%A4%A7%E9%87%8F%E7%9A%84TCP%E8%BF%9E%E6%8E%A5%E4%BC%9A%E9%80%A0%E6%88%90%E8%B5%84%E6%BA%90%E7%9A%84%E5%B7%A8%E5%A4%A7%E6%B5%AA%E8%B4%B9%EF%BC%8C%E8%80%8C%E4%B8%94%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%AF%8F%E7%A7%92%E5%A4%84%E7%90%86TCP%E8%BF%9E%E6%8E%A5%E7%9A%84%E6%95%B0%E6%8D%AE%E4%B9%9F%E6%98%AF%E6%9C%89%E9%99%90%E5%88%B6%E7%9A%84%EF%BC%8C%E5%BF%85%E5%AE%9A%E4%BC%9A%E9%80%A0%E6%88%90%E6%80%A7%E8%83%BD%E7%93%B6%E9%A2%88%EF%BC%8C%E4%BD%BF%E5%B9%B6%E5%8F%91%E9%87%8F%E4%B8%8D%E9%AB%98%E3%80%82%0A3.%20%E4%BF%A1%E9%81%93%E7%9A%84%E5%8E%9F%E7%90%86%E6%98%AF%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E4%B8%80%E4%B8%AA%E4%BF%A1%E9%81%93%EF%BC%8C%E5%A4%9A%E4%B8%AA%E4%BF%A1%E9%81%93%E5%85%B1%E7%94%A8%E5%90%8C%E4%B8%80%E4%B8%AATCP%E8%BF%9E%E6%8E%A5%EF%BC%8C%E4%B8%80%E4%B8%AATCP%E8%BF%9E%E6%8E%A5%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E4%BF%A1%E9%81%93%E7%9A%84%E4%B8%AA%E6%95%B0%E6%98%AF%E6%B2%A1%E6%9C%89%E9%99%90%E5%88%B6%E7%9A%84%EF%BC%8C%E5%8D%B3%E4%BD%BF%E7%AA%81%E5%8F%91%E7%9A%84%E5%A4%A7%E9%87%8F%E8%AF%B7%E6%B1%82%E4%B9%9F%E4%B8%8D%E4%BC%9A%E9%80%A0%E6%88%90%E6%80%A7%E8%83%BD%E7%93%B6%E9%A2%88%E3%80%82

产品经理工具网站

创建时间:2020/9/22 9:52
更新时间:2020/9/22 9:53
作者:Chris

https://www.inneed.club/resources/index

%60https%3A%2F%2Fwww.inneed.club%2Fresources%2Findex%60

to-do

创建时间:2020/9/11 10:58
更新时间:2020/9/14 12:57
作者:Chris
来源:about:blank

  1. 内部类
  2. RouteLocatorBuilder
  3. 函数式编程
  4. spring gateway的lb是如何实现的



cloud2020课程

创建时间:2020/9/10 10:30
更新时间:2020/9/10 10:30
作者:Chris

https://blog.csdn.net/kingtok/article/details/104963122

脑图笔记地址: https://www.processon.com/view/link/5e68624ce4b00b99c1debca5#map

源码:https://github.com/TNoOne/cloud2020
笔记:https://blog.csdn.net/qq_41211642/article/details/104772140

QPS
https://www.cnblogs.com/longxiaojiangi/p/9259745.html

https%3A%2F%2Fblog.csdn.net%2Fkingtok%2Farticle%2Fdetails%2F104963122%0A%0A%E8%84%91%E5%9B%BE%E7%AC%94%E8%AE%B0%E5%9C%B0%E5%9D%80%EF%BC%9A%20https%3A%2F%2Fwww.processon.com%2Fview%2Flink%2F5e68624ce4b00b99c1debca5%23map%0A%0A%E6%BA%90%E7%A0%81%EF%BC%9Ahttps%3A%2F%2Fgithub.com%2FTNoOne%2Fcloud2020%0A%E7%AC%94%E8%AE%B0%EF%BC%9Ahttps%3A%2F%2Fblog.csdn.net%2Fqq_41211642%2Farticle%2Fdetails%2F104772140%0A%0A%0AQPS%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Flongxiaojiangi%2Fp%2F9259745.html%0A%0A

1. 校验用户身份

创建时间:2020/9/2 15:46
更新时间:2020/9/6 17:29
作者:Chris

1. 校验用户身份
1.1 过滤器

当初始化时会创建 一个名为SpringSecurityFilterChain的servlet过滤器,类型为FilterChainProxy.

  1. SecurityContextPersistenceFilter 整个拦截过程的入口和出口

  2. UsernamePasswordAuthenticationFilter 帐号密码的认证由此拦截器拦截处理

  3. FilterSecurityInterceptor 用于保护web资源,使用 AccessDecisionManager 对当前用户进入授权访问

AuthenticationManager  校验用户身份
AccessDecisionManager 校验用户权

1.2 会话

用户认证成功后,为了避免用户每次操作都进行认证,可以将用户的身份信息放在会话中进行管理,SpringSecurity提供了会话管理,将认证成功的身份信息放在SecurityContextHolder上下文,SecurityContext上下文是和当前线程绑定的。

Authentication authentication  = SecurityContextHolder.getContext().getAuthentication()
authentication.getPrincipal()
1.2.3 会话配置

ifRequired:默认情况下SpringSecurity会为每一个登录成功的用户新建一个Session。
always:如果没有就新建一个。
never: SpringSecurity 对登录成功的用户不创建Session,但如果应用程序里面某个地方新建了Session,那么SpringSecurity会用它。
stateless: SpringSecurity 对登录成功的用户不创建Session, 你的应用程序里面也不会允许新建Session,并且它不使用cookie,所以每个请求都需要重新验证身份,这种无状态架构适用于RestAPI及无状态认证机制。

2. 校验用户权

SpringSecurity 通过http.authorizeRequests()对web请求进行授权保护

SpringSecurity通过投票的机制来验证授权

AffirmativeBased()
ConsensusBased()
UnanimousBased()

授权方式包括Web授权和方法授权

Web授权:通过URL拦截进行授权, FilterSecurityInterceptor
方法授权:通过方法拦截进行授权, MethodSecurityInterceptor

3. CSRF

SpringSecurity为了防止CSRF的发生,限制了除get以外的大多数方法。

  1. 关闭***CSRF***
  2. 在页面添加token, springsecurity会验证token,如果token合法则可以继续请求
%23%23%23%23%23%201.%20%E6%A0%A1%E9%AA%8C%E7%94%A8%E6%88%B7%E8%BA%AB%E4%BB%BD%0A%0A%23%23%23%23%23%23%201.1%20%E8%BF%87%E6%BB%A4%E5%99%A8%0A%0A%E5%BD%93%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%E4%BC%9A%E5%88%9B%E5%BB%BA%20%E4%B8%80%E4%B8%AA%E5%90%8D%E4%B8%BASpringSecurityFilterChain%E7%9A%84servlet%E8%BF%87%E6%BB%A4%E5%99%A8%EF%BC%8C%E7%B1%BB%E5%9E%8B%E4%B8%BAFilterChainProxy.%0A%0A1.%20SecurityContextPersistenceFilter%20%20%E6%95%B4%E4%B8%AA%E6%8B%A6%E6%88%AA%E8%BF%87%E7%A8%8B%E7%9A%84%E5%85%A5%E5%8F%A3%E5%92%8C%E5%87%BA%E5%8F%A3%0A%0A2.%20UsernamePasswordAuthenticationFilter%20%E5%B8%90%E5%8F%B7%E5%AF%86%E7%A0%81%E7%9A%84%E8%AE%A4%E8%AF%81%E7%94%B1%E6%AD%A4%E6%8B%A6%E6%88%AA%E5%99%A8%E6%8B%A6%E6%88%AA%E5%A4%84%E7%90%86%0A%0A3.%20FilterSecurityInterceptor%20%E7%94%A8%E4%BA%8E%E4%BF%9D%E6%8A%A4web%E8%B5%84%E6%BA%90%2C%E4%BD%BF%E7%94%A8%20AccessDecisionManager%20%E5%AF%B9%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7%E8%BF%9B%E5%85%A5%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%0A%0A%60%60%60java%0AAuthenticationManager%20%20%E6%A0%A1%E9%AA%8C%E7%94%A8%E6%88%B7%E8%BA%AB%E4%BB%BD%0AAccessDecisionManager%20%E6%A0%A1%E9%AA%8C%E7%94%A8%E6%88%B7%E6%9D%83%0A%60%60%60%0A%0A%23%23%23%23%23%23%201.2%20%E4%BC%9A%E8%AF%9D%0A%0A%E7%94%A8%E6%88%B7%E8%AE%A4%E8%AF%81%E6%88%90%E5%8A%9F%E5%90%8E%EF%BC%8C%E4%B8%BA%E4%BA%86%E9%81%BF%E5%85%8D%E7%94%A8%E6%88%B7%E6%AF%8F%E6%AC%A1%E6%93%8D%E4%BD%9C%E9%83%BD%E8%BF%9B%E8%A1%8C%E8%AE%A4%E8%AF%81%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%B0%86%E7%94%A8%E6%88%B7%E7%9A%84%E8%BA%AB%E4%BB%BD%E4%BF%A1%E6%81%AF%E6%94%BE%E5%9C%A8%E4%BC%9A%E8%AF%9D%E4%B8%AD%E8%BF%9B%E8%A1%8C%E7%AE%A1%E7%90%86%EF%BC%8CSpringSecurity%E6%8F%90%E4%BE%9B%E4%BA%86%E4%BC%9A%E8%AF%9D%E7%AE%A1%E7%90%86%EF%BC%8C%E5%B0%86%E8%AE%A4%E8%AF%81%E6%88%90%E5%8A%9F%E7%9A%84%E8%BA%AB%E4%BB%BD%E4%BF%A1%E6%81%AF%E6%94%BE%E5%9C%A8SecurityContextHolder%E4%B8%8A%E4%B8%8B%E6%96%87%EF%BC%8CSecurityContext%E4%B8%8A%E4%B8%8B%E6%96%87%E6%98%AF%E5%92%8C%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E7%BB%91%E5%AE%9A%E7%9A%84%E3%80%82%0A%0A%60%60%60java%0AAuthentication%20authentication%20%20%3D%20SecurityContextHolder.getContext().getAuthentication()%0Aauthentication.getPrincipal()%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%201.2.3%20%E4%BC%9A%E8%AF%9D%E9%85%8D%E7%BD%AE%0A%0A%3E%20%20**ifRequired**%EF%BC%9A%E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5%E4%B8%8BSpringSecurity%E4%BC%9A%E4%B8%BA%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%99%BB%E5%BD%95%E6%88%90%E5%8A%9F%E7%9A%84%E7%94%A8%E6%88%B7%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AASession%E3%80%82%0A%3E%20%20**always**%EF%BC%9A%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%B0%B1%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AA%E3%80%82%0A%3E%20**never**%3A%20SpringSecurity%20%E5%AF%B9%E7%99%BB%E5%BD%95%E6%88%90%E5%8A%9F%E7%9A%84%E7%94%A8%E6%88%B7%E4%B8%8D%E5%88%9B%E5%BB%BASession%EF%BC%8C%E4%BD%86%E5%A6%82%E6%9E%9C%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E9%87%8C%E9%9D%A2%E6%9F%90%E4%B8%AA%E5%9C%B0%E6%96%B9%E6%96%B0%E5%BB%BA%E4%BA%86Session%EF%BC%8C%E9%82%A3%E4%B9%88SpringSecurity%E4%BC%9A%E7%94%A8%E5%AE%83%E3%80%82%0A%3E%20%20**stateless**%3A%20SpringSecurity%20%E5%AF%B9%E7%99%BB%E5%BD%95%E6%88%90%E5%8A%9F%E7%9A%84%E7%94%A8%E6%88%B7%E4%B8%8D%E5%88%9B%E5%BB%BASession%EF%BC%8C%20%E4%BD%A0%E7%9A%84%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E9%87%8C%E9%9D%A2%E4%B9%9F%E4%B8%8D%E4%BC%9A%E5%85%81%E8%AE%B8%E6%96%B0%E5%BB%BASession%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%AE%83%E4%B8%8D%E4%BD%BF%E7%94%A8cookie%EF%BC%8C%E6%89%80%E4%BB%A5%E6%AF%8F%E4%B8%AA%E8%AF%B7%E6%B1%82%E9%83%BD%E9%9C%80%E8%A6%81%E9%87%8D%E6%96%B0%E9%AA%8C%E8%AF%81%E8%BA%AB%E4%BB%BD%EF%BC%8C%E8%BF%99%E7%A7%8D%E6%97%A0%E7%8A%B6%E6%80%81%E6%9E%B6%E6%9E%84%E9%80%82%E7%94%A8%E4%BA%8ERestAPI%E5%8F%8A%E6%97%A0%E7%8A%B6%E6%80%81%E8%AE%A4%E8%AF%81%E6%9C%BA%E5%88%B6%E3%80%82%0A%0A%0A%23%23%23%23%23%20%202.%20%E6%A0%A1%E9%AA%8C%E7%94%A8%E6%88%B7%E6%9D%83%0A%0A%0ASpringSecurity%20%E9%80%9A%E8%BF%87http.authorizeRequests()%E5%AF%B9web%E8%AF%B7%E6%B1%82%E8%BF%9B%E8%A1%8C%E6%8E%88%E6%9D%83%E4%BF%9D%E6%8A%A4%0A%0A%0ASpringSecurity%E9%80%9A%E8%BF%87%E6%8A%95%E7%A5%A8%E7%9A%84%E6%9C%BA%E5%88%B6%E6%9D%A5%E9%AA%8C%E8%AF%81%E6%8E%88%E6%9D%83%0A%0A%3E%20AffirmativeBased()%0A%3E%20ConsensusBased()%0A%3E%20UnanimousBased()%0A%0A%E6%8E%88%E6%9D%83%E6%96%B9%E5%BC%8F%E5%8C%85%E6%8B%ACWeb%E6%8E%88%E6%9D%83%E5%92%8C%E6%96%B9%E6%B3%95%E6%8E%88%E6%9D%83%0A%0A%3E%20Web%E6%8E%88%E6%9D%83%EF%BC%9A%E9%80%9A%E8%BF%87URL%E6%8B%A6%E6%88%AA%E8%BF%9B%E8%A1%8C%E6%8E%88%E6%9D%83%2C%20FilterSecurityInterceptor%0A%3E%20%E6%96%B9%E6%B3%95%E6%8E%88%E6%9D%83%EF%BC%9A%E9%80%9A%E8%BF%87%E6%96%B9%E6%B3%95%E6%8B%A6%E6%88%AA%E8%BF%9B%E8%A1%8C%E6%8E%88%E6%9D%83%EF%BC%8C%20MethodSecurityInterceptor%0A%0A%0A%23%23%23%23%23%203.%20CSRF%0ASpringSecurity%E4%B8%BA%E4%BA%86%E9%98%B2%E6%AD%A2CSRF%E7%9A%84%E5%8F%91%E7%94%9F%EF%BC%8C%E9%99%90%E5%88%B6%E4%BA%86%E9%99%A4get%E4%BB%A5%E5%A4%96%E7%9A%84%E5%A4%A7%E5%A4%9A%E6%95%B0%E6%96%B9%E6%B3%95%E3%80%82%0A%0A1.%20%E5%85%B3%E9%97%AD***CSRF***%0A2.%20%E5%9C%A8%E9%A1%B5%E9%9D%A2%E6%B7%BB%E5%8A%A0token%EF%BC%8C%20springsecurity%E4%BC%9A%E9%AA%8C%E8%AF%81token%EF%BC%8C%E5%A6%82%E6%9E%9Ctoken%E5%90%88%E6%B3%95%E5%88%99%E5%8F%AF%E4%BB%A5%E7%BB%A7%E7%BB%AD%E8%AF%B7%E6%B1%82%0A%0A

zk 监听

创建时间:2020/9/3 22:08
更新时间:2020/9/3 22:11
作者:Chris

  1. why

    配置统一存放,管理

  2. 为什么要用

    1. 配置文件vs配置中心

      便捷性:配置文件不适合集群,分布式场景

      安全性:统一存储,通过跳板机

      实时性:配置改完不需要重启服务,可以自动更新

  3. how 配置中心如何使用

    1. 配置中心本质就是一个系统

    2. 功能:

      对于配置信息的CRUD,并提供接口给应用程序访问

    3. 实现原理:本质存储配置信息

      信息可以存储的地方:mysql,redis,mq,nacos

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务

配置中心服务端:

​ 本质和数据库一样用来存储数据

​ 使用树形结点

配置中心客户端:

​ 从ZK读取配置信息加载到Spring容器中

zkui

@Autowired
Environment environment
!%5B4e664abefb81313653af4c4a560216e4.png%5D(en-resource%3A%2F%2Fdatabase%2F663%3A0)%0A%0A1.%20why%0A%0A%20%20%20%E9%85%8D%E7%BD%AE%E7%BB%9F%E4%B8%80%E5%AD%98%E6%94%BE%EF%BC%8C%E7%AE%A1%E7%90%86%0A%0A2.%20%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8%0A%0A%20%20%201.%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6vs%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%0A%0A%20%20%20%20%20%20%E4%BE%BF%E6%8D%B7%E6%80%A7%EF%BC%9A%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%8D%E9%80%82%E5%90%88%E9%9B%86%E7%BE%A4%EF%BC%8C%E5%88%86%E5%B8%83%E5%BC%8F%E5%9C%BA%E6%99%AF%0A%0A%20%20%20%20%20%20%E5%AE%89%E5%85%A8%E6%80%A7%EF%BC%9A%E7%BB%9F%E4%B8%80%E5%AD%98%E5%82%A8%EF%BC%8C%E9%80%9A%E8%BF%87%E8%B7%B3%E6%9D%BF%E6%9C%BA%0A%0A%20%20%20%20%20%20%E5%AE%9E%E6%97%B6%E6%80%A7%EF%BC%9A%E9%85%8D%E7%BD%AE%E6%94%B9%E5%AE%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E9%87%8D%E5%90%AF%E6%9C%8D%E5%8A%A1%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0%0A%0A%20%20%20%20%20%20%0A%0A3.%20how%20%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%0A%0A%20%20%201.%20%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E6%9C%AC%E8%B4%A8%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E7%B3%BB%E7%BB%9F%0A%0A%20%20%202.%20%E5%8A%9F%E8%83%BD%EF%BC%9A%0A%0A%20%20%20%20%20%20%E5%AF%B9%E4%BA%8E%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E7%9A%84CRUD%EF%BC%8C%E5%B9%B6%E6%8F%90%E4%BE%9B%E6%8E%A5%E5%8F%A3%E7%BB%99%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E8%AE%BF%E9%97%AE%0A%0A%20%20%203.%20%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%EF%BC%9A%E6%9C%AC%E8%B4%A8%E5%AD%98%E5%82%A8%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%0A%0A%20%20%20%20%20%20%E4%BF%A1%E6%81%AF%E5%8F%AF%E4%BB%A5%E5%AD%98%E5%82%A8%E7%9A%84%E5%9C%B0%E6%96%B9%EF%BC%9Amysql%2Credis%2Cmq%2Cnacos%0A%0A%20%20%20%20%20%20%0A%0A%0AZooKeeper%E6%98%AF%E4%B8%80%E4%B8%AA%E5%88%86%E5%B8%83%E5%BC%8F%E7%9A%84%EF%BC%8C%E5%BC%80%E6%94%BE%E6%BA%90%E7%A0%81%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E5%8D%8F%E8%B0%83%E6%9C%8D%E5%8A%A1%0A!%5B42da5222950884ebd95df66b54e6509f.png%5D(en-resource%3A%2F%2Fdatabase%2F665%3A0)%0A%0A%0A%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E6%9C%8D%E5%8A%A1%E7%AB%AF%EF%BC%9A%0A%0A%E2%80%8B%09%E6%9C%AC%E8%B4%A8%E5%92%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%80%E6%A0%B7%E7%94%A8%E6%9D%A5%E5%AD%98%E5%82%A8%E6%95%B0%E6%8D%AE%0A%0A%E2%80%8B%09%E4%BD%BF%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E7%82%B9%0A%0A%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E5%AE%A2%E6%88%B7%E7%AB%AF%EF%BC%9A%0A%0A%E2%80%8B%09%E4%BB%8EZK%E8%AF%BB%E5%8F%96%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E5%8A%A0%E8%BD%BD%E5%88%B0Spring%E5%AE%B9%E5%99%A8%E4%B8%AD%0A%0A!%5Bbf65b2b468a40c13a9b8f677d8777481.png%5D(en-resource%3A%2F%2Fdatabase%2F667%3A0)%0A%0A%0Azkui%0A%0A!%5B75611b11d74047b5dcb66059cdf0ea6c.png%5D(en-resource%3A%2F%2Fdatabase%2F669%3A0)%0A%0A%60%60%60%0A%40Autowired%0AEnvironment%20environment%0A%60%60%60%0A%0A

acp exam note

创建时间:2020/9/2 16:22
更新时间:2020/9/2 16:22
作者:Chris

1. 海史密斯适应型领导力

海史密斯将适应型领导力定义为两个维度:保持敏捷和行事敏捷。
保持敏捷包括:注重敏捷项目管理的基石,比如增量交付,持续整合和适应变动的需求。
敏捷领导者必须进行的“行事敏捷”活动包括:少做;价值的速度,质量,吸引和激励。

%23%23%23%23%201.%20%E6%B5%B7%E5%8F%B2%E5%AF%86%E6%96%AF%E9%80%82%E5%BA%94%E5%9E%8B%E9%A2%86%E5%AF%BC%E5%8A%9B%0A%0A%3E%20%E6%B5%B7%E5%8F%B2%E5%AF%86%E6%96%AF%E5%B0%86%E9%80%82%E5%BA%94%E5%9E%8B%E9%A2%86%E5%AF%BC%E5%8A%9B%E5%AE%9A%E4%B9%89%E4%B8%BA%E4%B8%A4%E4%B8%AA%E7%BB%B4%E5%BA%A6%EF%BC%9A%E4%BF%9D%E6%8C%81%E6%95%8F%E6%8D%B7%E5%92%8C%E8%A1%8C%E4%BA%8B%E6%95%8F%E6%8D%B7%E3%80%82%0A%3E%20%E4%BF%9D%E6%8C%81%E6%95%8F%E6%8D%B7%E5%8C%85%E6%8B%AC%EF%BC%9A%E6%B3%A8%E9%87%8D%E6%95%8F%E6%8D%B7%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E7%9A%84%E5%9F%BA%E7%9F%B3%EF%BC%8C%E6%AF%94%E5%A6%82%E5%A2%9E%E9%87%8F%E4%BA%A4%E4%BB%98%EF%BC%8C%E6%8C%81%E7%BB%AD%E6%95%B4%E5%90%88%E5%92%8C%E9%80%82%E5%BA%94%E5%8F%98%E5%8A%A8%E7%9A%84%E9%9C%80%E6%B1%82%E3%80%82%0A%3E%20%E6%95%8F%E6%8D%B7%E9%A2%86%E5%AF%BC%E8%80%85%E5%BF%85%E9%A1%BB%E8%BF%9B%E8%A1%8C%E7%9A%84%E2%80%9C%E8%A1%8C%E4%BA%8B%E6%95%8F%E6%8D%B7%E2%80%9D%E6%B4%BB%E5%8A%A8%E5%8C%85%E6%8B%AC%EF%BC%9A%E5%B0%91%E5%81%9A%EF%BC%9B%E4%BB%B7%E5%80%BC%E7%9A%84%E9%80%9F%E5%BA%A6%EF%BC%8C%E8%B4%A8%E9%87%8F%EF%BC%8C%E5%90%B8%E5%BC%95%E5%92%8C%E6%BF%80%E5%8A%B1%E3%80%82

angile manifesto

创建时间:2020/9/2 16:19
更新时间:2020/9/2 16:21
作者:Chris

Manifesto for Agile Software Development

  1. Individuals and interactions over processes and tools
  2. Working software over comprehensive documentation
  3. Customer collaboration over contract negotiation
  4. Responding to change over following a plan

Principles behind the Agile Manifesto
We follow these principles:

  1. Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.
  2. Welcome changing requirements, even late in development. Agile processes harness change for the customer's competitive advantage.
  3. Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.
  4. Business people and developers must work together daily throughout the project.
  5. Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.
  6. The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.
  7. Working software is the primary measure of progress.
  8. Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely.
  9. Continuous attention to technical excellence and good design enhances agility.
  10. Simplicity, the art of maximizing the amount of work not done, is essential.
  11. The best architectures, requirements, and designs emerge from self-organizing teams.
  12. At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

看板

Scrum 和 XP 的区别

Scrum 偏重于过程,XP 则偏重于实践,但是实际中,两者是结合一起应用的。

  1. 产品负责人(Product Owner):主要负责确定产品的功能和达到要求的标准,指定软件的发布日期和交付的内容,同时有权力接受或拒绝开发团队的工作成果。
  2. 流程管理员(Scrum Master):主要负责整个Scrum流程在项目中的顺利实施和进行,以及清除挡在客户和开发工作之间的沟通障碍,使得客户可以直接驱动开发。
  3. 开发团队(Scrum Team):主要负责软件产品在Scrum规定流程下进行开发工作,人数控制在5~10人左右,每个成员可能负责不同的技术方面,但要求每成员必须要有很强的自我管理能力,同时具有一定的表达能力;成员可以采用任何工作方式,只要能达到Sprint的目标。

in each sprint we deliver the [Minimum Viable Product,MVP] to customer 对用户有价值的最小可用产品

  1. 首先我们需要确认一个 PB ( Product Backlog , 即按优先顺序排列的一个产品需求列表) ,这是由 PO(Product Owner) 负责的
  2. ST(Scrum Team) 会根据 PB 列表,进行工作量的预估和安排
  3. 有了 PB 列表,我们需要通过 Sprint Planning Meeting( Sprint 计划会议)来从中挑选出一个 Story 作为本次迭代完成的目标,这个目标的时间周期是1~4个星期,然后把这个Story进行细化,形成一个Sprint Backlog

Sprint Planning Meeting ( Sprint 计划会议)来从中挑选出一个 Story 作为本次迭代完成的目标
Daily meeting
Weekly meeting
Sprint Retrospective Meeting(回顾会议)

TDD是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD 是 XP(Extreme Programming)的核心实践。
TDD 有三层含义:

  1. Task-Driven Development,任务驱动开发,要对问题进行分析并进行任务分解。
  2. Test-Driven Development,测试驱动开发。
  3. Test-Driven Design,测试保护下的设计改善。TDD 并不能直接提高设计能力,它只是给你更多机会和保障去改善设计。
%5Btoc%5D%0A%0A%23%23%23%23%20%20Manifesto%20for%20Agile%20Software%20Development%0A%3E1.%20Individuals%20and%20interactions%20over%20processes%20and%20tools%20%0A%3E2.%20Working%20software%20over%20comprehensive%20documentation%20%0A%3E3.%20Customer%20collaboration%20over%20contract%20negotiation%0A%3E4.%20Responding%20to%20change%20over%20following%20a%20plan%0A%0APrinciples%20behind%20the%20Agile%20Manifesto%0AWe%20follow%20these%20principles%3A%0A%3E1.%20Our%20highest%20priority%20is%20to%20satisfy%20the%20customer%20through%20early%20and%20continuous%20delivery%20of%20valuable%20software.%0A%3E2.%20Welcome%20changing%20requirements%2C%20even%20late%20in%20development.%20Agile%20processes%20harness%20change%20for%20the%20customer's%20competitive%20advantage.%0A%3E3.%20Deliver%20working%20software%20frequently%2C%20from%20a%20couple%20of%20weeks%20to%20a%20couple%20of%20months%2C%20with%20a%20preference%20to%20the%20shorter%20timescale.%0A%3E4.%20Business%20people%20and%20developers%20must%20work%20together%20daily%20throughout%20the%20project.%0A%3E5.%20Build%20projects%20around%20motivated%20individuals.%20Give%20them%20the%20environment%20and%20support%20they%20need%2C%20and%20trust%20them%20to%20get%20the%20job%20done.%0A%3E6.%20The%20most%20efficient%20and%20effective%20method%20of%20conveying%20information%20to%20and%20within%20a%20development%20team%20is%20face-to-face%20conversation.%0A%3E7.%20Working%20software%20is%20the%20primary%20measure%20of%20progress.%0A%3E8.%20Agile%20processes%20promote%20sustainable%20development.%20The%20sponsors%2C%20developers%2C%20and%20users%20should%20be%20able%20to%20maintain%20a%20constant%20pace%20indefinitely.%0A%3E9.%20Continuous%20attention%20to%20technical%20excellence%20and%20good%20design%20enhances%20agility.%0A%3E10.%20Simplicity%2C%20the%20art%20of%20maximizing%20the%20amount%20of%20work%20not%20done%2C%20is%20essential.%0A%3E11.%20The%20best%20architectures%2C%20requirements%2C%20and%20designs%20emerge%20from%20self-organizing%20teams.%0A%3E12.%20At%20regular%20intervals%2C%20the%20team%20reflects%20on%20how%20to%20become%20more%20effective%2C%20then%20tunes%20and%20adjusts%20its%20behavior%20accordingly.%0A%0A%0A%23%23%23%23%20%E7%9C%8B%E6%9D%BF%0A%0A!%5B360662c0d1b90b274f4103bf71eee9fe.png%5D(en-resource%3A%2F%2Fdatabase%2F1325%3A1)%0A%0A%0A%0A%23%23%23%23%20Scrum%20%E5%92%8C%20XP%20%E7%9A%84%E5%8C%BA%E5%88%AB%0AScrum%20%E5%81%8F%E9%87%8D%E4%BA%8E%E8%BF%87%E7%A8%8B%EF%BC%8CXP%20%E5%88%99%E5%81%8F%E9%87%8D%E4%BA%8E%E5%AE%9E%E8%B7%B5%EF%BC%8C%E4%BD%86%E6%98%AF%E5%AE%9E%E9%99%85%E4%B8%AD%EF%BC%8C%E4%B8%A4%E8%80%85%E6%98%AF%E7%BB%93%E5%90%88%E4%B8%80%E8%B5%B7%E5%BA%94%E7%94%A8%E7%9A%84%E3%80%82%0A1.%20%E4%BA%A7%E5%93%81%E8%B4%9F%E8%B4%A3%E4%BA%BA%EF%BC%88Product%20Owner%EF%BC%89%EF%BC%9A%E4%B8%BB%E8%A6%81%E8%B4%9F%E8%B4%A3%E7%A1%AE%E5%AE%9A%E4%BA%A7%E5%93%81%E7%9A%84%E5%8A%9F%E8%83%BD%E5%92%8C%E8%BE%BE%E5%88%B0%E8%A6%81%E6%B1%82%E7%9A%84%E6%A0%87%E5%87%86%EF%BC%8C%E6%8C%87%E5%AE%9A%E8%BD%AF%E4%BB%B6%E7%9A%84%E5%8F%91%E5%B8%83%E6%97%A5%E6%9C%9F%E5%92%8C%E4%BA%A4%E4%BB%98%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8C%E5%90%8C%E6%97%B6%E6%9C%89%E6%9D%83%E5%8A%9B%E6%8E%A5%E5%8F%97%E6%88%96%E6%8B%92%E7%BB%9D%E5%BC%80%E5%8F%91%E5%9B%A2%E9%98%9F%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%88%90%E6%9E%9C%E3%80%82%0A2.%20%E6%B5%81%E7%A8%8B%E7%AE%A1%E7%90%86%E5%91%98%EF%BC%88Scrum%20Master%EF%BC%89%EF%BC%9A%E4%B8%BB%E8%A6%81%E8%B4%9F%E8%B4%A3%E6%95%B4%E4%B8%AAScrum%E6%B5%81%E7%A8%8B%E5%9C%A8%E9%A1%B9%E7%9B%AE%E4%B8%AD%E7%9A%84%E9%A1%BA%E5%88%A9%E5%AE%9E%E6%96%BD%E5%92%8C%E8%BF%9B%E8%A1%8C%EF%BC%8C%E4%BB%A5%E5%8F%8A%E6%B8%85%E9%99%A4%E6%8C%A1%E5%9C%A8%E5%AE%A2%E6%88%B7%E5%92%8C%E5%BC%80%E5%8F%91%E5%B7%A5%E4%BD%9C%E4%B9%8B%E9%97%B4%E7%9A%84%E6%B2%9F%E9%80%9A%E9%9A%9C%E7%A2%8D%EF%BC%8C%E4%BD%BF%E5%BE%97%E5%AE%A2%E6%88%B7%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91%E3%80%82%0A3.%20%E5%BC%80%E5%8F%91%E5%9B%A2%E9%98%9F%EF%BC%88Scrum%20Team%EF%BC%89%EF%BC%9A%E4%B8%BB%E8%A6%81%E8%B4%9F%E8%B4%A3%E8%BD%AF%E4%BB%B6%E4%BA%A7%E5%93%81%E5%9C%A8Scrum%E8%A7%84%E5%AE%9A%E6%B5%81%E7%A8%8B%E4%B8%8B%E8%BF%9B%E8%A1%8C%E5%BC%80%E5%8F%91%E5%B7%A5%E4%BD%9C%EF%BC%8C%E4%BA%BA%E6%95%B0%E6%8E%A7%E5%88%B6%E5%9C%A85~10%E4%BA%BA%E5%B7%A6%E5%8F%B3%EF%BC%8C%E6%AF%8F%E4%B8%AA%E6%88%90%E5%91%98%E5%8F%AF%E8%83%BD%E8%B4%9F%E8%B4%A3%E4%B8%8D%E5%90%8C%E7%9A%84%E6%8A%80%E6%9C%AF%E6%96%B9%E9%9D%A2%EF%BC%8C%E4%BD%86%E8%A6%81%E6%B1%82%E6%AF%8F%E6%88%90%E5%91%98%E5%BF%85%E9%A1%BB%E8%A6%81%E6%9C%89%E5%BE%88%E5%BC%BA%E7%9A%84%E8%87%AA%E6%88%91%E7%AE%A1%E7%90%86%E8%83%BD%E5%8A%9B%EF%BC%8C%E5%90%8C%E6%97%B6%E5%85%B7%E6%9C%89%E4%B8%80%E5%AE%9A%E7%9A%84%E8%A1%A8%E8%BE%BE%E8%83%BD%E5%8A%9B%EF%BC%9B%E6%88%90%E5%91%98%E5%8F%AF%E4%BB%A5%E9%87%87%E7%94%A8%E4%BB%BB%E4%BD%95%E5%B7%A5%E4%BD%9C%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%8F%AA%E8%A6%81%E8%83%BD%E8%BE%BE%E5%88%B0Sprint%E7%9A%84%E7%9B%AE%E6%A0%87%E3%80%82%0A%0A!%5B1a0adfc6fba0eef4927431aa69e915c1.png%5D(en-resource%3A%2F%2Fdatabase%2F1323%3A1)%0A%0A%0Ain%20each%20sprint%20we%20deliver%20the%20%5BMinimum%20Viable%20Product%2CMVP%5D%20to%20customer%20%E5%AF%B9%E7%94%A8%E6%88%B7%E6%9C%89%E4%BB%B7%E5%80%BC%E7%9A%84%E6%9C%80%E5%B0%8F%E5%8F%AF%E7%94%A8%E4%BA%A7%E5%93%81%0A%0A1.%20%E9%A6%96%E5%85%88%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E7%A1%AE%E8%AE%A4%E4%B8%80%E4%B8%AA%20PB%20(%20Product%20Backlog%20%2C%20%E5%8D%B3%E6%8C%89%E4%BC%98%E5%85%88%E9%A1%BA%E5%BA%8F%E6%8E%92%E5%88%97%E7%9A%84%E4%B8%80%E4%B8%AA%E4%BA%A7%E5%93%81%E9%9C%80%E6%B1%82%E5%88%97%E8%A1%A8)%20%EF%BC%8C%E8%BF%99%E6%98%AF%E7%94%B1%20PO%EF%BC%88Product%20Owner%EF%BC%89%20%E8%B4%9F%E8%B4%A3%E7%9A%84%0A2.%20ST%EF%BC%88Scrum%20Team%EF%BC%89%20%E4%BC%9A%E6%A0%B9%E6%8D%AE%20PB%20%E5%88%97%E8%A1%A8%EF%BC%8C%E8%BF%9B%E8%A1%8C%E5%B7%A5%E4%BD%9C%E9%87%8F%E7%9A%84%E9%A2%84%E4%BC%B0%E5%92%8C%E5%AE%89%E6%8E%92%0A3.%20%E6%9C%89%E4%BA%86%20PB%20%E5%88%97%E8%A1%A8%EF%BC%8C%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E9%80%9A%E8%BF%87%20Sprint%20Planning%20Meeting(%20Sprint%20%E8%AE%A1%E5%88%92%E4%BC%9A%E8%AE%AE)%E6%9D%A5%E4%BB%8E%E4%B8%AD%E6%8C%91%E9%80%89%E5%87%BA%E4%B8%80%E4%B8%AA%20Story%20%E4%BD%9C%E4%B8%BA%E6%9C%AC%E6%AC%A1%E8%BF%AD%E4%BB%A3%E5%AE%8C%E6%88%90%E7%9A%84%E7%9B%AE%E6%A0%87%EF%BC%8C%E8%BF%99%E4%B8%AA%E7%9B%AE%E6%A0%87%E7%9A%84%E6%97%B6%E9%97%B4%E5%91%A8%E6%9C%9F%E6%98%AF1~4%E4%B8%AA%E6%98%9F%E6%9C%9F%EF%BC%8C%E7%84%B6%E5%90%8E%E6%8A%8A%E8%BF%99%E4%B8%AAStory%E8%BF%9B%E8%A1%8C%E7%BB%86%E5%8C%96%EF%BC%8C%E5%BD%A2%E6%88%90%E4%B8%80%E4%B8%AASprint%20Backlog%0A%0ASprint%20Planning%20Meeting%20(%20Sprint%20%E8%AE%A1%E5%88%92%E4%BC%9A%E8%AE%AE)%E6%9D%A5%E4%BB%8E%E4%B8%AD%E6%8C%91%E9%80%89%E5%87%BA%E4%B8%80%E4%B8%AA%20Story%20%E4%BD%9C%E4%B8%BA%E6%9C%AC%E6%AC%A1%E8%BF%AD%E4%BB%A3%E5%AE%8C%E6%88%90%E7%9A%84%E7%9B%AE%E6%A0%87%0ADaily%20meeting%0AWeekly%20meeting%0ASprint%20Retrospective%20Meeting%EF%BC%88%E5%9B%9E%E9%A1%BE%E4%BC%9A%E8%AE%AE%EF%BC%89%0A%0ATDD%E6%98%AF%E6%95%8F%E6%8D%B7%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E4%B8%80%E9%A1%B9%E6%A0%B8%E5%BF%83%E5%AE%9E%E8%B7%B5%E5%92%8C%E6%8A%80%E6%9C%AF%EF%BC%8C%E4%B9%9F%E6%98%AF%E4%B8%80%E7%A7%8D%E8%AE%BE%E8%AE%A1%E6%96%B9%E6%B3%95%E8%AE%BA%E3%80%82TDD%E7%9A%84%E5%8E%9F%E7%90%86%E6%98%AF%E5%9C%A8%E5%BC%80%E5%8F%91%E5%8A%9F%E8%83%BD%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%89%8D%EF%BC%8C%E5%85%88%E7%BC%96%E5%86%99%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E4%BB%A3%E7%A0%81%EF%BC%8C%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E7%A1%AE%E5%AE%9A%E9%9C%80%E8%A6%81%E7%BC%96%E5%86%99%E4%BB%80%E4%B9%88%E4%BA%A7%E5%93%81%E4%BB%A3%E7%A0%81%E3%80%82TDD%20%E6%98%AF%20XP%EF%BC%88Extreme%20Programming%EF%BC%89%E7%9A%84%E6%A0%B8%E5%BF%83%E5%AE%9E%E8%B7%B5%E3%80%82%0ATDD%20%E6%9C%89%E4%B8%89%E5%B1%82%E5%90%AB%E4%B9%89%EF%BC%9A%0A%3E1.%20Task-Driven%20Development%EF%BC%8C%E4%BB%BB%E5%8A%A1%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91%EF%BC%8C%E8%A6%81%E5%AF%B9%E9%97%AE%E9%A2%98%E8%BF%9B%E8%A1%8C%E5%88%86%E6%9E%90%E5%B9%B6%E8%BF%9B%E8%A1%8C%E4%BB%BB%E5%8A%A1%E5%88%86%E8%A7%A3%E3%80%82%0A%3E2.%20Test-Driven%20Development%EF%BC%8C%E6%B5%8B%E8%AF%95%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91%E3%80%82%20%0A%3E3.%20Test-Driven%20Design%EF%BC%8C%E6%B5%8B%E8%AF%95%E4%BF%9D%E6%8A%A4%E4%B8%8B%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%94%B9%E5%96%84%E3%80%82TDD%20%E5%B9%B6%E4%B8%8D%E8%83%BD%E7%9B%B4%E6%8E%A5%E6%8F%90%E9%AB%98%E8%AE%BE%E8%AE%A1%E8%83%BD%E5%8A%9B%EF%BC%8C%E5%AE%83%E5%8F%AA%E6%98%AF%E7%BB%99%E4%BD%A0%E6%9B%B4%E5%A4%9A%E6%9C%BA%E4%BC%9A%E5%92%8C%E4%BF%9D%E9%9A%9C%E5%8E%BB%E6%94%B9%E5%96%84%E8%AE%BE%E8%AE%A1%E3%80%82

markdown

创建时间:2020/9/2 16:18
更新时间:2020/9/2 16:18
作者:Chris

标题

使用 = 和 - 标记一级和二级标题


字体

*斜体文本*
_斜体文本_
**粗体文本**
__粗体文本__
***粗斜体文本***
___粗斜体文本___

分隔线

你可以在一行中用三个以上的 星号、减号、底线
来建立一个分隔线,行内不能有其他东西
你也可以在星号或是减号中间插入空格。
下面每种写法都可以建立分隔线:
***
* * *
*****
- - -
----------


删除线

如果段落上的文字要添加删除线,只需要在文字的两端加上两个波浪线 ~~ 即可,实例如下
RUNOOB.COM
GOOGLE.COM
BAIDU.COM


下划线

<u>带下划线文本</u>

脚注

创建脚注格式类似这样 [^RUNOOB]。
创建脚注格式类似这样 [^Chris]。

创建脚注格式类似这样 [^RUNOOB]
创建脚注格式类似这样 [^Chris]

[^RUNOOB]: 菜鸟教程 -- 学的不仅是技术,更是梦想!!!

[^Chris]: A smart and intellient man


Markdown 列表

Markdown 支持有序列表和无序列表。
无序列表使用星号(*)、加号(+)或是减号(-)作为列表标记:
有序列表使用数字并加上 . 号来表示,如:

  • 第一项
  • 第二项
  • 第三项
  1. 第一项
  2. 第二项
  3. 第三项

列表嵌套

列表嵌套只需在子列表中的选项添加四个空格即可:

  1. 第一项:
    • 第一项嵌套的第一个元素
    • 第一项嵌套的第二个元素
  2. 第二项:
    • 第二项嵌套的第一个元素
    • 第二项嵌套的第二个元素

区块

  1. Markdown 区块引用是在段落开头使用 > 符号 ,然后后面紧跟一个空格符号:

区块引用
菜鸟教程
学的不仅是技术更是梦想

  1. 另外区块是可以嵌套的,一个 > 符号是最外层,两个 > 符号是第一层嵌套,以此类推:

最外层

第一层嵌套

第二层嵌套

  1. 区块中使用列表

区块中使用列表

  1. 第一项
  • 第一项
  • 第二项
  • 第三项
  1. 第二项
  • 第一项
  • 第二项
  • 第三项
  1. 列表中使用区块
  • 第一项

    菜鸟教程
    学的不仅是技术更是梦想

  • 第二项

Markdown 代码

  1. 如果是段落上的一个函数或片段的代码可以用反引号把它包起,例如:
    printf() 函数

  2. 代码区块
    代码区块使用 4 个空格或者一个制表符(Tab 键)。实例如下:

$(document).ready(function(){
    alert('RUNOOB');}
);
$(document).ready(function () {
    alert('RUNOOB');
});
from math import hypot

class Vector:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
    def __repr__(self):
        return 'Vector(%r, %r)' % (self.x, self.y)
    def __abs__(self):
        return hypot(self.x, self.y)
    def __bool__(self):
        return bool(abs(self))
    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)
    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

Markdown 链接

  1. 链接名称
    这是一个链接 菜鸟教程
  2. <链接地址>
    https://www.runoob.com
  3. 高级链接
    我们可以通过变量来设置一个链接,变量赋值在文档末尾进行:
    这个链接用 1 作为网址变量 Google
    这个链接用 runoob 作为网址变量 Runoob
    然后在文档的结尾为变量赋值(网址)

Markdown 图片




Markdown 表格

  1. Markdown 制作表格使用 | 来分隔不同的单元格,使用 - 来分隔表头和其他行。

    表头表头
    单元格单元格
    单元格单元格
  2. 我们可以设置表格的对齐方式:

-: 设置内容和标题栏居右对齐。
:- 设置内容和标题栏居左对齐。
:-: 设置内容和标题栏居中对齐。

左对齐右对齐居中对齐
单元格单元格单元格
单元格单元格单元格

Markdown 高级技巧

  1. 支持的 HTML 元素
    不在 Markdown 涵盖范围之内的标签,都可以直接在文档里面用 HTML 撰写。

    目前支持的 HTML 元素有:<kbd> <b> <i> <em> <sup> <sub> <br>等 ,如:
    

    使用 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> 重启电脑

  2. 转义
    Markdown 使用了很多特殊符号来表示特定的意义,如果需要显示特定的符号则需要使用转义字符,Markdown 使用反斜杠转义特殊字符:

    **文本加粗** 
    \*\* 正常显示星号 \*\*
    
  3. Markdown 支持以下这些符号前面加上反斜杠来帮助插入普通的符号:

    \   反斜线
    `   反引号
    *   星号
    _   下划线
    {}  花括号
    []  方括号
    ()  小括号
    #   井字号
    +   加号
    -   减号
    .   英文句点
    !   感叹号
    
    
    
%0A%0A%0A%23%23%20**%E6%A0%87%E9%A2%98**%0A%E4%BD%BF%E7%94%A8%20%3D%20%E5%92%8C%20-%20%E6%A0%87%E8%AE%B0%E4%B8%80%E7%BA%A7%E5%92%8C%E4%BA%8C%E7%BA%A7%E6%A0%87%E9%A2%98%0A***%0A%23%23%20%E5%AD%97%E4%BD%93%0A%09*%E6%96%9C%E4%BD%93%E6%96%87%E6%9C%AC*%0A%09_%E6%96%9C%E4%BD%93%E6%96%87%E6%9C%AC_%0A%09**%E7%B2%97%E4%BD%93%E6%96%87%E6%9C%AC**%0A%09__%E7%B2%97%E4%BD%93%E6%96%87%E6%9C%AC__%0A%09***%E7%B2%97%E6%96%9C%E4%BD%93%E6%96%87%E6%9C%AC***%0A%09___%E7%B2%97%E6%96%9C%E4%BD%93%E6%96%87%E6%9C%AC___%0A***%0A%23%23%20**%E5%88%86%E9%9A%94%E7%BA%BF**%0A%E4%BD%A0%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%B8%80%E8%A1%8C%E4%B8%AD%E7%94%A8%E4%B8%89%E4%B8%AA%E4%BB%A5%E4%B8%8A%E7%9A%84%20***%E6%98%9F%E5%8F%B7%E3%80%81%E5%87%8F%E5%8F%B7%E3%80%81%E5%BA%95%E7%BA%BF***%0A%E6%9D%A5%E5%BB%BA%E7%AB%8B%E4%B8%80%E4%B8%AA%E5%88%86%E9%9A%94%E7%BA%BF%EF%BC%8C%E8%A1%8C%E5%86%85%E4%B8%8D%E8%83%BD%E6%9C%89%E5%85%B6%E4%BB%96%E4%B8%9C%E8%A5%BF%0A%E4%BD%A0%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%98%9F%E5%8F%B7%E6%88%96%E6%98%AF%E5%87%8F%E5%8F%B7%E4%B8%AD%E9%97%B4%E6%8F%92%E5%85%A5%E7%A9%BA%E6%A0%BC%E3%80%82%0A%E4%B8%8B%E9%9D%A2%E6%AF%8F%E7%A7%8D%E5%86%99%E6%B3%95%E9%83%BD%E5%8F%AF%E4%BB%A5%E5%BB%BA%E7%AB%8B%E5%88%86%E9%9A%94%E7%BA%BF%EF%BC%9A%0A%09***%0A%09*%20*%20*%0A%09*****%0A%09-%20-%20-%0A%09----------%0A***%0A%23%23%20**%E5%88%A0%E9%99%A4%E7%BA%BF**%0A%E5%A6%82%E6%9E%9C%E6%AE%B5%E8%90%BD%E4%B8%8A%E7%9A%84%E6%96%87%E5%AD%97%E8%A6%81%E6%B7%BB%E5%8A%A0%E5%88%A0%E9%99%A4%E7%BA%BF%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E5%9C%A8%E6%96%87%E5%AD%97%E7%9A%84%E4%B8%A4%E7%AB%AF%E5%8A%A0%E4%B8%8A%E4%B8%A4%E4%B8%AA%E6%B3%A2%E6%B5%AA%E7%BA%BF%20~~%20%E5%8D%B3%E5%8F%AF%EF%BC%8C%E5%AE%9E%E4%BE%8B%E5%A6%82%E4%B8%8B%0ARUNOOB.COM%0AGOOGLE.COM%0A~~BAIDU.COM~~%0A***%0A%23%23%20**%E4%B8%8B%E5%88%92%E7%BA%BF**%0A%09%3Cu%3E%E5%B8%A6%E4%B8%8B%E5%88%92%E7%BA%BF%E6%96%87%E6%9C%AC%3C%2Fu%3E%0A***%0A%23%23%20**%E8%84%9A%E6%B3%A8**%0A%20%20%20%20%E5%88%9B%E5%BB%BA%E8%84%9A%E6%B3%A8%E6%A0%BC%E5%BC%8F%E7%B1%BB%E4%BC%BC%E8%BF%99%E6%A0%B7%20%5B%5ERUNOOB%5D%E3%80%82%0A%20%20%20%20%E5%88%9B%E5%BB%BA%E8%84%9A%E6%B3%A8%E6%A0%BC%E5%BC%8F%E7%B1%BB%E4%BC%BC%E8%BF%99%E6%A0%B7%20%5B%5EChris%5D%E3%80%82%0A%0A%E5%88%9B%E5%BB%BA%E8%84%9A%E6%B3%A8%E6%A0%BC%E5%BC%8F%E7%B1%BB%E4%BC%BC%E8%BF%99%E6%A0%B7%20%5B%5ERUNOOB%5D%20%20%0A%E5%88%9B%E5%BB%BA%E8%84%9A%E6%B3%A8%E6%A0%BC%E5%BC%8F%E7%B1%BB%E4%BC%BC%E8%BF%99%E6%A0%B7%20%5B%5EChris%5D%0A%0A%5B%5ERUNOOB%5D%3A%20%E8%8F%9C%E9%B8%9F%E6%95%99%E7%A8%8B%20--%20%E5%AD%A6%E7%9A%84%E4%B8%8D%E4%BB%85%E6%98%AF%E6%8A%80%E6%9C%AF%EF%BC%8C%E6%9B%B4%E6%98%AF%E6%A2%A6%E6%83%B3%EF%BC%81%EF%BC%81%EF%BC%81%20%20%0A%5B%5EChris%5D%3A%20A%20smart%20and%20intellient%20man%0A***%0A%23%23%20**Markdown%20%E5%88%97%E8%A1%A8**%0AMarkdown%20%E6%94%AF%E6%8C%81%E6%9C%89%E5%BA%8F%E5%88%97%E8%A1%A8%E5%92%8C%E6%97%A0%E5%BA%8F%E5%88%97%E8%A1%A8%E3%80%82%0A%E6%97%A0%E5%BA%8F%E5%88%97%E8%A1%A8%E4%BD%BF%E7%94%A8%E6%98%9F%E5%8F%B7(*)%E3%80%81%E5%8A%A0%E5%8F%B7(%2B)%E6%88%96%E6%98%AF%E5%87%8F%E5%8F%B7(-)%E4%BD%9C%E4%B8%BA%E5%88%97%E8%A1%A8%E6%A0%87%E8%AE%B0%EF%BC%9A%0A%E6%9C%89%E5%BA%8F%E5%88%97%E8%A1%A8%E4%BD%BF%E7%94%A8%E6%95%B0%E5%AD%97%E5%B9%B6%E5%8A%A0%E4%B8%8A%20.%20%E5%8F%B7%E6%9D%A5%E8%A1%A8%E7%A4%BA%EF%BC%8C%E5%A6%82%EF%BC%9A%0A*%20%E7%AC%AC%E4%B8%80%E9%A1%B9%0A%2B%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%0A-%20%E7%AC%AC%E4%B8%89%E9%A1%B9%0A%0A1.%20%E7%AC%AC%E4%B8%80%E9%A1%B9%20%20%0A2.%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%20%20%0A3.%20%E7%AC%AC%E4%B8%89%E9%A1%B9%20%20%0A***%0A%0A%23%23%20**%E5%88%97%E8%A1%A8%E5%B5%8C%E5%A5%97**%0A%E5%88%97%E8%A1%A8%E5%B5%8C%E5%A5%97%E5%8F%AA%E9%9C%80%E5%9C%A8%E5%AD%90%E5%88%97%E8%A1%A8%E4%B8%AD%E7%9A%84%E9%80%89%E9%A1%B9%E6%B7%BB%E5%8A%A0%E5%9B%9B%E4%B8%AA%E7%A9%BA%E6%A0%BC%E5%8D%B3%E5%8F%AF%EF%BC%9A%0A1.%20%E7%AC%AC%E4%B8%80%E9%A1%B9%EF%BC%9A%0A%20%20%20%20-%20%E7%AC%AC%E4%B8%80%E9%A1%B9%E5%B5%8C%E5%A5%97%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%0A%20%20%20%20-%20%E7%AC%AC%E4%B8%80%E9%A1%B9%E5%B5%8C%E5%A5%97%E7%9A%84%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%85%83%E7%B4%A0%0A2.%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%EF%BC%9A%0A%20%20%20%20-%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%E5%B5%8C%E5%A5%97%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%0A%20%20%20%20-%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%E5%B5%8C%E5%A5%97%E7%9A%84%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%85%83%E7%B4%A0%0A***%0A%0A%23%23%20**%E5%8C%BA%E5%9D%97**%0A1.%20Markdown%20%E5%8C%BA%E5%9D%97%E5%BC%95%E7%94%A8%E6%98%AF%E5%9C%A8%E6%AE%B5%E8%90%BD%E5%BC%80%E5%A4%B4%E4%BD%BF%E7%94%A8%20**%3E**%20%E7%AC%A6%E5%8F%B7%20%EF%BC%8C%E7%84%B6%E5%90%8E%E5%90%8E%E9%9D%A2%E7%B4%A7%E8%B7%9F%E4%B8%80%E4%B8%AA%E7%A9%BA%E6%A0%BC%E7%AC%A6%E5%8F%B7%EF%BC%9A%0A%3E%20%E5%8C%BA%E5%9D%97%E5%BC%95%E7%94%A8%0A%3E%20%E8%8F%9C%E9%B8%9F%E6%95%99%E7%A8%8B%0A%3E%20%E5%AD%A6%E7%9A%84%E4%B8%8D%E4%BB%85%E6%98%AF%E6%8A%80%E6%9C%AF%E6%9B%B4%E6%98%AF%E6%A2%A6%E6%83%B3%0A%0A2.%20%E5%8F%A6%E5%A4%96%E5%8C%BA%E5%9D%97%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%B5%8C%E5%A5%97%E7%9A%84%EF%BC%8C%E4%B8%80%E4%B8%AA%20**%3E**%20%E7%AC%A6%E5%8F%B7%E6%98%AF%E6%9C%80%E5%A4%96%E5%B1%82%EF%BC%8C%E4%B8%A4%E4%B8%AA%20**%3E**%20%E7%AC%A6%E5%8F%B7%E6%98%AF%E7%AC%AC%E4%B8%80%E5%B1%82%E5%B5%8C%E5%A5%97%EF%BC%8C%E4%BB%A5%E6%AD%A4%E7%B1%BB%E6%8E%A8%EF%BC%9A%0A%3E%20%E6%9C%80%E5%A4%96%E5%B1%82%0A%3E%20%3E%20%E7%AC%AC%E4%B8%80%E5%B1%82%E5%B5%8C%E5%A5%97%0A%3E%20%3E%20%3E%20%E7%AC%AC%E4%BA%8C%E5%B1%82%E5%B5%8C%E5%A5%97%0A%0A3.%20%E5%8C%BA%E5%9D%97%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%88%97%E8%A1%A8%0A%3E%20%E5%8C%BA%E5%9D%97%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%88%97%E8%A1%A8%0A%3E%201.%20%E7%AC%AC%E4%B8%80%E9%A1%B9%0A%3E%20%3E%20%2B%20%E7%AC%AC%E4%B8%80%E9%A1%B9%0A%3E%20%3E%20%2B%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%0A%3E%20%3E%20%2B%20%E7%AC%AC%E4%B8%89%E9%A1%B9%0A%3E%202.%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%0A%3E%20%3E%20%2B%20%E7%AC%AC%E4%B8%80%E9%A1%B9%0A%3E%20%3E%20%2B%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%0A%3E%20%3E%20%2B%20%E7%AC%AC%E4%B8%89%E9%A1%B9%0A%0A4.%20%E5%88%97%E8%A1%A8%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%8C%BA%E5%9D%97%0A*%20%E7%AC%AC%E4%B8%80%E9%A1%B9%0A%20%20%20%20%3E%20%E8%8F%9C%E9%B8%9F%E6%95%99%E7%A8%8B%0A%20%20%20%20%3E%20%E5%AD%A6%E7%9A%84%E4%B8%8D%E4%BB%85%E6%98%AF%E6%8A%80%E6%9C%AF%E6%9B%B4%E6%98%AF%E6%A2%A6%E6%83%B3%0A*%20%E7%AC%AC%E4%BA%8C%E9%A1%B9%0A***%0A%23%23%20**Markdown%20%E4%BB%A3%E7%A0%81**%0A1.%20%E5%A6%82%E6%9E%9C%E6%98%AF%E6%AE%B5%E8%90%BD%E4%B8%8A%E7%9A%84%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E6%88%96%E7%89%87%E6%AE%B5%E7%9A%84%E4%BB%A3%E7%A0%81%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%8F%8D%E5%BC%95%E5%8F%B7%E6%8A%8A%E5%AE%83%E5%8C%85%E8%B5%B7%EF%BC%8C%E4%BE%8B%E5%A6%82%EF%BC%9A%0A%60printf()%60%20%E5%87%BD%E6%95%B0%0A%0A2.%20%E4%BB%A3%E7%A0%81%E5%8C%BA%E5%9D%97%0A%E4%BB%A3%E7%A0%81%E5%8C%BA%E5%9D%97%E4%BD%BF%E7%94%A8%204%20%E4%B8%AA%E7%A9%BA%E6%A0%BC%E6%88%96%E8%80%85%E4%B8%80%E4%B8%AA%E5%88%B6%E8%A1%A8%E7%AC%A6%EF%BC%88Tab%20%E9%94%AE%EF%BC%89%E3%80%82%E5%AE%9E%E4%BE%8B%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60%0A%24(document).ready(function()%7B%0A%20%20%20%20alert('RUNOOB')%3B%7D%0A)%3B%0A%60%60%60%0A%60%60%60javascript%0A%24(document).ready(function%20()%20%7B%0A%20%20%20%20alert('RUNOOB')%3B%0A%7D)%3B%0A%60%60%60%0A%0A%60%60%60%0Afrom%20math%20import%20hypot%0A%0Aclass%20Vector%3A%0A%20%20%20%20def%20__init__(self%2C%20x%3D0%2C%20y%3D0)%3A%0A%20%20%20%20%20%20%20%20self.x%20%3D%20x%0A%20%20%20%20%20%20%20%20self.y%20%3D%20y%0A%20%20%20%20def%20__repr__(self)%3A%0A%20%20%20%20%20%20%20%20return%20'Vector(%25r%2C%20%25r)'%20%25%20(self.x%2C%20self.y)%0A%20%20%20%20def%20__abs__(self)%3A%0A%20%20%20%20%20%20%20%20return%20hypot(self.x%2C%20self.y)%0A%20%20%20%20def%20__bool__(self)%3A%0A%20%20%20%20%20%20%20%20return%20bool(abs(self))%0A%20%20%20%20def%20__add__(self%2C%20other)%3A%0A%20%20%20%20%20%20%20%20x%20%3D%20self.x%20%2B%20other.x%0A%20%20%20%20%20%20%20%20y%20%3D%20self.y%20%2B%20other.y%0A%20%20%20%20%20%20%20%20return%20Vector(x%2C%20y)%0A%20%20%20%20def%20__mul__(self%2C%20scalar)%3A%0A%20%20%20%20%20%20%20%20return%20Vector(self.x%20*%20scalar%2C%20self.y%20*%20scalar)%0A%60%60%60%0A%0A***%0A%0A%23%23%20**Markdown%20%E9%93%BE%E6%8E%A5**%0A1.%20%5B%E9%93%BE%E6%8E%A5%E5%90%8D%E7%A7%B0%5D(%E9%93%BE%E6%8E%A5%E5%9C%B0%E5%9D%80)%0A%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E9%93%BE%E6%8E%A5%20%5B%E8%8F%9C%E9%B8%9F%E6%95%99%E7%A8%8B%5D(https%3A%2F%2Fwww.runoob.com)%0A2.%20%3C%E9%93%BE%E6%8E%A5%E5%9C%B0%E5%9D%80%3E%0A%3Chttps%3A%2F%2Fwww.runoob.com%3E%0A3.%20%E9%AB%98%E7%BA%A7%E9%93%BE%E6%8E%A5%0A%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%8F%98%E9%87%8F%E6%9D%A5%E8%AE%BE%E7%BD%AE%E4%B8%80%E4%B8%AA%E9%93%BE%E6%8E%A5%EF%BC%8C%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC%E5%9C%A8%E6%96%87%E6%A1%A3%E6%9C%AB%E5%B0%BE%E8%BF%9B%E8%A1%8C%EF%BC%9A%0A%E8%BF%99%E4%B8%AA%E9%93%BE%E6%8E%A5%E7%94%A8%201%20%E4%BD%9C%E4%B8%BA%E7%BD%91%E5%9D%80%E5%8F%98%E9%87%8F%20%5BGoogle%5D%5B1%5D%0A%E8%BF%99%E4%B8%AA%E9%93%BE%E6%8E%A5%E7%94%A8%20runoob%20%E4%BD%9C%E4%B8%BA%E7%BD%91%E5%9D%80%E5%8F%98%E9%87%8F%20%5BRunoob%5D%5Brunoob%5D%0A%E7%84%B6%E5%90%8E%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E7%BB%93%E5%B0%BE%E4%B8%BA%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC%EF%BC%88%E7%BD%91%E5%9D%80%EF%BC%89%0A%5B1%5D%3A%20http%3A%2F%2Fwww.google.com%2F%0A%5Brunoob%5D%3A%20http%3A%2F%2Fwww.runoob.com%2F%0A***%0A%23%23%20**Markdown%20%E5%9B%BE%E7%89%87**%0A%3E%20!%5Balt%20%E5%B1%9E%E6%80%A7%E6%96%87%E6%9C%AC%5D(%E5%9B%BE%E7%89%87%E5%9C%B0%E5%9D%80)%20%20%0A%3E%20!%5Balt%20%E5%B1%9E%E6%80%A7%E6%96%87%E6%9C%AC%5D(%E5%9B%BE%E7%89%87%E5%9C%B0%E5%9D%80%20%22%E5%8F%AF%E9%80%89%E6%A0%87%E9%A2%98%22)%0A%0A!%5BRUNOOB%20%E5%9B%BE%E6%A0%87%5D(http%3A%2F%2Fstatic.runoob.com%2Fimages%2Frunoob-logo.png)%20%20%0A!%5BRUNOOB%20%E5%9B%BE%E6%A0%87%5D(http%3A%2F%2Fstatic.runoob.com%2Fimages%2Frunoob-logo.png%20%22RUNOOB%22)%0A%0A***%0A%23%23%20**Markdown%20%E8%A1%A8%E6%A0%BC**%0A1.%20Markdown%20%E5%88%B6%E4%BD%9C%E8%A1%A8%E6%A0%BC%E4%BD%BF%E7%94%A8%20%7C%20%E6%9D%A5%E5%88%86%E9%9A%94%E4%B8%8D%E5%90%8C%E7%9A%84%E5%8D%95%E5%85%83%E6%A0%BC%EF%BC%8C%E4%BD%BF%E7%94%A8%20-%20%E6%9D%A5%E5%88%86%E9%9A%94%E8%A1%A8%E5%A4%B4%E5%92%8C%E5%85%B6%E4%BB%96%E8%A1%8C%E3%80%82%0A%09%7C%20%20%E8%A1%A8%E5%A4%B4%20%20%20%7C%20%E8%A1%A8%E5%A4%B4%20%20%7C%0A%09%7C%20%20----%20%20%20%7C%20----%20%20%7C%0A%09%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%20%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%7C%0A%09%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%20%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%7C%0A%0A2.%20%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E8%AE%BE%E7%BD%AE%E8%A1%A8%E6%A0%BC%E7%9A%84%E5%AF%B9%E9%BD%90%E6%96%B9%E5%BC%8F%EF%BC%9A%0A%3E%20**-%3A**%20%20%E8%AE%BE%E7%BD%AE%E5%86%85%E5%AE%B9%E5%92%8C%E6%A0%87%E9%A2%98%E6%A0%8F%E5%B1%85%E5%8F%B3%E5%AF%B9%E9%BD%90%E3%80%82%20%20%0A%3E%20**%3A-**%20%20%E8%AE%BE%E7%BD%AE%E5%86%85%E5%AE%B9%E5%92%8C%E6%A0%87%E9%A2%98%E6%A0%8F%E5%B1%85%E5%B7%A6%E5%AF%B9%E9%BD%90%E3%80%82%20%20%0A%3E%20**%3A-%3A**%20%E8%AE%BE%E7%BD%AE%E5%86%85%E5%AE%B9%E5%92%8C%E6%A0%87%E9%A2%98%E6%A0%8F%E5%B1%85%E4%B8%AD%E5%AF%B9%E9%BD%90%E3%80%82%20%20%0A%0A%7C%20%E5%B7%A6%E5%AF%B9%E9%BD%90%20%7C%20%E5%8F%B3%E5%AF%B9%E9%BD%90%20%7C%20%E5%B1%85%E4%B8%AD%E5%AF%B9%E9%BD%90%20%7C%0A%7C%20%3A-----%20%7C%20%20----%3A%20%7C%20%3A----%3A%20%20%20%7C%0A%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%20%20%7C%0A%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%7C%20%E5%8D%95%E5%85%83%E6%A0%BC%20%20%20%7C%0A%0A***%0A%23%23%20**Markdown%20%E9%AB%98%E7%BA%A7%E6%8A%80%E5%B7%A7**%0A1.%20%E6%94%AF%E6%8C%81%E7%9A%84%20HTML%20%E5%85%83%E7%B4%A0%0A%20%20%20%E4%B8%8D%E5%9C%A8%20Markdown%20%E6%B6%B5%E7%9B%96%E8%8C%83%E5%9B%B4%E4%B9%8B%E5%86%85%E7%9A%84%E6%A0%87%E7%AD%BE%EF%BC%8C%E9%83%BD%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E5%9C%A8%E6%96%87%E6%A1%A3%E9%87%8C%E9%9D%A2%E7%94%A8%20HTML%20%E6%92%B0%E5%86%99%E3%80%82%0A%09%60%60%60%20%0A%09%E7%9B%AE%E5%89%8D%E6%94%AF%E6%8C%81%E7%9A%84%20HTML%20%E5%85%83%E7%B4%A0%E6%9C%89%EF%BC%9A%3Ckbd%3E%20%3Cb%3E%20%3Ci%3E%20%3Cem%3E%20%3Csup%3E%20%3Csub%3E%20%3Cbr%3E%E7%AD%89%20%EF%BC%8C%E5%A6%82%EF%BC%9A%0A%09%60%60%60%0A%09%E4%BD%BF%E7%94%A8%20%3Ckbd%3ECtrl%3C%2Fkbd%3E%2B%3Ckbd%3EAlt%3C%2Fkbd%3E%2B%3Ckbd%3EDel%3C%2Fkbd%3E%20%E9%87%8D%E5%90%AF%E7%94%B5%E8%84%91%0A2.%20%E8%BD%AC%E4%B9%89%0AMarkdown%20%E4%BD%BF%E7%94%A8%E4%BA%86%E5%BE%88%E5%A4%9A%E7%89%B9%E6%AE%8A%E7%AC%A6%E5%8F%B7%E6%9D%A5%E8%A1%A8%E7%A4%BA%E7%89%B9%E5%AE%9A%E7%9A%84%E6%84%8F%E4%B9%89%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E6%98%BE%E7%A4%BA%E7%89%B9%E5%AE%9A%E7%9A%84%E7%AC%A6%E5%8F%B7%E5%88%99%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E8%BD%AC%E4%B9%89%E5%AD%97%E7%AC%A6%EF%BC%8CMarkdown%20%E4%BD%BF%E7%94%A8%E5%8F%8D%E6%96%9C%E6%9D%A0%E8%BD%AC%E4%B9%89%E7%89%B9%E6%AE%8A%E5%AD%97%E7%AC%A6%EF%BC%9A%0A%0A%09%60%60%60%0A%09**%E6%96%87%E6%9C%AC%E5%8A%A0%E7%B2%97**%20%0A%09%5C*%5C*%20%E6%AD%A3%E5%B8%B8%E6%98%BE%E7%A4%BA%E6%98%9F%E5%8F%B7%20%5C*%5C*%0A%09%60%60%60%0A%0A3.%20Markdown%20%E6%94%AF%E6%8C%81%E4%BB%A5%E4%B8%8B%E8%BF%99%E4%BA%9B%E7%AC%A6%E5%8F%B7%E5%89%8D%E9%9D%A2%E5%8A%A0%E4%B8%8A%E5%8F%8D%E6%96%9C%E6%9D%A0%E6%9D%A5%E5%B8%AE%E5%8A%A9%E6%8F%92%E5%85%A5%E6%99%AE%E9%80%9A%E7%9A%84%E7%AC%A6%E5%8F%B7%EF%BC%9A%0A%09%60%60%60%0A%09%5C%20%20%20%E5%8F%8D%E6%96%9C%E7%BA%BF%0A%09%60%20%20%20%E5%8F%8D%E5%BC%95%E5%8F%B7%0A%09*%20%20%20%E6%98%9F%E5%8F%B7%0A%09_%20%20%20%E4%B8%8B%E5%88%92%E7%BA%BF%0A%09%7B%7D%20%20%E8%8A%B1%E6%8B%AC%E5%8F%B7%0A%09%5B%5D%20%20%E6%96%B9%E6%8B%AC%E5%8F%B7%0A%09()%20%20%E5%B0%8F%E6%8B%AC%E5%8F%B7%0A%09%23%20%20%20%E4%BA%95%E5%AD%97%E5%8F%B7%0A%09%2B%20%20%20%E5%8A%A0%E5%8F%B7%0A%09-%20%20%20%E5%87%8F%E5%8F%B7%0A%09.%20%20%20%E8%8B%B1%E6%96%87%E5%8F%A5%E7%82%B9%0A%09!%20%20%20%E6%84%9F%E5%8F%B9%E5%8F%B7%0A%09%0A%09%0A%09%60%60%60%0A%0A

Joplin

创建时间:2020/9/2 16:17
更新时间:2020/9/2 16:18
作者:Chris

Joplin是一个免费的开源笔记记录和待办事项应用程序,可以处理笔记本中组织的大量笔记。Evernote导出的笔记可以直接导入到Joplin中,同时也可以导入普通Markdown文件。通过WebDAV您可以直接将Joplin中的笔记同步到坚果云。

Joplin同步到坚果云

以移动端为例:
1.由于Joplin的同步需要指定文件夹,因此在连接webdav前,请先在坚果云上创建一个英文名称的根目录文件夹,如“Joplin”
2.打开Joplin的配置界面,在同步中选择WebDAV
WebDAV URL : https://dav.jianguoyun.com/dav/Joplin
(注:需要在服务器地址后面添加刚才创建的文件夹的名称)
WebDAV 用户名:您的坚果云账号邮箱
WebDAV 密码:在坚果云中生成的第三方应用密码(如何生成应用授权密码)
3.点击“检查同步配置”,提示连接成功代表您已成功将Joplin与坚果云进行关联。


font family

  1. Consolos
  2. Lucida Console
  3. Courier New

%0AJoplin%E6%98%AF%E4%B8%80%E4%B8%AA%E5%85%8D%E8%B4%B9%E7%9A%84%E5%BC%80%E6%BA%90%E7%AC%94%E8%AE%B0%E8%AE%B0%E5%BD%95%E5%92%8C%E5%BE%85%E5%8A%9E%E4%BA%8B%E9%A1%B9%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%A4%84%E7%90%86%E7%AC%94%E8%AE%B0%E6%9C%AC%E4%B8%AD%E7%BB%84%E7%BB%87%E7%9A%84%E5%A4%A7%E9%87%8F%E7%AC%94%E8%AE%B0%E3%80%82Evernote%E5%AF%BC%E5%87%BA%E7%9A%84%E7%AC%94%E8%AE%B0%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E5%AF%BC%E5%85%A5%E5%88%B0Joplin%E4%B8%AD%EF%BC%8C%E5%90%8C%E6%97%B6%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%AF%BC%E5%85%A5%E6%99%AE%E9%80%9AMarkdown%E6%96%87%E4%BB%B6%E3%80%82%E9%80%9A%E8%BF%87WebDAV%E6%82%A8%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E5%B0%86Joplin%E4%B8%AD%E7%9A%84%E7%AC%94%E8%AE%B0%E5%90%8C%E6%AD%A5%E5%88%B0%E5%9D%9A%E6%9E%9C%E4%BA%91%E3%80%82%0A%0A%23%20Joplin%E5%90%8C%E6%AD%A5%E5%88%B0%E5%9D%9A%E6%9E%9C%E4%BA%91%0A%E4%BB%A5%E7%A7%BB%E5%8A%A8%E7%AB%AF%E4%B8%BA%E4%BE%8B%EF%BC%9A%0A1.%E7%94%B1%E4%BA%8EJoplin%E7%9A%84%E5%90%8C%E6%AD%A5%E9%9C%80%E8%A6%81%E6%8C%87%E5%AE%9A%E6%96%87%E4%BB%B6%E5%A4%B9%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%9C%A8%E8%BF%9E%E6%8E%A5webdav%E5%89%8D%EF%BC%8C%E8%AF%B7%E5%85%88%E5%9C%A8%E5%9D%9A%E6%9E%9C%E4%BA%91%E4%B8%8A%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%8B%B1%E6%96%87%E5%90%8D%E7%A7%B0%E7%9A%84%E6%A0%B9%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E5%A4%B9%EF%BC%8C%E5%A6%82%E2%80%9CJoplin%E2%80%9D%0A2.%E6%89%93%E5%BC%80Joplin%E7%9A%84%E9%85%8D%E7%BD%AE%E7%95%8C%E9%9D%A2%EF%BC%8C%E5%9C%A8%E5%90%8C%E6%AD%A5%E4%B8%AD%E9%80%89%E6%8B%A9WebDAV%0AWebDAV%20URL%20%3A%20https%3A%2F%2Fdav.jianguoyun.com%2Fdav%2FJoplin%0A%EF%BC%88%E6%B3%A8%EF%BC%9A%E9%9C%80%E8%A6%81%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%9C%B0%E5%9D%80%E5%90%8E%E9%9D%A2%E6%B7%BB%E5%8A%A0%E5%88%9A%E6%89%8D%E5%88%9B%E5%BB%BA%E7%9A%84%E6%96%87%E4%BB%B6%E5%A4%B9%E7%9A%84%E5%90%8D%E7%A7%B0%EF%BC%89%0AWebDAV%20%E7%94%A8%E6%88%B7%E5%90%8D%EF%BC%9A%E6%82%A8%E7%9A%84%E5%9D%9A%E6%9E%9C%E4%BA%91%E8%B4%A6%E5%8F%B7%E9%82%AE%E7%AE%B1%0AWebDAV%20%E5%AF%86%E7%A0%81%EF%BC%9A%E5%9C%A8%E5%9D%9A%E6%9E%9C%E4%BA%91%E4%B8%AD%E7%94%9F%E6%88%90%E7%9A%84%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%94%E7%94%A8%E5%AF%86%E7%A0%81%EF%BC%88%E5%A6%82%E4%BD%95%E7%94%9F%E6%88%90%E5%BA%94%E7%94%A8%E6%8E%88%E6%9D%83%E5%AF%86%E7%A0%81%EF%BC%89%0A3.%E7%82%B9%E5%87%BB%E2%80%9C%E6%A3%80%E6%9F%A5%E5%90%8C%E6%AD%A5%E9%85%8D%E7%BD%AE%E2%80%9D%EF%BC%8C%E6%8F%90%E7%A4%BA%E8%BF%9E%E6%8E%A5%E6%88%90%E5%8A%9F%E4%BB%A3%E8%A1%A8%E6%82%A8%E5%B7%B2%E6%88%90%E5%8A%9F%E5%B0%86Joplin%E4%B8%8E%E5%9D%9A%E6%9E%9C%E4%BA%91%E8%BF%9B%E8%A1%8C%E5%85%B3%E8%81%94%E3%80%82%0A***%0A%23%23%20**font%20family**%0A1.%20Consolos%20%20%0A2.%20Lucida%20Console%20%20%0A3.%20Courier%20New%20%20%0A%0A!%5B0bc45fd161c48af3cc46bf053531d8ca.png%5D(en-resource%3A%2F%2Fdatabase%2F1311%3A0)%0A%0A%0A

spring es

创建时间:2020/9/2 15:44
更新时间:2020/9/2 15:44
作者:Chris

https://www.cnblogs.com/lifengdi/archive/2019/09/20/11554923.html

https%3A%2F%2Fwww.cnblogs.com%2Flifengdi%2Farchive%2F2019%2F09%2F20%2F11554923.html

fluent_python

创建时间:2020/9/2 15:42
更新时间:2020/9/2 15:43
作者:Chris

2.2.2 列表推导同 filter 和 map 的比较
symbols = '$¢£¥€¤'
codes = [ord(symbol) for symbol in symbols if ord(symbol) > 127]
print(codes)

codes = list(filter(lambda c: c > 127, map(ord, symbols)))
print(codes)

不管是哪种数据结构,字符串、列表、字节序列、数组、XML 元素,抑或是数据库查询结果,它们都共用一套丰富的操作:迭代、切片、排序,还有拼接。

列表推导<kbd>(list comprehension)</kbd> 简称为 listcomps,<kbd>生成式表达器</kbd> (generator expression)则称为 genexps

symbols = '$¢£¥€¤'
codes = [ord(symbol) for symbol in symbols]
print(codes)
36, 162, 163, 165, 8364, 164]
2.2.3 笛卡儿积

列表推导可以生成两个或以上的可迭代类型的笛卡儿积。 笛卡儿积是一个列表,列表里的元素是由输入的可迭> 代类型的元素对构成的元组,因此笛卡儿积列表的长度等于输入变量的长度的乘积

self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]

2.2.4 生成器表达式

列表推导的作用只有一个:生成列表。如果想生成其他类型的序列,生成器表达式就派上了用场。
生成器表达式的语法跟列表推导差不多,只不过把方括号换成圆括号而已
如果生成器表达式是一个函数调用过程中的唯一参数,那么不需要额外再用括号把它围起来。

<kbd>生成器表达式逐个产出元素,从来不会一次性产出一个含有 6 个 T 恤样式的列表</kbd>

colors = ['black', 'white']
sizes = ['S', 'M', 'L']
for tshirt in ((c, s) for c in colors for s in sizes):   
	print(tshirt)
2.3.1 元组和记录

元组其实是对数据的记录:元组中的每个元素都存放了记录中一个字段的数据,外加这个字段的位置。 正是这个位置信息给数据赋予了意义。

2.3.2 元组拆包

元组拆包可以应用到任何可迭代对象上,唯一的硬性要求是,被可迭代对象中的元素数量必须要跟接受这些元素的元组的空档数一致。除非我们用 * 来表示忽略多余的元素.

for country, _ in traveler_ids: print(country)

最好辨认的元组拆包形式就是平行赋值,也就是说把一个可迭代对象里的元素,一并赋值
到由对应的变量组成的元组中

lax_coordinates = (33.9425, -118.408056)
latitude, longitude = lax_coordinates  # 元组拆包

函数用 *args 来获取不确定数量的参数算是一种经典写法了
a, b, *rest = range(5)
(0, 1, [2, 3, 4])
在平行赋值中, * 前缀只能用在一个变量名前面,但是这个变量可以出现在赋值表达式的任意位置

a, *body, c, d = range(5)
a, body, c, d
(0, [1, 2], 3, 4)
2.3.3 嵌套元组拆包

接受表达式的元组可以是嵌套式的,例如 (a, b, (c, d)) 。只要这个接受元组的嵌套结构符合表达式本身的嵌套结构,Python 就可以作出正确的对应

2.3.4 具名元组

collections.namedtuple 是一个工厂函数,它可以用来构建一个带字段名的元组和一个有名字的类——这个带名字的类对调试程序有很大帮助。

Card = collections.namedtuple('Card', ['rank', 'suit'])

创建一个具名元组需要两个参数,一个是类名,另一个是类的各个字段的名字。后者可以是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串。

City = namedtuple('City', 'name country population coordinates')
tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))

print(tokyo.country)
print(tokyo.population)
print(tokyo[0])

_fields 属性是一个包含这个类所有字段名称的元组。
_make() 通过接受一个可迭代对象来生成这个类的一个实例,它的作用跟City(*delhi_data) 是一样的。
_asdict() 把具名元组以 collections.OrderedDict 的形式返回,我们可以利用它来把元组里的信息友好地呈现出来

print(City._fields)
LatLong = namedtuple('LatLong', 'lat long')
delhi_data = ('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889))
delhi = City._make(delhi_data)

print(delhi._asdict())
for key, value in delhi._asdict().items():
    print(key + ':', value)
2.3.5 作为不可变列表的元组

2.4 切片

当只有最后一个位置信息时,我们也可以快速看出切片和区间里有几个元素range(3)和 my_list[:3] 都返回 3 个元素

mylist = [1, 2, 3, 4, 5, 'a', 'b', 'c']
print(mylist[:2])
print(mylist[2:])
[1, 2]
[3, 4, 5, 'a', 'b', 'c']
2.4.2 对对象进行切片

可以用 s[a: b : c] 的形式对 s 在 a 和 b 之间以 c 为间隔取值。
c 的值还可以为负,负值意味着反向取值。

s = 'bicycle'
print(s[::3])
print(s[::-1])
print(s[::-2])
bye
elcycib
eccb

deck[12::13] 的形式在未洗过的牌里把每种花色的 A 拿出来

2.4.4 给切片赋值

如果赋值的对象是一个切片,那么赋值语句的右侧必须是个可迭代对象。即便只有单独一个值,
也要把它转换成可迭代的序列

l = list(range(10))
l[2:5] = [20, 30]
print(l)
del l[5:7]
print(l)
l[3::2] = [11, 22]
print(l)
# l[2:5] = 100
l[2:5] = [100]
print(l)

[0, 1, 20, 30, 5, 6, 7, 8, 9]
[0, 1, 20, 30, 5, 8, 9]
[0, 1, 20, 11, 5, 22, 9]
[0, 1, 100, 22, 9]
2.5 对序列使用 + 和 *

+ 和 * 都遵循这个规律,不修改原有的操作对象,而是构建一个全新的序列

l = [1, 2, 3]
l * 5
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
5 * 'abcd'
'abcdabcdabcdabcdabcd'

建立由列表组成的列表

list_temp = [['_'] * 3 for i in range(3)]
print(list_temp)

list_temp[1][2] = "X"
print(list_temp)

[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
[['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]
2.6 序列的增量赋值

+= 和 *= 的表现取决于它们的第一个操作对象, += 背后的特殊方法是 __iadd__ (用于“就地加法”) *= 背后的特殊方法是 __imul__ (用于“就地加法”)

  1. 如果a 实 现 了 __iadd__ 方 法, 就 会 调 用 这 个 方 法。 同 时 对 可 变 序 列( 例 如 list 、bytearray 和 array.array )来说,a 会就地改动
  2. 如果 a 没有实现 __iadd__ 的话, a += b 这个表达式的效果就变得跟 a = a + b 一样了:首先计算 a + b ,得到一个新的对象,然后赋值给 a
lst = list(range(3))
id_list = id(lst)
print("id_list", id_list)
lst += ["A", "B"]
print(lst)
id_list = id(lst)
print("id_list:", id_list)
tpl = tuple(range(3))
id_tuple = id(tpl)
print("id_tuple:", id_tuple)
tpl += ("A", "B")
print(tpl)
id_tuple = id(tpl)
print("id_tuple:", id_tuple)


id_list 1798125102280
[0, 1, 2, 'A', 'B']
id_list: 1798125102280
id_tuple: 1798125055864
(0, 1, 2, 'A', 'B')
id_tuple: 1798121809352

对不可变序列进行重复拼接操作的话,效率会很低,因为每次都有一个新对象,而解释器需要把原来对象中的元素先复制到新的对象里,然后再追加新的元素

Python Tutor

是一个对 Python 运行原理进行可视化分析的工具

2.7  list.sort 方法和内置函数 sorted

list.sort 方法会就地排序列表,也就是说不会把原列表复制一份。这也是这个方法的返回值是 None 的原因,提醒你本方法不会新建一个列表

如果一个函数或者方法对对象进行的是就地改动,那它就应该返回None ,好让调用者知道传入的参数发生了变动,而且并未产生新的对象

sorted 它会新建一个列表作为返回值。这个方法可以接受任何形式的可迭代对象作为参数,甚至包括不可变序列或生成器。而不管sorted 接受的是怎样的参数,它最后都会返回一个列表。

不管是 list.sort 方法还是 sorted 函数,都有两个可选的关键字参数。

reverse 默认为False 升序排列

fruits = ['grape', 'raspberry', 'apple', 'banana']
print(sorted(fruits))
print(sorted(fruits, reverse=True))
print(sorted(fruits, key=len, reverse=True))

['apple', 'banana', 'grape', 'raspberry']
['raspberry', 'grape', 'banana', 'apple']
['raspberry', 'banana', 'grape', 'apple']
2.9 当列表不是首选时
  1. 要存放1000 万个浮点数的话,数组( array )的效率要高得多,因为数组在背后存的并不是 float对象,而是数字的机器翻译,也就是字节表述
  2. 如果需要频繁对序列做先进先出的操作, deque (双端队列)的速度应该会更快
  3. 如果在你的代码里,包含操作(比如检查一个元素是否出现在一个集合中)的频率很高,用 set (集合)会更合适。 set 专为检查元素是否存在做过优化。但是它并不是序列,因为 set 是无序的
2.9.1 数组
  1. 如果我们需要一个只包含数字的列表,那么 array.array 比 list 更高效。

  2. 数组支持所有跟可变序列有关的操作,包括 .pop 、 .insert 和 .extend 。

  3. 数组还提供从文件读取和存入文件的更快的方法,如 .frombytes 和 .tofile 。

from array import array
from random import random

float_array_1 = array('d', (random() for x in (range(10 ** 7))))
first = float_array_1[0]
last = float_array_1[-1]
print(first, last)

fb = open("./float.bin", "wb")
float_array_1.tofile(fb)
fb.close()

float_array_2 = array('d')
fb = open("./float.bin", "rb")

# 把 1000 万个浮点数从二进制文件里读取出来
float_array_2.fromfile(fb, 10 ** 7)
fb.close()
first = float_array_2[0]
last = float_array_2[-1]

print(first, last)

# 检查两个数组的内容是不是完全一样
if float_array_1 == float_array_2:
    print(True)
else:
    print(False)
2.9.2 内存视图
  1. memoryview 是一个内置类,它能让用户在不复制内容的情况下操作同一个数组的不同切片.
  2. memoryview.cast 的概念跟数组模块类似,能用不同的方式读写同一块内存数据,而且内容
    字节不会随意移动
  3. memoryview.cast 会把同一块内存里的内容打包成一个全新的 memoryview 对象给你
2.9.4 双向队列和其他形式的队列
%0A%0A%23%23%23%23%23%202.2.2%20%E5%88%97%E8%A1%A8%E6%8E%A8%E5%AF%BC%E5%90%8C%20filter%20%E5%92%8C%20map%20%E7%9A%84%E6%AF%94%E8%BE%83%0A%0A%60%60%60python%0Asymbols%20%3D%20'%24%C2%A2%C2%A3%C2%A5%E2%82%AC%C2%A4'%0Acodes%20%3D%20%5Bord(symbol)%20for%20symbol%20in%20symbols%20if%20ord(symbol)%20%3E%20127%5D%0Aprint(codes)%0A%0Acodes%20%3D%20list(filter(lambda%20c%3A%20c%20%3E%20127%2C%20map(ord%2C%20symbols)))%0Aprint(codes)%0A%60%60%60%0A%0A%0A%0A%E4%B8%8D%E7%AE%A1%E6%98%AF%E5%93%AA%E7%A7%8D%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%EF%BC%8C%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%81%E5%88%97%E8%A1%A8%E3%80%81%E5%AD%97%E8%8A%82%E5%BA%8F%E5%88%97%E3%80%81%E6%95%B0%E7%BB%84%E3%80%81XML%20%E5%85%83%E7%B4%A0%EF%BC%8C%E6%8A%91%E6%88%96%E6%98%AF%E6%95%B0%E6%8D%AE%E5%BA%93%E6%9F%A5%E8%AF%A2%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%AE%83%E4%BB%AC%E9%83%BD%E5%85%B1%E7%94%A8%E4%B8%80%E5%A5%97%E4%B8%B0%E5%AF%8C%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%9A%E8%BF%AD%E4%BB%A3%E3%80%81%E5%88%87%E7%89%87%E3%80%81%E6%8E%92%E5%BA%8F%EF%BC%8C%E8%BF%98%E6%9C%89%E6%8B%BC%E6%8E%A5%E3%80%82%0A%0A%E5%88%97%E8%A1%A8%E6%8E%A8%E5%AF%BC%3Ckbd%3E%EF%BC%88list%20comprehension%EF%BC%89%3C%2Fkbd%3E%20%E7%AE%80%E7%A7%B0%E4%B8%BA%20listcomps%EF%BC%8C%3Ckbd%3E%E7%94%9F%E6%88%90%E5%BC%8F%E8%A1%A8%E8%BE%BE%E5%99%A8%3C%2Fkbd%3E%20%20%EF%BC%88generator%20expression%EF%BC%89%E5%88%99%E7%A7%B0%E4%B8%BA%20genexps%0A%0A%60%60%60%0Asymbols%20%3D%20'%24%C2%A2%C2%A3%C2%A5%E2%82%AC%C2%A4'%0Acodes%20%3D%20%5Bord(symbol)%20for%20symbol%20in%20symbols%5D%0Aprint(codes)%0A36%2C%20162%2C%20163%2C%20165%2C%208364%2C%20164%5D%0A%60%60%60%0A%0A%23%23%23%23%23%202.2.3%20%E7%AC%9B%E5%8D%A1%E5%84%BF%E7%A7%AF%0A%0A%3E%20%E5%88%97%E8%A1%A8%E6%8E%A8%E5%AF%BC%E5%8F%AF%E4%BB%A5%E7%94%9F%E6%88%90%E4%B8%A4%E4%B8%AA%E6%88%96%E4%BB%A5%E4%B8%8A%E7%9A%84%E5%8F%AF%E8%BF%AD%E4%BB%A3%E7%B1%BB%E5%9E%8B%E7%9A%84%E7%AC%9B%E5%8D%A1%E5%84%BF%E7%A7%AF%E3%80%82%20%20%E7%AC%9B%E5%8D%A1%E5%84%BF%E7%A7%AF%E6%98%AF%E4%B8%80%E4%B8%AA%E5%88%97%E8%A1%A8%EF%BC%8C%E5%88%97%E8%A1%A8%E9%87%8C%E7%9A%84%E5%85%83%E7%B4%A0%E6%98%AF%E7%94%B1%E8%BE%93%E5%85%A5%E7%9A%84%E5%8F%AF%E8%BF%AD%3E%20%E4%BB%A3%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%85%83%E7%B4%A0%E5%AF%B9%E6%9E%84%E6%88%90%E7%9A%84%E5%85%83%E7%BB%84%EF%BC%8C%E5%9B%A0%E6%AD%A4%E7%AC%9B%E5%8D%A1%E5%84%BF%E7%A7%AF%E5%88%97%E8%A1%A8%E7%9A%84%E9%95%BF%E5%BA%A6%E7%AD%89%E4%BA%8E%E8%BE%93%E5%85%A5%E5%8F%98%E9%87%8F%E7%9A%84%E9%95%BF%E5%BA%A6%E7%9A%84%E4%B9%98%E7%A7%AF%20%20%0A%0A%60self._cards%20%3D%20%5BCard(rank%2C%20suit)%20for%20suit%20in%20self.suits%20for%20rank%20in%20self.ranks%5D%60%0A%0A%23%23%23%23%23%202.2.4%20%E7%94%9F%E6%88%90%E5%99%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%0A%3E%20%E5%88%97%E8%A1%A8%E6%8E%A8%E5%AF%BC%E7%9A%84%E4%BD%9C%E7%94%A8%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%EF%BC%9A%E7%94%9F%E6%88%90%E5%88%97%E8%A1%A8%E3%80%82%E5%A6%82%E6%9E%9C%E6%83%B3%E7%94%9F%E6%88%90%E5%85%B6%E4%BB%96%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%BA%8F%E5%88%97%EF%BC%8C%E7%94%9F%E6%88%90%E5%99%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%B0%B1%E6%B4%BE%E4%B8%8A%E4%BA%86%E7%94%A8%E5%9C%BA%E3%80%82%0A%3E%20%E7%94%9F%E6%88%90%E5%99%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E8%AF%AD%E6%B3%95%E8%B7%9F%E5%88%97%E8%A1%A8%E6%8E%A8%E5%AF%BC%E5%B7%AE%E4%B8%8D%E5%A4%9A%EF%BC%8C%E5%8F%AA%E4%B8%8D%E8%BF%87%E6%8A%8A%E6%96%B9%E6%8B%AC%E5%8F%B7%E6%8D%A2%E6%88%90%E5%9C%86%E6%8B%AC%E5%8F%B7%E8%80%8C%E5%B7%B2%0A%3E%20%E5%A6%82%E6%9E%9C%E7%94%9F%E6%88%90%E5%99%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%98%AF%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%94%AF%E4%B8%80%E5%8F%82%E6%95%B0%EF%BC%8C%E9%82%A3%E4%B9%88%E4%B8%8D%E9%9C%80%E8%A6%81%E9%A2%9D%E5%A4%96%E5%86%8D%E7%94%A8%E6%8B%AC%E5%8F%B7%E6%8A%8A%E5%AE%83%E5%9B%B4%E8%B5%B7%E6%9D%A5%E3%80%82%20%20%0A%0A%20%3Ckbd%3E%E7%94%9F%E6%88%90%E5%99%A8%E8%A1%A8%E8%BE%BE%E5%BC%8F%E9%80%90%E4%B8%AA%E4%BA%A7%E5%87%BA%E5%85%83%E7%B4%A0%EF%BC%8C%E4%BB%8E%E6%9D%A5%E4%B8%8D%E4%BC%9A%E4%B8%80%E6%AC%A1%E6%80%A7%E4%BA%A7%E5%87%BA%E4%B8%80%E4%B8%AA%E5%90%AB%E6%9C%89%206%20%E4%B8%AA%20T%20%E6%81%A4%E6%A0%B7%E5%BC%8F%E7%9A%84%E5%88%97%E8%A1%A8%3C%2Fkbd%3E%0A%0A%60%60%60%20%0Acolors%20%3D%20%5B'black'%2C%20'white'%5D%0Asizes%20%3D%20%5B'S'%2C%20'M'%2C%20'L'%5D%0Afor%20tshirt%20in%20((c%2C%20s)%20for%20c%20in%20colors%20for%20s%20in%20sizes)%3A%20%20%20%0A%09print(tshirt)%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%202.3.1%20%E5%85%83%E7%BB%84%E5%92%8C%E8%AE%B0%E5%BD%95%0A%0A%3E%20%E5%85%83%E7%BB%84%E5%85%B6%E5%AE%9E%E6%98%AF%E5%AF%B9%E6%95%B0%E6%8D%AE%E7%9A%84%E8%AE%B0%E5%BD%95%EF%BC%9A%E5%85%83%E7%BB%84%E4%B8%AD%E7%9A%84%E6%AF%8F%E4%B8%AA%E5%85%83%E7%B4%A0%E9%83%BD%E5%AD%98%E6%94%BE%E4%BA%86%E8%AE%B0%E5%BD%95%E4%B8%AD%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A4%96%E5%8A%A0%E8%BF%99%E4%B8%AA%E5%AD%97%E6%AE%B5%E7%9A%84%E4%BD%8D%E7%BD%AE%E3%80%82%20%E6%AD%A3%E6%98%AF%E8%BF%99%E4%B8%AA%E4%BD%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E7%BB%99%E6%95%B0%E6%8D%AE%E8%B5%8B%E4%BA%88%E4%BA%86%E6%84%8F%E4%B9%89%E3%80%82%0A%0A%23%23%23%23%23%202.3.2%20%E5%85%83%E7%BB%84%E6%8B%86%E5%8C%85%0A%0A%3E%20%E5%85%83%E7%BB%84%E6%8B%86%E5%8C%85%E5%8F%AF%E4%BB%A5%E5%BA%94%E7%94%A8%E5%88%B0%E4%BB%BB%E4%BD%95%E5%8F%AF%E8%BF%AD%E4%BB%A3%E5%AF%B9%E8%B1%A1%E4%B8%8A%EF%BC%8C%E5%94%AF%E4%B8%80%E7%9A%84%E7%A1%AC%E6%80%A7%E8%A6%81%E6%B1%82%E6%98%AF%EF%BC%8C%E8%A2%AB%E5%8F%AF%E8%BF%AD%E4%BB%A3%E5%AF%B9%E8%B1%A1%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%E6%95%B0%E9%87%8F%E5%BF%85%E9%A1%BB%E8%A6%81%E8%B7%9F%E6%8E%A5%E5%8F%97%E8%BF%99%E4%BA%9B%E5%85%83%E7%B4%A0%E7%9A%84%E5%85%83%E7%BB%84%E7%9A%84%E7%A9%BA%E6%A1%A3%E6%95%B0%E4%B8%80%E8%87%B4%E3%80%82%E9%99%A4%E9%9D%9E%E6%88%91%E4%BB%AC%E7%94%A8%20*%20%E6%9D%A5%E8%A1%A8%E7%A4%BA%E5%BF%BD%E7%95%A5%E5%A4%9A%E4%BD%99%E7%9A%84%E5%85%83%E7%B4%A0.%20%20%0A%0A%60for%20country%2C%20_%20in%20traveler_ids%3A%20%20%20%20print(country)%60%0A%0A%3E%20%E6%9C%80%E5%A5%BD%E8%BE%A8%E8%AE%A4%E7%9A%84%E5%85%83%E7%BB%84%E6%8B%86%E5%8C%85%E5%BD%A2%E5%BC%8F%E5%B0%B1%E6%98%AF%E5%B9%B3%E8%A1%8C%E8%B5%8B%E5%80%BC%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%E6%8A%8A%E4%B8%80%E4%B8%AA%E5%8F%AF%E8%BF%AD%E4%BB%A3%E5%AF%B9%E8%B1%A1%E9%87%8C%E7%9A%84%E5%85%83%E7%B4%A0%EF%BC%8C%E4%B8%80%E5%B9%B6%E8%B5%8B%E5%80%BC%0A%3E%20%E5%88%B0%E7%94%B1%E5%AF%B9%E5%BA%94%E7%9A%84%E5%8F%98%E9%87%8F%E7%BB%84%E6%88%90%E7%9A%84%E5%85%83%E7%BB%84%E4%B8%AD%0A%0A%60%60%60%0Alax_coordinates%20%3D%20(33.9425%2C%20-118.408056)%0Alatitude%2C%20longitude%20%3D%20lax_coordinates%20%20%23%20%E5%85%83%E7%BB%84%E6%8B%86%E5%8C%85%0A%60%60%60%0A%0A%3E%20%E5%87%BD%E6%95%B0%E7%94%A8%20*args%20%E6%9D%A5%E8%8E%B7%E5%8F%96%E4%B8%8D%E7%A1%AE%E5%AE%9A%E6%95%B0%E9%87%8F%E7%9A%84%E5%8F%82%E6%95%B0%E7%AE%97%E6%98%AF%E4%B8%80%E7%A7%8D%E7%BB%8F%E5%85%B8%E5%86%99%E6%B3%95%E4%BA%86%0A%3E%20a%2C%20b%2C%20*rest%20%3D%20range(5)%0A%3E%20(0%2C%201%2C%20%5B2%2C%203%2C%204%5D)%0A%3E%20%E5%9C%A8%E5%B9%B3%E8%A1%8C%E8%B5%8B%E5%80%BC%E4%B8%AD%EF%BC%8C%20*%20%E5%89%8D%E7%BC%80%E5%8F%AA%E8%83%BD%E7%94%A8%E5%9C%A8%E4%B8%80%E4%B8%AA%E5%8F%98%E9%87%8F%E5%90%8D%E5%89%8D%E9%9D%A2%EF%BC%8C%E4%BD%86%E6%98%AF%E8%BF%99%E4%B8%AA%E5%8F%98%E9%87%8F%E5%8F%AF%E4%BB%A5%E5%87%BA%E7%8E%B0%E5%9C%A8%E8%B5%8B%E5%80%BC%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E4%BB%BB%E6%84%8F%E4%BD%8D%E7%BD%AE%0A%0A%60%60%60%0Aa%2C%20*body%2C%20c%2C%20d%20%3D%20range(5)%0Aa%2C%20body%2C%20c%2C%20d%0A(0%2C%20%5B1%2C%202%5D%2C%203%2C%204)%0A%60%60%60%0A%0A%23%23%23%23%23%202.3.3%20%E5%B5%8C%E5%A5%97%E5%85%83%E7%BB%84%E6%8B%86%E5%8C%85%0A%0A%3E%20%E6%8E%A5%E5%8F%97%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E5%85%83%E7%BB%84%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%B5%8C%E5%A5%97%E5%BC%8F%E7%9A%84%EF%BC%8C%E4%BE%8B%E5%A6%82%20(a%2C%20b%2C%20(c%2C%20d))%20%E3%80%82%E5%8F%AA%E8%A6%81%E8%BF%99%E4%B8%AA%E6%8E%A5%E5%8F%97%E5%85%83%E7%BB%84%E7%9A%84%E5%B5%8C%E5%A5%97%E7%BB%93%E6%9E%84%E7%AC%A6%E5%90%88%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%9C%AC%E8%BA%AB%E7%9A%84%E5%B5%8C%E5%A5%97%E7%BB%93%E6%9E%84%EF%BC%8CPython%20%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BD%9C%E5%87%BA%E6%AD%A3%E7%A1%AE%E7%9A%84%E5%AF%B9%E5%BA%94%0A%0A%23%23%23%23%23%202.3.4%20%E5%85%B7%E5%90%8D%E5%85%83%E7%BB%84%0A%3E%20collections.namedtuple%20%E6%98%AF%E4%B8%80%E4%B8%AA%E5%B7%A5%E5%8E%82%E5%87%BD%E6%95%B0%EF%BC%8C%E5%AE%83%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%B8%A6%E5%AD%97%E6%AE%B5%E5%90%8D%E7%9A%84%E5%85%83%E7%BB%84%E5%92%8C%E4%B8%80%E4%B8%AA%E6%9C%89%E5%90%8D%E5%AD%97%E7%9A%84%E7%B1%BB%E2%80%94%E2%80%94%E8%BF%99%E4%B8%AA%E5%B8%A6%E5%90%8D%E5%AD%97%E7%9A%84%E7%B1%BB%E5%AF%B9%E8%B0%83%E8%AF%95%E7%A8%8B%E5%BA%8F%E6%9C%89%E5%BE%88%E5%A4%A7%E5%B8%AE%E5%8A%A9%E3%80%82%0A%0A%60%60%60python%0ACard%20%3D%20collections.namedtuple('Card'%2C%20%5B'rank'%2C%20'suit'%5D)%0A%60%60%60%0A%0A%3E%20%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%85%B7%E5%90%8D%E5%85%83%E7%BB%84%E9%9C%80%E8%A6%81%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%98%AF%E7%B1%BB%E5%90%8D%EF%BC%8C%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%98%AF%E7%B1%BB%E7%9A%84%E5%90%84%E4%B8%AA%E5%AD%97%E6%AE%B5%E7%9A%84%E5%90%8D%E5%AD%97%E3%80%82%E5%90%8E%E8%80%85%E5%8F%AF%E4%BB%A5%E6%98%AF%E7%94%B1%E6%95%B0%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%BB%84%E6%88%90%E7%9A%84%E5%8F%AF%E8%BF%AD%E4%BB%A3%E5%AF%B9%E8%B1%A1%EF%BC%8C%E6%88%96%E8%80%85%E6%98%AF%E7%94%B1%E7%A9%BA%E6%A0%BC%E5%88%86%E9%9A%94%E5%BC%80%E7%9A%84%E5%AD%97%E6%AE%B5%E5%90%8D%E7%BB%84%E6%88%90%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%82%0A%0A%60%60%60python%0ACity%20%3D%20namedtuple('City'%2C%20'name%20country%20population%20coordinates')%0Atokyo%20%3D%20City('Tokyo'%2C%20'JP'%2C%2036.933%2C%20(35.689722%2C%20139.691667))%0A%0Aprint(tokyo.country)%0Aprint(tokyo.population)%0Aprint(tokyo%5B0%5D)%0A%0A%60%60%60%0A%0A%0A%0A%3E%20_fields%20%E5%B1%9E%E6%80%A7%E6%98%AF%E4%B8%80%E4%B8%AA%E5%8C%85%E5%90%AB%E8%BF%99%E4%B8%AA%E7%B1%BB%E6%89%80%E6%9C%89%E5%AD%97%E6%AE%B5%E5%90%8D%E7%A7%B0%E7%9A%84%E5%85%83%E7%BB%84%E3%80%82%0A%3E%20_make()%20%E9%80%9A%E8%BF%87%E6%8E%A5%E5%8F%97%E4%B8%80%E4%B8%AA%E5%8F%AF%E8%BF%AD%E4%BB%A3%E5%AF%B9%E8%B1%A1%E6%9D%A5%E7%94%9F%E6%88%90%E8%BF%99%E4%B8%AA%E7%B1%BB%E7%9A%84%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E5%AE%83%E7%9A%84%E4%BD%9C%E7%94%A8%E8%B7%9FCity(*delhi_data)%20%E6%98%AF%E4%B8%80%E6%A0%B7%E7%9A%84%E3%80%82%0A%3E%20_asdict()%20%E6%8A%8A%E5%85%B7%E5%90%8D%E5%85%83%E7%BB%84%E4%BB%A5%20collections.OrderedDict%20%E7%9A%84%E5%BD%A2%E5%BC%8F%E8%BF%94%E5%9B%9E%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E5%88%A9%E7%94%A8%E5%AE%83%E6%9D%A5%E6%8A%8A%E5%85%83%E7%BB%84%E9%87%8C%E7%9A%84%E4%BF%A1%E6%81%AF%E5%8F%8B%E5%A5%BD%E5%9C%B0%E5%91%88%E7%8E%B0%E5%87%BA%E6%9D%A5%0A%0A%60%60%60python%0Aprint(City._fields)%0ALatLong%20%3D%20namedtuple('LatLong'%2C%20'lat%20long')%0Adelhi_data%20%3D%20('Delhi%20NCR'%2C%20'IN'%2C%2021.935%2C%20LatLong(28.613889%2C%2077.208889))%0Adelhi%20%3D%20City._make(delhi_data)%0A%0Aprint(delhi._asdict())%0Afor%20key%2C%20value%20in%20delhi._asdict().items()%3A%0A%20%20%20%20print(key%20%2B%20'%3A'%2C%20value)%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%202.3.5%E3%80%80%E4%BD%9C%E4%B8%BA%E4%B8%8D%E5%8F%AF%E5%8F%98%E5%88%97%E8%A1%A8%E7%9A%84%E5%85%83%E7%BB%84%0A%0A!%5B5a248c5564e38f27bb4af556615cb85f.png%5D(en-resource%3A%2F%2Fdatabase%2F1219%3A0)%0A%0A%0A%23%23%23%23%23%202.4%E3%80%80%E5%88%87%E7%89%87%0A%0A%E5%BD%93%E5%8F%AA%E6%9C%89%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AA%E4%BD%8D%E7%BD%AE%E4%BF%A1%E6%81%AF%E6%97%B6%EF%BC%8C%E6%88%91%E4%BB%AC%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%BF%AB%E9%80%9F%E7%9C%8B%E5%87%BA%E5%88%87%E7%89%87%E5%92%8C%E5%8C%BA%E9%97%B4%E9%87%8C%E6%9C%89%E5%87%A0%E4%B8%AA%E5%85%83%E7%B4%A0range(3)%E5%92%8C%20my_list%5B%3A3%5D%20%E9%83%BD%E8%BF%94%E5%9B%9E%203%20%E4%B8%AA%E5%85%83%E7%B4%A0%0A%0A%60%60%60python%0Amylist%20%3D%20%5B1%2C%202%2C%203%2C%204%2C%205%2C%20'a'%2C%20'b'%2C%20'c'%5D%0Aprint(mylist%5B%3A2%5D)%0Aprint(mylist%5B2%3A%5D)%0A%5B1%2C%202%5D%0A%5B3%2C%204%2C%205%2C%20'a'%2C%20'b'%2C%20'c'%5D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%202.4.2%E3%80%80%E5%AF%B9%E5%AF%B9%E8%B1%A1%E8%BF%9B%E8%A1%8C%E5%88%87%E7%89%87%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%94%A8%20s%5Ba%3A%20b%20%3A%20c%5D%20%E7%9A%84%E5%BD%A2%E5%BC%8F%E5%AF%B9%20s%20%E5%9C%A8%20a%20%E5%92%8C%20b%20%E4%B9%8B%E9%97%B4%E4%BB%A5%20c%20%E4%B8%BA%E9%97%B4%E9%9A%94%E5%8F%96%E5%80%BC%E3%80%82%20%0A%3E%20c%20%E7%9A%84%E5%80%BC%E8%BF%98%E5%8F%AF%E4%BB%A5%E4%B8%BA%E8%B4%9F%EF%BC%8C%E8%B4%9F%E5%80%BC%E6%84%8F%E5%91%B3%E7%9D%80%E5%8F%8D%E5%90%91%E5%8F%96%E5%80%BC%E3%80%82%0A%0A%60%60%60%0As%20%3D%20'bicycle'%0Aprint(s%5B%3A%3A3%5D)%0Aprint(s%5B%3A%3A-1%5D)%0Aprint(s%5B%3A%3A-2%5D)%0Abye%0Aelcycib%0Aeccb%0A%60%60%60%0A%0A%3E%20deck%5B12%3A%3A13%5D%20%E7%9A%84%E5%BD%A2%E5%BC%8F%E5%9C%A8%E6%9C%AA%E6%B4%97%E8%BF%87%E7%9A%84%E7%89%8C%E9%87%8C%E6%8A%8A%E6%AF%8F%E7%A7%8D%E8%8A%B1%E8%89%B2%E7%9A%84%20A%20%E6%8B%BF%E5%87%BA%E6%9D%A5%0A%0A%0A%0A%23%23%23%23%23%202.4.4%E3%80%80%E7%BB%99%E5%88%87%E7%89%87%E8%B5%8B%E5%80%BC%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E8%B5%8B%E5%80%BC%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%98%AF%E4%B8%80%E4%B8%AA%E5%88%87%E7%89%87%EF%BC%8C%E9%82%A3%E4%B9%88%E8%B5%8B%E5%80%BC%E8%AF%AD%E5%8F%A5%E7%9A%84%E5%8F%B3%E4%BE%A7%E5%BF%85%E9%A1%BB%E6%98%AF%E4%B8%AA%E5%8F%AF%E8%BF%AD%E4%BB%A3%E5%AF%B9%E8%B1%A1%E3%80%82%E5%8D%B3%E4%BE%BF%E5%8F%AA%E6%9C%89%E5%8D%95%E7%8B%AC%E4%B8%80%E4%B8%AA%E5%80%BC%EF%BC%8C%0A%3E%20%E4%B9%9F%E8%A6%81%E6%8A%8A%E5%AE%83%E8%BD%AC%E6%8D%A2%E6%88%90%E5%8F%AF%E8%BF%AD%E4%BB%A3%E7%9A%84%E5%BA%8F%E5%88%97%0A%0A%0A%0A%60%60%60python%0Al%20%3D%20list(range(10))%0Al%5B2%3A5%5D%20%3D%20%5B20%2C%2030%5D%0Aprint(l)%0Adel%20l%5B5%3A7%5D%0Aprint(l)%0Al%5B3%3A%3A2%5D%20%3D%20%5B11%2C%2022%5D%0Aprint(l)%0A%23%20l%5B2%3A5%5D%20%3D%20100%0Al%5B2%3A5%5D%20%3D%20%5B100%5D%0Aprint(l)%0A%0A%5B0%2C%201%2C%2020%2C%2030%2C%205%2C%206%2C%207%2C%208%2C%209%5D%0A%5B0%2C%201%2C%2020%2C%2030%2C%205%2C%208%2C%209%5D%0A%5B0%2C%201%2C%2020%2C%2011%2C%205%2C%2022%2C%209%5D%0A%5B0%2C%201%2C%20100%2C%2022%2C%209%5D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%202.5%E3%80%80%E5%AF%B9%E5%BA%8F%E5%88%97%E4%BD%BF%E7%94%A8%20%2B%20%E5%92%8C%20*%0A%0A%3E%20%5C%2B%20%E5%92%8C%20*%20%E9%83%BD%E9%81%B5%E5%BE%AA%E8%BF%99%E4%B8%AA%E8%A7%84%E5%BE%8B%EF%BC%8C%E4%B8%8D%E4%BF%AE%E6%94%B9%E5%8E%9F%E6%9C%89%E7%9A%84%E6%93%8D%E4%BD%9C%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%80%8C%E6%98%AF%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%85%A8%E6%96%B0%E7%9A%84%E5%BA%8F%E5%88%97%0A%0A%20%60%60%60%20%0Al%20%3D%20%5B1%2C%202%2C%203%5D%0Al%20*%205%0A%5B1%2C%202%2C%203%2C%201%2C%202%2C%203%2C%201%2C%202%2C%203%2C%201%2C%202%2C%203%2C%201%2C%202%2C%203%5D%0A5%20*%20'abcd'%0A'abcdabcdabcdabcdabcd'%0A%20%60%60%60%0A%0A%0A%0A%3E%20%E5%BB%BA%E7%AB%8B%E7%94%B1%E5%88%97%E8%A1%A8%E7%BB%84%E6%88%90%E7%9A%84%E5%88%97%E8%A1%A8%0A%0A%60%60%60python%0Alist_temp%20%3D%20%5B%5B'_'%5D%20*%203%20for%20i%20in%20range(3)%5D%0Aprint(list_temp)%0A%0Alist_temp%5B1%5D%5B2%5D%20%3D%20%22X%22%0Aprint(list_temp)%0A%0A%5B%5B'_'%2C%20'_'%2C%20'_'%5D%2C%20%5B'_'%2C%20'_'%2C%20'_'%5D%2C%20%5B'_'%2C%20'_'%2C%20'_'%5D%5D%0A%5B%5B'_'%2C%20'_'%2C%20'_'%5D%2C%20%5B'_'%2C%20'_'%2C%20'X'%5D%2C%20%5B'_'%2C%20'_'%2C%20'_'%5D%5D%0A%60%60%60%0A%0A%23%23%23%23%23%202.6%E3%80%80%E5%BA%8F%E5%88%97%E7%9A%84%E5%A2%9E%E9%87%8F%E8%B5%8B%E5%80%BC%0A%3E%20%2B%3D%20%E5%92%8C%20*%3D%20%E7%9A%84%E8%A1%A8%E7%8E%B0%E5%8F%96%E5%86%B3%E4%BA%8E%E5%AE%83%E4%BB%AC%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%93%8D%E4%BD%9C%E5%AF%B9%E8%B1%A1%2C%20%2B%3D%20%E8%83%8C%E5%90%8E%E7%9A%84%E7%89%B9%E6%AE%8A%E6%96%B9%E6%B3%95%E6%98%AF%20%20%5C_%5C_iadd%5C_%5C_%20%20%EF%BC%88%E7%94%A8%E4%BA%8E%E2%80%9C%E5%B0%B1%E5%9C%B0%E5%8A%A0%E6%B3%95%E2%80%9D%EF%BC%89%20*%3D%20%E8%83%8C%E5%90%8E%E7%9A%84%E7%89%B9%E6%AE%8A%E6%96%B9%E6%B3%95%E6%98%AF%20%5C_%5C_imul%5C_%5C_%20%EF%BC%88%E7%94%A8%E4%BA%8E%E2%80%9C%E5%B0%B1%E5%9C%B0%E5%8A%A0%E6%B3%95%E2%80%9D%EF%BC%89%0A%3E%0A%3E1.%20%E5%A6%82%E6%9E%9Ca%20%E5%AE%9E%20%E7%8E%B0%20%E4%BA%86%20%5C_%5C_iadd%5C_%5C_%20%20%E6%96%B9%20%E6%B3%95%EF%BC%8C%20%E5%B0%B1%20%E4%BC%9A%20%E8%B0%83%20%E7%94%A8%20%E8%BF%99%20%E4%B8%AA%20%E6%96%B9%20%E6%B3%95%E3%80%82%20%E5%90%8C%20%E6%97%B6%20%E5%AF%B9%20%E5%8F%AF%20%E5%8F%98%20%E5%BA%8F%20%E5%88%97%EF%BC%88%20%E4%BE%8B%20%E5%A6%82%20list%20%E3%80%81bytearray%20%E5%92%8C%20array.array%20%EF%BC%89%E6%9D%A5%E8%AF%B4%EF%BC%8Ca%20%E4%BC%9A%E5%B0%B1%E5%9C%B0%E6%94%B9%E5%8A%A8%0A%3E2.%20%E5%A6%82%E6%9E%9C%20a%20%E6%B2%A1%E6%9C%89%E5%AE%9E%E7%8E%B0%20%20%5C_%5C_iadd%5C_%5C_%20%20%E7%9A%84%E8%AF%9D%EF%BC%8C%20a%20%2B%3D%20b%20%E8%BF%99%E4%B8%AA%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E6%95%88%E6%9E%9C%E5%B0%B1%E5%8F%98%E5%BE%97%E8%B7%9F%20a%20%3D%20a%20%2B%20b%20%E4%B8%80%E6%A0%B7%E4%BA%86%EF%BC%9A%E9%A6%96%E5%85%88%E8%AE%A1%E7%AE%97%20a%20%2B%20b%20%EF%BC%8C%E5%BE%97%E5%88%B0%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E7%84%B6%E5%90%8E%E8%B5%8B%E5%80%BC%E7%BB%99%20a%20%20%0A%0A%60%60%60python%0Alst%20%3D%20list(range(3))%0Aid_list%20%3D%20id(lst)%0Aprint(%22id_list%22%2C%20id_list)%0Alst%20%2B%3D%20%5B%22A%22%2C%20%22B%22%5D%0Aprint(lst)%0Aid_list%20%3D%20id(lst)%0Aprint(%22id_list%3A%22%2C%20id_list)%0Atpl%20%3D%20tuple(range(3))%0Aid_tuple%20%3D%20id(tpl)%0Aprint(%22id_tuple%3A%22%2C%20id_tuple)%0Atpl%20%2B%3D%20(%22A%22%2C%20%22B%22)%0Aprint(tpl)%0Aid_tuple%20%3D%20id(tpl)%0Aprint(%22id_tuple%3A%22%2C%20id_tuple)%0A%0A%0Aid_list%201798125102280%0A%5B0%2C%201%2C%202%2C%20'A'%2C%20'B'%5D%0Aid_list%3A%201798125102280%0Aid_tuple%3A%201798125055864%0A(0%2C%201%2C%202%2C%20'A'%2C%20'B')%0Aid_tuple%3A%201798121809352%0A%60%60%60%0A%0A%3E%20%E5%AF%B9%E4%B8%8D%E5%8F%AF%E5%8F%98%E5%BA%8F%E5%88%97%E8%BF%9B%E8%A1%8C%E9%87%8D%E5%A4%8D%E6%8B%BC%E6%8E%A5%E6%93%8D%E4%BD%9C%E7%9A%84%E8%AF%9D%EF%BC%8C%E6%95%88%E7%8E%87%E4%BC%9A%E5%BE%88%E4%BD%8E%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%AF%8F%E6%AC%A1%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AA%E6%96%B0%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%80%8C%E8%A7%A3%E9%87%8A%E5%99%A8%E9%9C%80%E8%A6%81%E6%8A%8A%E5%8E%9F%E6%9D%A5%E5%AF%B9%E8%B1%A1%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%E5%85%88%E5%A4%8D%E5%88%B6%E5%88%B0%E6%96%B0%E7%9A%84%E5%AF%B9%E8%B1%A1%E9%87%8C%EF%BC%8C%E7%84%B6%E5%90%8E%E5%86%8D%E8%BF%BD%E5%8A%A0%E6%96%B0%E7%9A%84%E5%85%83%E7%B4%A0%0A%0A%0A%0A%5BPython%20Tutor%5D(http%3A%2F%2Fwww.pythontutor.com%2F)%0A%0A%3E%20%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AF%B9%20Python%20%E8%BF%90%E8%A1%8C%E5%8E%9F%E7%90%86%E8%BF%9B%E8%A1%8C%E5%8F%AF%E8%A7%86%E5%8C%96%E5%88%86%E6%9E%90%E7%9A%84%E5%B7%A5%E5%85%B7%0A%0A%0A%0A%23%23%23%23%23%202.7%E3%80%80%20list.sort%20%E6%96%B9%E6%B3%95%E5%92%8C%E5%86%85%E7%BD%AE%E5%87%BD%E6%95%B0%20sorted%0A%0Alist.sort%20%E6%96%B9%E6%B3%95%E4%BC%9A%E5%B0%B1%E5%9C%B0%E6%8E%92%E5%BA%8F%E5%88%97%E8%A1%A8%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%E4%B8%8D%E4%BC%9A%E6%8A%8A%E5%8E%9F%E5%88%97%E8%A1%A8%E5%A4%8D%E5%88%B6%E4%B8%80%E4%BB%BD%E3%80%82%E8%BF%99%E4%B9%9F%E6%98%AF%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E6%98%AF%20None%20%E7%9A%84%E5%8E%9F%E5%9B%A0%EF%BC%8C%E6%8F%90%E9%86%92%E4%BD%A0%E6%9C%AC%E6%96%B9%E6%B3%95%E4%B8%8D%E4%BC%9A%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%88%97%E8%A1%A8%0A%0A%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E6%88%96%E8%80%85%E6%96%B9%E6%B3%95%E5%AF%B9%E5%AF%B9%E8%B1%A1%E8%BF%9B%E8%A1%8C%E7%9A%84%E6%98%AF%E5%B0%B1%E5%9C%B0%E6%94%B9%E5%8A%A8%EF%BC%8C%E9%82%A3%E5%AE%83%E5%B0%B1%E5%BA%94%E8%AF%A5%E8%BF%94%E5%9B%9ENone%20%EF%BC%8C%E5%A5%BD%E8%AE%A9%E8%B0%83%E7%94%A8%E8%80%85%E7%9F%A5%E9%81%93%E4%BC%A0%E5%85%A5%E7%9A%84%E5%8F%82%E6%95%B0%E5%8F%91%E7%94%9F%E4%BA%86%E5%8F%98%E5%8A%A8%EF%BC%8C%E8%80%8C%E4%B8%94%E5%B9%B6%E6%9C%AA%E4%BA%A7%E7%94%9F%E6%96%B0%E7%9A%84%E5%AF%B9%E8%B1%A1%0A%0Asorted%20%E5%AE%83%E4%BC%9A%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%88%97%E8%A1%A8%E4%BD%9C%E4%B8%BA%E8%BF%94%E5%9B%9E%E5%80%BC%E3%80%82%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E6%8E%A5%E5%8F%97%E4%BB%BB%E4%BD%95%E5%BD%A2%E5%BC%8F%E7%9A%84%E5%8F%AF%E8%BF%AD%E4%BB%A3%E5%AF%B9%E8%B1%A1%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0%EF%BC%8C%E7%94%9A%E8%87%B3%E5%8C%85%E6%8B%AC%E4%B8%8D%E5%8F%AF%E5%8F%98%E5%BA%8F%E5%88%97%E6%88%96%E7%94%9F%E6%88%90%E5%99%A8%E3%80%82%E8%80%8C%E4%B8%8D%E7%AE%A1sorted%20%E6%8E%A5%E5%8F%97%E7%9A%84%E6%98%AF%E6%80%8E%E6%A0%B7%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%8C%E5%AE%83%E6%9C%80%E5%90%8E%E9%83%BD%E4%BC%9A%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E5%88%97%E8%A1%A8%E3%80%82%0A%0A%E4%B8%8D%E7%AE%A1%E6%98%AF%20list.sort%20%E6%96%B9%E6%B3%95%E8%BF%98%E6%98%AF%20sorted%20%E5%87%BD%E6%95%B0%EF%BC%8C%E9%83%BD%E6%9C%89%E4%B8%A4%E4%B8%AA%E5%8F%AF%E9%80%89%E7%9A%84%E5%85%B3%E9%94%AE%E5%AD%97%E5%8F%82%E6%95%B0%E3%80%82%0A%0Areverse%20%E9%BB%98%E8%AE%A4%E4%B8%BAFalse%20%E5%8D%87%E5%BA%8F%E6%8E%92%E5%88%97%0A%0A%0A%0A%60%60%60python%0Afruits%20%3D%20%5B'grape'%2C%20'raspberry'%2C%20'apple'%2C%20'banana'%5D%0Aprint(sorted(fruits))%0Aprint(sorted(fruits%2C%20reverse%3DTrue))%0Aprint(sorted(fruits%2C%20key%3Dlen%2C%20reverse%3DTrue))%0A%0A%5B'apple'%2C%20'banana'%2C%20'grape'%2C%20'raspberry'%5D%0A%5B'raspberry'%2C%20'grape'%2C%20'banana'%2C%20'apple'%5D%0A%5B'raspberry'%2C%20'banana'%2C%20'grape'%2C%20'apple'%5D%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%23%23%202.9%E3%80%80%E5%BD%93%E5%88%97%E8%A1%A8%E4%B8%8D%E6%98%AF%E9%A6%96%E9%80%89%E6%97%B6%0A%0A1.%20%E8%A6%81%E5%AD%98%E6%94%BE1000%20%E4%B8%87%E4%B8%AA%E6%B5%AE%E7%82%B9%E6%95%B0%E7%9A%84%E8%AF%9D%EF%BC%8C%E6%95%B0%E7%BB%84%EF%BC%88%20array%20%EF%BC%89%E7%9A%84%E6%95%88%E7%8E%87%E8%A6%81%E9%AB%98%E5%BE%97%E5%A4%9A%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%95%B0%E7%BB%84%E5%9C%A8%E8%83%8C%E5%90%8E%E5%AD%98%E7%9A%84%E5%B9%B6%E4%B8%8D%E6%98%AF%20float%E5%AF%B9%E8%B1%A1%EF%BC%8C%E8%80%8C%E6%98%AF%E6%95%B0%E5%AD%97%E7%9A%84%E6%9C%BA%E5%99%A8%E7%BF%BB%E8%AF%91%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%AD%97%E8%8A%82%E8%A1%A8%E8%BF%B0%0A2.%20%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E9%A2%91%E7%B9%81%E5%AF%B9%E5%BA%8F%E5%88%97%E5%81%9A%E5%85%88%E8%BF%9B%E5%85%88%E5%87%BA%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%8C%20deque%20%EF%BC%88%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%EF%BC%89%E7%9A%84%E9%80%9F%E5%BA%A6%E5%BA%94%E8%AF%A5%E4%BC%9A%E6%9B%B4%E5%BF%AB%0A3.%20%E5%A6%82%E6%9E%9C%E5%9C%A8%E4%BD%A0%E7%9A%84%E4%BB%A3%E7%A0%81%E9%87%8C%EF%BC%8C%E5%8C%85%E5%90%AB%E6%93%8D%E4%BD%9C%EF%BC%88%E6%AF%94%E5%A6%82%E6%A3%80%E6%9F%A5%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E6%98%AF%E5%90%A6%E5%87%BA%E7%8E%B0%E5%9C%A8%E4%B8%80%E4%B8%AA%E9%9B%86%E5%90%88%E4%B8%AD%EF%BC%89%E7%9A%84%E9%A2%91%E7%8E%87%E5%BE%88%E9%AB%98%EF%BC%8C%E7%94%A8%20set%20%EF%BC%88%E9%9B%86%E5%90%88%EF%BC%89%E4%BC%9A%E6%9B%B4%E5%90%88%E9%80%82%E3%80%82%20set%20%E4%B8%93%E4%B8%BA%E6%A3%80%E6%9F%A5%E5%85%83%E7%B4%A0%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E5%81%9A%E8%BF%87%E4%BC%98%E5%8C%96%E3%80%82%E4%BD%86%E6%98%AF%E5%AE%83%E5%B9%B6%E4%B8%8D%E6%98%AF%E5%BA%8F%E5%88%97%EF%BC%8C%E5%9B%A0%E4%B8%BA%20set%20%E6%98%AF%E6%97%A0%E5%BA%8F%E7%9A%84%0A%0A%23%23%23%23%23%23%202.9.1%20%E6%95%B0%E7%BB%84%0A%0A1.%20%E5%A6%82%E6%9E%9C%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E4%B8%80%E4%B8%AA%E5%8F%AA%E5%8C%85%E5%90%AB%E6%95%B0%E5%AD%97%E7%9A%84%E5%88%97%E8%A1%A8%EF%BC%8C%E9%82%A3%E4%B9%88%20array.array%20%E6%AF%94%20list%20%E6%9B%B4%E9%AB%98%E6%95%88%E3%80%82%0A%0A2.%20%E6%95%B0%E7%BB%84%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E8%B7%9F%E5%8F%AF%E5%8F%98%E5%BA%8F%E5%88%97%E6%9C%89%E5%85%B3%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%8C%85%E6%8B%AC%20.pop%20%E3%80%81%20.insert%20%E5%92%8C%20.extend%20%E3%80%82%0A%0A3.%20%E6%95%B0%E7%BB%84%E8%BF%98%E6%8F%90%E4%BE%9B%E4%BB%8E%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96%E5%92%8C%E5%AD%98%E5%85%A5%E6%96%87%E4%BB%B6%E7%9A%84%E6%9B%B4%E5%BF%AB%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%A6%82%20.frombytes%20%E5%92%8C%20.tofile%20%E3%80%82%0A%0A%0A%0A%60%60%60python%0Afrom%20array%20import%20array%0Afrom%20random%20import%20random%0A%0Afloat_array_1%20%3D%20array('d'%2C%20(random()%20for%20x%20in%20(range(10%20**%207))))%0Afirst%20%3D%20float_array_1%5B0%5D%0Alast%20%3D%20float_array_1%5B-1%5D%0Aprint(first%2C%20last)%0A%0Afb%20%3D%20open(%22.%2Ffloat.bin%22%2C%20%22wb%22)%0Afloat_array_1.tofile(fb)%0Afb.close()%0A%0Afloat_array_2%20%3D%20array('d')%0Afb%20%3D%20open(%22.%2Ffloat.bin%22%2C%20%22rb%22)%0A%0A%23%20%E6%8A%8A%201000%20%E4%B8%87%E4%B8%AA%E6%B5%AE%E7%82%B9%E6%95%B0%E4%BB%8E%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6%E9%87%8C%E8%AF%BB%E5%8F%96%E5%87%BA%E6%9D%A5%0Afloat_array_2.fromfile(fb%2C%2010%20**%207)%0Afb.close()%0Afirst%20%3D%20float_array_2%5B0%5D%0Alast%20%3D%20float_array_2%5B-1%5D%0A%0Aprint(first%2C%20last)%0A%0A%23%20%E6%A3%80%E6%9F%A5%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E5%86%85%E5%AE%B9%E6%98%AF%E4%B8%8D%E6%98%AF%E5%AE%8C%E5%85%A8%E4%B8%80%E6%A0%B7%0Aif%20float_array_1%20%3D%3D%20float_array_2%3A%0A%20%20%20%20print(True)%0Aelse%3A%0A%20%20%20%20print(False)%0A%60%60%60%0A%0A%23%23%23%23%23%23%202.9.2%20%E5%86%85%E5%AD%98%E8%A7%86%E5%9B%BE%0A%0A1.%20memoryview%20%E6%98%AF%E4%B8%80%E4%B8%AA%E5%86%85%E7%BD%AE%E7%B1%BB%EF%BC%8C%E5%AE%83%E8%83%BD%E8%AE%A9%E7%94%A8%E6%88%B7%E5%9C%A8%E4%B8%8D%E5%A4%8D%E5%88%B6%E5%86%85%E5%AE%B9%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E6%93%8D%E4%BD%9C%E5%90%8C%E4%B8%80%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%B8%8D%E5%90%8C%E5%88%87%E7%89%87.%0A2.%20memoryview.cast%20%E7%9A%84%E6%A6%82%E5%BF%B5%E8%B7%9F%E6%95%B0%E7%BB%84%E6%A8%A1%E5%9D%97%E7%B1%BB%E4%BC%BC%EF%BC%8C%E8%83%BD%E7%94%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E6%96%B9%E5%BC%8F%E8%AF%BB%E5%86%99%E5%90%8C%E4%B8%80%E5%9D%97%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%80%8C%E4%B8%94%E5%86%85%E5%AE%B9%0A%20%20%20%E5%AD%97%E8%8A%82%E4%B8%8D%E4%BC%9A%E9%9A%8F%E6%84%8F%E7%A7%BB%E5%8A%A8%0A3.%20memoryview.cast%20%E4%BC%9A%E6%8A%8A%E5%90%8C%E4%B8%80%E5%9D%97%E5%86%85%E5%AD%98%E9%87%8C%E7%9A%84%E5%86%85%E5%AE%B9%E6%89%93%E5%8C%85%E6%88%90%E4%B8%80%E4%B8%AA%E5%85%A8%E6%96%B0%E7%9A%84%20memoryview%20%E5%AF%B9%E8%B1%A1%E7%BB%99%E4%BD%A0%0A%0A%0A%0A%0A%0A%23%23%23%23%23%202.9.4%E3%80%80%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E5%92%8C%E5%85%B6%E4%BB%96%E5%BD%A2%E5%BC%8F%E7%9A%84%E9%98%9F%E5%88%97%0A%0A

faker

创建时间:2020/9/2 15:42
更新时间:2020/9/2 15:42
作者:Chris

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple faker
  • 简体中文:

  • 繁体中文:zh_TW

  • 美国英文:en_US

  • 英国英文:en_GB

  • 德文:de_DE

  • 日文:ja_JP

  • 韩文:ko_KR

  • 法文:fr_FR

Provider

Faker 库在设计上,为了解耦,将 Provider 对象做成了 Faker 对象的”插件“。Faker 可以添加一个个 Provider 对象,Provider 对象为 Faker 对象提供了生成某项数据的核心实现。

Address

Address,用于生成一些和地址相关的数据,如地址、城市、邮政编码、街道等内容, 用法如下:

from faker import Faker

faker = Faker("zh_CN")
address = faker.address()
building_number = faker.building_number()
city = faker.city()
cityname = faker.city_name()
city_suf = faker.city_suffix()
country = faker.country()
country_2 = faker.country_code(representation="alpha-2")
district = faker.district()
postcode = faker.postcode()
province = faker.province()
street_address = faker.street_address()
street_name = faker.street_name()
street_suffix = faker.street_suffix()

print("address:", address)
print("building_number:", building_number)
print("city:", city)
print("cityname:", cityname)
print("city_suf:", city_suf)
print("country:", country)
print("country_2:", country_2)
print("district:", district)
print("postcode:", postcode)
print("province:", province)
print("street_address:", street_address)
print("street_name:", street_name)
print("street_suffix:", street_suffix)
Color,

用于生成和颜色相关的数据,如 HEX、RGB、RGBA 等格式的颜色,用法如下:

from faker import Faker

faker = Faker()

color_name = faker.color_name()
hex_color = faker.hex_color()
rgb_color = faker.rgb_color()
rgb_css_color = faker.rgb_css_color()
safe_color_name = faker.safe_color_name()
safe_hex_color = faker.safe_hex_color()

print("color_name :", color_name)
print("hex_color :", hex_color)
print("rgb_color :", rgb_color)
print("rgb_css_color :", rgb_css_color)
print("safe_color_name :", safe_color_name)
print("safe_hex_color :", safe_hex_color)
%60%60%60%0Apip%20install%20-i%20https%3A%2F%2Fpypi.tuna.tsinghua.edu.cn%2Fsimple%20faker%0A%60%60%60%0A%0A%20%20-%20%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%EF%BC%9A%09%0A%0A%20%20-%20%E7%B9%81%E4%BD%93%E4%B8%AD%E6%96%87%EF%BC%9Azh_TW%0A%0A%20%20-%20%E7%BE%8E%E5%9B%BD%E8%8B%B1%E6%96%87%EF%BC%9Aen_US%0A%0A%20%20-%20%E8%8B%B1%E5%9B%BD%E8%8B%B1%E6%96%87%EF%BC%9Aen_GB%0A%0A%20%20-%20%E5%BE%B7%E6%96%87%EF%BC%9Ade_DE%0A%0A%20%20-%20%E6%97%A5%E6%96%87%EF%BC%9Aja_JP%0A%0A%20%20-%20%E9%9F%A9%E6%96%87%EF%BC%9Ako_KR%0A%0A%20%20-%20%E6%B3%95%E6%96%87%EF%BC%9Afr_FR%0A%0A%23%23%23%23%23%20Provider%0A%0AFaker%20%E5%BA%93%E5%9C%A8%E8%AE%BE%E8%AE%A1%E4%B8%8A%EF%BC%8C%E4%B8%BA%E4%BA%86%E8%A7%A3%E8%80%A6%EF%BC%8C%E5%B0%86%20Provider%20%E5%AF%B9%E8%B1%A1%E5%81%9A%E6%88%90%E4%BA%86%20Faker%20%E5%AF%B9%E8%B1%A1%E7%9A%84%E2%80%9D%E6%8F%92%E4%BB%B6%E2%80%9C%E3%80%82Faker%20%E5%8F%AF%E4%BB%A5%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E4%B8%AA%20Provider%20%E5%AF%B9%E8%B1%A1%EF%BC%8CProvider%20%E5%AF%B9%E8%B1%A1%E4%B8%BA%20Faker%20%E5%AF%B9%E8%B1%A1%E6%8F%90%E4%BE%9B%E4%BA%86%E7%94%9F%E6%88%90%E6%9F%90%E9%A1%B9%E6%95%B0%E6%8D%AE%E7%9A%84%E6%A0%B8%E5%BF%83%E5%AE%9E%E7%8E%B0%E3%80%82%0A%0A%0A%0A%23%23%23%23%23%20Address%0A%0A%3E%20Address%EF%BC%8C%E7%94%A8%E4%BA%8E%E7%94%9F%E6%88%90%E4%B8%80%E4%BA%9B%E5%92%8C%E5%9C%B0%E5%9D%80%E7%9B%B8%E5%85%B3%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E5%9C%B0%E5%9D%80%E3%80%81%E5%9F%8E%E5%B8%82%E3%80%81%E9%82%AE%E6%94%BF%E7%BC%96%E7%A0%81%E3%80%81%E8%A1%97%E9%81%93%E7%AD%89%E5%86%85%E5%AE%B9%EF%BC%8C%20%E7%94%A8%E6%B3%95%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60python%0Afrom%20faker%20import%20Faker%0A%0Afaker%20%3D%20Faker(%22zh_CN%22)%0Aaddress%20%3D%20faker.address()%0Abuilding_number%20%3D%20faker.building_number()%0Acity%20%3D%20faker.city()%0Acityname%20%3D%20faker.city_name()%0Acity_suf%20%3D%20faker.city_suffix()%0Acountry%20%3D%20faker.country()%0Acountry_2%20%3D%20faker.country_code(representation%3D%22alpha-2%22)%0Adistrict%20%3D%20faker.district()%0Apostcode%20%3D%20faker.postcode()%0Aprovince%20%3D%20faker.province()%0Astreet_address%20%3D%20faker.street_address()%0Astreet_name%20%3D%20faker.street_name()%0Astreet_suffix%20%3D%20faker.street_suffix()%0A%0Aprint(%22address%3A%22%2C%20address)%0Aprint(%22building_number%3A%22%2C%20building_number)%0Aprint(%22city%3A%22%2C%20city)%0Aprint(%22cityname%3A%22%2C%20cityname)%0Aprint(%22city_suf%3A%22%2C%20city_suf)%0Aprint(%22country%3A%22%2C%20country)%0Aprint(%22country_2%3A%22%2C%20country_2)%0Aprint(%22district%3A%22%2C%20district)%0Aprint(%22postcode%3A%22%2C%20postcode)%0Aprint(%22province%3A%22%2C%20province)%0Aprint(%22street_address%3A%22%2C%20street_address)%0Aprint(%22street_name%3A%22%2C%20street_name)%0Aprint(%22street_suffix%3A%22%2C%20street_suffix)%0A%60%60%60%0A%0A%23%23%23%23%23%20Color%EF%BC%8C%0A%0A%3E%20%E7%94%A8%E4%BA%8E%E7%94%9F%E6%88%90%E5%92%8C%E9%A2%9C%E8%89%B2%E7%9B%B8%E5%85%B3%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%20HEX%E3%80%81RGB%E3%80%81RGBA%20%E7%AD%89%E6%A0%BC%E5%BC%8F%E7%9A%84%E9%A2%9C%E8%89%B2%EF%BC%8C%E7%94%A8%E6%B3%95%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60python%0Afrom%20faker%20import%20Faker%0A%0Afaker%20%3D%20Faker()%0A%0Acolor_name%20%3D%20faker.color_name()%0Ahex_color%20%3D%20faker.hex_color()%0Argb_color%20%3D%20faker.rgb_color()%0Argb_css_color%20%3D%20faker.rgb_css_color()%0Asafe_color_name%20%3D%20faker.safe_color_name()%0Asafe_hex_color%20%3D%20faker.safe_hex_color()%0A%0Aprint(%22color_name%20%3A%22%2C%20color_name)%0Aprint(%22hex_color%20%3A%22%2C%20hex_color)%0Aprint(%22rgb_color%20%3A%22%2C%20rgb_color)%0Aprint(%22rgb_css_color%20%3A%22%2C%20rgb_css_color)%0Aprint(%22safe_color_name%20%3A%22%2C%20safe_color_name)%0Aprint(%22safe_hex_color%20%3A%22%2C%20safe_hex_color)%0A%60%60%60

常用命令

创建时间:2020/9/2 15:41
更新时间:2020/9/2 15:41
作者:Chris

命令

pip --version
pip install camelcase

在 https://pypi.org/,您可以找到更多的包

列出系统上安装的所有软件包

pip list

升级pip

python -m pip install --upgrade pi

dir(__builtins__)
help(int)

卸载装包

pip uninstall pip install camelcase

安装包

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple lxml

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple lxml
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple mysql-connector
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple  openpyxl
pip install openpyxl --ignore-installed openpyxl
%23%23%20**%E5%91%BD%E4%BB%A4**%0A%60%60%60%0Apip%20--version%0Apip%20install%20camelcase%0A%60%60%60%0A%E5%9C%A8%20https%3A%2F%2Fpypi.org%2F%EF%BC%8C%E6%82%A8%E5%8F%AF%E4%BB%A5%E6%89%BE%E5%88%B0%E6%9B%B4%E5%A4%9A%E7%9A%84%E5%8C%85%20%20%0A%0A%23%23%20**%E5%88%97%E5%87%BA%E7%B3%BB%E7%BB%9F%E4%B8%8A%E5%AE%89%E8%A3%85%E7%9A%84%E6%89%80%E6%9C%89%E8%BD%AF%E4%BB%B6%E5%8C%85**%0A%60pip%20list%60%20%20%0A%0A%0A%23%23%20**%E5%8D%87%E7%BA%A7pip**%20%20%0A%60python%20-m%20pip%20install%20--upgrade%20pi%60%0A%0A%60%60%60%0Adir(__builtins__)%0Ahelp(int)%0A%60%60%60%0A%23%23%20**%E5%8D%B8%E8%BD%BD%E8%A3%85%E5%8C%85**%0A%60pip%20uninstall%20%20pip%20install%20camelcase%60%20%20%0A%0A%23%23%20**%E5%AE%89%E8%A3%85%E5%8C%85**%0A%60pip%20install%20-i%20https%3A%2F%2Fpypi.tuna.tsinghua.edu.cn%2Fsimple%20lxml%60%0A%60%60%60%0Apip%20install%20-i%20https%3A%2F%2Fpypi.tuna.tsinghua.edu.cn%2Fsimple%20lxml%0Apip%20install%20-i%20https%3A%2F%2Fpypi.tuna.tsinghua.edu.cn%2Fsimple%20mysql-connector%0Apip%20install%20-i%20https%3A%2F%2Fpypi.tuna.tsinghua.edu.cn%2Fsimple%20%20openpyxl%0Apip%20install%20openpyxl%20--ignore-installed%20openpyxl%0A%60%60%60

linux安装python3.7

创建时间:2020/9/2 15:41
更新时间:2020/9/2 15:41
作者:Chris

1.%20%E5%AE%89%E8%A3%85%E4%BE%9D%E8%B5%96%E5%8C%85%0A%0A-%20%E9%A6%96%E5%85%88%E5%AE%89%E8%A3%85gcc%E7%BC%96%E8%AF%91%E5%99%A8%0A%3E%20%20gcc%20--version%20%20%0A%3E%20%20%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E6%98%AF%E5%90%A6%E5%AE%89%E8%A3%85%20%20%0A%3E%20%20yum%20-y%20install%20gcc%20%20%0A%3E%20%20%E5%AE%89%E8%A3%85gcc%20%20%0A%20%20%20%0A-%20%E5%AE%89%E8%A3%85%E5%85%B6%E4%BB%96%E4%BE%9D%E8%B5%96%E5%8C%85%EF%BC%8C%EF%BC%88%E4%B8%8D%E8%A6%81%E7%BC%BA%E5%B0%91%EF%BC%89%0A%20%60%60%60%0A%20sudo%20yum%20-y%20install%20zlib-devel%20bzip2-devel%20openssl-devel%20ncurses-devel%20sqlite-devel%20readline-devel%20tk-devel%20gdbm-devel%20db4-devel%20libpcap-devel%20xz-devel%20libffi-devel%0A%20%60%60%60%0A%0A2.%20%E4%B8%8B%E8%BD%BDPython3.7.0%E6%BA%90%E7%A0%81%EF%BC%8C%E6%A0%B9%E6%8D%AE%E9%9C%80%E6%B1%82%E4%B8%8B%E8%BD%BD%0A%3E%20%E5%9C%A8https%3A%2F%2Fwww.python.org%2Fftp%2Fpython%2F%E4%B8%AD%E9%80%89%E6%8B%A9%E8%87%AA%E5%B7%B1%E9%9C%80%E8%A6%81%E7%9A%84python%E6%BA%90%E7%A0%81%E5%8C%85%EF%BC%8C%E6%88%91%E4%B8%8B%E8%BD%BD%E7%9A%84%E6%98%AFpython3.7.3%20%20%0A%3E%20%E4%B8%8B%E8%BD%BD%20wget%20https%3A%2F%2Fwww.python.org%2Fftp%2Fpython%2F3.7.3%2FPython-3.7.3.tgz%0A%0A%0A3.%20%E8%A7%A3%E5%8E%8BPython-3.7.0.tgz%20%20%0A%60tar%20-zxvf%20Python-3.7.3.tgz%60%0A%0A4.%20%E8%BF%9B%E5%85%A5%E7%9B%AE%E5%BD%95%EF%BC%9A%20%20%0A%60cd%20Python-3.7.3%2F%60%0A%0A5.%20%E6%B7%BB%E5%8A%A0%E9%85%8D%E7%BD%AE%EF%BC%8C%E7%94%A8%E4%BA%8E%E4%BF%9D%E5%AD%98python3%E7%A8%8B%E5%BA%8F%EF%BC%9A%0A%20%20%60.%2Fconfigure%20--prefix%3D%2Fusr%2Fpython3%60%0A%0A6.%20%E7%BC%96%E8%AF%91%EF%BC%8C%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85%0A%60%60%60%0Amake%0Asudo%20make%20install%0A%60%60%60%0A%0A7.%20%E5%BB%BA%E7%AB%8B%E8%BD%AF%E8%BF%9E%E6%8E%A5%0A%60%60%60%0Aln%20-s%20%2Fusr%2Fpython3%2Fbin%2Fpython3.7%20%2Fusr%2Fbin%2Fpython3%0Aln%20-s%20%2Fusr%2Fpython3%2Fbin%2Fpip3.7%20%2Fusr%2Fbin%2Fpip3%0A%60%60%60%0A%0A

module_splint

创建时间:2020/9/2 15:40
更新时间:2020/9/2 15:41
作者:Chris

APScheduler
https://www.cnblogs.com/zhaoyingjie/p/9664081.html
https://www.cnblogs.com/Neeo/p/10435059.html
https://apscheduler.readthedocs.io/en/latest/modules/triggers/cron.html
skipped: maximum number of running instances reached
https://www.cnblogs.com/yongqing/p/9595987.htm

repr()函数将对象转化为供解释器读取的形式
https://www.runoob.com/python/python-func-repr.html

Difference between str and repr in Python
http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python

Python获取指定文件夹下的文件
https://www.cnblogs.com/yuanyongqiang/p/11714281.html

Deep Thoughts by Raymond Hettinger
https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
https://rhettinger.wordpress.com/
https://blog.lilydjwg.me/2014/3/13/python-3-s-super-and-__class__.43499.html

python命名规范
https://www.jianshu.com/p/4bd28460d912

Python程序员常犯的10个错误
http://bookshadow.com/weblog/2014/05/14/top-10-mistakes-that-python-programmers-make/

PyCharm中Python代码提示:Shadows name from outer scope
https://www.crifan.com/pycharm_python_code_notice_shadows_name_from_outer_scope/

python实现十大经典算法
https://www.cnblogs.com/123blog/p/10405443.html
https://blog.csdn.net/coxhuang/article/details/90381254

DeepClone
https://www.runoob.com/w3cnote/python-understanding-dict-copy-shallow-or-deep.html

python 字符串前面加u,r,b的含义
https://www.cnblogs.com/liangmingshen/p/9274021.html
r"\n\n\n\n” #表示一个普通生字符串 \n\n\n\n,而不表示换行了。

python 字符串前面加 f

https://blog.csdn.net/Kwoky/article/details/84754901

格式化字符串常量(formatted string literals),是Python3.6新引入的一种字符串格式化方法,
该方法源于PEP 498 – Literal StringI nterpolation,主要目的是使格式化字符串的操作更加简便。
f-string在形式上是以 <kbd>f</kbd> 或 <kbd>F</kbd> 修饰符引领的字符串(f'xxx' 或 F'xxx'),
以大括号 <kbd>{}</kbd> 标明被替换的字段;
f-string在本质上并不是字符串常量,而是一个在运行时运算求值的表达式

comedian = {'name': 'Eric Idle', 'age': 74}
f"The comedian is {comedian['name']}, aged {comedian['age']}."
Python -- log日志

https://www.cnblogs.com/Agoni-7/p/11129296.html

lxml

https://stackoverflow.com/questions/13694143/parsing-cdata-in-xml-with-python?r=SearchResults
https://www.cnblogs.com/zhangxinqi/p/9210211.html

configparser

https://blog.csdn.net/AlanGuoo/article/details/95239795
https://www.cnblogs.com/hanmk/p/9843136.html

Python 定义自己的常量类

https://www.lizenghai.com/archives/1911.html

Python 语言参考手册中的“Data Model”

https://docs.python.org/3/reference/datamodel.html

openpyxl模块

https://www.cnblogs.com/programmer-tlh/p/10461353.html

%20**APScheduler**%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fzhaoyingjie%2Fp%2F9664081.html%0Ahttps%3A%2F%2Fwww.cnblogs.com%2FNeeo%2Fp%2F10435059.html%0Ahttps%3A%2F%2Fapscheduler.readthedocs.io%2Fen%2Flatest%2Fmodules%2Ftriggers%2Fcron.html%20%20%0Askipped%3A%20maximum%20number%20of%20running%20instances%20reached%20%20%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fyongqing%2Fp%2F9595987.htm%0A%0A%0A%20**repr()%E5%87%BD%E6%95%B0%E5%B0%86%E5%AF%B9%E8%B1%A1%E8%BD%AC%E5%8C%96%E4%B8%BA%E4%BE%9B%E8%A7%A3%E9%87%8A%E5%99%A8%E8%AF%BB%E5%8F%96%E7%9A%84%E5%BD%A2%E5%BC%8F**%0Ahttps%3A%2F%2Fwww.runoob.com%2Fpython%2Fpython-func-repr.html%0A%0A%20**Difference%20between%20%20__str__%20and%20%20__repr__%20in%20Python**%0Ahttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F1436703%2Fdifference-between-str-and-repr-in-python%0A%0A%20**Python%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E6%96%87%E4%BB%B6%E5%A4%B9%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6**%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fyuanyongqiang%2Fp%2F11714281.html%0A%0A%20**Deep%20Thoughts%20by%20Raymond%20Hettinger**%0Ahttps%3A%2F%2Frhettinger.wordpress.com%2F2011%2F05%2F26%2Fsuper-considered-super%2F%0Ahttps%3A%2F%2Frhettinger.wordpress.com%2F%0A%3Chttps%3A%2F%2Fblog.lilydjwg.me%2F2014%2F3%2F13%2Fpython-3-s-super-and-__class__.43499.html%3E%0A%0A%0A%20**python%E5%91%BD%E5%90%8D%E8%A7%84%E8%8C%83**%0Ahttps%3A%2F%2Fwww.jianshu.com%2Fp%2F4bd28460d912%0A%0A%0A%20**Python%E7%A8%8B%E5%BA%8F%E5%91%98%E5%B8%B8%E7%8A%AF%E7%9A%8410%E4%B8%AA%E9%94%99%E8%AF%AF**%0Ahttp%3A%2F%2Fbookshadow.com%2Fweblog%2F2014%2F05%2F14%2Ftop-10-mistakes-that-python-programmers-make%2F%0A%0A%20**PyCharm%E4%B8%ADPython%E4%BB%A3%E7%A0%81%E6%8F%90%E7%A4%BA%EF%BC%9AShadows%20name%20from%20outer%20scope**%0Ahttps%3A%2F%2Fwww.crifan.com%2Fpycharm_python_code_notice_shadows_name_from_outer_scope%2F%0A%0A%0A%20**python%E5%AE%9E%E7%8E%B0%E5%8D%81%E5%A4%A7%E7%BB%8F%E5%85%B8%E7%AE%97%E6%B3%95**%0Ahttps%3A%2F%2Fwww.cnblogs.com%2F123blog%2Fp%2F10405443.html%0Ahttps%3A%2F%2Fblog.csdn.net%2Fcoxhuang%2Farticle%2Fdetails%2F90381254%0A%0A%20**DeepClone**%0Ahttps%3A%2F%2Fwww.runoob.com%2Fw3cnote%2Fpython-understanding-dict-copy-shallow-or-deep.html%0A%0A%0A%20**python%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%89%8D%E9%9D%A2%E5%8A%A0u%2Cr%2Cb%E7%9A%84%E5%90%AB%E4%B9%89**%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fliangmingshen%2Fp%2F9274021.html%20%20%0Ar%22%5Cn%5Cn%5Cn%5Cn%E2%80%9D%E3%80%80%23%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E6%99%AE%E9%80%9A%E7%94%9F%E5%AD%97%E7%AC%A6%E4%B8%B2%20%5Cn%5Cn%5Cn%5Cn%EF%BC%8C%E8%80%8C%E4%B8%8D%E8%A1%A8%E7%A4%BA%E6%8D%A2%E8%A1%8C%E4%BA%86%E3%80%82%0A%0A%23%23%23%23%23%20%20**python%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%89%8D%E9%9D%A2%E5%8A%A0%20f**%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2FKwoky%2Farticle%2Fdetails%2F84754901%0A%0A%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%EF%BC%88formatted%20string%20literals%EF%BC%89%EF%BC%8C%E6%98%AFPython3.6%E6%96%B0%E5%BC%95%E5%85%A5%E7%9A%84%E4%B8%80%E7%A7%8D%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%96%B9%E6%B3%95%EF%BC%8C%20%20%0A%E8%AF%A5%E6%96%B9%E6%B3%95%E6%BA%90%E4%BA%8EPEP%20498%20%E2%80%93%20Literal%20StringI%20nterpolation%EF%BC%8C%E4%B8%BB%E8%A6%81%E7%9B%AE%E7%9A%84%E6%98%AF%E4%BD%BF%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E6%93%8D%E4%BD%9C%E6%9B%B4%E5%8A%A0%E7%AE%80%E4%BE%BF%E3%80%82%20%20%20%0Af-string%E5%9C%A8%E5%BD%A2%E5%BC%8F%E4%B8%8A%E6%98%AF%E4%BB%A5%20%3Ckbd%3Ef%3C%2Fkbd%3E%20%E6%88%96%20%3Ckbd%3EF%3C%2Fkbd%3E%20%E4%BF%AE%E9%A5%B0%E7%AC%A6%E5%BC%95%E9%A2%86%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%88f'xxx'%20%E6%88%96%20F'xxx'%EF%BC%89%EF%BC%8C%20%20%0A%E4%BB%A5%E5%A4%A7%E6%8B%AC%E5%8F%B7%20%3Ckbd%3E%7B%7D%3C%2Fkbd%3E%20%E6%A0%87%E6%98%8E%E8%A2%AB%E6%9B%BF%E6%8D%A2%E7%9A%84%E5%AD%97%E6%AE%B5%EF%BC%9B%20%20%0A%60f-string%E5%9C%A8%E6%9C%AC%E8%B4%A8%E4%B8%8A%E5%B9%B6%E4%B8%8D%E6%98%AF%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%EF%BC%8C%E8%80%8C%E6%98%AF%E4%B8%80%E4%B8%AA%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E8%BF%90%E7%AE%97%E6%B1%82%E5%80%BC%E7%9A%84%E8%A1%A8%E8%BE%BE%E5%BC%8F%60%0A%0A%60%60%60%0Acomedian%20%3D%20%7B'name'%3A%20'Eric%20Idle'%2C%20'age'%3A%2074%7D%0Af%22The%20comedian%20is%20%7Bcomedian%5B'name'%5D%7D%2C%20aged%20%7Bcomedian%5B'age'%5D%7D.%22%0A%60%60%60%0A%0A%23%23%23%23%23%20%20Python%20--%20log%E6%97%A5%E5%BF%97%0A%0Ahttps%3A%2F%2Fwww.cnblogs.com%2FAgoni-7%2Fp%2F11129296.html%0A%0A%23%23%23%23%23%20%20**lxml**%0A%0Ahttps%3A%2F%2Fstackoverflow.com%2Fquestions%2F13694143%2Fparsing-cdata-in-xml-with-python%3Fr%3DSearchResults%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fzhangxinqi%2Fp%2F9210211.html%0A%0A%23%23%23%23%23%20%20**configparser**%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2FAlanGuoo%2Farticle%2Fdetails%2F95239795%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fhanmk%2Fp%2F9843136.html%0A%0A%23%23%23%23%23%20%20**Python%20%E5%AE%9A%E4%B9%89%E8%87%AA%E5%B7%B1%E7%9A%84%E5%B8%B8%E9%87%8F%E7%B1%BB**%0A%0Ahttps%3A%2F%2Fwww.lizenghai.com%2Farchives%2F1911.html%0A%0A%23%23%23%23%23%20%20**Python%20%E8%AF%AD%E8%A8%80%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C%E4%B8%AD%E7%9A%84%E2%80%9CData%20Model%E2%80%9D**%0A%0Ahttps%3A%2F%2Fdocs.python.org%2F3%2Freference%2Fdatamodel.html%0A%0A%23%23%23%23%23%20%20openpyxl%E6%A8%A1%E5%9D%97%0A%0Ahttps%3A%2F%2Fwww.cnblogs.com%2Fprogrammer-tlh%2Fp%2F10461353.html

因用了Insert into select语句,同事被开除了!

创建时间:2020/9/2 15:38
更新时间:2020/9/2 15:40
作者:Chris

Insert into select 请慎用,同事因为使用了 Insert into select 语句引发了重大生产事故,最后被开除。

某天 xxx 接到一个需求,需要将表 A 的数据迁移到表 B 中去做一个备份。他本想通过程序先查询查出来然后批量插入,但 xxx 觉得这样有点慢,需要耗费大量的网络 I/O,决定采取别的方法进行实现。

通过在某度的海洋里遨游,他发现了可以使用 insert into select 实现,这样就可以避免使用网络 I/O,直接使用 SQL 依靠数据库 I/O 完成,这样简直不要太棒,然后他就被开除了。

事故发生的经过

由于数据数据库中 order_today 数据量过大,当时好像有 700W 了,并且每天在以 30W 的速度增加。

所以上司命令 xxx 将 order_today 内的部分数据迁移到 order_record 中,并将 order_today 中的数据删除,这样来降低 order_today 表中的数据量。

由于考虑到会占用数据库 I/O,为了不影响业务,计划是 9:00 以后开始迁移,但是 xxx 在 8:00 的时候,尝试迁移了少部分数据(1000 条),觉得没啥问题,就开始考虑大批量迁移。

在迁移的过程中,应急群是先反应有小部分用户出现支付失败,随后反应大批用户出现支付失败的情况,以及初始化订单失败的情况,同时腾讯也开始报警。

然后 xxx 就慌了,立即停止了迁移。本以为停止迁移就就可以恢复了,但是并没有。

后面发生的你们可以脑补一下,当时整个支付系统瘫痪了快一个小时,客服电话都被打爆。

事故还原

在本地建立一个精简版的数据库,并生成了 100w 的数据。模拟线上发生的情况。

建立表结构

订单表如下:

CREATE TABLE `order_today` (
`id` VARCHAR ( 32 ) NOT NULL COMMENT '主键',
`merchant_id` VARCHAR ( 32 ) CHARACTER SET utf8 COLLATE utf8 _general_ci NOT NULL COMMENT '商户编号',
`amount` DECIMAL ( 15, 2 ) NOT NULL COMMENT '订单金额',
`pay_success_time` datetime NOT NULL COMMENT '支付成功时间',
`order_status` VARCHAR ( 10 ) CHARACTER SET utf8 COLLATE utf8 _general_ci NOT NULL COMMENT '支付状态 S:支付成功、F:订单支付失败',
`remark` VARCHAR ( 100 ) CHARACTER SET utf8 COLLATE utf8 _general _ci DEFAULT NULL COMMENT '备注',
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT _TIMESTAMP COMMENT '创建时间',
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT _TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间 -- 修改时自动更新',
PRIMARY KEY ( `id` ) USING BTREE,
KEY `idx_merchant_id` ( `merchant_id` ) USING BTREE COMMENT '商户编号' 
) ENGINE = INNODB DEFAULT CHARSET = utf8;

订单记录表如下:

CREATETABLE order_record like order_today;

今日订单表数据如下:

模拟迁移

把 8 号之前的数据都迁移到 order_record 表中去:

INSERT INTO order_record SELECT * FROM order_today WHERE pay_success_time < '2020-03-08 00:00:00';

在 Navicat 中运行迁移的 SQL,同时开另个一个窗口插入数据,模拟下单:

从上面可以发现一开始能正常插入,但是后面突然就卡住了,并且耗费了 23s 才成功,然后才能继续插入。这个时候已经迁移成功了,所以能正常插入了。

出现的原因

在默认的事务隔离级别下:insert into order_record select * from order_today 加锁规则是:order_record 表锁,order_today 逐步锁(扫描一个锁一个)。

分析执行过程:

通过观察迁移 SQL 的执行情况你会发现 order_today 是全表扫描,也就意味着在执行 insert into select from 语句时,MySQL 会从上到下扫描 order_today 内的记录并且加锁,这样一来不就和直接锁表是一样了。

这也就可以解释,为什么一开始只有少量用户出现支付失败,后续大量用户出现支付失败,初始化订单失败等情况,因为一开始只锁定了少部分数据,没有被锁定的数据还是可以正常被修改为正常状态。

由于锁定的数据越来越多,就导致出现了大量支付失败。最后全部锁住,导致无法插入订单,而出现初始化订单失败。

解决方案

由于查询条件会导致 order_today 全表扫描,什么能避免全表扫描呢,很简单嘛,给 pay_success_time 字段添加一个 idx_pay_suc_time 索引就可以了。

由于走索引查询,就不会出现扫描全表的情况而锁表了,只会锁定符合条件的记录。

最终的 SQL:

INSERTINTO order_record SELECT * FROM order_today FORCE INDEX (idx_pay_suc_time) WHERE pay_success_time <= '2020-03-08 00:00:00';

执行过程如下:

总结
使用 insert into table A select * from table B 语句时,一定要确保 table B 后面的 where,order 或者其他条件,都需要有对应的索引,来避免出现 table B 全部记录被锁定的情况。

%0AInsert%20into%20select%20%E8%AF%B7%E6%85%8E%E7%94%A8%EF%BC%8C%E5%90%8C%E4%BA%8B%E5%9B%A0%E4%B8%BA%E4%BD%BF%E7%94%A8%E4%BA%86%20Insert%20into%20select%20%E8%AF%AD%E5%8F%A5%E5%BC%95%E5%8F%91%E4%BA%86%E9%87%8D%E5%A4%A7%E7%94%9F%E4%BA%A7%E4%BA%8B%E6%95%85%EF%BC%8C%E6%9C%80%E5%90%8E%E8%A2%AB%E5%BC%80%E9%99%A4%E3%80%82%0A%0A%E6%9F%90%E5%A4%A9%20xxx%20%E6%8E%A5%E5%88%B0%E4%B8%80%E4%B8%AA%E9%9C%80%E6%B1%82%EF%BC%8C%E9%9C%80%E8%A6%81%E5%B0%86%E8%A1%A8%20A%20%E7%9A%84%E6%95%B0%E6%8D%AE%E8%BF%81%E7%A7%BB%E5%88%B0%E8%A1%A8%20B%20%E4%B8%AD%E5%8E%BB%E5%81%9A%E4%B8%80%E4%B8%AA%E5%A4%87%E4%BB%BD%E3%80%82%E4%BB%96%E6%9C%AC%E6%83%B3%E9%80%9A%E8%BF%87%E7%A8%8B%E5%BA%8F%E5%85%88%E6%9F%A5%E8%AF%A2%E6%9F%A5%E5%87%BA%E6%9D%A5%E7%84%B6%E5%90%8E%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%EF%BC%8C%E4%BD%86%20xxx%20%E8%A7%89%E5%BE%97%E8%BF%99%E6%A0%B7%E6%9C%89%E7%82%B9%E6%85%A2%EF%BC%8C%E9%9C%80%E8%A6%81%E8%80%97%E8%B4%B9%E5%A4%A7%E9%87%8F%E7%9A%84%E7%BD%91%E7%BB%9C%20I%2FO%EF%BC%8C%E5%86%B3%E5%AE%9A%E9%87%87%E5%8F%96%E5%88%AB%E7%9A%84%E6%96%B9%E6%B3%95%E8%BF%9B%E8%A1%8C%E5%AE%9E%E7%8E%B0%E3%80%82%0A%0A%E9%80%9A%E8%BF%87%E5%9C%A8%E6%9F%90%E5%BA%A6%E7%9A%84%E6%B5%B7%E6%B4%8B%E9%87%8C%E9%81%A8%E6%B8%B8%EF%BC%8C%E4%BB%96%E5%8F%91%E7%8E%B0%E4%BA%86%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20insert%20into%20select%20%E5%AE%9E%E7%8E%B0%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%B0%B1%E5%8F%AF%E4%BB%A5%E9%81%BF%E5%85%8D%E4%BD%BF%E7%94%A8%E7%BD%91%E7%BB%9C%20I%2FO%EF%BC%8C%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%20SQL%20%E4%BE%9D%E9%9D%A0%E6%95%B0%E6%8D%AE%E5%BA%93%20I%2FO%20%E5%AE%8C%E6%88%90%EF%BC%8C%E8%BF%99%E6%A0%B7%E7%AE%80%E7%9B%B4%E4%B8%8D%E8%A6%81%E5%A4%AA%E6%A3%92%EF%BC%8C%E7%84%B6%E5%90%8E%E4%BB%96%E5%B0%B1%E8%A2%AB%E5%BC%80%E9%99%A4%E4%BA%86%E3%80%82%0A%0A%E4%BA%8B%E6%95%85%E5%8F%91%E7%94%9F%E7%9A%84%E7%BB%8F%E8%BF%87%0A%0A%E7%94%B1%E4%BA%8E%E6%95%B0%E6%8D%AE%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%20order_today%20%E6%95%B0%E6%8D%AE%E9%87%8F%E8%BF%87%E5%A4%A7%EF%BC%8C%E5%BD%93%E6%97%B6%E5%A5%BD%E5%83%8F%E6%9C%89%20700W%20%E4%BA%86%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%AF%8F%E5%A4%A9%E5%9C%A8%E4%BB%A5%2030W%20%E7%9A%84%E9%80%9F%E5%BA%A6%E5%A2%9E%E5%8A%A0%E3%80%82%0A%0A%E6%89%80%E4%BB%A5%E4%B8%8A%E5%8F%B8%E5%91%BD%E4%BB%A4%20xxx%20%E5%B0%86%20order%5C_today%20%E5%86%85%E7%9A%84%E9%83%A8%E5%88%86%E6%95%B0%E6%8D%AE%E8%BF%81%E7%A7%BB%E5%88%B0%20order%5C_record%20%E4%B8%AD%EF%BC%8C%E5%B9%B6%E5%B0%86%20order%5C_today%20%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%88%A0%E9%99%A4%EF%BC%8C%E8%BF%99%E6%A0%B7%E6%9D%A5%E9%99%8D%E4%BD%8E%20order%5C_today%20%E8%A1%A8%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E9%87%8F%E3%80%82%0A%0A%E7%94%B1%E4%BA%8E%E8%80%83%E8%99%91%E5%88%B0%E4%BC%9A%E5%8D%A0%E7%94%A8%E6%95%B0%E6%8D%AE%E5%BA%93%20I%2FO%EF%BC%8C%E4%B8%BA%E4%BA%86%E4%B8%8D%E5%BD%B1%E5%93%8D%E4%B8%9A%E5%8A%A1%EF%BC%8C%E8%AE%A1%E5%88%92%E6%98%AF%209%EF%BC%9A00%20%E4%BB%A5%E5%90%8E%E5%BC%80%E5%A7%8B%E8%BF%81%E7%A7%BB%EF%BC%8C%E4%BD%86%E6%98%AF%20xxx%20%E5%9C%A8%208%EF%BC%9A00%20%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%B0%9D%E8%AF%95%E8%BF%81%E7%A7%BB%E4%BA%86%E5%B0%91%E9%83%A8%E5%88%86%E6%95%B0%E6%8D%AE%EF%BC%881000%20%E6%9D%A1%EF%BC%89%EF%BC%8C%E8%A7%89%E5%BE%97%E6%B2%A1%E5%95%A5%E9%97%AE%E9%A2%98%EF%BC%8C%E5%B0%B1%E5%BC%80%E5%A7%8B%E8%80%83%E8%99%91%E5%A4%A7%E6%89%B9%E9%87%8F%E8%BF%81%E7%A7%BB%E3%80%82%0A%0A%E5%9C%A8%E8%BF%81%E7%A7%BB%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%EF%BC%8C%E5%BA%94%E6%80%A5%E7%BE%A4%E6%98%AF%E5%85%88%E5%8F%8D%E5%BA%94%E6%9C%89%E5%B0%8F%E9%83%A8%E5%88%86%E7%94%A8%E6%88%B7%E5%87%BA%E7%8E%B0%E6%94%AF%E4%BB%98%E5%A4%B1%E8%B4%A5%EF%BC%8C%E9%9A%8F%E5%90%8E%E5%8F%8D%E5%BA%94%E5%A4%A7%E6%89%B9%E7%94%A8%E6%88%B7%E5%87%BA%E7%8E%B0%E6%94%AF%E4%BB%98%E5%A4%B1%E8%B4%A5%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%8C%E4%BB%A5%E5%8F%8A%E5%88%9D%E5%A7%8B%E5%8C%96%E8%AE%A2%E5%8D%95%E5%A4%B1%E8%B4%A5%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%8C%E5%90%8C%E6%97%B6%E8%85%BE%E8%AE%AF%E4%B9%9F%E5%BC%80%E5%A7%8B%E6%8A%A5%E8%AD%A6%E3%80%82%0A%0A%E7%84%B6%E5%90%8E%20xxx%20%E5%B0%B1%E6%85%8C%E4%BA%86%EF%BC%8C%E7%AB%8B%E5%8D%B3%E5%81%9C%E6%AD%A2%E4%BA%86%E8%BF%81%E7%A7%BB%E3%80%82%E6%9C%AC%E4%BB%A5%E4%B8%BA%E5%81%9C%E6%AD%A2%E8%BF%81%E7%A7%BB%E5%B0%B1%E5%B0%B1%E5%8F%AF%E4%BB%A5%E6%81%A2%E5%A4%8D%E4%BA%86%EF%BC%8C%E4%BD%86%E6%98%AF%E5%B9%B6%E6%B2%A1%E6%9C%89%E3%80%82%0A%0A%E5%90%8E%E9%9D%A2%E5%8F%91%E7%94%9F%E7%9A%84%E4%BD%A0%E4%BB%AC%E5%8F%AF%E4%BB%A5%E8%84%91%E8%A1%A5%E4%B8%80%E4%B8%8B%EF%BC%8C%E5%BD%93%E6%97%B6%E6%95%B4%E4%B8%AA%E6%94%AF%E4%BB%98%E7%B3%BB%E7%BB%9F%E7%98%AB%E7%97%AA%E4%BA%86%E5%BF%AB%E4%B8%80%E4%B8%AA%E5%B0%8F%E6%97%B6%EF%BC%8C%E5%AE%A2%E6%9C%8D%E7%94%B5%E8%AF%9D%E9%83%BD%E8%A2%AB%E6%89%93%E7%88%86%E3%80%82%0A%0A%E4%BA%8B%E6%95%85%E8%BF%98%E5%8E%9F%0A%0A%E5%9C%A8%E6%9C%AC%E5%9C%B0%E5%BB%BA%E7%AB%8B%E4%B8%80%E4%B8%AA%E7%B2%BE%E7%AE%80%E7%89%88%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%8C%E5%B9%B6%E7%94%9F%E6%88%90%E4%BA%86%20100w%20%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%E6%A8%A1%E6%8B%9F%E7%BA%BF%E4%B8%8A%E5%8F%91%E7%94%9F%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%0A%0A%E5%BB%BA%E7%AB%8B%E8%A1%A8%E7%BB%93%E6%9E%84%0A%0A%E8%AE%A2%E5%8D%95%E8%A1%A8%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60sql%0ACREATE%20TABLE%20%60order_today%60%20(%0A%60id%60%20VARCHAR%20(%2032%20)%20NOT%20NULL%20COMMENT%20'%E4%B8%BB%E9%94%AE'%2C%0A%60merchant_id%60%20VARCHAR%20(%2032%20)%20CHARACTER%20SET%20utf8%20COLLATE%20utf8%20_general_ci%20NOT%20NULL%20COMMENT%20'%E5%95%86%E6%88%B7%E7%BC%96%E5%8F%B7'%2C%0A%60amount%60%20DECIMAL%20(%2015%2C%202%20)%20NOT%20NULL%20COMMENT%20'%E8%AE%A2%E5%8D%95%E9%87%91%E9%A2%9D'%2C%0A%60pay_success_time%60%20datetime%20NOT%20NULL%20COMMENT%20'%E6%94%AF%E4%BB%98%E6%88%90%E5%8A%9F%E6%97%B6%E9%97%B4'%2C%0A%60order_status%60%20VARCHAR%20(%2010%20)%20CHARACTER%20SET%20utf8%20COLLATE%20utf8%20_general_ci%20NOT%20NULL%20COMMENT%20'%E6%94%AF%E4%BB%98%E7%8A%B6%E6%80%81%20S%EF%BC%9A%E6%94%AF%E4%BB%98%E6%88%90%E5%8A%9F%E3%80%81F%EF%BC%9A%E8%AE%A2%E5%8D%95%E6%94%AF%E4%BB%98%E5%A4%B1%E8%B4%A5'%2C%0A%60remark%60%20VARCHAR%20(%20100%20)%20CHARACTER%20SET%20utf8%20COLLATE%20utf8%20_general%20_ci%20DEFAULT%20NULL%20COMMENT%20'%E5%A4%87%E6%B3%A8'%2C%0A%60create_time%60%20TIMESTAMP%20NOT%20NULL%20DEFAULT%20CURRENT%20_TIMESTAMP%20COMMENT%20'%E5%88%9B%E5%BB%BA%E6%97%B6%E9%97%B4'%2C%0A%60update_time%60%20TIMESTAMP%20NOT%20NULL%20DEFAULT%20CURRENT%20_TIMESTAMP%20ON%20UPDATE%20CURRENT_TIMESTAMP%20COMMENT%20'%E4%BF%AE%E6%94%B9%E6%97%B6%E9%97%B4%20--%20%E4%BF%AE%E6%94%B9%E6%97%B6%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0'%2C%0APRIMARY%20KEY%20(%20%60id%60%20)%20USING%20BTREE%2C%0AKEY%20%60idx_merchant_id%60%20(%20%60merchant_id%60%20)%20USING%20BTREE%20COMMENT%20'%E5%95%86%E6%88%B7%E7%BC%96%E5%8F%B7'%20%0A)%20ENGINE%20%3D%20INNODB%20DEFAULT%20CHARSET%20%3D%20utf8%3B%0A%60%60%60%0A%0A%E8%AE%A2%E5%8D%95%E8%AE%B0%E5%BD%95%E8%A1%A8%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0ACREATETABLE%20order%5C_record%20like%20order%5C_today%3B%0A%0A%E4%BB%8A%E6%97%A5%E8%AE%A2%E5%8D%95%E8%A1%A8%E6%95%B0%E6%8D%AE%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A!%5Bc19407fb2740ab27c4175abfec3b7c23.png%5D(en-resource%3A%2F%2Fdatabase%2F1199%3A1)%0A%0A%0A%E6%A8%A1%E6%8B%9F%E8%BF%81%E7%A7%BB%0A%0A%E6%8A%8A%208%20%E5%8F%B7%E4%B9%8B%E5%89%8D%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E8%BF%81%E7%A7%BB%E5%88%B0%20order_record%20%E8%A1%A8%E4%B8%AD%E5%8E%BB%EF%BC%9A%0A%0A%60%60%60sql%0AINSERT%20INTO%20order_record%20SELECT%20*%20FROM%20order_today%20WHERE%20pay_success_time%20%3C%20'2020-03-08%2000%3A00%3A00'%3B%0A%60%60%60%0A%0A%E5%9C%A8%20Navicat%20%E4%B8%AD%E8%BF%90%E8%A1%8C%E8%BF%81%E7%A7%BB%E7%9A%84%20SQL%EF%BC%8C%E5%90%8C%E6%97%B6%E5%BC%80%E5%8F%A6%E4%B8%AA%E4%B8%80%E4%B8%AA%E7%AA%97%E5%8F%A3%E6%8F%92%E5%85%A5%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%A8%A1%E6%8B%9F%E4%B8%8B%E5%8D%95%EF%BC%9A%0A%0A!%5Be132f46874aef455f06a82273a6178fe.png%5D(en-resource%3A%2F%2Fdatabase%2F1201%3A1)%0A%0A%0A%E4%BB%8E%E4%B8%8A%E9%9D%A2%E5%8F%AF%E4%BB%A5%E5%8F%91%E7%8E%B0%E4%B8%80%E5%BC%80%E5%A7%8B%E8%83%BD%E6%AD%A3%E5%B8%B8%E6%8F%92%E5%85%A5%EF%BC%8C%E4%BD%86%E6%98%AF%E5%90%8E%E9%9D%A2%E7%AA%81%E7%84%B6%E5%B0%B1%E5%8D%A1%E4%BD%8F%E4%BA%86%EF%BC%8C%E5%B9%B6%E4%B8%94%E8%80%97%E8%B4%B9%E4%BA%86%2023s%20%E6%89%8D%E6%88%90%E5%8A%9F%EF%BC%8C%E7%84%B6%E5%90%8E%E6%89%8D%E8%83%BD%E7%BB%A7%E7%BB%AD%E6%8F%92%E5%85%A5%E3%80%82%E8%BF%99%E4%B8%AA%E6%97%B6%E5%80%99%E5%B7%B2%E7%BB%8F%E8%BF%81%E7%A7%BB%E6%88%90%E5%8A%9F%E4%BA%86%EF%BC%8C%E6%89%80%E4%BB%A5%E8%83%BD%E6%AD%A3%E5%B8%B8%E6%8F%92%E5%85%A5%E4%BA%86%E3%80%82%0A%0A%E5%87%BA%E7%8E%B0%E7%9A%84%E5%8E%9F%E5%9B%A0%0A%0A%E5%9C%A8%E9%BB%98%E8%AE%A4%E7%9A%84%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E4%B8%8B%EF%BC%9Ainsert%20into%20order%5C_record%20select%20*%20from%20order%5C_today%20%E5%8A%A0%E9%94%81%E8%A7%84%E5%88%99%E6%98%AF%EF%BC%9Aorder%5C_record%20%E8%A1%A8%E9%94%81%EF%BC%8Corder%5C_today%20%E9%80%90%E6%AD%A5%E9%94%81%EF%BC%88%E6%89%AB%E6%8F%8F%E4%B8%80%E4%B8%AA%E9%94%81%E4%B8%80%E4%B8%AA%EF%BC%89%E3%80%82%0A%0A%E5%88%86%E6%9E%90%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%EF%BC%9A%0A%0A!%5Bb87ae71322fe1ae25730b61f6fdfab57.png%5D(en-resource%3A%2F%2Fdatabase%2F1203%3A1)%0A%0A%0A%E9%80%9A%E8%BF%87%E8%A7%82%E5%AF%9F%E8%BF%81%E7%A7%BB%20SQL%20%E7%9A%84%E6%89%A7%E8%A1%8C%E6%83%85%E5%86%B5%E4%BD%A0%E4%BC%9A%E5%8F%91%E7%8E%B0%20order%5C_today%20%E6%98%AF%E5%85%A8%E8%A1%A8%E6%89%AB%E6%8F%8F%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%84%8F%E5%91%B3%E7%9D%80%E5%9C%A8%E6%89%A7%E8%A1%8C%20insert%20into%20select%20from%20%E8%AF%AD%E5%8F%A5%E6%97%B6%EF%BC%8CMySQL%20%E4%BC%9A%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%AB%E6%8F%8F%20order%5C_today%20%E5%86%85%E7%9A%84%E8%AE%B0%E5%BD%95%E5%B9%B6%E4%B8%94%E5%8A%A0%E9%94%81%EF%BC%8C%E8%BF%99%E6%A0%B7%E4%B8%80%E6%9D%A5%E4%B8%8D%E5%B0%B1%E5%92%8C%E7%9B%B4%E6%8E%A5%E9%94%81%E8%A1%A8%E6%98%AF%E4%B8%80%E6%A0%B7%E4%BA%86%E3%80%82%0A%0A%E8%BF%99%E4%B9%9F%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%A7%A3%E9%87%8A%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%80%E5%BC%80%E5%A7%8B%E5%8F%AA%E6%9C%89%E5%B0%91%E9%87%8F%E7%94%A8%E6%88%B7%E5%87%BA%E7%8E%B0%E6%94%AF%E4%BB%98%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%90%8E%E7%BB%AD%E5%A4%A7%E9%87%8F%E7%94%A8%E6%88%B7%E5%87%BA%E7%8E%B0%E6%94%AF%E4%BB%98%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%88%9D%E5%A7%8B%E5%8C%96%E8%AE%A2%E5%8D%95%E5%A4%B1%E8%B4%A5%E7%AD%89%E6%83%85%E5%86%B5%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%B8%80%E5%BC%80%E5%A7%8B%E5%8F%AA%E9%94%81%E5%AE%9A%E4%BA%86%E5%B0%91%E9%83%A8%E5%88%86%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%B2%A1%E6%9C%89%E8%A2%AB%E9%94%81%E5%AE%9A%E7%9A%84%E6%95%B0%E6%8D%AE%E8%BF%98%E6%98%AF%E5%8F%AF%E4%BB%A5%E6%AD%A3%E5%B8%B8%E8%A2%AB%E4%BF%AE%E6%94%B9%E4%B8%BA%E6%AD%A3%E5%B8%B8%E7%8A%B6%E6%80%81%E3%80%82%0A%0A%E7%94%B1%E4%BA%8E%E9%94%81%E5%AE%9A%E7%9A%84%E6%95%B0%E6%8D%AE%E8%B6%8A%E6%9D%A5%E8%B6%8A%E5%A4%9A%EF%BC%8C%E5%B0%B1%E5%AF%BC%E8%87%B4%E5%87%BA%E7%8E%B0%E4%BA%86%E5%A4%A7%E9%87%8F%E6%94%AF%E4%BB%98%E5%A4%B1%E8%B4%A5%E3%80%82%E6%9C%80%E5%90%8E%E5%85%A8%E9%83%A8%E9%94%81%E4%BD%8F%EF%BC%8C%E5%AF%BC%E8%87%B4%E6%97%A0%E6%B3%95%E6%8F%92%E5%85%A5%E8%AE%A2%E5%8D%95%EF%BC%8C%E8%80%8C%E5%87%BA%E7%8E%B0%E5%88%9D%E5%A7%8B%E5%8C%96%E8%AE%A2%E5%8D%95%E5%A4%B1%E8%B4%A5%E3%80%82%0A%0A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%0A%0A%E7%94%B1%E4%BA%8E%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%E4%BC%9A%E5%AF%BC%E8%87%B4%20order%5C_today%20%E5%85%A8%E8%A1%A8%E6%89%AB%E6%8F%8F%EF%BC%8C%E4%BB%80%E4%B9%88%E8%83%BD%E9%81%BF%E5%85%8D%E5%85%A8%E8%A1%A8%E6%89%AB%E6%8F%8F%E5%91%A2%EF%BC%8C%E5%BE%88%E7%AE%80%E5%8D%95%E5%98%9B%EF%BC%8C%E7%BB%99%20pay%5C_success%5C_time%20%E5%AD%97%E6%AE%B5%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%20idx%5C_pay%5C_suc%5C_time%20%E7%B4%A2%E5%BC%95%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BA%86%E3%80%82%0A%0A%E7%94%B1%E4%BA%8E%E8%B5%B0%E7%B4%A2%E5%BC%95%E6%9F%A5%E8%AF%A2%EF%BC%8C%E5%B0%B1%E4%B8%8D%E4%BC%9A%E5%87%BA%E7%8E%B0%E6%89%AB%E6%8F%8F%E5%85%A8%E8%A1%A8%E7%9A%84%E6%83%85%E5%86%B5%E8%80%8C%E9%94%81%E8%A1%A8%E4%BA%86%EF%BC%8C%E5%8F%AA%E4%BC%9A%E9%94%81%E5%AE%9A%E7%AC%A6%E5%90%88%E6%9D%A1%E4%BB%B6%E7%9A%84%E8%AE%B0%E5%BD%95%E3%80%82%0A%0A%E6%9C%80%E7%BB%88%E7%9A%84%20SQL%EF%BC%9A%0A%0A%60%60%60sql%0AINSERTINTO%20order_record%20SELECT%20*%20FROM%20order_today%20FORCE%20INDEX%20(idx_pay_suc_time)%20WHERE%20pay_success_time%20%3C%3D%20'2020-03-08%2000%3A00%3A00'%3B%0A%60%60%60%0A%0A%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A!%5B1c6a822b9bcbecd9e53fd46a68322d7d.png%5D(en-resource%3A%2F%2Fdatabase%2F1205%3A1)%0A%0A%E6%80%BB%E7%BB%93%0A%E4%BD%BF%E7%94%A8%20insert%20into%20table%20A%20select%20*%20from%20table%20B%20%E8%AF%AD%E5%8F%A5%E6%97%B6%EF%BC%8C%E4%B8%80%E5%AE%9A%E8%A6%81%E7%A1%AE%E4%BF%9D%20table%20B%20%E5%90%8E%E9%9D%A2%E7%9A%84%20where%EF%BC%8Corder%20%E6%88%96%E8%80%85%E5%85%B6%E4%BB%96%E6%9D%A1%E4%BB%B6%EF%BC%8C%E9%83%BD%E9%9C%80%E8%A6%81%E6%9C%89%E5%AF%B9%E5%BA%94%E7%9A%84%E7%B4%A2%E5%BC%95%EF%BC%8C%E6%9D%A5%E9%81%BF%E5%85%8D%E5%87%BA%E7%8E%B0%20table%20B%20%E5%85%A8%E9%83%A8%E8%AE%B0%E5%BD%95%E8%A2%AB%E9%94%81%E5%AE%9A%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%0A

spring-mybatis

创建时间:2020/9/2 15:32
更新时间:2020/9/2 15:33
作者:Chris

1. type-aliases-package

mapper.xml文件中resultMap的type或者parameterType会使用自定义的pojo,
此时可以用完全限定名来指定这些POJO的引用,例如

<select resultType="com.e3mall.cmsao.mapper.User">

或者你可以通过在application.properties中指定POJO扫描包来让mybatis自动扫描到自定义POJO

application.properties

mybatis.type-aliases-package=com.e3mall.cms.dao.mapper

application.yml

mybatis:
  mapper-locations: classpath:mapper/*.xml
  #所有Entity别名类所在包
  type-aliases-package: com.chris.springcloud.payment.main.entities
%0A%0A%23%23%23%23%201.%20type-aliases-package%0A%0Amapper.xml%E6%96%87%E4%BB%B6%E4%B8%ADresultMap%E7%9A%84**type**%E6%88%96%E8%80%85**parameterType**%E4%BC%9A%E4%BD%BF%E7%94%A8%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84pojo%EF%BC%8C%0A%E6%AD%A4%E6%97%B6%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%AE%8C%E5%85%A8%E9%99%90%E5%AE%9A%E5%90%8D%E6%9D%A5%E6%8C%87%E5%AE%9A%E8%BF%99%E4%BA%9BPOJO%E7%9A%84%E5%BC%95%E7%94%A8%EF%BC%8C%E4%BE%8B%E5%A6%82%0A%0A%60%60%60%0A%3Cselect%20id%3D%22getUsers%22%20resultType%3D%22com.e3mall.cmsao.mapper.User%22%3E%0A%60%60%60%0A%0A%20%20%E6%88%96%E8%80%85%E4%BD%A0%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%9C%A8application.properties%E4%B8%AD%E6%8C%87%E5%AE%9APOJO%E6%89%AB%E6%8F%8F%E5%8C%85%E6%9D%A5%E8%AE%A9mybatis%E8%87%AA%E5%8A%A8%E6%89%AB%E6%8F%8F%E5%88%B0%E8%87%AA%E5%AE%9A%E4%B9%89POJO%0A%0Aapplication.properties%0A%0A%20%20%60%60%60%0Amybatis.type-aliases-package%3Dcom.e3mall.cms.dao.mapper%0A%20%20%60%60%60%0A%0A%20application.yml%0A%0A%60%60%60%0Amybatis%3A%0A%20%20mapper-locations%3A%20classpath%3Amapper%2F*.xml%0A%20%20%23%E6%89%80%E6%9C%89Entity%E5%88%AB%E5%90%8D%E7%B1%BB%E6%89%80%E5%9C%A8%E5%8C%85%0A%20%20type-aliases-package%3A%20com.chris.springcloud.payment.main.entities%0A%60%60%60%0A

connectivity verification

创建时间:2020/9/2 15:30
更新时间:2020/9/2 15:30
作者:Chris

ProtocolDefault port number
https443
http80
ftp21
sftp/SSH22
sftp -oPort=22 sftpHost
sftp -oPort=22 userName@sftpHost
sftp -oPort=22 82.196.50.13
sftp -oPort=22 ilayer_uat@82.196.50.13
nc 82.196.50.13 22
ftp 10.205.5.75 21
telnet 219.139.242.199 22

An useful option to check connectivity for FTP/SFTP is <kbd>nc</kbd>. In this case we provide the proxy setup. For example:

/usr/bin/nc -v omcs-proxy.oracleoutsourcing.com 80 mft-ftp.cegedim-srh.net 22
ping vmohssgds061.oracleoutsourcing.com -l 950 -n 100
tracert -d vmohssgds061.oracleoutsourcing.com

you can include the details of the proxy by using option –x

curl -x omcs-proxy.oracleoutsourcing.com:80 -k -v https://61.183.154.3:443/jdcj?wsdl
curl -x omcs-proxy.oracleoutsourcing.com:80 -k -v http://61.183.154.3:8182/jdcj?wsdl

if you want to download a file, you can use curl with the -O or -o options. The former will save the file in the current working directory with the same name as in the remote location, whereas the latter allows you to specify a different filename and/or location.

  1. Save as yourfile.tar.gz
$ curl -OL http://yourdomain.com/yourfile.tar.gz 
  1. Save as newfile.tar.gz
$ curl -oL newfile.tar.gz http://yourdomain.com/yourfile.tar.gz 
  1. Download Files from an FTP Server with or without Authentication
$ curl -u username:password -O ftp://yourftpserver/yourfile.tar.gz 
  1. Upload Files to an FTP server with or without Authentication
$ curl -u username:password -T mylocalfile.tar.gz ftp://yourftpserver
%7C%20Protocol%20%7C%20Default%20port%20number%20%7C%0A%7C%20--------%20%7C%20-------------------%20%7C%0A%7C%20https%20%20%20%20%7C%20443%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20http%20%20%20%20%20%7C%2080%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20ftp%20%20%20%20%20%20%7C%2021%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20sftp%2FSSH%20%7C%2022%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%0A%20%20%20%20sftp%20-oPort%3D22%20sftpHost%0A%20%20%20%20sftp%20-oPort%3D22%20userName%40sftpHost%0A%20%20%20%20sftp%20-oPort%3D22%2082.196.50.13%0A%20%20%20%20sftp%20-oPort%3D22%20ilayer_uat%4082.196.50.13%0A%60%60%60%0Anc%2082.196.50.13%2022%0Aftp%2010.205.5.75%2021%0Atelnet%20219.139.242.199%2022%0A%60%60%60%0AAn%20useful%20option%20to%20check%20connectivity%20for%20FTP%2FSFTP%20is%20%3Ckbd%3Enc%3C%2Fkbd%3E.%20In%20this%20case%20we%20provide%20the%20proxy%20setup.%20For%20example%3A%0A%0A%60%60%60%0A%2Fusr%2Fbin%2Fnc%20-v%20omcs-proxy.oracleoutsourcing.com%2080%20mft-ftp.cegedim-srh.net%2022%0A%60%60%60%0A%60%60%60%0Aping%20vmohssgds061.oracleoutsourcing.com%20-l%20950%20-n%20100%0Atracert%20-d%20vmohssgds061.oracleoutsourcing.com%0A%60%60%60%0Ayou%20can%20include%20the%20details%20of%20the%20proxy%20by%20using%20option%20%E2%80%93x%0A%0A%60%60%60%0Acurl%20-x%20omcs-proxy.oracleoutsourcing.com%3A80%20-k%20-v%20https%3A%2F%2F61.183.154.3%3A443%2Fjdcj%3Fwsdl%0Acurl%20-x%20omcs-proxy.oracleoutsourcing.com%3A80%20-k%20-v%20http%3A%2F%2F61.183.154.3%3A8182%2Fjdcj%3Fwsdl%0A%60%60%60%0A%0Aif%20you%20want%20to%20download%20a%20file%2C%20you%20can%20use%20curl%20with%20the%20-O%20or%20-o%20options.%20The%20former%20will%20save%20the%20file%20in%20the%20current%20working%20directory%20with%20the%20same%20name%20as%20in%20the%20remote%20location%2C%20whereas%20the%20latter%20allows%20you%20to%20specify%20a%20different%20filename%20and%2For%20location.%0A%0A1.%20Save%20as%20yourfile.tar.gz%20%0A%0A%60%60%60%0A%24%20curl%20-OL%20http%3A%2F%2Fyourdomain.com%2Fyourfile.tar.gz%20%0A%60%60%60%0A%0A2.%20Save%20as%20newfile.tar.gz%0A%0A%60%60%60%0A%24%20curl%20-oL%20newfile.tar.gz%20http%3A%2F%2Fyourdomain.com%2Fyourfile.tar.gz%20%0A%60%60%60%0A3.%20Download%20Files%20from%20an%20FTP%20Server%20with%20or%20without%20Authentication%0A%0A%60%60%60%0A%24%20curl%20-u%20username%3Apassword%20-O%20ftp%3A%2F%2Fyourftpserver%2Fyourfile.tar.gz%20%0A%60%60%60%0A4.%20Upload%20Files%20to%20an%20FTP%20server%20with%20or%20without%20Authentication%0A%0A%60%60%60%0A%24%20curl%20-u%20username%3Apassword%20-T%20mylocalfile.tar.gz%20ftp%3A%2F%2Fyourftpserver%0A%60%60%60

shell

创建时间:2020/9/2 15:27
更新时间:2020/9/2 15:29
作者:Chris

bash file returns unexpected token `$'do\r''

apt-get install dos2unix 
dos2unix my_script.sh

#!/bin/bash --用哪个命令编译器来解释,放在第一行

执行shell脚本的方法有两种

1. bash script.sh  --不需要对脚本写解析器,
2.  ./script.sh

每两分钟执行一次

crontab -e
*/2 * * * *  /home/chris/shells/clearftpdir.sh
crontab -l --查看系统中现有的定时任务
crontab -u root -l --查看root用户下的定时任务
变量
用户自定义变量:由用户自已定义修改和使用
shell预定义变量:
位置变量:通过命令行给程序传递执行参数,总共可以接收九个位置变量$1~$9
变量名以字母或下划线开头,区分大小写
v_name=value
$v_name or ${v_name}
从键盘输入值并赋值给变量
read -p "msg" v_name
unset v_name

位置变量:从$1 到$9

数学运算:

total=expre $1 + $2

total=$(($1+$2))

+

-

* total=$(($1*$2))

/

%

$# 命令行中位置参数的个数
$* 所有位置参数的内容
$? 上一条命令执行后返回的状态,0表示执行成功,非0表示执行失败
$0 当前执行的进程/程度名
对引号"":可以解释$引用的变量,不能解释转义字符
单引号'': 不能解释变量,$被视为普通字符,不能解释转义字符
反引号``:用来解释命令并把命令的返回值输出给变量。

--解释输出中的转义字符

echo -e "my name is chris*\n*my name is user1" 

--输出不换行等待键盘输入

echo -n "pls input your name" 
read name
read -p "pls input your name:" name
echo "my name is $name"
echo -e "httpd  process \033[32;40m[ok]\033[0m"

\033[前景色;背景色m

\033[0m --恢复到系统默认的颜色, 不然往后的颜色都会被改变

\033[30m -- \033[37m 设置前景色(字体颜色)

\033[30m 将字符的显示颜色改为黑色

\033[31m 将字符的显示颜色改为红色

\033[32m 将字符的显示颜色改为绿色

\033[33m 将字符的显示颜色改为淡红色

\033[34m 将字符的显示颜色改为蓝色

\033[35m 将字符的显示颜色改为紫色

\033[36m 将字符的显示颜色改为淡蓝色

\033[37m 将字符的显示颜色改为灰色

\033[40m -- \033[47m 设置背景色

\033[40m 将背景色设置为黑色

\033[41m 将背景色设置为红色

\033[42m 将背景色设置为绿色

\033[43m 将背景色设置为淡红色

\033[44m 将背景色设置为蓝色

\033[45m 将背景色设置为紫色

\033[46m 将背景色设置为淡蓝色

\033[47m 将背景色设置为灰色

--输出前n行

cat /etc/passwd | head -n

--输出后n行

cat /etc/passwd | tail -n

--输出的同时并将输出的内容保存到另一个文件中

cat /etc/passwd | tee copy.1
将字符块原样输出, x 为块开始和结束标记,其可以为任何字符
cat<<x
pls choose your name:
​    1>chris
​    2>john
​    3>jeffery
​    4>frederic
x
nl  --number lines of files
cat /etc/passwd | head -n | nl
nl /etc/passwd
nl /etc/passwd >> mypass.txt

条件测试

test 测试表达式是否成立,成立返回0否则返回其它值

测试文件状态

格式:[ 操作符 文件或目录 ]

操作符

-d 测试是否为目录

-e 测试目录或文件是否存在

-f 测试是否为文件

-r 测试当前用户是否有read权限

-w 测试当前用户是否有write权限

-x 测试当前用户是否有excute权限

-L 测试是否为link文件

字符串比较

格式:

[str1 = str2]

[str1 != str2]

[-z str] --判断字符串是否为空

整数值比较

[ 整数1 操作符 整数2]

-eq

-ne

-gt

-lt

-le

-ge

逻辑测试

-a &&

-o ||

!

if 语句

if [ $score -lt 60 ]; then

​ echo '60以下'

elif [ $score -ge 60 ] && [ $score -lt 70 ]; then

​ echo '60-70之间'

elif [ $score -ge 70 ] && [ $score -lt 80 ]; then

​ echo '70-80之间'

elif [ $score -gt 80 ] && [ $score -lt 90 ]; then

​ echo '80-90之间'

else

​ echo '90以上!'

fi

case 语句

weekday=date +%w

case $weekday in

​ 1 )

​ echo 'Monday'

​ ;;

​ 2 )

​ echo 'Tuesday'

​ ;;

esac

while 语句

num=3

tot=0

while [ $num -gt 0 ]; do

​ echo $num

tot=((tot+$num))

​ num=((num-1))

done

for 语句

for i in user0 user1 user2 user3 user4 user5

do

​ echo $i

​ userdel -r $i

done

for (( i = 1; i <= 10; i++ )); do

​ echo $i

​ user="user$i"

​ userdel -r $user

done

--skip the user5

for (( i = 1; i <= 10; i++ )); do

​ echo $i

​ user="user$i"

if [ $i -eq 5 ]; then

continue

fi

​ userdel -r $user

done

--input 1 to 5

for (( i = 1; i <= 10; i++ )); do

​ echo $i

​ user="user$i"

if [ $i -eq 5 ]; then

break

fi

done

shift 用于迁移位置变量,将$1~$9 依次向左传递

tot=0

while [ $# -gt 0 ]; do

​ tot=((tot+$1))

​ shift

done

函数

function add(){

echo $(($1+$2))

}

add 11 12

find 查文件
find . -name '*.txt'  -- search files in current dir which's extension is .txt
find . -name '*file[1-6]*.txt' 
find . -perm 755 -type f
-type
c     character (unbuffered) special
d     directory
f     regular file
find / -user user1 -- find the files create by user1 from root dir
stat ./test.txt --display file or file system status
find . -mtime -5   -- find the files which're been modified for 5 days
find . -mtime +3  -- find the files which're been modified before 3 days ago 
find . -size +1000000c -- find files which's size is roughly 1M
find . -name '*file[1-6]*.txt'  | xargs rm -rf  --xargs 将find找到的文件作为参数传给后面的rm命令处理,因为rm删除文件时需要文件名
grep 查文件中的内容

grep "linux" *

grep -c "linux" filename --print a count of matching lines for each input file

grep -n "linux" filename --prefix each line of output with the line number within its input file

grep -i "linux" filename --ignore-case

grep -v "linux" filename --to select non-matching lines

grep -E "^linux" filename --search the line start by linux

grep -E "linux$" filename --search the line end by linux

grep -E ".+linux.+" finename --seach the line including linux but not start and end by linux

grep -E "^$" filename --empty line

grep -E "^.$" filename --match lines which only have one character

grep -E '[0-9]+' filename --match numbers

grep -En '[0-9]+.[0-9]+.[0-9]+.[0-9]+' filename --match ip

grep -En '([0-9]+.){3}[0-9]+' filename

grep -E '2014:22:5[0-9]' filename --在文件中查找时间在2014:22:50到2014:22:59之间的行

grep -E '^[^210]' filename --在文件中查找不是以210开头的行

grep -E '^2004|^2015' filename --在文件中查找是以2004或以2015开头的行

grep -E '[6-9][0-9]' filename --查找从60到99之间的成绩

. 任意一个字符

+ 多个字符

* 零个或多个字符

[0-9a-z] 匹配[]是的任意一个

(linux)+ 匹配出现多次的单元()

\ 对正则表达示式中的特殊字符进行车转义

(unit){n} 匹配n个的单元

(unit){n,} 匹配n个以上的单元

(unit){n,x} 匹配n到x个的单元

awk -F: '{print }'

awk 默认的分隔符是空格

cat /etc/passwd | cut -d: -f1 --以:为分隔符并取出第一列

cat /etc/passwd | awk -F: '{print $1}' --以:为分隔符并取出第一列

cat /etc/passwd | awk -F: '{print "username: "$1" => Shell: "$7}' --以:为分隔符并取出第一列和第七列

cat /etc/passwd | awk -F: '{print $1}'

NR -- awk中的一个常量代表行号

NF -- awk中的一个常量代表列号

df | awk '{if(NR==4){print $0}}' --打印出第四行的整行

df | awk '{if(NR==4){print $1}}' --打印出第四行的第一列

df | awk '{if(NR==4){print int($5)}}' --将字符串转成int型方便进行整形比较

df | awk 'END{print NR}' --打印出总共的行数

df | awk 'END{print NF}' --打印出总共的列数

sed 行定位的使用

sed -n '3,5'p filename --打印出3到5行

sed '3,5'd filename --打印出除第3到5行之外的数据

cat /etc/passwd | sed -n "/bash/"p --打印出包含bash的行

cat /etc/passwd | sed -n '2,/sys:/'p --打印出第2行到包含sys:的行

cat sedtemp | sed -n '/333/,$'p --打印出包含333的行到最后一行

uniq 可检查文本文件中重复出现的行列
uniq filename		--打印出过滤掉紧挨重复行的唯一值
uniq -c filename	--打印出紧挨重复行出现的次数
uniq -d filename	--只打印出紧挨重复的行
Linux sort命令用于将文本文件内容加以排序
sort filename	--升序排列
sort -r filename	--降序排列
sort uniqtemp | uniq -c
cat uniqtemp | sort -t: -k2 -r 	--以:分隔后的第二列的倒序进行排序,默认分隔符为空格
%0A%0A%5Bbash%20file%20returns%20unexpected%20token%20%60%24'do%5Cr''%5D(https%3A%2F%2Fstackoverflow.com%2Fquestions%2F27176781%2Fbash-file-returns-unexpected-token-do-r)%0A%0A%60%60%60%0Aapt-get%20install%20dos2unix%20%0Ados2unix%20my_script.sh%0A%60%60%60%0A%0A%5C%23!%2Fbin%2Fbash%20%20--%E7%94%A8%E5%93%AA%E4%B8%AA%E5%91%BD%E4%BB%A4%E7%BC%96%E8%AF%91%E5%99%A8%E6%9D%A5%E8%A7%A3%E9%87%8A%EF%BC%8C%E6%94%BE%E5%9C%A8%E7%AC%AC%E4%B8%80%E8%A1%8C%0A%0A%E6%89%A7%E8%A1%8Cshell%E8%84%9A%E6%9C%AC%E7%9A%84%E6%96%B9%E6%B3%95%E6%9C%89%E4%B8%A4%E7%A7%8D%0A%0A%60%60%60%0A1.%20bash%20script.sh%20%20--%E4%B8%8D%E9%9C%80%E8%A6%81%E5%AF%B9%E8%84%9A%E6%9C%AC%E5%86%99%E8%A7%A3%E6%9E%90%E5%99%A8%EF%BC%8C%0A2.%20%20.%2Fscript.sh%0A%60%60%60%0A%0A%E6%AF%8F%E4%B8%A4%E5%88%86%E9%92%9F%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%0A%0A%60%60%60%0Acrontab%20-e%0A*%2F2%20*%20*%20*%20*%20%20%2Fhome%2Fchris%2Fshells%2Fclearftpdir.sh%0A%60%60%60%0A%0A%7C%20crontab%20-l%20%20--%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%8E%B0%E6%9C%89%E7%9A%84%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%20%20%20%20%20%20%20%20%7C%0A%7C%20---------------------------------------------%20%7C%0A%7C%20crontab%20-u%20root%20-l%20--%E6%9F%A5%E7%9C%8Broot%E7%94%A8%E6%88%B7%E4%B8%8B%E7%9A%84%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%20%7C%0A%0A%0A%0A%23%23%23%23%23%20%E5%8F%98%E9%87%8F%0A%0A%7C%20%E7%94%A8%E6%88%B7%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%98%E9%87%8F%EF%BC%9A%E7%94%B1%E7%94%A8%E6%88%B7%E8%87%AA%E5%B7%B2%E5%AE%9A%E4%B9%89%E4%BF%AE%E6%94%B9%E5%92%8C%E4%BD%BF%E7%94%A8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20------------------------------------------------------------%20%7C%0A%7C%20shell%E9%A2%84%E5%AE%9A%E4%B9%89%E5%8F%98%E9%87%8F%EF%BC%9A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%E4%BD%8D%E7%BD%AE%E5%8F%98%E9%87%8F%EF%BC%9A%E9%80%9A%E8%BF%87%E5%91%BD%E4%BB%A4%E8%A1%8C%E7%BB%99%E7%A8%8B%E5%BA%8F%E4%BC%A0%E9%80%92%E6%89%A7%E8%A1%8C%E5%8F%82%E6%95%B0%2C%E6%80%BB%E5%85%B1%E5%8F%AF%E4%BB%A5%E6%8E%A5%E6%94%B6%E4%B9%9D%E4%B8%AA%E4%BD%8D%E7%BD%AE%E5%8F%98%E9%87%8F%241~%249%20%7C%0A%0A%23%23%23%23%23%20%E5%8F%98%E9%87%8F%E5%90%8D%E4%BB%A5%E5%AD%97%E6%AF%8D%E6%88%96%E4%B8%8B%E5%88%92%E7%BA%BF%E5%BC%80%E5%A4%B4%EF%BC%8C%E5%8C%BA%E5%88%86%E5%A4%A7%E5%B0%8F%E5%86%99%0A%0A%60%60%60%0Av_name%3Dvalue%0A%24v_name%20or%20%24%7Bv_name%7D%0A%60%60%60%0A%0A%23%23%23%23%23%20%E4%BB%8E%E9%94%AE%E7%9B%98%E8%BE%93%E5%85%A5%E5%80%BC%E5%B9%B6%E8%B5%8B%E5%80%BC%E7%BB%99%E5%8F%98%E9%87%8F%0A%0A%60%60%60%0Aread%20-p%20%22msg%22%20v_name%0Aunset%20v_name%0A%60%60%60%0A%0A%E4%BD%8D%E7%BD%AE%E5%8F%98%E9%87%8F%EF%BC%9A%E4%BB%8E%241%20%E5%88%B0%249%0A%0A%E6%95%B0%E5%AD%A6%E8%BF%90%E7%AE%97%EF%BC%9A%0A%0Atotal%3Dexpre%20%241%20%2B%20%242%0A%0Atotal%3D%24((%241%2B%242))%0A%0A%5C%2B%20%0A%0A%5C-%20%0A%0A%5C*%20%09total%3D%24((%241%5C*%242))%0A%0A%2F%20%0A%0A%25%0A%0A%7C%20%24%23%20%E5%91%BD%E4%BB%A4%E8%A1%8C%E4%B8%AD%E4%BD%8D%E7%BD%AE%E5%8F%82%E6%95%B0%E7%9A%84%E4%B8%AA%E6%95%B0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20------------------------------------------------------------%20%7C%0A%7C%20%24*%20%20%E6%89%80%E6%9C%89%E4%BD%8D%E7%BD%AE%E5%8F%82%E6%95%B0%E7%9A%84%E5%86%85%E5%AE%B9%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%24%3F%20%E4%B8%8A%E4%B8%80%E6%9D%A1%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E5%90%8E%E8%BF%94%E5%9B%9E%E7%9A%84%E7%8A%B6%E6%80%81%EF%BC%8C0%E8%A1%A8%E7%A4%BA%E6%89%A7%E8%A1%8C%E6%88%90%E5%8A%9F%EF%BC%8C%E9%9D%9E0%E8%A1%A8%E7%A4%BA%E6%89%A7%E8%A1%8C%E5%A4%B1%E8%B4%A5%20%7C%0A%7C%20*%240%20%E5%BD%93%E5%89%8D%E6%89%A7%E8%A1%8C%E7%9A%84%E8%BF%9B%E7%A8%8B%2F%E7%A8%8B%E5%BA%A6%E5%90%8D*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%0A%60%60%60%0A%E5%AF%B9%E5%BC%95%E5%8F%B7%22%22%EF%BC%9A%E5%8F%AF%E4%BB%A5%E8%A7%A3%E9%87%8A%24%E5%BC%95%E7%94%A8%E7%9A%84%E5%8F%98%E9%87%8F%EF%BC%8C%E4%B8%8D%E8%83%BD%E8%A7%A3%E9%87%8A%E8%BD%AC%E4%B9%89%E5%AD%97%E7%AC%A6%0A%E5%8D%95%E5%BC%95%E5%8F%B7''%EF%BC%9A%20%E4%B8%8D%E8%83%BD%E8%A7%A3%E9%87%8A%E5%8F%98%E9%87%8F%EF%BC%8C%24%E8%A2%AB%E8%A7%86%E4%B8%BA%E6%99%AE%E9%80%9A%E5%AD%97%E7%AC%A6%EF%BC%8C%E4%B8%8D%E8%83%BD%E8%A7%A3%E9%87%8A%E8%BD%AC%E4%B9%89%E5%AD%97%E7%AC%A6%0A%E5%8F%8D%E5%BC%95%E5%8F%B7%60%60%EF%BC%9A%E7%94%A8%E6%9D%A5%E8%A7%A3%E9%87%8A%E5%91%BD%E4%BB%A4%E5%B9%B6%E6%8A%8A%E5%91%BD%E4%BB%A4%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E8%BE%93%E5%87%BA%E7%BB%99%E5%8F%98%E9%87%8F%E3%80%82%0A%60%60%60%0A%0A%0A%0A--%E8%A7%A3%E9%87%8A%E8%BE%93%E5%87%BA%E4%B8%AD%E7%9A%84%E8%BD%AC%E4%B9%89%E5%AD%97%E7%AC%A6%0A%0A%60%60%60%0Aecho%20-e%20%22my%20name%20is%20chris*%5Cn*my%20name%20is%20user1%22%20%0A%60%60%60%0A%0A--%E8%BE%93%E5%87%BA%E4%B8%8D%E6%8D%A2%E8%A1%8C%E7%AD%89%E5%BE%85%E9%94%AE%E7%9B%98%E8%BE%93%E5%85%A5%0A%0A%60%60%60%0Aecho%20-n%20%22pls%20input%20your%20name%22%20%0Aread%20name%0Aread%20-p%20%22pls%20input%20your%20name%3A%22%20name%0Aecho%20%22my%20name%20is%20%24name%22%0Aecho%20-e%20%22httpd%20%20process%20%5C033%5B32%3B40m%5Bok%5D%5C033%5B0m%22%0A%60%60%60%0A%0A%5C033%5B%E5%89%8D%E6%99%AF%E8%89%B2%3B%E8%83%8C%E6%99%AF%E8%89%B2m%0A%0A%5C033%5B0m%20--%E6%81%A2%E5%A4%8D%E5%88%B0%E7%B3%BB%E7%BB%9F%E9%BB%98%E8%AE%A4%E7%9A%84%E9%A2%9C%E8%89%B2%EF%BC%8C%20%E4%B8%8D%E7%84%B6%E5%BE%80%E5%90%8E%E7%9A%84%E9%A2%9C%E8%89%B2%E9%83%BD%E4%BC%9A%E8%A2%AB%E6%94%B9%E5%8F%98%0A%0A%5C033%5B30m%20--%20%5C033%5B37m%20%E8%AE%BE%E7%BD%AE%E5%89%8D%E6%99%AF%E8%89%B2(%E5%AD%97%E4%BD%93%E9%A2%9C%E8%89%B2)%0A%0A%5C033%5B30m%20%20%20%20%20%20%20%20%E5%B0%86%E5%AD%97%E7%AC%A6%E7%9A%84%E6%98%BE%E7%A4%BA%E9%A2%9C%E8%89%B2%E6%94%B9%E4%B8%BA%E9%BB%91%E8%89%B2%0A%0A%5C033%5B31m%20%20%20%20%20%20%20%20%E5%B0%86%E5%AD%97%E7%AC%A6%E7%9A%84%E6%98%BE%E7%A4%BA%E9%A2%9C%E8%89%B2%E6%94%B9%E4%B8%BA%E7%BA%A2%E8%89%B2%0A%0A%5C033%5B32m%20%20%20%20%20%20%20%20%E5%B0%86%E5%AD%97%E7%AC%A6%E7%9A%84%E6%98%BE%E7%A4%BA%E9%A2%9C%E8%89%B2%E6%94%B9%E4%B8%BA%E7%BB%BF%E8%89%B2%0A%0A%5C033%5B33m%20%20%20%20%20%20%20%20%E5%B0%86%E5%AD%97%E7%AC%A6%E7%9A%84%E6%98%BE%E7%A4%BA%E9%A2%9C%E8%89%B2%E6%94%B9%E4%B8%BA%E6%B7%A1%E7%BA%A2%E8%89%B2%0A%0A%5C033%5B34m%20%20%20%20%20%20%20%20%E5%B0%86%E5%AD%97%E7%AC%A6%E7%9A%84%E6%98%BE%E7%A4%BA%E9%A2%9C%E8%89%B2%E6%94%B9%E4%B8%BA%E8%93%9D%E8%89%B2%0A%0A%5C033%5B35m%20%20%20%20%20%20%20%20%E5%B0%86%E5%AD%97%E7%AC%A6%E7%9A%84%E6%98%BE%E7%A4%BA%E9%A2%9C%E8%89%B2%E6%94%B9%E4%B8%BA%E7%B4%AB%E8%89%B2%0A%0A%5C033%5B36m%20%20%20%20%20%20%20%20%E5%B0%86%E5%AD%97%E7%AC%A6%E7%9A%84%E6%98%BE%E7%A4%BA%E9%A2%9C%E8%89%B2%E6%94%B9%E4%B8%BA%E6%B7%A1%E8%93%9D%E8%89%B2%0A%0A%5C033%5B37m%20%20%20%20%20%20%20%20%E5%B0%86%E5%AD%97%E7%AC%A6%E7%9A%84%E6%98%BE%E7%A4%BA%E9%A2%9C%E8%89%B2%E6%94%B9%E4%B8%BA%E7%81%B0%E8%89%B2%0A%0A%5C033%5B40m%20--%20%5C033%5B47m%20%E8%AE%BE%E7%BD%AE%E8%83%8C%E6%99%AF%E8%89%B2%0A%0A%5C033%5B40m%20%20%20%20%20%20%20%20%E5%B0%86%E8%83%8C%E6%99%AF%E8%89%B2%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%91%E8%89%B2%0A%0A%5C033%5B41m%20%20%20%20%20%20%20%20%E5%B0%86%E8%83%8C%E6%99%AF%E8%89%B2%E8%AE%BE%E7%BD%AE%E4%B8%BA%E7%BA%A2%E8%89%B2%0A%0A%5C033%5B42m%20%20%20%20%20%20%20%20%E5%B0%86%E8%83%8C%E6%99%AF%E8%89%B2%E8%AE%BE%E7%BD%AE%E4%B8%BA%E7%BB%BF%E8%89%B2%0A%0A%5C033%5B43m%20%20%20%20%20%20%20%20%E5%B0%86%E8%83%8C%E6%99%AF%E8%89%B2%E8%AE%BE%E7%BD%AE%E4%B8%BA%E6%B7%A1%E7%BA%A2%E8%89%B2%0A%0A%5C033%5B44m%20%20%20%20%20%20%20%20%E5%B0%86%E8%83%8C%E6%99%AF%E8%89%B2%E8%AE%BE%E7%BD%AE%E4%B8%BA%E8%93%9D%E8%89%B2%0A%0A%5C033%5B45m%20%20%20%20%20%20%20%20%E5%B0%86%E8%83%8C%E6%99%AF%E8%89%B2%E8%AE%BE%E7%BD%AE%E4%B8%BA%E7%B4%AB%E8%89%B2%0A%0A%5C033%5B46m%20%20%20%20%20%20%20%20%E5%B0%86%E8%83%8C%E6%99%AF%E8%89%B2%E8%AE%BE%E7%BD%AE%E4%B8%BA%E6%B7%A1%E8%93%9D%E8%89%B2%0A%0A%5C033%5B47m%20%20%20%20%20%20%20%20%E5%B0%86%E8%83%8C%E6%99%AF%E8%89%B2%E8%AE%BE%E7%BD%AE%E4%B8%BA%E7%81%B0%E8%89%B2%0A%0A--%E8%BE%93%E5%87%BA%E5%89%8Dn%E8%A1%8C%0A%0A%60%60%60%0Acat%20%2Fetc%2Fpasswd%20%7C%20head%20-n%0A%60%60%60%0A%0A--%E8%BE%93%E5%87%BA%E5%90%8En%E8%A1%8C%0A%0A%60%60%60%0Acat%20%2Fetc%2Fpasswd%20%7C%20tail%20-n%0A%60%60%60%0A%0A--%E8%BE%93%E5%87%BA%E7%9A%84%E5%90%8C%E6%97%B6%E5%B9%B6%E5%B0%86%E8%BE%93%E5%87%BA%E7%9A%84%E5%86%85%E5%AE%B9%E4%BF%9D%E5%AD%98%E5%88%B0%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E4%B8%AD%0A%0A%60%60%60%0Acat%20%2Fetc%2Fpasswd%20%7C%20tee%20copy.1%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20%E5%B0%86%E5%AD%97%E7%AC%A6%E5%9D%97%E5%8E%9F%E6%A0%B7%E8%BE%93%E5%87%BA%EF%BC%8C%20x%20%E4%B8%BA%E5%9D%97%E5%BC%80%E5%A7%8B%E5%92%8C%E7%BB%93%E6%9D%9F%E6%A0%87%E8%AE%B0%EF%BC%8C%E5%85%B6%E5%8F%AF%E4%BB%A5%E4%B8%BA%E4%BB%BB%E4%BD%95%E5%AD%97%E7%AC%A6%0A%0A%60%60%60shell%0Acat%3C%3Cx%0Apls%20choose%20your%20name%3A%0A%E2%80%8B%20%20%20%201%3Echris%0A%E2%80%8B%20%20%20%202%3Ejohn%0A%E2%80%8B%20%20%20%203%3Ejeffery%0A%E2%80%8B%20%20%20%204%3Efrederic%0Ax%0A%60%60%60%0A%0A%60%60%60shell%0Anl%20%20--number%20lines%20of%20files%0Acat%20%2Fetc%2Fpasswd%20%7C%20head%20-n%20%7C%20nl%0Anl%20%2Fetc%2Fpasswd%0Anl%20%2Fetc%2Fpasswd%20%3E%3E%20mypass.txt%0A%60%60%60%0A%0A%E6%9D%A1%E4%BB%B6%E6%B5%8B%E8%AF%95%0A%0Atest%20%E6%B5%8B%E8%AF%95%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%98%AF%E5%90%A6%E6%88%90%E7%AB%8B%EF%BC%8C%E6%88%90%E7%AB%8B%E8%BF%94%E5%9B%9E0%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9E%E5%85%B6%E5%AE%83%E5%80%BC%0A%0A%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6%E7%8A%B6%E6%80%81%0A%0A%E6%A0%BC%E5%BC%8F%EF%BC%9A%5B%20%E6%93%8D%E4%BD%9C%E7%AC%A6%20%20%E6%96%87%E4%BB%B6%E6%88%96%E7%9B%AE%E5%BD%95%20%5D%0A%0A%E6%93%8D%E4%BD%9C%E7%AC%A6%0A%0A-d%20%20%E6%B5%8B%E8%AF%95%E6%98%AF%E5%90%A6%E4%B8%BA%E7%9B%AE%E5%BD%95%0A%0A-e%20%20%E6%B5%8B%E8%AF%95%E7%9B%AE%E5%BD%95%E6%88%96%E6%96%87%E4%BB%B6%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%0A%0A-f%20%20%20%E6%B5%8B%E8%AF%95%E6%98%AF%E5%90%A6%E4%B8%BA%E6%96%87%E4%BB%B6%0A%0A-r%20%20%E6%B5%8B%E8%AF%95%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7%E6%98%AF%E5%90%A6%E6%9C%89read%E6%9D%83%E9%99%90%0A%0A-w%20%E6%B5%8B%E8%AF%95%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7%E6%98%AF%E5%90%A6%E6%9C%89write%E6%9D%83%E9%99%90%0A%0A-x%20%20%E6%B5%8B%E8%AF%95%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7%E6%98%AF%E5%90%A6%E6%9C%89excute%E6%9D%83%E9%99%90%0A%0A-L%20%E6%B5%8B%E8%AF%95%E6%98%AF%E5%90%A6%E4%B8%BAlink%E6%96%87%E4%BB%B6%0A%0A!%5B022afe80f8fbfe92a531b2fc2835f93b.png%5D(en-resource%3A%2F%2Fdatabase%2F1161%3A0)%0A%0A%0A%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%AF%94%E8%BE%83%0A%0A%E6%A0%BC%E5%BC%8F%EF%BC%9A%0A%0A%5Bstr1%20%3D%20str2%5D%0A%0A%5Bstr1%20!%3D%20str2%5D%0A%0A%5B-z%20str%5D%20--%E5%88%A4%E6%96%AD%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%0A%0A%E6%95%B4%E6%95%B0%E5%80%BC%E6%AF%94%E8%BE%83%0A%0A%5B%20%E6%95%B4%E6%95%B01%20%E6%93%8D%E4%BD%9C%E7%AC%A6%20%E6%95%B4%E6%95%B02%5D%0A%0A-eq%0A%0A-ne%0A%0A-gt%0A%0A-lt%0A%0A-le%0A%0A-ge%0A%0A!%5Bee779ad398475dce33bee79269a5c142.png%5D(en-resource%3A%2F%2Fdatabase%2F1163%3A0)%0A%0A%0A%E9%80%BB%E8%BE%91%E6%B5%8B%E8%AF%95%0A%0A-a%20%26%26%0A%0A-o%20%7C%7C%0A%0A!%0A%0Aif%20%E8%AF%AD%E5%8F%A5%0A%0Aif%20%5B%20%24score%20-lt%2060%20%5D%3B%20then%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20'60%E4%BB%A5%E4%B8%8B'%0A%0Aelif%20%5B%20%24score%20-ge%2060%20%5D%20%26%26%20%5B%20%24score%20-lt%2070%20%5D%3B%20then%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20'60-70%E4%B9%8B%E9%97%B4'%0A%0Aelif%20%5B%20%24score%20-ge%2070%20%5D%20%26%26%20%5B%20%24score%20-lt%2080%20%5D%3B%20then%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20'70-80%E4%B9%8B%E9%97%B4'%0A%0Aelif%20%5B%20%24score%20-gt%2080%20%5D%20%26%26%20%5B%20%24score%20-lt%2090%20%5D%3B%20then%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20'80-90%E4%B9%8B%E9%97%B4'%0A%0Aelse%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20'90%E4%BB%A5%E4%B8%8A%EF%BC%81'%0A%0Afi%0A%0Acase%09%E8%AF%AD%E5%8F%A5%0A%0Aweekday%3D%60date%20%2B%25w%60%0A%0Acase%20%24weekday%20in%0A%0A%E2%80%8B%091%20)%0A%0A%E2%80%8B%09echo%20'Monday'%09%0A%0A%E2%80%8B%09%3B%3B%0A%0A%E2%80%8B%092%20)%0A%0A%E2%80%8B%09echo%20'Tuesday'%20%0A%0A%E2%80%8B%09%3B%3B%0A%0Aesac%0A%0Awhile%20%E8%AF%AD%E5%8F%A5%0A%0Anum%3D3%0A%0Atot%3D0%0A%0Awhile%20%5B%20%24num%20-gt%200%20%5D%3B%20do%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20%24num%0A%0A%20tot%3D%24((%24tot%2B%24num))%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20num%3D%24((%24num-1))%0A%0Adone%0A%0Afor%20%E8%AF%AD%E5%8F%A5%0A%0Afor%20i%20in%20user0%20user1%20user2%20user3%20user4%20user5%0A%0Ado%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20%24i%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20userdel%20-r%20%24i%0A%0Adone%0A%0Afor%20((%20i%20%3D%201%3B%20i%20%3C%3D%2010%3B%20i%2B%2B%20))%3B%20do%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20%24i%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20user%3D%22user%24i%22%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20userdel%20-r%20%24user%0A%0Adone%0A%0A--skip%20the%20user5%0A%0Afor%20((%20i%20%3D%201%3B%20i%20%3C%3D%2010%3B%20i%2B%2B%20))%3B%20do%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20%24i%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20user%3D%22user%24i%22%0A%0A%20if%20%5B%20%24i%20-eq%205%20%5D%3B%20then%0A%0Acontinue%0A%0A%20fi%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20userdel%20-r%20%24user%0A%0Adone%0A%0A--input%201%20to%205%0A%0Afor%20((%20i%20%3D%201%3B%20i%20%3C%3D%2010%3B%20i%2B%2B%20))%3B%20do%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20echo%20%24i%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20user%3D%22user%24i%22%0A%0A%20if%20%5B%20%24i%20-eq%205%20%5D%3B%20then%0A%0Abreak%0A%0A%20fi%0A%0Adone%0A%0Ashift%20%E7%94%A8%E4%BA%8E%E8%BF%81%E7%A7%BB%E4%BD%8D%E7%BD%AE%E5%8F%98%E9%87%8F%EF%BC%8C%E5%B0%86%241~%249%20%E4%BE%9D%E6%AC%A1%E5%90%91%E5%B7%A6%E4%BC%A0%E9%80%92%0A%0Atot%3D0%0A%0Awhile%20%5B%20%24%23%20-gt%200%20%5D%3B%20do%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20tot%3D%24((%24tot%2B%241))%0A%0A%E2%80%8B%20%20%20%20%20%20%20%20shift%0A%0Adone%0A%0A%E5%87%BD%E6%95%B0%0A%0Afunction%20add()%7B%0A%0A%20%20echo%20%24((%241%2B%242))%0A%0A%7D%0A%0Aadd%2011%2012%0A%0A%0A%0A%23%23%23%23%23%20find%20%E6%9F%A5%E6%96%87%E4%BB%B6%0A%0A%60%60%60shell%0Afind%20.%20-name%20'*.txt'%20%20--%20search%20files%20in%20current%20dir%20which's%20extension%20is%20.txt%0Afind%20.%20-name%20'*file%5B1-6%5D*.txt'%20%0Afind%20.%20-perm%20755%20-type%20f%0A%60%60%60%0A%0A%60%60%60shell%0A-type%0Ac%20%20%20%20%20character%20(unbuffered)%20special%0Ad%20%20%20%20%20directory%0Af%20%20%20%20%20regular%20file%0A%60%60%60%0A%0A%60%60%60shell%0Afind%20%2F%20-user%20user1%20--%20find%20the%20files%20create%20by%20user1%20from%20root%20dir%0Astat%20.%2Ftest.txt%20--display%20file%20or%20file%20system%20status%0Afind%20.%20-mtime%20-5%20%20%20--%20find%20the%20files%20which're%20been%20modified%20for%205%20days%0Afind%20.%20-mtime%20%2B3%20%20--%20find%20the%20files%20which're%20been%20modified%20before%203%20days%20ago%20%0Afind%20.%20-size%20%2B1000000c%20--%20find%20files%20which's%20size%20is%20roughly%201M%0Afind%20.%20-name%20'*file%5B1-6%5D*.txt'%20%20%7C%20xargs%20rm%20-rf%20%20--xargs%20%E5%B0%86find%E6%89%BE%E5%88%B0%E7%9A%84%E6%96%87%E4%BB%B6%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0%E4%BC%A0%E7%BB%99%E5%90%8E%E9%9D%A2%E7%9A%84rm%E5%91%BD%E4%BB%A4%E5%A4%84%E7%90%86%EF%BC%8C%E5%9B%A0%E4%B8%BArm%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E6%97%B6%E9%9C%80%E8%A6%81%E6%96%87%E4%BB%B6%E5%90%8D%0A%60%60%60%0A%0A%23%23%23%23%23%20grep%20%E6%9F%A5%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%0A%0Agrep%20%22linux%22%20*%0A%0Agrep%20-c%20%22linux%22%20filename%20*--print%20a%20count%20of%20matching%20lines%20for%20each%20input%20file*%0A%0Agrep%20-n%20%22linux%22%20filename%20*--prefix%20each%20line%20of%20output%20with%20the%20line%20number%20within%20its%20input%20file*%0A%0Agrep%20-i%20%22linux%22%20filename%20-*-ignore-case*%0A%0Agrep%20-v%20%22linux%22%20filename%20*--to%20select%20non-matching%20lines*%0A%0Agrep%20-E%20%22%5Elinux%22%20filename%20*--search%20the%20line%20start%20by%20linux*%0A%0Agrep%20-E%20%22linux%24%22%20filename%20*--search%20the%20line%20end%20by%20linux*%0A%0Agrep%20-E%20%22.%2Blinux.%2B%22%20finename%20*--seach%20the%20line%20including%20linux%20but%20not%20start%20and%20end%20by%20linux*%0A%0Agrep%20-E%20%22%5E%24%22%20filename%20*--empty%20line*%0A%0Agrep%20-E%20%22%5E.%24%22%20filename%20*--match%20lines%20which%20only%20have%20one%20character*%0A%0Agrep%20-E%20'%5B0-9%5D%2B'%20filename%20*--match%20numbers*%0A%0Agrep%20-En%20'%5B0-9%5D%2B%5C.%5B0-9%5D%2B%5C.%5B0-9%5D%2B%5C.%5B0-9%5D%2B'%20filename%20*--match%20ip*%0A%0Agrep%20-En%20'(%5B0-9%5D%2B%5C.)%7B3%7D%5B0-9%5D%2B'%20filename%0A%0Agrep%20-E%20'2014%3A22%3A5%5B0-9%5D'%20filename%20%20*--%E5%9C%A8%E6%96%87%E4%BB%B6%E4%B8%AD%E6%9F%A5%E6%89%BE%E6%97%B6%E9%97%B4%E5%9C%A82014%3A22%3A50%E5%88%B02014%3A22%3A59%E4%B9%8B%E9%97%B4%E7%9A%84%E8%A1%8C*%0A%0Agrep%20-E%20'%5E%5B%5E210%5D'%20filename%20*--%E5%9C%A8%E6%96%87%E4%BB%B6%E4%B8%AD%E6%9F%A5%E6%89%BE%E4%B8%8D%E6%98%AF%E4%BB%A5210%E5%BC%80%E5%A4%B4%E7%9A%84%E8%A1%8C*%0A%0Agrep%20-E%20'%5E2004%7C%5E2015'%20filename%20%20*--%E5%9C%A8%E6%96%87%E4%BB%B6%E4%B8%AD%E6%9F%A5%E6%89%BE%E6%98%AF%E4%BB%A52004%E6%88%96%E4%BB%A52015%E5%BC%80%E5%A4%B4%E7%9A%84%E8%A1%8C*%0A%0Agrep%20-E%20'%5B6-9%5D%5B0-9%5D'%20filename%09*--%E6%9F%A5%E6%89%BE%E4%BB%8E60%E5%88%B099%E4%B9%8B%E9%97%B4%E7%9A%84%E6%88%90%E7%BB%A9*%0A%0A.%20%E4%BB%BB%E6%84%8F%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%0A%0A%5C%2B%20%E5%A4%9A%E4%B8%AA%E5%AD%97%E7%AC%A6%0A%0A%5C*%20%E9%9B%B6%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E5%AD%97%E7%AC%A6%0A%0A%5B0-9a-z%5D%20%E5%8C%B9%E9%85%8D%5B%5D%E6%98%AF%E7%9A%84%E4%BB%BB%E6%84%8F%E4%B8%80%E4%B8%AA%0A%0A(linux)%2B%20%20%E5%8C%B9%E9%85%8D%E5%87%BA%E7%8E%B0%E5%A4%9A%E6%AC%A1%E7%9A%84%E5%8D%95%E5%85%83()%0A%0A%5C%20%E5%AF%B9%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E7%A4%BA%E5%BC%8F%E4%B8%AD%E7%9A%84%E7%89%B9%E6%AE%8A%E5%AD%97%E7%AC%A6%E8%BF%9B%E8%A1%8C%E8%BD%A6%E8%BD%AC%E4%B9%89%0A%0A(unit)%7Bn%7D%20%E5%8C%B9%E9%85%8Dn%E4%B8%AA%E7%9A%84%E5%8D%95%E5%85%83%0A%0A(unit)%7Bn%2C%7D%20%E5%8C%B9%E9%85%8Dn%E4%B8%AA%E4%BB%A5%E4%B8%8A%E7%9A%84%E5%8D%95%E5%85%83%0A%0A(unit)%7Bn%2Cx%7D%20%E5%8C%B9%E9%85%8Dn%E5%88%B0x%E4%B8%AA%E7%9A%84%E5%8D%95%E5%85%83%0A%0Aawk%20-F%3A%20'%7Bprint%20%7D'%0A%0Aawk%20%E9%BB%98%E8%AE%A4%E7%9A%84%E5%88%86%E9%9A%94%E7%AC%A6%E6%98%AF%E7%A9%BA%E6%A0%BC%0A%0Acat%20%2Fetc%2Fpasswd%20%7C%20cut%20-d%3A%20-f1%20%20--%E4%BB%A5%3A%E4%B8%BA%E5%88%86%E9%9A%94%E7%AC%A6%E5%B9%B6%E5%8F%96%E5%87%BA%E7%AC%AC%E4%B8%80%E5%88%97%0A%0Acat%20%2Fetc%2Fpasswd%20%7C%20awk%20-F%3A%20'%7Bprint%20%241%7D'%20%20--%E4%BB%A5%3A%E4%B8%BA%E5%88%86%E9%9A%94%E7%AC%A6%E5%B9%B6%E5%8F%96%E5%87%BA%E7%AC%AC%E4%B8%80%E5%88%97%0A%0Acat%20%2Fetc%2Fpasswd%20%7C%20awk%20-F%3A%20'%7Bprint%20%22username%3A%20%22%241%22%20%3D%3E%20Shell%3A%20%22%247%7D'%20--%E4%BB%A5%3A%E4%B8%BA%E5%88%86%E9%9A%94%E7%AC%A6%E5%B9%B6%E5%8F%96%E5%87%BA%E7%AC%AC%E4%B8%80%E5%88%97%E5%92%8C%E7%AC%AC%E4%B8%83%E5%88%97%0A%0Acat%20%2Fetc%2Fpasswd%20%7C%20awk%20-F%3A%20'%7Bprint%20%241%7D'%20%0A%0ANR%09--%20awk%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AA%E5%B8%B8%E9%87%8F%E4%BB%A3%E8%A1%A8%E8%A1%8C%E5%8F%B7%0A%0ANF%09--%20awk%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AA%E5%B8%B8%E9%87%8F%E4%BB%A3%E8%A1%A8%E5%88%97%E5%8F%B7%0A%0Adf%20%7C%20awk%20'%7Bif(NR%3D%3D4)%7Bprint%20%240%7D%7D'%20--%E6%89%93%E5%8D%B0%E5%87%BA%E7%AC%AC%E5%9B%9B%E8%A1%8C%E7%9A%84%E6%95%B4%E8%A1%8C%0A%0Adf%20%7C%20awk%20'%7Bif(NR%3D%3D4)%7Bprint%20%241%7D%7D'%20--%E6%89%93%E5%8D%B0%E5%87%BA%E7%AC%AC%E5%9B%9B%E8%A1%8C%E7%9A%84%E7%AC%AC%E4%B8%80%E5%88%97%0A%0Adf%20%7C%20awk%20'%7Bif(NR%3D%3D4)%7Bprint%20int(%245)%7D%7D'%20--%E5%B0%86%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E6%88%90int%E5%9E%8B%E6%96%B9%E4%BE%BF%E8%BF%9B%E8%A1%8C%E6%95%B4%E5%BD%A2%E6%AF%94%E8%BE%83%0A%0Adf%20%7C%20awk%20'END%7Bprint%20NR%7D'%20%20--%E6%89%93%E5%8D%B0%E5%87%BA%E6%80%BB%E5%85%B1%E7%9A%84%E8%A1%8C%E6%95%B0%0A%0Adf%20%7C%20awk%20'END%7Bprint%20NF%7D'%20%20--%E6%89%93%E5%8D%B0%E5%87%BA%E6%80%BB%E5%85%B1%E7%9A%84%E5%88%97%E6%95%B0%0A%0Ased%20%E8%A1%8C%E5%AE%9A%E4%BD%8D%E7%9A%84%E4%BD%BF%E7%94%A8%0A%0Ased%20-n%20'3%2C5'p%20filename%09--%E6%89%93%E5%8D%B0%E5%87%BA3%E5%88%B05%E8%A1%8C%0A%0Ased%20'3%2C5'd%20filename%09%09--%E6%89%93%E5%8D%B0%E5%87%BA%E9%99%A4%E7%AC%AC3%E5%88%B05%E8%A1%8C%E4%B9%8B%E5%A4%96%E7%9A%84%E6%95%B0%E6%8D%AE%0A%0Acat%20%2Fetc%2Fpasswd%20%7C%20sed%20-n%20%22%2Fbash%2F%22p%20--%E6%89%93%E5%8D%B0%E5%87%BA%E5%8C%85%E5%90%ABbash%E7%9A%84%E8%A1%8C%0A%0Acat%20%2Fetc%2Fpasswd%20%7C%20sed%20-n%20'2%2C%2Fsys%3A%2F'p%20--%E6%89%93%E5%8D%B0%E5%87%BA%E7%AC%AC2%E8%A1%8C%E5%88%B0%E5%8C%85%E5%90%ABsys%3A%E7%9A%84%E8%A1%8C%0A%0Acat%20sedtemp%20%7C%20sed%20-n%20'%2F333%2F%2C%24'p%20%20%20%20%20%20--%E6%89%93%E5%8D%B0%E5%87%BA%E5%8C%85%E5%90%AB333%E7%9A%84%E8%A1%8C%E5%88%B0%E6%9C%80%E5%90%8E%E4%B8%80%E8%A1%8C%0A%0A%0A%0A%23%23%23%23%23%20uniq%20%E5%8F%AF%E6%A3%80%E6%9F%A5%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E4%B8%AD%E9%87%8D%E5%A4%8D%E5%87%BA%E7%8E%B0%E7%9A%84%E8%A1%8C%E5%88%97%0A%0A%60%60%60%0Auniq%20filename%09%09--%E6%89%93%E5%8D%B0%E5%87%BA%E8%BF%87%E6%BB%A4%E6%8E%89%E7%B4%A7%E6%8C%A8%E9%87%8D%E5%A4%8D%E8%A1%8C%E7%9A%84%E5%94%AF%E4%B8%80%E5%80%BC%0Auniq%20-c%20filename%09--%E6%89%93%E5%8D%B0%E5%87%BA%E7%B4%A7%E6%8C%A8%E9%87%8D%E5%A4%8D%E8%A1%8C%E5%87%BA%E7%8E%B0%E7%9A%84%E6%AC%A1%E6%95%B0%0Auniq%20-d%20filename%09--%E5%8F%AA%E6%89%93%E5%8D%B0%E5%87%BA%E7%B4%A7%E6%8C%A8%E9%87%8D%E5%A4%8D%E7%9A%84%E8%A1%8C%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%20Linux%20sort%E5%91%BD%E4%BB%A4%E7%94%A8%E4%BA%8E%E5%B0%86%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E5%8A%A0%E4%BB%A5%E6%8E%92%E5%BA%8F%0A%0A%60%60%60%0Asort%20filename%09--%E5%8D%87%E5%BA%8F%E6%8E%92%E5%88%97%0Asort%20-r%20filename%09--%E9%99%8D%E5%BA%8F%E6%8E%92%E5%88%97%0Asort%20uniqtemp%20%7C%20uniq%20-c%0Acat%20uniqtemp%20%7C%20sort%20-t%3A%20-k2%20-r%20%09--%E4%BB%A5%3A%E5%88%86%E9%9A%94%E5%90%8E%E7%9A%84%E7%AC%AC%E4%BA%8C%E5%88%97%E7%9A%84%E5%80%92%E5%BA%8F%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%BA%8F%EF%BC%8C%E9%BB%98%E8%AE%A4%E5%88%86%E9%9A%94%E7%AC%A6%E4%B8%BA%E7%A9%BA%E6%A0%BC%0A%60%60%60%0A%0A

ubuntu

创建时间:2020/9/2 15:26
更新时间:2020/9/2 15:26
作者:Chris

1. 解决使用vi 出现方向键错乱的情况

编辑/etc/vim/vimrc.tiny 使用root权限操作:
将“set compatible” 改成 “set nocompatible”
新增一条配置:
set backspace=2
最终效果是:
set nocompatible
set backspace=2
保存退出。

2. 防火墙

sudo ufw status
sudo ufw disable
sudo ufw enable

ufw default allow/deny:外来访问默认允许/拒绝
ufw allow/deny 20:允许/拒绝 访问20端口

查看所有服务状态

sudo service --status-all

停止启动重启服务

sudo service ssh stop|start|restart
systemctl stop|start|restart  ssh

3. 设置静态IP

vi /etc/hostname 修改主机名称为hadoopmaster
ifconfig 获取本机IP 例如 192.168.101.131
修改主机的映射配置
vi /ect/hosts
写入192.168.101.131 hadoopmaster
保存并重启主机
如果主机名称修改不生效
root@ubuntu: vi /etc/cloud/cloud.cfg
#This will cause the set+update hostname module to not operate (if true)
preserve_hostname: false
修改为
preserve_hostname: true

4. Install SSH
apt-get install openssh-server
##start ssh
/etc/init.d/ssh start
##check if ssh started
ps -e | grep sshd
##allow root login through ssh
vi /etc/ssh/sshd_config
PermitRootLogin yes
5.生成SSH密钥

在整个hadoop的整个处理过程中都是利用ssh进行通讯的,就算是本机也知必须配置ssh免登录处理:
由于电脑上可能出现过ssh的相关配置,因此必须删除根目录下的".ssh"的文件夹

rm -rf ~/.ssh

在hadoopmaster 主机上生成ssh key

ssh-keygen -t rsa

把生成的共钥拷贝到授权的文件之中
root@hadoopmaster:~/.ssh# cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
测试免登录处理
root@hadoopmaster:~/.ssh# ssh
root@hadoopmaster
使用exit退出运程登录

6. 设置root密码

Ubuntu的默认root密码是随机的,即每次开机都有一个新的root密码。
解决方法:
我们可以在终端输入命令“sudo passwd”,然后输入当前用户的密码后"Enter"。
终端会提示我们输入新的密码并确认,此时的密码就是root新密码。
修改成功后,输入命令 su root,再输入新的密码就ok了。
将当前用户注销
logout

%23%23%23%23%201.%20%E8%A7%A3%E5%86%B3%E4%BD%BF%E7%94%A8vi%20%E5%87%BA%E7%8E%B0%E6%96%B9%E5%90%91%E9%94%AE%E9%94%99%E4%B9%B1%E7%9A%84%E6%83%85%E5%86%B5%0A%3E%20%E7%BC%96%E8%BE%91%2Fetc%2Fvim%2Fvimrc.tiny%20%E4%BD%BF%E7%94%A8root%E6%9D%83%E9%99%90%E6%93%8D%E4%BD%9C%EF%BC%9A%0A%3E%20%E5%B0%86%E2%80%9Cset%20compatible%E2%80%9D%20%E6%94%B9%E6%88%90%20%E2%80%9Cset%20nocompatible%E2%80%9D%0A%3E%20%E6%96%B0%E5%A2%9E%E4%B8%80%E6%9D%A1%E9%85%8D%E7%BD%AE%EF%BC%9A%0A%3E%20set%20backspace%3D2%0A%3E%20%E6%9C%80%E7%BB%88%E6%95%88%E6%9E%9C%E6%98%AF%EF%BC%9A%0A%3E%20set%20nocompatible%0A%3E%20set%20backspace%3D2%0A%3E%20%E4%BF%9D%E5%AD%98%E9%80%80%E5%87%BA%E3%80%82%0A%0A%0A%0A%23%23%23%23%202.%20%E9%98%B2%E7%81%AB%E5%A2%99%0A%0A%3E%20sudo%20ufw%20status%0A%3E%20sudo%20ufw%20disable%0A%3E%20sudo%20ufw%20enable%0A%3E%0A%3E%20ufw%20default%20allow%2Fdeny%3A%E5%A4%96%E6%9D%A5%E8%AE%BF%E9%97%AE%E9%BB%98%E8%AE%A4%E5%85%81%E8%AE%B8%2F%E6%8B%92%E7%BB%9D%0A%3E%20ufw%20allow%2Fdeny%2020%EF%BC%9A%E5%85%81%E8%AE%B8%2F%E6%8B%92%E7%BB%9D%20%E8%AE%BF%E9%97%AE20%E7%AB%AF%E5%8F%A3%0A%0A%E6%9F%A5%E7%9C%8B%E6%89%80%E6%9C%89%E6%9C%8D%E5%8A%A1%E7%8A%B6%E6%80%81%0A%0A%60%60%60%0Asudo%20service%20--status-all%0A%60%60%60%0A%0A%E5%81%9C%E6%AD%A2%E5%90%AF%E5%8A%A8%E9%87%8D%E5%90%AF%E6%9C%8D%E5%8A%A1%0A%0A%60%60%60%0Asudo%20service%20ssh%20stop%7Cstart%7Crestart%0Asystemctl%20stop%7Cstart%7Crestart%20%20ssh%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.%20%E8%AE%BE%E7%BD%AE%E9%9D%99%E6%80%81IP%0A%3E%20vi%20%2Fetc%2Fhostname%20%E4%BF%AE%E6%94%B9%E4%B8%BB%E6%9C%BA%E5%90%8D%E7%A7%B0%E4%B8%BAhadoopmaster%0Aifconfig%20%E8%8E%B7%E5%8F%96%E6%9C%AC%E6%9C%BAIP%20%E4%BE%8B%E5%A6%82%20192.168.101.131%0A%E4%BF%AE%E6%94%B9%E4%B8%BB%E6%9C%BA%E7%9A%84%E6%98%A0%E5%B0%84%E9%85%8D%E7%BD%AE%0Avi%20%2Fect%2Fhosts%0A%E5%86%99%E5%85%A5192.168.101.131%20%20hadoopmaster%0A%E4%BF%9D%E5%AD%98%E5%B9%B6%E9%87%8D%E5%90%AF%E4%B8%BB%E6%9C%BA%0A%E5%A6%82%E6%9E%9C%E4%B8%BB%E6%9C%BA%E5%90%8D%E7%A7%B0%E4%BF%AE%E6%94%B9%E4%B8%8D%E7%94%9F%E6%95%88%0Aroot%40ubuntu%3A%20vi%20%2Fetc%2Fcloud%2Fcloud.cfg%20%0A%23This%20will%20cause%20the%20set%2Bupdate%20hostname%20module%20to%20not%20operate%20(if%20true)%0Apreserve_hostname%3A%20false%0A%E4%BF%AE%E6%94%B9%E4%B8%BA%0Apreserve_hostname%3A%20true%0A%0A%0A%0A%23%23%23%23%23%204.%20Install%20SSH%0A%0A%60%60%60shell%0Aapt-get%20install%20openssh-server%0A%23%23start%20ssh%0A%2Fetc%2Finit.d%2Fssh%20start%0A%23%23check%20if%20ssh%20started%0Aps%20-e%20%7C%20grep%20sshd%0A%23%23allow%20root%20login%20through%20ssh%0Avi%20%2Fetc%2Fssh%2Fsshd_config%0APermitRootLogin%20yes%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%205.%E7%94%9F%E6%88%90SSH%E5%AF%86%E9%92%A5%0A%0A%E5%9C%A8%E6%95%B4%E4%B8%AAhadoop%E7%9A%84%E6%95%B4%E4%B8%AA%E5%A4%84%E7%90%86%E8%BF%87%E7%A8%8B%E4%B8%AD%E9%83%BD%E6%98%AF%E5%88%A9%E7%94%A8ssh%E8%BF%9B%E8%A1%8C%E9%80%9A%E8%AE%AF%E7%9A%84%EF%BC%8C%E5%B0%B1%E7%AE%97%E6%98%AF%E6%9C%AC%E6%9C%BA%E4%B9%9F%E7%9F%A5%E5%BF%85%E9%A1%BB%E9%85%8D%E7%BD%AEssh%E5%85%8D%E7%99%BB%E5%BD%95%E5%A4%84%E7%90%86%EF%BC%9A%0A%E7%94%B1%E4%BA%8E%E7%94%B5%E8%84%91%E4%B8%8A%E5%8F%AF%E8%83%BD%E5%87%BA%E7%8E%B0%E8%BF%87ssh%E7%9A%84%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%BF%85%E9%A1%BB%E5%88%A0%E9%99%A4%E6%A0%B9%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%22.ssh%22%E7%9A%84%E6%96%87%E4%BB%B6%E5%A4%B9%0A%60%60%60%0Arm%20-rf%20~%2F.ssh%0A%60%60%60%0A%E5%9C%A8hadoopmaster%20%E4%B8%BB%E6%9C%BA%E4%B8%8A%E7%94%9F%E6%88%90ssh%20key%0A%60%60%60%0Assh-keygen%20-t%20rsa%0A%60%60%60%0A%0A%E6%8A%8A%E7%94%9F%E6%88%90%E7%9A%84%E5%85%B1%E9%92%A5%E6%8B%B7%E8%B4%9D%E5%88%B0%E6%8E%88%E6%9D%83%E7%9A%84%E6%96%87%E4%BB%B6%E4%B9%8B%E4%B8%AD%0Aroot%40hadoopmaster%3A~%2F.ssh%23%20cat%20~%2F.ssh%2Fid_rsa.pub%20%3E%3E%20~%2F.ssh%2Fauthorized_keys%0A%E6%B5%8B%E8%AF%95%E5%85%8D%E7%99%BB%E5%BD%95%E5%A4%84%E7%90%86%0Aroot%40hadoopmaster%3A~%2F.ssh%23%20ssh%20%5Broot%40hadoopmaster%5D(mailto%3Aroot%40hadoopmaster)%0A%E4%BD%BF%E7%94%A8exit%E9%80%80%E5%87%BA%E8%BF%90%E7%A8%8B%E7%99%BB%E5%BD%95%0A%0A%23%23%23%23%23%206.%20%E8%AE%BE%E7%BD%AEroot%E5%AF%86%E7%A0%81%0A%0A%3E%20Ubuntu%E7%9A%84%E9%BB%98%E8%AE%A4root%E5%AF%86%E7%A0%81%E6%98%AF%E9%9A%8F%E6%9C%BA%E7%9A%84%EF%BC%8C%E5%8D%B3%E6%AF%8F%E6%AC%A1%E5%BC%80%E6%9C%BA%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84root%E5%AF%86%E7%A0%81%E3%80%82%0A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%EF%BC%9A%0A%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E5%9C%A8%E7%BB%88%E7%AB%AF%E8%BE%93%E5%85%A5%E5%91%BD%E4%BB%A4%E2%80%9Csudo%20passwd%E2%80%9D%EF%BC%8C%E7%84%B6%E5%90%8E%E8%BE%93%E5%85%A5%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7%E7%9A%84%E5%AF%86%E7%A0%81%E5%90%8E%22Enter%22%E3%80%82%0A%E7%BB%88%E7%AB%AF%E4%BC%9A%E6%8F%90%E7%A4%BA%E6%88%91%E4%BB%AC%E8%BE%93%E5%85%A5%E6%96%B0%E7%9A%84%E5%AF%86%E7%A0%81%E5%B9%B6%E7%A1%AE%E8%AE%A4%EF%BC%8C%E6%AD%A4%E6%97%B6%E7%9A%84%E5%AF%86%E7%A0%81%E5%B0%B1%E6%98%AFroot%E6%96%B0%E5%AF%86%E7%A0%81%E3%80%82%0A%E4%BF%AE%E6%94%B9%E6%88%90%E5%8A%9F%E5%90%8E%EF%BC%8C%E8%BE%93%E5%85%A5%E5%91%BD%E4%BB%A4%20su%20root%EF%BC%8C%E5%86%8D%E8%BE%93%E5%85%A5%E6%96%B0%E7%9A%84%E5%AF%86%E7%A0%81%E5%B0%B1ok%E4%BA%86%E3%80%82%0A%E5%B0%86%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7%E6%B3%A8%E9%94%80%0Alogout

git pull & git pull --rebase

创建时间:2020/9/2 15:21
更新时间:2020/9/2 15:23
作者:Chris

git pull & git pull --rebase
目前我的两个分支master 和 dev2018-10-17-001

git checkout dev2018-10-17-001
git pull origin master 将远程分支(master)要与当前分支合并

git reflog 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作)

git reset --hard 5306c99 //回滚到指定版本同进回滚index和working区
git pull --rebase origin master

git%20pull%20%26%20git%20pull%20--rebase%0A%E7%9B%AE%E5%89%8D%E6%88%91%E7%9A%84%E4%B8%A4%E4%B8%AA%E5%88%86%E6%94%AFmaster%20%E5%92%8C%20dev2018-10-17-001%0A%0A!%5Bf30c66a3ba4723e084477ee121c09166.png%5D(en-resource%3A%2F%2Fdatabase%2F1135%3A0)%0A%0Agit%20checkout%20dev2018-10-17-001%0Agit%20pull%20origin%20master%20%20%E5%B0%86%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF(master)%E8%A6%81%E4%B8%8E%E5%BD%93%E5%89%8D%E5%88%86%E6%94%AF%E5%90%88%E5%B9%B6%0A%0A!%5Bimage.png%5D(data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAlkAAACpCAYAAAAY9Sh3AAAgAElEQVR4Ae29D2wc13Uv%2FEtRJAFsOSmMOI5NLpcS%2FSLJLwkfm76EaqoVJTJ6SUpKH5AXIguna4fWk%2FASgCaQQFIEiSAJJyIcgCa%2BtpAezcr7YqzLtEBFsUmfSkrUKvnEui%2Fl28SvlhLT4ZKi80eF0diygcQomg%2Fn3rkzd2Zn7sz%2Bo7jcQ0DamXvvOfec370zc%2BbcO%2Be847e%2F%2Fe1vwX%2BMACPACDACjAAjwAgwAhVF4HeJ246HP1ZRpsyMEWAEGAFGgBFgBBiBekbg23%2F5DH6nngFg3RkBRoARYAQYAUaAEagGAm%2B%2F%2FTYbWdUAlnkyAowAI8AIMAKMQH0j8G%2F%2F9m9sZNX3FGDtGQFGgBFgBBgBRqAaCLCRVQ1UmScjwAgwAowAI8AI1D0C62Nk7WhBc64LD3bXPd4MACNQOwjs%2BBD%2BKvc5fJOv28IxqxVsakXOQoQrUPJB%2FMG3pvAHLRVgte4sPo3O%2BadQk6KvO1Ybu8N%2F%2F%2Fd%2Fh%2Fi6UIl5z3gXHkioM%2BD2yVm8OnM%2FHsy9H7dbf4g3nKo7dvTuJ3bhA3gRy0%2FfrqgMLt2zL%2BJG%2Fy8kfzISn2%2FGu1Rvqs5bTvUry8gfWAKe2IV4xy1x%2FGsq7%2F4Ito%2Fchdc%2Bfw3%2Fcl0x8vslrD%2BELVqVHANZ4JKRipQsonoL3jf9cdzbpMZNY6LLasko5IJDY7dWPC2at8UcoE9QCYf78KbQwUAndL3PZgfcws%2BizJ33%2FDH%2Bbk8nlv%2FpCfz3NQDi%2FMO4fOXreOr1Bnx171fwRR2Ynz%2BHHf%2F4A6udRgfZtvknFh%2Fr3KG9hb%2B48nUsffBpdP1MtbHEbXgc1x%2FISb5UROe%2F%2Fx9l5e05fPby3%2BKfbc2UTP8XX5t%2BBn9jl0c72P7EpzCCBfzXp3%2FlQ9CEb%2BYaMN%2F6%2F%2BE7nlo%2Fus%2BMfw6ntOv2eye%2Fja%2FMBPPwsKz%2Bafcf4oWRB7V%2BXsWwj25agzIPSfeP4Y80LhITrWDDHJY%2FTn5z4s6pV74%2BlZC95cln0fT9R%2FHXS5XgZuJBBlEH8h1fReW6%2Bi7mTneg71tfwr9%2B4c%2Fwmql7rtvQCLiMLPEAx4u40WoZF5US%2FfoSllsrN%2F0qJZbOx6s7nTc%2F8RaWn74LDwrDYhbLXuPIoxfRbJlbgjBenr6GnzV34d7uJbw6swXve%2Fw%2BYbCaDSwlkWaUCMNmF9635BhnutGlKCCMpQ8Bx%2F4Br53%2BON7pVEDUnb4Lr7XOCiOZ5PzAE7%2FUjNS3go2%2Flbfwzs77gZlf4N37gbezd%2BGd9HolsDDQKUMNABnF8dxHgCiG1u1baH7go8DaD%2FDwg8Dyz%2B9DMxlWr6%2FhqctP4Cl8FH9%2BoBWzXqOG6P7DH%2BPhNd0IIhAsQ%2BjN57Dj8g9cqDz85i38t3saAJBFV%2Fj38M6v4a%2Fv%2FxE%2BO%2F2MZlg57R7e%2BSf44pv%2FF%2FO64edUhxw14fFH38CzrX4Glom0kE4YWHgBH2tdMREWX3f9RfzX1heLpwuiyL6Aj%2FVLGckoSOf%2BEKiqoaUZcuTRef5T%2BPLS3%2BFPvddxkLym8kpjY%2BortK5wTtgkG0pOW6rqH%2Bx%2FCgmMYPLsj6vfV7V6uPhVZHcv4D%2Ft%2FzPMXaxWJ8y32ghQGFLpydrRgnsT9HAPNrDe9cQubH%2F0LiGT%2FqC%2FZ3wX3jV3C3ePWN4e21Oiezs0w0FppXtXAPzm2X%2FQHvyqUbG%2Fbk%2BQLicQUNf9ETxAxqXyXAF4o%2F9FbJl%2BP959EcJgeTtMDMKPvGszTkPBI%2FcRvG%2FbXbg3%2FyJuaHVOq5Cj67%2FEmyvNmmET1P42%2FuXANWlQFTShuh%2FapW8vv4V3NdM4RvAE5m%2FhTdyNd%2BN%2B3Nv8Jl5bfgv32pyiHfz66RfxWsfHsaUbeCMMgzd%2FhMu4Hw%2Fjo%2FjS3b%2FAn715C1%2BK1M2PcPnNTnyp4W%2BlF0zRNPwXfBFz%2BCx5vCL%2B5d%2Bka6ABn77%2FFr7m8lxpDN7zx%2FjmQ7fwtekcug60ahXRDrc%2FsRNNzy64vVTCENiBmM3iVczbx%2FKggG7Hh%2FBogoyJYAOr%2BYlP4YVHpSWoe3M%2BM%2F4pNM%2BtITFi9blyHakDL%2BIG3osvT38SX2iiPjVDRcnikXP12b8P8MYpgsLfG08v4Fsdn0RHN%2FAdMSfcnidbzu4%2FxF91Akg8iNjKdXwrvwNfSAB2vUcWu9zb5fWbyK7sQNx6QQjWnTy2ZJA54%2BDwdMtI18%2B3Pq8bbe56h04K4%2FI2WganXvZHuc%2FhFDXVjFGvLH5YF8wJuOXwyqn3Sd3Zcgq978GztuEr50H8GfKKAoF0xMSDGc0bZ%2B665bH7q9TYSnhd%2F7fs%2FgRWrn7VVYb9T%2BGzuwHs%2BgTes%2FYcfrT6CD68C1g53S6MmJYnF5DY5ZCoclHS8iV8duIRvMeqfv0vH8Vfn%2F0xdJqm%2BQUIZ%2FK1EUye%2BK7VkrxcJyEuJVrosPqiypYnp%2FB7V6%2Bi6ZjFd%2B05nPd4rZaufh%2BJR76Eey%2ByN8sCtCZ%2FpJHVchfetfIWgo2J%2B3Bvs%2BXlIuPodAvePWN5bXAX7n0cyLfOCi8OeUqkB4ce7rP4F2HcvN8Dzha87zQtPfl4iDwto5%2BSUUfLmrN4VRCRUfUR3DNDy5zBdei8D7fnfig9LrYRab3BX1%2FCz5%2B9D%2FHnu3CvbTx6JSJd7sJrtEzo%2BvsFXj35fmwfAV77fLDx6iLxnux4P%2B5uuoXXNONky0iX4ElNSzFM39l8F27P6fLchXtJP9G35p2iOYFf4ufL78eWJ%2B4C5n4IbNuqSRhAp7WQh7fxmzxw9zZ60BsMuy33I44cvvtmKz69837gZ88A93yygFtQwXd%2FPIdvfpC8YI5uD99zH%2FBmTniihGfqoftAy5e0XKhug9C8Yz%2Bh9vT3nlbsxS%2BA%2F%2Fw0rn9AFuVf%2FiY%2B9RJ5vRrw1d%2BXy5N%2Fg4%2BiS1YX8f970dkBZI%2FpXqwmfPP5BmQ%2F%2F23L00IPJvKy6X8%2BdC33ILbyBl7Rm7mOH8QXmi0vFz0IT38I22fIkKK%2FLfjC40Cq9dvinB6ij3e%2FiK%2FM%2FAp%2FeuDb%2BFPxsC6U4cundTldnRVx8iss54HEtvcKmi9P09Lot%2FEVcUa6%2FyE%2BMyOXSmMJYLj1BXTkPobE%2FN8jtdyOEUH3Hjdm4kEf4K3a0YhE06t41r6OgnT3jIOL5wq%2BYhuzZIC0a%2FrSebAOwkDx8TZ%2Bp%2F%2Fb%2BI6Fc%2BHS8HsRjrXPnIBJTkD2aYku9LOwFoZoO5p3WJ5qwgzXcdLCLJCO5A%2Bcu2ZcKjK22ijIw08jvuv7yJ8oqMB7dgHZjhHEyfD5%2FqM4vzqMjvgHAfwYSyfaneU%2BYVQ9hZaLtAT4QfzB4G6sHGrH%2F%2Fbc4iVN0HIh7QmjZcR2zAlRrH1WgicVxPDhR4DzHe1iOZAMtgKv1cV5rBzrwO8BvGRYOJw1U%2BLakxUs9S38THl6rr%2BJt5veLzw8cl8PcPsZZXCRF0guSwXzoprbuD0PYbzcXREPFr1NkUFyH%2B7NdeEBu%2FO38DbdNBBUtwWI38LtpRZ84PFbyLf%2BElumt%2BI3M8CWxyWTXz99DTeeVstezZ59UFT%2BIdw9%2FyL%2Bxe7TOXj3NvIY6Utssk4soVkGXeGepfvwgK2DNHr0vXBu75zTV5Qj6veB%2BDLy9sNGGcIWNe2nev4j%2BI21tPeb5bfw64tv4QPP03IjgCdUL2Y61arYX%2FIi%2FfOrv8A399yP%2FzENYGcRHF7%2FW%2FwPfA1ffc%2F%2FdBFJzxTwzy99HTteouXDPxH1%2F%2FzGLcQfuB9oaAV%2BDnQ1AD8BsPwGGVKtwJZO0L6uHf9IzWmZ8k%2Fw1Ve%2Fju8%2BSMuEz2GH%2Fyqjq2%2Ffk%2B6H8YX8S%2FiYvmzV3YA%2Fyr6Er%2BhlXmI%2FOm%2BbgvNXMWwt0eH6G1hpasA2wDKygO89owwuz8O3gI8q%2BBXm5oH0859DogQPluLi%2BhUG0IP4gvLkiMrbyIvrljw7a8Lj14FX8SztX1Nz0IvZ9RfxbHYHOuzl7AdxyuYpvU76%2FjZf3UN5uiR3Tkw6XG9CR4L6D%2FY2Ooz0owhYlzInfPbHyV5lfyP734s%2Fvf4rbN%2FfAMwv2HMFQXRezHQVTLhQu5LHVu%2BkiONr88KQiuP7yNFS4mGNdv9T6Dv2Ca3g%2B9bxj%2FHT7wMHJxbQZHmwtEbBhy2daGr4BD6sPFyi5Spep%2FlpGWsrzzkeKpeR5%2BIaw%2B9pNK4qPqkJBKSRtfQWftN0l8twqrb0uvGyPXdXgfFSUv9B3ia6YfvWbcH78m%2FhbfLa5H%2BJX5NXDm%2Fh9o678c78m3J%2FlSWIlJe8Y1vxvh2%2FsDaw3497O27h5wd8PDQ7WvCBR9%2FCz06%2BhQdGlEdNMlO6%2B%2Bvos7Tq37CoUmHY6Zvx%2FahnfonbIx6vo9h7Jhu%2FG8A7%2FTxSfnQ2%2Fy14Vxx4e84HI7uNdvD63%2BJTZGABeBhAs2HflEYlDv%2FmZ7dw%2FYOt%2BAurQhhS%2F6EVD7%2B05ruvipr9Pw8As%2F%2BYQ9d%2F%2Fijwpsbx9hz%2BzDakfoDZnz%2BCri20jHgfsOURXD%2FwiN2448DT6FIb9u1Sv4P34suP34NvHSv2gRtAt%2FQGVpvucRlOfr1WsuzG03%2BHjz0N0L6qF3Jb3MtbkTt6L5rjwMocefMaAXup0sOAHi4l%2F%2FksdZbMKwJhkA6C9I3CPZ0RWJqxDpgTRr5N%2BObIPfhWgMf0xtMvYWW6EdufBjo73sCzB5S31Uxn7DIIl7LG1thjCZWfRuexGH5ke6ukd0oxeu1sLybPAvcenkLffAxwLQmqVj6%2FPkuAPq1Cilbxrx4PWggBV28wBGRaHbH35z48MH7%2FuosnDI7PL%2BM3cdr7U8af8LA1416%2FT85NddQlGZmJD2F7biveiWbEabP7GWfZyZaKjC%2F7BLhn%2FEOA5sVzqmgJsRlvn%2Fwh3pj5IfLP3oUHplvK089hXvRRJANLbFLfii3ZX4oN8tILF62rdz%2Fh0Hkp7hn%2FOO7FsmvJ09uGzsXSnl9FMWVr%2Fwt%2FcfeHsVfRrOUwv6UT39zpXfYiZ%2BovkEcrupDD3%2BAHmEUrPo1bWCZb8PUcLuPD%2BLTahEHLgh%2BgOrkBf8f0E5D%2FnsM86OtCz1eKqn%2Fvr1iCWcOc12NFxlKiAZ8R7WmJxf1lHILoxBLPgzg1rnZ9eDus3rkwAD5%2FHavxe7C9yG4%2BM%2F5JfAHX8Qx5VIWHbQce97tuTXwFZjvxZeXxEvvTbiNfzgOpVJ5GHVYwn30Qjz4hl0b9VbpHLtP5V8IX66A5EcDDr%2Fgz4555hhXM5xvQ2d2IRF56EEPpTHPXiIsfZ6us1HEQ5K%2Fg9bVPIL7fwD%2BkquVJZx%2BV3lQYW4eew%2BuxZs%2FeVMvbpDdeWsavGh7BfypDDrQ0471refyrzpePaw4Ba7mQln%2F%2BAZj%2BOLbnPmQrUc7SlHej%2BRZaArO9Se5N6IBcFlPLj7YAAQfvevTj2P6oqlSen1%2Fg1c%2FfjebnnT1LjvcqqO6XQPw%2BbME1%2Fy8gC8IRaHuWxMcCwLsSWn%2F07D45i9udH3dtdlebv%2BPjb7o22CsNyv%2FVPzIAIPZtKVzux71iabIZ8Vyz1ZVT5woZoX0VaJbJM35eOmGwWvPIHnMzR3Ot9ZWg9SUfeY6%2BrkI4uAjX8NRPbuGLv38flkX5D%2FDfp4E%2FP%2FAVXH9INbxle7rwgf%2BI5pf%2Fl6j4yZv34esPAX8hNvSt4al%2F%2BhH%2Bbs%2FT%2BKJFNv9PT%2BCp1xWP0n4%2Fc2QHVp6Re6BcHK6%2FiJPP0hd3cvPz906%2BgO%2BNOIZhIB1o%2F9TfA9OfxAs5J8m7vbnY1UnUE%2FdGZbEh2%2FZGuOvUpmq5xyuEf%2BJjjow2P6JZwVc%2Bfw%2F%2B6vnP4YURi4erPoAvfTl38h688Pzn8AXRxLsRPYDOVFwyT7MO3%2BmnPWWfxAvqnqVvbscKnnl2p1iCFXrYdWasg%2BeESUEy%2BD6GUxZmq89ex%2FcS97gIvjP3Bl4Y2SE2xDsVBjrj3DXj4vD3HJU8DsTnx%2Fjfz30ffUVtGP8u8tdOIjGxgA%2FTO9ZfPoeVXXFLKPfmdWAVPzrUq%2B2R%2Bi7%2Bz1%2BmxHIi0Tperu9i7lAzPjuxgL5jFqsiPVstjz2CXz0n92xZHPinBhF4x29%2F%2B9vf7njYuUHXoA5liSy8PM0%2FrZLxU5ZoTLyZEBAbz4GT4gu%2BIhQrla6ILrhpsQiQAeQfx6xYTiW1jzwn7rCcJSlXGSLaSN66Kr8CrAzHdeZCe8QeyRd8cbjOUnB3ZSLw%2F44%2Fibo3sghD%2BiLSCcKqvDxlosvkjEDdIOD1umiK254ZrawWDz0bv8vzFlYRgFqRs4oQSNb0dd8wMNRb8FVg1bsuu4OgLxbLZswM1hkBNrLWGXDujhFgBBgBRoARYATqAwEysuTG9%2FrQl7VkBBgBRoARYAQYAUZg3RBgI2vdoOaOGAFGgBFgBBgBRqCeECg0srpHMN1fwSAm2w9henEO48V%2Bor3ZR6FUXEql2%2Bx4sn6MACPACDACjMAGQ8AxsrpHkFucQ26oHU2pM8iNFZ8wpDjdujC%2BOIKe4oiq0HqjyFEF1e4YS8b0jkHPHTMCjAAjwAhsGARknCzyjgwBp9o6gbFz2Hb2MYxFCn4TQY8bEzjQNhGhYZ01KRWXUunqDF5WlxFgBBgBRoARuNMIeHIXtmBb8xpeKcbAIgMt02tnGieFVtJHcGAcGDh%2FBqkYlSzgVNtJXLC07Rmbw7BIWQ4kFucwTOXZUbQOzFotgn7IQ7Ib%2BXQDUqlG0Uj2RWGeZd0lux%2FPuUdOh072ta3%2FHHIWz%2BxgJ%2Frt%2FH5BsgDw8NTpeshYvXwNe4YsbFankDw4gZfQEoiL6MnDk8rC8FS6%2B%2BNikJ%2BWhik8eqIdTatTSC%2F3IpUAlB76OBEXVe4np8JTp%2FEfWxqXozJjvYdnMGYGHbiKEWAEGAFGgBHYoAjI5cIbE5jMtmN48QxSWFX5KyOI3IXxzC5cSXaita0TrYMLwlg6ME5GzxLGDlL5KLIeThcGVDkZXxZtqIGlmLQjFc%2FI%2FtpGkU%2BdwEBoXo8WDJzW5GzrhJTRh2dyCvG%2BQxFyE3t0J7qhc5osjUj1Acct%2FU4t9%2BKw2JcWjIswlkrAU2qh4ZKcAjo6IugANCWASRqjWC%2F25I8gmb6J%2BFa5J0%2BOkzU%2BQj%2B1vBuMp3lsycDcjUtqzNtGgSHFk7QIwkyNE%2F8yAowAI8AIMAK1g4C9J0s8HJNTWIn1IkN7s6q%2BJ6tUkBZwyjbIlpFfbUTcTpkSxHMJF%2BeBVGYuYFO%2FxvNGHvlYDKFb%2F7t3I5HNOMuqwlB1y5KdJM%2BV%2FCN8I3nHglQILS9BB%2BKZvWp5GBcwKYxjrSO1T4%2Fmg8tbGYanxkM%2F3N6BPTEy5ufk%2Fj%2Fh0WrANs1IXl%2FMdOH4mBFgBBgBRoARqCwC7uXCh2JoEst2wPhiEgPbZx0jwrffWVzKHsVwZg4pUU%2BeqbAlP19GZRTeRP7lcPKXxh9D6ziwk5YFFxsjLk%2BG861si42Ap9KoC%2BNDDUgnO605IJdfVW3JeNrLpooT%2FzICjAAjwAgwApsTAduTpdRbyS8D2%2BNQ6TFVue%2Fv9kPoa55C0l7%2BcfZd%2BbYvKHR7MQqqwwq6U0jF9D1kDr%2BeMWffj85GGAfksWuOR1pO02ldxy%2BvYiVBhqhVSlgkohl8Lj76Sdl46swqe1w8ns5Y2JIIL6FaNrVL%2BYARYAQYAUaAEdiUCEhPFi0LDbVbCrYjl7qJdDLCF4a0RLY8h8xirwaOonVvcBaboF1ejFmcTSeRUV6wSBvfqRu53CQ2y7s21Lv5raSnkE2IXffWpnjd6JIyqqU8Tfjoh%2FSV32AMOSU%2FlN5hLAy4lIVnWL%2FF1ru9asXh6R4L56OGWfQn45jOUKgQSx7XnChWRm7PCDACjAAjwAhsXARcCaLF113FhG8g46xv1fpqTipJX5f15enrQtr8Xuk%2FuWTlfEFYaf53mN%2B643mH9eXuGQFGgBFgBBiBTYoA5S507cm6MPBYcarOXEV26Kjbk0UeqaoYWMWJVpOtGc%2BaHDYWmhFgBBgBRoAR8EPA5cnya8BljAAjwAgwAowAI8AIMALFIUCerIKN78Wx4NaMACPACDACjAAjwAgwAn4IsJHlhwqXMQKMACPACDACjAAjUCYC9WVkUcqaxTmMi8jrZSJXbfJakrXaWDB%2FRoARYAQYAUagBhGwjSz6KjBnR%2BLeyBHfTSjT14d6mhZT2ztVdydkXO8%2BKX2OnE9ug9Ypt%2BdaxTMLrLeud2oecb%2BMACPACDACGx0B19eFrgTAG13yUuSj2FZtE6VQrj9NLcnqQocMqRPAsSNInz7jE9Q2ajwxF1M%2BYQQYAUaAEWAEag4Bl5HlLz15BnYjn25AKtUomqykVRwsWefErdLOu0cwvRdAoh1Nq1NIL%2FcilQAcQ47aOgFCnXJAxOu6fA17hnrRRD1qASvJ4zaccCRVdHq5CHxKTewAp%2FTgP4OUiE1KqX%2F0yPQm%2FQDQsp0rbx%2Fg6O%2FIUXDkoVNyqnbbKL2PL54OJigIcBqMGfHVMVC662WFuBTqV6Cb0IOSa0cITiuUowTYFAqkBQNK2Wr%2FerAGFnBJ9empc8YhZNxhxlqx519GgBFgBBgBRiAIAXu5kBokhpwlw%2Bl%2BPUVyO1LxDFopfU5yCujoiJSSpikBTLaNIhvrxZ78ESTTNxHfSnzJ6NmNS3Y6nlFgSF%2Fma0SqDzhu1Z9adlKxiETWii45hbhFJ8tHkRVR4DulrHYiaXrwUxnV%2B%2F0F6deF8QwZGBa%2FwQVhuIUHWvXQCTnPOSl4oPXXNop86oRVN4t%2BpVvbEaRXdVnNmAljCqNSb%2BJh6W7GpQUDpzX92jqrFERW16NRJOqWy4U6JnqbYo49WLvG2FNnGgfXvDZjXYx03JYRYAQYAUagfhFwebKct3wvIAs4pQwWkX9uN8hUCk1Lk72KCwD2YQGTFKC03%2BK7vQN7Yu1ILc5Bpseh8pvIUx7AG7JNdnLC5k%2BGAvERf64UQFSyYFWU81OifkFddu9GIptBv6ULKF1Othf7HlL6af1hGfnVRsTtugCmRsy6sC9By3DFJudewsV5iNRGe2zvpKf%2Fii5bSmN3THVBY5kZwSsuz6KqjPjrxVon89aZxkGf10as9Q74mBFgBBgBRoARCEbAZWQFN6tCjbYEGJ17F8aHGpBOdmJMGDByySc6fbEt3fn7yKA71VasIROlz4iJpY2Y6Ymyo%2FQp24iE2ePATlq%2BXGzUllij8yi5pYhwv7tk8qoSGrGuas%2FMnBFgBBgBRmCTIOBaLixNpwZsIw%2BU2BOk7ycycBNeA2cJ0NDSWNUz5tefI4%2BROErl9kPoa55C0l7C0%2FdyGRi8vIqVRNJZHiQ%2BiQBDqjuFVCyCgWTEjIzBdvS5lni98plxEcZWcgorzXH3UjDtaVqsxLKeVx4y7JJIWN5Ou5a8W8WE2RBY70aPYEDLfNqcKGYcbAHI25hHPhYyP4uVU%2BfPx4wAI8AIMAJ1gYDLkyX2ZA1Zetubxk04zOJsOimWm1KgDeFTyCbE7nITEYBZ9CfjmM7MIaf6i%2BQ5cHuWCvtzy6M2f8OziVlsAI%2FSHy0vLc%2B5czMWbEb3UZWW2AZjyGXmQLgUbmBvx7C9VOrdiO%2FDTxSZMbswMIp9i2eQkx16PFLRcFFyhi4DB4koysnQUR8ZAKB9fkNKR%2Fdmcmd8NIZkGKHd2rsXIcn4jQkcT59DxsIzOziK7JDlHQsdB61f16EZa1dTPmEEGAFGgBFgBAIQ4NyFAcCIYvJW9K0iedDZH0YbzPvy6utKE3G5dXIp1Plys1x%2BtUIvDTEMdqJ%2FplZkZjkZAUaAEWAEGAE3ApS70OXJclfzGcSeoaNuTxZ5%2BGgTfzX%2ByKgbarc504cI9oZ%2Fu3TzHtC%2BsEyqUYbIYANr8w40a8YIMAKMQJ0gwJ6sOhloVpMRYAQYAUaAEWAE1g8B8mRVYOP7%2BgnMPTECjAAjwAgwAowAI1ArCLCRVSsjxXIyAowAI8AIMAKMQE0hsHGNLBE6YA7uBMMbFNtaknWDQugWi75QrE7YCHc%2FpZ7R5nw9Q0GpfJiOEWAEGAFGYDMj4DKy6Ms5me5E%2FlbXwKmFB9WdkHG9%2BySDJmC8LePRNwVOUJ1drowkyb%2BYudQzdgZ75p%2B0As6qyy9ITqfcnrtjXYrI9Usb693pohxat3xOuT%2FPWfQPAsPnD7ljirl6K%2BdkvedAObIyLSPACDACjEAQAvbXhU7uu2pENA%2Fq3lBe0XQuhn4qUVVLsrr0JWPiBHDsCNKnzyDuqqO8f73ID3biAH3pR8aTnQInuA6HLRqMIHe4CxfzSeyZPyJ5uPgHnHSPYJhyMLq%2B4DTJSXwopVBYAusuHE6tYbJNfRlaJs%2BZkzi1dw6Huyc41ETAUHIxI8AIMAL1joD0ZImI5Ho%2BPQ8stnfC6%2FHwvnHr5%2FJ4QKRrkXTKiyA9ZhSZWwblFN4C2%2FugexG8SzLBPIXEHjmJr%2BrTo5H71EPn9moA23x0kAFOpV7S26E8N4o1yerUe3m6vIaW7mZcLENH41mgm9DDK4eSx%2B%2BXcgkGGCeU9291CmetUAo79%2B9CE9qxrxuAqU7vpjmJb3Rcw3GXwaQ3KDzu2duO7GWvoW%2BQs5CFbwlFl4%2Bn01pIjPJ5Xri8gERfhbxZrjmoRa0nbVx1%2BhJ6yPUggvAGz0FfoLiQEWAEGAFGoGIISCProRiaVleh3vHd3MlrsQtXkp1opfQyySnEh6I%2ByNuRimdsOnR0iOUVSvjc2jaKrMgFaPFVCaghkwjLerck8syfpzB6dDkHF0TU8wOhD%2Fgw%2FbT%2B2kaRT52w0uXMot9Ot3ME6VVdVjIUd%2BOSXT8KDDkGo%2BM1dOtuxqUFA6e1cWjrRLhuukzFHe%2Fc2gAs50WSbpI303EN6azkYaoThoeI8t4OxIArx5xAruESUKLrBVwqOkZWI1KUPUAYoH5zswX7O4ArF%2F1nuL9cYTwBEUctFhPJ0v15RC31zEFxbShaT13B9afNz%2BQU1DUGmOeg4s6%2FjAAjwAgwAtVDwLUny7cb8lpkM87%2BGEo1k21E%2FCHf1p5CzTsm8s82LJoAACAASURBVMFV4oFUYZ6h%2Bmn9YRn51Qi6b%2B%2FAnpjmpVskz4TKHUiGxE2kz3q9NR7oCk6XcHEewpgo8GCptmLZMsAzpdoU8buSh9ivRRHuWw9O4BWNNrBu5qQwqpPpm1hJX0PcMn4CZdZ4lnaojHLLYB1cQyrjGLSCJ%2BWHXNbmcGhHEXjaPNS42gXFH3jnoM7BW1dw%2FWnzU7%2FGjHNQ74CPGQFGgBFgBKqFgNyTRfnirDfy8vLWVUvMKHzdeQ0hvGTFGjJR%2BglI9OwlNeZGjJAQ2ssPgEjiPE6Jlc8ht9joyU%2FoQ1BG0Us%2FXUPT0FHE1Z4stGBbs2RoqhMtth8Sy4ST87vQlz6C1osdmD7dgZ3jS8IzVoZY4aQiSr%2BVu1C0bsFAXwPSx8qYCwU8dTFKG0udQ9WOjXOwar0yY0aAEWAEGAELAenJujGPK6vtGLb3RWn4kAGWSFpLZHJ%2FSF9CNzScN%2FmeMc9eEo2N%2F6FD619fRCntK2ueQtJeojup7b8x8AnVT6Mlj0gswkNVeBR6cZj2LxX8kTHYjr7%2BloIap8CMizC2klNYaY67v24rek%2BW02PBERkW0MaZdIe1R8tUR8tUtKx5bCJg%2BbmgJ62APIXWvi%2BttJhD2nuVyF51xp48OriGizeK4eJuW8BTVW%2BPI%2B63zE7pkRb1vVOKIOBXzMHd6BHVtMynXUfFzE%2BdvXEOWg2LlVPnz8eMACPACDACoQhYXxfS8sgR4PwZ5BaP2kSUO69%2FZgIHBmPIZeaQEjX6l1yzOJtOImPVraSnkE3EbHrzgZsWlBNQ7MuizbzOQyaxOIfhKG%2FktIyyPOfOMxjlqzNaYgvUjzSQy37DQpkFnGqLYrzNoj8ZxzQtlQ1ZKGg6XBgYxb7FM8hJQD0eqWi4qC%2FqyvM80gP9DFJqyMReKqWjo4MUk8rV%2FqrgOgq%2FEJ%2FsRD8ZNTcyyFt60lwKl3UJY5MLyNFm8hnVF%2BFnktM9X5x5JHHvoa8dJ%2F36Lp2nNaII5E2GEdoR30qGdIR9YDcmcDx9Dhma6wCyg6PIDlneuND5qaTx%2Fjpj5DcHva35nBFgBBgBRqDyCGye3IX0Vt63iuRB5%2BFMG7ZpP1E1N4jLIaEHPW10j2KAVX4QNxvHio0befZOA8e1OVExrHzmm8NbGn4QLylOKR8xAowAI8AI1A8ClLtw8xhZ4nN1xwMmhtH2jlVhUOkhO9RuM5ZeP%2FuUD8pCgLxMFL%2Brcpv4yxKngDjYqKb9cplUI1bS62HcFwjGBYwAI8AIMAIbBIFNZmRtEFRZDEaAEWAEGAFGgBGoewTIyAoP4VD3MDEAjAAjwAgwAowAI8AIFI8AG1nFY8YUjAAjwAgwAowAI8AIhCLARlYoRHeggZVGxZuK5w5IYu6yVuQ0a8G1jAAjwAgwAoxAVRCQRpYVL0emJaH0JJ6I2YFd0wZllc7Ej4Y2CPuVBzLkCkZgHRGo1vxU10Uxcz9IlqDy9YLpTve%2FXnpyP4wAI8AIVB4BK04WBedRcapkRPHM4ggQGpJAph8ZE1%2F26VG2Ky9oXXEU6XEmNr7KtSLnOiO5s%2F8EUssLyKr4Y%2BvcP3fHCDACjAAjsDEQ8F0ufGn8SaRdkbfpbVZ5rKJFsqZYRxTYNGEF8xReMi2ivKwvjqeCzEWr8YS1fKU8cvZyW%2FcIpsdGME06nD%2BEASGb0kO%2BqQ%2BIVDVSHj3PXs%2FYOQx0H5K0Fv1OJYgwLgN08Mii8%2FTK6dQpDwjx9PGCeHja%2Bgk5RhCkgy1uwYHXS%2BE59%2FQXTU4znl7daawcvgUCWgUeuSx9ZYT0kP4CWIbNT6%2BcDtYBDFUxpRRKreHUwFVVEvobKguAbdr81GUpdX66riFvdHrXuHvCorjqooxdqPrcgBFgBBiBTYuA48lyqbiEV5aBPSJiNSUJpkCbnegXbawH3ow58OaFgU5csDxcfkE6Zb3VKd24KalvCE9qTQ%2BHYYyitc2bi64L45lduJLslMmsBc9zGHj5MYwBaEoAp9oo0vpR7Jk%2FgmT%2BBL5h6UdR3VNxxZP0O4GBiypGUyNSfRDpeihiOfV%2FuHsC%2FTNkEAXhYqWWUbK4sDXVmTyDBv1EyhhNB9K97FyBpcpJygbJ4tGBlqn3Xq1AsFitPzHn9PFzgW%2BfmOenR059LhnT8xBmvcgPyrm%2Fz%2B7NfGCWhWg1%2FcTY6hHxS5mfQPD159HduoalBqY5YdaRaxkBRoARqEcEfD1ZLiAo91tMppaRHiJ6szXn1nPRB53o%2B8AyvWgKaucq78K%2BxE2kz3oNLADdu5HIZqSBRTSUZifbiPhDFgM7n90CJse9qU4WcEqk9KG2lD9Po6OV1Eknijw9nPpnKIejCZclXJwHUhm%2FN31TnUtZ90mYfpQQW%2Bkg8tbFYMqO6Gbud1ainIJVpWXxk08v0%2FrzGT%2B9ZaTjUKz9uchlwlE5P%2FyblFiq6ecztsXPT7peZH5FcU3r159Xd5fE5cwJFyM%2BYQQYAUagLhAI8GS1YFszkL9MxkgHoOXdqwwqXRgfakDa9vSQ9yjqnq4ICZrLFlJLjGziZcBFJHEel%2FvbcouNrj1vpjpTd%2BtdV3k5KTn2UQzbeTApH6KPwVy2ohHHr%2Bx%2B3Az2dzQCsaOu%2FJ%2BUe3PfnUqvEzg%2FS7%2F%2BKj8n3BjyGSPACDACmwkBX08WJflNYQpnyWMj3px7cbi7VLXDvV49Y559H4Fd0UO6HX39Pj4aSsqbSGJgu0W8%2FRD6EiU8bLtTSMUiGHIRcREPpeQUVprjcPZySRlNdQUQVEq%2FAsbO%2BASNQ1FyFvDXCmhMmqfE0mtrWydaQz%2Bs0Gg172mQnKJ11PGzWTv620UlYj12kHRS%2F0aRJe8iLbPTdRTpz0eWSHQ%2BjSLOT6J04Sl03w25342WxP2vzcA5YXnI9H1jPtJxESPACDACdYGA48lKaG%2FgrjfgWfQn45jOzCE3ZGFi15MHyrkJ01v7sF1HbWdxNp1ERnku7C8Y3R6NlfQUsolon2JdGKB9VWeQS1myKJ70pdtgDDnVF24inbT2Vaklw8Ahlcuhw6KeHozm%2FWaSTXRcYMlCe7og9rg4mJnqXHia9JMClfC%2Fe3zc4%2BAe28hymqSgJdzlOWQWe7VW2jhppe5Dk5zUspTxIzo3X%2FsL26pg7dao8CxAlsKGEUtM89Nw%2Fd2YwPH0OWToWqal8sFRZIeUl9k0JyKKxc0YAUaAEagjBDZRguhSR00uVfptzi%2BVI9MFIEBejr5VJA86e9zoQ4K%2BfDnJlHn8AtDmYkaAEWAEGIE7iADlLnQ8WXdQEO66ThCYuYrs0FG3J4s8kQUfItQJHqwmI8AIMAKMwKZGgD1Zm3p4WTlGgBFgBBgBRoARuBMIkCfLd%2BP7nRCG%2B2QEGAFGgBFgBBgBRmAzIcBG1mYaTdaFEWAEGAFGgBFgBDYMAvVlZFG0bG8KkQ0zFB5BaklWj%2Bgb85TCEZxzQnxUTUjaiO%2BTEqlq%2FTFjRoARYAQYgY2KgMvIMuYz26ga1Jxcd%2BIhvN59OjkYC%2BIlWcajzB7gMXqC6uxy1V7yL%2BBtmAsU%2B23P%2FJNORgA94rnKy3n%2BUEEsM2K5s%2F%2Bck18xlG4W%2FYPAcAAvg4gRq9Z7LCOKxc0YAUaAEWAEChCwvy4MzglYQFO7BRT%2FqG2iNuSvJVldiJIBdAI4dgTp02cQd9VRXjyZ2%2B%2BASE0kc1a%2BIuKSBdfhsEWDEeQOd%2BFiPinyTwoeLv4BJ90jMt%2Bl%2FhXjzEm06kFCyXjam4eMZabz6cLh1Bom26xUTFHoZk7i1F6V41LnxceMACPACDAC9YSANLJEdHRDihPyJGj5zbIqTUj3CKb3Aki0o2l1CunlXqQSFMCQolzTG%2Fdu5NMNSKUaBaYraSceUs%2FYOWy7fA17hqy8ha4gpkTrBOy0%2ByMuHll0nsF19OA%2Fg5SId%2BoNNmqW08uTRHD1GTRbPHK6dACwrf8ccgW4uPVWAUDH7KTE7novT2EoJyyBrCCtepkIbkrVKoArHXvkLNBN1FPibZUwO0hhVU5Jrh8D0IIBVaR%2BKS8ejbNl3OzcvwtNaMS%2BbuACgusuKXr6bU7iG83XcPygN%2F%2Bk3sh93LO3HdnLJ92FrrMWDPQ1IH2sMMXPzv4k4uknccHVXp0E0124vIDhPj2Rs6Ip4dczRsACbEw8dc6cCJnXnqC4Dl0J8jEJI8AIMAKMgC8CcrnwoRiaVlfh%2F9giDwM9ZK10IckpxIfUsg3QlAAm20aRjfViT%2F4IkumbiG9VaW%2FakYpnrFQjo8inTmh7YhqR6gOOW2lITi2r1D1kEO3GJS09CYbUHpcWDJzWZGnrxAHbO2Gqowc%2FyU%2BpTvz%2BNDmTU0BHh7Vs5NF9cEEYKE6ffryozEPnwYwilPvjMot%2BW%2B8jSK%2Fq%2FE24UGoUitA96qR1sZJFU0JrqbdM8SLSvqhE0mQIBeKp912Z451bG4Bl6S0ieTMd15C2BsRURwZLYogyDrQDMeDKMSeYabhklFR8AZd0r5WXiFLxLGvJxe36FuzvAK5c9L8yEEgHgGKCxcpN0k2CeOaSaw576kzzzDWvzXPJVp8PGAFGgBFgBMpCwLUny5cTeR%2By2gOIUqNkGxFXqWqyV623%2FAVM2gaP4rSAU%2FYDfRn5VY2OHCqTzsOSjAGR4217B%2FbEZJoUuW%2BHPFoqp9sSLs4Dqcycs0dGdQVTnd0o4ECTU%2BR8K%2FPhGIYZ5bQz4OIrpBEXMiRuIn220BPjy8sujICZWLaM6sWyGQcerOSBgfMyynvrwQm8orUMrKMlurZOYcCvpK8hTimeFv3mgMYs8iF5o8jT5YOdyYgiAzWIzu5bzVu7oPgD71zSOXjrvNemPs%2F0eW2cS3oHfMwIMAKMACNQDgJyuZCSwlpv3YV7Usph76WNmLDZtXTo5iES047Lzci5xUbX0pepzs0l6pk7xxst05xq83kYR2UX2K58XIAISa19%2Bq88Zj6dWEUv%2FXQNTUNHER%2FshNxP1YJtzbLSVCdabD%2BEb3Rcw%2BT8LvSlj6D1YgemT3dg5%2FiSzz6qYBkKasiQgrOE6dQHLwWKNoF0DodSx0TnULVjwzVWtT6ZMSPACDACdYaA9GTdmMeV1XYMj3UVqk8GWCLpLPOJ%2FVsRjQKdGz2UYhEMAfHGrZYOdQbuY2EcJKew0hwv%2BCLMVOfmEnJGujZPIWkv4UVJHA2gGMwqggsZg%2B3o61fLtH56mb0qgZjRnp9FZ3nYj3PkMlpCgzZ3LEPlLC3lmerUsuaxiYAlbZME5EFtF%2Fu%2BCltZ3ijNo2q3IW8PruGivR%2FOrpH7zciL5Uenmm2PI%2B63BG99nRj5y0gxl3ajR%2FClZT5nr2JR80zJRb9RrrFi5dT58zEjwAgwAoyAQMD6upD2LB0Bzp9BbvGoDY3cDDuBA4Mx5DJzSImam0irTdBqydCm8B7IZb9hUezdcO5tq85n0Z%2BMY5qWhIasMvut273xW20Ml9636HViA7jNU%2FXr80vLL8tz7lx70PT3IRFFtMQWhJloUGlcgAsDo9i3eAY5OUguDx8wi7PpJDJqDO2N7ybMgpQLKydDQH1kAEDspVJj74ytFJPK1ZJxcB2FX4hPdqKfDJ4bGeQtPWl%2BhntelzA2uYCc3yZ0gzeqh75onAzgb6BT6ATSk9GEdmvfYsBeL8WEfm9M4Hj6HDKLtOeOPioZRXZot2wROs90Rvqxg3XhNaa342NGgBFgBBiBchCoYu5C%2BXXTJfF5fjki3kFaepvvW0XyoDIE5AbzvrzzlWT1pNsE%2BFUPnKI500b7yONG3rvTwHFt3Ivq0GfeOPTSsIX6Qtep4CNGgBFgBBiBTYQA5S6042RtIr0qpwotYQ0ddXuyyAtUsMG%2FQl3Sw5m%2BoLP%2ByFPjHzpAteDfqAhcGDiCbedPYOBihE385CE6GJWzt10Xxoegeeicegpqmkk1yhAgpq8dHRI%2BYgQYAUaAEahhBKroyaphVFh0RoARYAQYAUaAEWAEykCAPFnhIRzK6IBJGQFGgBFgBBgBRoARqFcE2Miq15FnvRmBqiBAe85U8OCqdMBMGQFGgBGoGQQqY2SJz%2FznEPmzdAVPqXSKfj1%2Fa0nW9cSl5L7oK8QKhYYwysAPfSM8XLk%2BCPD9Y31w5l4YgQ2GgDCy6MurAgOJNmH7xc0qSoFaeMDdCRnXu08yaGSU9IJxtm7%2BMrq%2Bx%2BgJqrPLVXvJv4C3Ya5QWIY980%2FCycsIgObcopTTFNGdNpBP6zHBjHSz6B8Ehs8fKoinZhDPXBXYn4OzrYd%2BDQXSmborZ66UQ2uSqcJ1gbhUA08rX6c9z9QctnSy5zbNQ09doNpunGl%2B5iLNN6Jz5jvNmaBrqGDOB8pSqQq3TpXiynwYgXpDQBhZS3k932AJEIjUK1ZanGLIS6Urpo9Kta0lWV0604PqBHDMmwuRGlHuu17kB1VeymvYk1FLPcF1IgYU0QyuIXW4Czv7T2DP%2FBGZFsnVd8BJ94jIs%2BjOAam%2ByrNkaaNclykrCKfOpwuHU2taCqcIdDMn4eTG1HmVchzWH8VRUzp0otVOnxRGV4osm4EmDJdK4xk8r83XQ0SsrcwEetgXQRl4%2F6BYcer6o7yw6vrT%2B%2FPOeb2OjxkBRmAjI2BcLlzJLwvZe8bOYaCbIn9bb132W5r%2Bpum%2BOZB3jAKbJqDlIbTf6oPpxI1ucQQD9DZo9efyWrjeNKU8rvogtD103jfGbb79ed80vW%2B27novT4mBhZmluxkX71u2T34%2BoYdXjiClqZwCzQaELaDcd6tTEBHXAezcvwtNsKKjm%2Br07pqTIt3N8SLCWvTs9csVKCOz21HrRf%2BFSct39icRT6e10BbR6ESSaQpIqste0nG0%2FgpZl0onOfnOTzEX9OtOXlc0D0PnGRnY6nr2elA810qk66tQ4YglpeJSIp1pXpvqImljJVx3JTA33es8TB%2BKocknS0DhnI9wn%2FCwjnTqGnctswARu%2Bp0j5v0eAXer03zLJJQ3IgRqG0EPHGy6ILZDQogurS1QdOsEak%2BiPQyFGGbbuCHuyfQP0MP8E6MiQvJikJtUVHC5wtWeWFA0mA6Sd6OVHwUrZQnkC5uO0cdvYXuwpVkp1xmomWGvVfh9ohoYtuHHjrimTmHgZeV8aH1J2RW8ZRm0W%2FnKqSb5QmbIyjVy3nCqhP9olTebHpmZOodwmgYlg4alRkX6yat9NPoqnG4k8Z4%2BaqImi7kbZ5COtuLOBlchjoyWIYpkrsQ6iauJJ1greFyUjLrBVwa8LaUc%2BIVYZxTaPNRtB705olswf4O4MoxPVJ6FDorbc%2FQblDiofAo8V7Z9POw%2FhpFAvOC7AjC2O2EWT%2B9H%2F04aH5SOqwzImXQBYq7RamAlkdlXsgZ0%2FVnmrvrOwflS4AJl8riaZrXpjp9NIKOtwmP7pM44ErFFH6vG7ai%2BcvcqN5ryW%2FOV2OMPPdI1z3dU2e6f7ru16Z5FoQilzMCmwsB4ckSyXnjzUD3biALO89b%2FqfOw0zP00aGQn9Vgyku4JRaZhF51mLi4Vgy9PSGms04%2B38oXU62EXE7LZDWH%2BgNWa8L6JUeaDHNSye8dio%2FIBkSN5E%2B6zUSAnjZxUu4OA%2FxkA70HohlB2Uc2oQlH6zkIfZrUTT01oMTeEXjFFg3cxKtbZ1Ipm9iJX0NcUqBtOjjddN4hR%2FSDVkZpp04haOF%2B1oonc2yNo6CaQQ6u3M1PnZBCQem%2FuQDlbAR%2F2g51V5%2BNdGFiRE0P2XKoMRemXO05%2FAuXIky54xzN8IcDBO3qHoTLtXBM3BeAzDVmdVqRyrVaG7iW6svF66iz%2Ftlpu%2Bcr8IYee%2BRuqzeOtP9U79fG%2BeZ3gEfMwKbFwHXcmHPXuDSwFXAumlvPLUpEbJ8sxVLiRRZWxljFRVWS2Js4kv5D9UDVfzqxk%2BEZNg%2BvEWi5rZOHMcJuVxqL7H6NC6zSBjXqaMiL6D0BrZgW7NkaqoTLay9J5PYhXj6CFqTU0BHR%2BnLceKG7BgTFKE9DT1ROCVzbig0XEPpdJBKGxOdg%2FAWxUxyaq1F0mvrvCg5NR6%2Bh9r8pD4SlEC6C%2FuagxJa%2BzAxzN31nIPrjadpXpvqfBD0FJGxRPsIT2Bgu6cq6ukN8kzqLwIBc568seOPCUN%2BPe4TUcX3bWeYZ77tuZAR2GQISCNLJK3djX24iguYxSXsxn6sIf9yJbTVbxpl8tt%2BCH3NumEjl%2BZCuZJ%2BiaRz8yM%2BCe1BpTOgN8dYhIexeGPTjQCdCRmD7bD3F%2BlV9rEZF3ETTU5hpTnuNlzIHR%2F5qye7M%2F8DYQRoOFiJj8UeLVMdLZWe3oUrxybg%2BDr9uygslXtp9nUX1gA6Js2IxzTZyEhBkBFhoFPdbI8j7rPfRX3R6N1Pp8j8fyP0R0uu%2FUkksnRNqb9odKq172%2FB%2FJRzbd%2FYbmDSu9REHPQ%2BLY7Guev0GjgHnSYVOtJl9Iy71kPReFpfLbrG1jSvTXWaHMGHlHhb%2F3gkuKVvjTDEtXuPcc5LDoFj5Ke7b6dWobhHkrFOf%2BRd1PZkFXP%2F1PuIMs%2BKlVPnz8eMQA0g4OzJSrSLDcUk81K%2BAcMpIH0xTAPah%2BRcjAnaW0BvLnZi3VmcTSeRycxB7FGhfTbC8xRGF9AvuamX59y5BEFfH%2BkeJB9aWmIbjCGn5Cigkct%2Bw4KU3kijGG90Q41jmpbKhqw%2BNd0vDIxi3%2BIZ5OTmHLnHyPa6RcMFlpzl7SGiG%2BYZpGKWjLSXakjp6OggxaRy9aAOrqPwC%2FHJTvTT3pMbGeQtPSnXYriscokrR5vQZ1RfxGcCx9O7nLlC27IGrb13tA%2FwcC%2Fykz78Q%2BjUbAikFy8Y7Yhvpd1aEUxGY3%2FueS32lakxN9IpKYN%2BzfPzwtkp9GVimCzY5xY0z5yxLZy7Hh0qMgeD9Aobd48s9v0jjM7QHxzdi5nzJo6uOjHO55BZHAHEfcStQ%2BE9Uh9beS9TRnngnBX7pZz7ru99oqR5TXLTkj1de6PIDln7bEPvny4EtBMH68J5pjXjQ0ZgEyNQW7kL6a2nb1Uz4uQmfNpPFL75vdxRpJul%2FChA3QTL5VjP9LTRPvK4ic20wHHbeC8SOZ9543CQD0EMVnufodNjpY8ohtI38OQ6XANRJOfrJApKoW3KnfOWIVbL8zoUI27ACGxwBCh3oePJ2uDCCvHInT901O3JorfbIsIHFKUmPZyH2m0S8qywgWXDUdYB7bnadl59xRnCit6kD4a0CaxWcZg0r5nVloyTTKoRK%2Bkj8ou8QB4bs0LJLz1mEbxwG1MNlsoPgTLmvJoXtTqv%2FeDgMkagVhGoLU9WraLMcjMCjAAjwAgwAoxAXSFAnizX14V1pT0rywgwAowAI8AIMAKMQBURYCOriuAya0aAEWAEGAFGgBGoXwTq0Miir%2B2KSUtTK5ODNhzrKVZqRe6NLifPl40%2BQiwfI8AIMAIbFQFpZFmxSlSuQPkb1RAp5eFODy4rp1%2BxhoFH1sDI6AGIU%2FiBPfNPOtHfC9pF1SdMh6h8CgQwFDh9umL%2FCIpZ9A8Cw3ZeSQObmq8qAlsRV0zNtahz2gGopueLUfd6mi%2FOePIRI8AIMALriYA0sqw0Ka1to8iCYiVRWpCQ2FNlSanSZVB%2FxfypL8WstCUiwnLKCqAXgU%2F3iMgnWJlwD6XqEEFO3yZkYJ0Ajh1BetW3ATBzEqeWgwKkBtBs6mLKudaL%2FKA1X4oNFFnT8yWC7jxfNvXsZ%2BUYAUbgziMQbbnQ9UbsZGCnWEc5EYxUy%2BGnpYGR9cqL4NCVrraMFm5HUqecWn5RvAM66Nnbjuxln3yCLv30IH%2FEiLwmxelQHVzIqAs3fCl5c4ICfQZgUExxz9g5DHRThHlLf5eXLAgXr5fJc%2B7C2pvvMIgnJT%2FW5NAC4Br1EfNjCiKCPUVg378LTWi3c3MaaSkAai3Pl4i6V3K%2BhOHJ9YwAI8AI1BsCEeJkGTKwD1DcKHow%2BgfppETSdlwpekhSstyZKNHUg4ZBeo9eEcYdhSUeRetBH6PJl5ySNi%2FgUkFUbI9%2Blj6SBXmPSLdO9IsCy2AI0UHqvZ64aAqLWGK7RULt8OjrGp3vYSNSfRD5GYkXGY%2BHuyfQP1MaLiJdB6XjSTqR3J1uTTxNY%2BRw8B7t3NoALF8VUehJ9uHmKaSzvYh7G%2Fqe1%2FZ8iax7ReeLL5BcyAgwAoxA3SIQbmRZGdhFChWCSWRg78W%2Bh%2Bg4BDdPME9gIYQgrJoexGeQWh5Fa9useOjnzsddEeDDOBTUe%2FXTG4hcYu1IWakmZNVN5CkBbJjuOh%2FvccVx8XZg5YIrR0aLZVbLh2cbzSXjsoSL8xCpc%2FZQAFA9iKyJ50O7kchmZBofr6oh5yt5iP1%2Fe%2BaPoHVgCT1jUY2sAMY1NF%2Bi6165%2BRKAGhczAowAI1CXCIQbWSXDQvunGpC2vRbSs1MyOyIUD%2BIFnLK8VzJq%2BBnLu1IW52BiLR9hcKNiaqqAS0H3WpLZgroKFZSIi0hoO07Jk88ht9jozukYxJMM%2BhL%2BXvrpGpqGjiI%2B2GlFdG%2FBtuYSGBVDEqRDMTxcbUubL8Xpvg7zxaUTnzACjAAjUB8IhO%2FJipSB3XoTNmDWM%2Bbd62RobKzS%2B2pGPHYT%2BZeNBFal3M%2B1r9vTVugXkH0%2BShZ5Dzv3qS6ru0adVQ4Xi%2BP2OOJ%2B%2B9SsrzILv0pUkhTxG4qLo3eQfsLYSk5hpTku94%2BZeJrGyCQ2LYVBmx%2FdKaTg7NEykQI1Pl%2Bi6h40X8zgcC0jwAgwAoxABAQ8aXUC9hG5lrdkpvgxbSlK5coS%2FdE%2BqQG5T0rsg0lIKVbSU8inYrjkk5letIjoAXD1JbLFF5HYl%2FTwJJimvnWelH0eQ9oeM7GXrBdNUg3AlpOw8hiOdp1srPOV%2BeXCcFGd%2BP1aS6UxvY6%2BBHXvcSPM9132wcTSA95lOp2d5ziQF7ULxMWNp3ncPXMpIs%2BCMfLI7Tp18SzEy9XWe1LT88U7Rv66G8fYiwefMwKMACPACERGgNLqeIysyLQ1eSt%2F7wAAGFZJREFU25AeKn15z36gmtXGI3iAUSBbSaMQgz4GmIcNnzoI1O98cTDgI0aAEWAEGIHiEajL3IW0j%2BtKxwkM0Ob1TfVnxRA7OCG%2BptNVI48ahdqIp4%2Bgf0av4eMwBOpxvoRhwvWMACPACDAC0RCoO09WNFi4FSPACDACjAAjwAgwAqUjUJeerNLhYkpGgBFgBBgBRoARYASiIxD%2BdWF0XtySEWAEGAFGgBFgBBgBRsBCgI2sjTgV6Iu4xUqkIdqIyrFMIvL9%2BeKTVRePHH3sMBI9t2fxHTBFVAT4mo6KVPXb8VhUH2PuwUbgDhpZ6%2FkAoPAHTv7B3GK1H3B6f7X0kIs6JmH6ReVjz8MqHjiyFsQIs262OZGb0TMngursctVe8i%2FgbdCoZ%2BwM9sw%2FCT0MijS85Bw18aKPGKb7WzTuBv0wi%2F5BYNiVc1Ij3fCHjm65oo3FSszBSvAIAzmoj6DyMH5U7%2BBmmktuTg5N8Vi7OUU7q0Z%2F5WAWTerCVneiz0IpuGTjInAHjaz1BoViMnWita0TyTSQOl2ZJMr%2BWsgci61to8j6NzCX3pjAAcqXuGG%2FBCxTP7P2FaylG%2FkJ4NgRpFe9bCkfYi%2Fyg3JOtCavYQ%2Fl1hTNgut6Dls0g2tIHe7Czv4ToJQ9kceqewTDGHWnFBIPxSA5dbm7cDi1hkk7HZFJP4tu5iROLffisDcIr852wx7XyjyLAOC6XdMR5oSvuOuN9Xr3pym9bmOh9cmHdYuAbWT1jJ3DQLdcphJv9q63X7LWHU%2BQ%2FXbUPYLpsRGxtJU7fwgDInGztsxlv%2FW739Ap9hCFFEigHcOK71iXNggB%2FakWgq%2FyJKjC6L8vXbyGlVhMJFGWVIb%2BPDq4vAieOhsXkyiCRj3MqaF8o5O08lh6VvQ21E6%2BMQ2IcAwST5MsxMNVHySTSwdPcFXRp8%2B4B%2FGykkibxlaOfQBPlyw%2B8ov6YsadbuSPeTxGlvCUg3DVif6%2Bc%2F8uNKEdIiOAqU7XvTmJb3Rcw3Hb6NEr%2FY979rYje9mb1Nwgp8ZmZ38S8XTaSbqOaHQXLi8g0Ve5lwrXGOrXrWf87OvBeJ8Imdea%2FoWH%2FtdtWfcXlw7e66FQAiop9C7qZcHXdLicwDbterfx9BfDKo02J4ws%2FCpduGj3eKtt0JxwlVdqC0SILDpmzj3QPVcKVzPc9V6sXXpYcz7K%2BPlByWX1hYBtZAGNSPUBx9vkm73z9ks3CYqAbr3xt1FEdMcAaEoAk%2BSxifViT%2F4IkumbiG%2Bl5QzyBuzCFct71JqcQnxIPiAp0bD08lAUaouvFSVeGh3B%2FVVieMQDNXvVeliZ9GvBwGlNh7ZOzQMRrJ9RxhvzuLLqpJ0R%2BRjtVC90g1TY%2BHFpRyqeEd44whMdHTIljRfrwQWRE9CVgNmPnZfO5Xkz4eLLTBSaxxaQ9daYizmh5pIJ6%2BD%2BSq3ZubUBWM6LmGJ0s8x0XEPacjua6oTBMjSH3FA7EAOuHCuMSxYsUxf2JRZwqSQPZQv2dwBXLi4Fsw%2BqoRQ7rpeKoIbh5YQVeeLIIyz%2B2det%2BXoIvk9Qn9q8bhtFPhUljl3w%2FDTPwWC6gnuW63oIxkbkiYxTUkxpMEpvKJD%2FKY1V8DVtltODC10rFTSUg7XxqzGPbfCcMF3vfv1EKTPLEjyXZtGv5myb17NtmhNAkH7h4xdFH26z2RFwJYjOTjoPDJpAF0h7kZS5HalFurmqv5vIq2CelrGyDwtyGaPfakPegGwG%2FSr9zo0JTGZ7sY%2BS%2FaoyxU7%2FNfWn6IS7d0KninDciFRmDilqqaX%2BMep3YwkX54FMZg57vOloStUPkuc39rdg7MYSyODD%2FJMFAUT9FVrAKfVQE7n%2Bdgtv3Ev%2BjcNLvTroFFHGQW8f9diVoomIFixKA9aKd0njrogLf1fyEHv1aLmvdWAJPWO9iFvNAutmTqJ1RnoqvoFriGfmkAOw4p0fhd2VV0J5F5czaFXXQNHcLMO%2BZHrqkIxEWnb3euIAeOeSfr0TadB9QuihzWuRM7IR8UrcJ%2FwwMs3rhzz3LD96vzLKrbmX7pVxYLVBekPjQP6iX%2BNiyjRcKnG9F9O13tY0tjcMc4J4BF7vegdFHBtlIT4aZhWZSyH6FSE6N61PBFxGViAEnpx8dju6EVbjL6i%2Fsvqy8uThEKYzRzHdv%2Bx4pQz9iUTG4%2FKhmltsdBtoJcrz0ngG%2BfMd2DkO7O9Yw%2BTBErwTrr5ncSl7FMPKiKQbTZvPg9BFE%2BHEgEsEap8mFJW%2BQeyNk5u%2B6c1%2Ft92uGljbzD0HwvswdBTxwU4cEJ6lFmwjZwQAU51osP2QWCacnN%2BFvvQRtF7swPRpGs%2BliMay7Cf6%2Fy0Y6GtA%2Blg5Y7qGV8oysJS0leKj%2BPn9akm9%2FapVWanzM4iunPtZcxw9%2B2PIT15DfGuXPZeUqJv7N2hOmK%2F39cGkEnMpSL%2F10YB7qW0EtOXCAEXEG1QJG2fp7S6RdNLXbD%2BEvoR3wmvLZqr7KP2JNfli9uYo5uRFm8Dx9E00qaW2KP3Rg3f8MdAS3UpzXC7RRdJP69d1OItLy7uwv7sDe5bVsqWrQXEnhG3zFJK2O9ydNDqQmdBht7XZm1zm2h6UiLgE8obP2Hoa94xp%2FWl1BVirunLGXfFQv7SEBm0%2BkqdILdua6mgPHS0hH5tA8abxMvKr1r4vJUeUX%2FK%2B4BoulmokbY8jvrpaKC95GYraJ0PGfDv6XF83WgqUdT1oINA4xCI81CLNT585aKIzXQ%2BaiAWHgmcM%2B7CKizPzyMd3I44IOtiMfOS06zbAgXFsDXPCI3rQ9e5pZj41yuIhrchciqKfYfyKvsY8OvBpzSMQwZM1i%2F5kHNO0LDJk6Rv0JqjDQUs7gzHkbO%2BK5UmyHxSzOJtOiqU49xJeif3pfYcckycpmzqKw90T6J8x9UeeFt0QkDqI5Tmjfm66BC21ejC7cHkNuaFeZAc7NWnD6bTGziEtzSzPIbPY65TBi7dWpQ6FwXkOGWspODs4iuyQ8ixFx6VQv%2BCx1T1uK%2BkpZBMxSxq37rDkL3kpVHAlw%2FEMUqoLsZeKvHxkhDr6ifknvH9quTy4jsIvxCc75TL4jQzyi2eQS0GMY7isSxibXECO9tbMqL5IUJOcgPiicbLTx0tmplPDHEhPDyy0W3soo5mMFwZGsc%2FSWfBXS%2B%2Bm6yHUQyQ%2FgJHbEdT4EHf3nHDPM2eM%2FO9LwXMw8H5mvB4Umn6%2FZDwfRSp%2BFf1YQgvtMSODXTQ16UANguT06ydKWbQ5UcjJIKdpbEH7rgLmBNwedtP17h7bQunskhBZaE8WfUxVOJdsDj4H5rkUrB%2BxqvT4%2BYjHRTWNAOcurOnhs4Snt6W%2BVSS15NC0WbMvf8RZEt0Mem4SHYoaG%2FLenQaOa2NbFAw%2Bc8Ohlw9WDN7JcCEkA33oEtH76gjPR4xAiQjwnCsROCYrEgHKXRjBk1UkV26%2B%2FgjQ8tbQUbcnizwMRYQWWH%2Bh67fHCwNHsO38CQxcDAgvoUNDb%2B4H9YJijmlPDHCqTfeaSXoKO5BJNcoN%2ByV97ViMHNyWEbjDCNDLBn0RbP3RCoL4sEsV8C8jUCUE2JNVJWCZLSPACDACjAAjwAjULwLkyQrf%2BF6%2F%2BLDmjAAjwAgwAowAI8AIlIwAG1klQ8eEjAAjwAgwAowAI8AIBCPARlYwNuXXWOkfvCkaymfMHAoQqAbW1eBZIHgRBRtNniJEr1pTxqRq0DJjRoARKB8BaWRZsTxkzjyVV67EOFS2TPQFh0qZYhdqB6Z6U53GogqHfnnIVDemOtUm2m%2BQfkHlYVxLpQvjW369H2b0dZ0%2B16QRuv46%2BMkWqrHfteLK80mf0Ev9fI1rnd5F5%2FRcklwOeYWP1n9cKqNArcpdGe2ZCyPACGwMBOTXhVaqEBmXpp4%2Fp%2B7C4dQaJtv8YgaZ6gIGk74Mays2%2FU8Ar5osLsTMyQNWTvRyHzCqgbUfT%2FtasWQgo2mvzIEo412dAI4dQfr0GTtFj5KWjCfKkZhsO%2BkT80q1KsRM1VAg3fqeTzYSzgFj4mDBR4wAI7DhEIi2XGi55JX3wfcNPUA1PSO6opOeDAryKQPHCb6RMpvLt9MBLTO9k2WdcocdwvSi4yVx1ZF8oj7YQ7ezP4l4Ou37aa9vnac%2F0kP26Xgzch5vnkl3BaEfZt7ks4XngE5XoLti7vPr8ixZ4yCaefRT40f5yKbHRiTW5w9hwPJM2fVWHwWYiaj%2Fem6xQmF0HXR%2BPWPnMNCtja%2FtBQrG2k%2BHaLiE8LTFttLdnFUGIyUDDgrLQAme13AqJN5VAWYiIKczp3OL7vnrGjs9ersYO92TLHVSmAbSkW6ucdeD8VIlXYOOPIpf6Jxw8ZyDTWdjGXDgoavUNRbQGxczAowAI1BRBCIYWWFZz03ytCMVz6CV0r1oWeRN2ctNdbInjWfbKPKpE1bqHivdSbJT9tfWWWQgTnoIAlcu%2Bnmx%2FOo8uAwuiLyGB0RsKnrYkhyjyHrgKUo%2FDTMPG5%2FTIFx8mmpF9LAdxqiNWatKQE0P08wuXFF4kixDzgO%2BKQFMkn6xXuzJH0EyfdOKHK6Y%2B2D2UAxNfuldFAlFyvaZL7K6Eak%2B4LiVOujUskr1FIy18CxRChylQ%2BQ5YeJpCwtYSZtlHkat3O9QpMZZxTZtqbTQ4PPBjCLT2%2BmSjiC96mYu55M158UYWYbVjXlcWdXSfYj%2Bp3DWiokVSOcdd9ccJkONPN3qGhsFhhxDLnhOmOeSWyP9zENXsWtM74OPGQFGgBGoHgLhRpaV9dx%2BkFAKl2wj4qGpMkhozWth5fdqKVsXjaeeZR1LuDgPpDLKm%2BTTkVhaCPA0mB6Ypjqfbsor0vQrCjONzoWLSRorw7ztidHaho17VuVcXMCkX9DTkjDTdPDRPTvpBNUkI6E%2FNIhmhDmhqVzcIXmx2pG9rLxYEahjvYhfdgwU5wXBoi0FM32PV6YXTbYYUvc9%2B%2BUVt3P%2FLmB%2B3lmmDKLzjrvNjzxcHdgT07zPIuWUZsgFzQkvz6LuIboAfMwIMAKMQG0hsAkivjtJfkVi4XGA9r7kFhuFZ8nxzJgGxlr2Oeb3wAyqc%2BflEgZlmx%2B9qd9q1jm4mHspJpGtmZNTG4AZ5cqLxUCP%2FfA8fw63co5KnxMhvZJBhCkkQw09jc%2Bq40minGeUx3EfvayIfJ4BmGnkhYcU0b0B6WQn5EsQLeWp3JOU1DyD%2FPkO7ByHWKqcPKi8tGa6wn60Ek8OTrsm0kuX3TriwUa%2FxiKqwc0YAUagbhEI92QVk%2FW8aBi1t%2BACWlOd1ZgedLFCI0E8WJNTWGmOY6fOV%2BzvcJa87CqxlHINF%2B3k1XaNfHuHTx3tL2qeQtJeOik291oE%2FTQx5KFDY8xo74eL5blw74Whh1g7%2Bvp9%2FIvljHsQnmIJqx3D%2Br6vAh2rUxA4J0rqjgyiduietVA2pDt2Yf921VJ6EfMvW%2BdBmKnmEX4L58QsLi3vwv7uDuxZVp7HQkYuOjHuu9EjmtHyoLYnS3gX1TJtIZ%2FAkihzyW9%2B3pFrLFALrmAEGAFGoGgEwj1ZtMQ2GEMuM4eUYH8T6WTAkltR3Zuyl5vqgrKs01u89kCAlDOKx6TncC%2Fyk52%2B3pXAOlryWJ5z5wu0%2Bhy74ZalMMO8Sb8gEN007oz2RBOESxA%2FWR6YYd407iFei0DMQHudjgDnzyC3eNQWjPKIhS%2F92c09Byas3XXwmRNNqTPIyYktl7dFomI3XcH4BXqxyCg5g1TMEnFoDrmhBZwSPJcwduwapu3rCCC91TJ8MGYedV2nbk9P4ZwALlxeQ26oV%2FTlkBrobkzgePocMou0V49kHEV2SHnHZtGfjAsdckMWtyDPltMZxFeRpdxD1v0a04XmY0aAEWAEykegxnIX0sOvwiEmyLt1Gjju99WXqY7evPtWkdToaBN5X%2F5IkRvuyx%2FEDcXBhNmGEnQDCRMZsyrM%2Fw0EQ4EofI0VQMIFjAAjUDsIUO5CNrJKHi%2B3t0OwyY4i2h6wkjtlwnpDgAyNoXZb6%2FK8fjabGjnga6xGBorFZAQYAR8EatDI8tGCixgBRoARYAQYAUaAEdhgCJCRFb7xfYMJzeIwAowAI8AIMAKMACNQCwiwkVULo8QyMgKMACPACDACjEDNIcBGVs0NGQvMCDACjAAjwAgwArWAQPWNLCv%2BjchPaOeb8%2BRH08tFbjQnVYcviEE89XI7jyBAedVE%2F1rOtZyrT99eSi809kebeQ360ZdmSk6vjHqdJ4edV0dXyhYTHWROO8LHHUOrdPWrQxmCW3U6rQGujEsNDBKLyAgwAnWKQFWNLBF5ncIcqICddrgDyjMYw6RVTnnovuEXENNnUIJ5UhRr4JTqS%2BQ1TMmgijMnndx8VE850JbzvnGxfLosvqjk%2Fky4UB63XuQHVZ66a9iTUcaaQXeRiy6IjgysE8Cxwpx4xStdPxQUqsNlxNaP6qwpI8AIMAKMQBEIVNHIomS3azhlG1a6VBSU0omQvpS%2FiaZ4s94A20RqnDnhgXIeaCaey8ivatHLKV%2BabzJiK32Jlq%2BPHpq6p6uyHp3C%2FkhRf%2F0MuAh9nLQslIuuCe3Y103cDLob6ai%2FSgSW1YauewTTYyPSG3f%2BEAYsbBWmRqxdHjfHkJE0FGhWy5vnihpP3hxnDFVfJFXP2DkMdBu8g5roUQ8vDBzBlY4zyLlkCKGuA1xCEOBqRoARYATqDoHqGVkiTcgqtmkGjGMsuXFuiTd6Eu22IxXPWN6nUdiJdI08yWDoxGScoonPIbf3Klr9DDyK1r2csSNtkySUbLhVecCSU4gPKQ%2BRW86Sznz6o%2Bjsvvp5OtBx2bm1wfa%2BkdGR6biGdFYRBOtuplP0lf1tSgCTbaPIxnqxJ38EyfRNxLfK1D3BWJMXbxeuJJ2xOGAlnpY0o8hSwnE1TgMqTyR54yhAraIbBVzj14hUH3Dcqiev6WFhmJajs8Q7mU8iZ1r69XSx%2BXHxKMynjAAjwAjUOQLVM7II2Fgv4pedh59tLGmg0%2FLfcLPjoZFVCzhlP0TJS9OIuErlEshT7i0axqgwmE7hKAr3XVk55y6rB7QliL6HKtOLJk2%2B8g4D%2BiNjIUg%2Fq0M%2FXFbywMB5GVWeDMhXbOHMugfT2Qwqe5BVefIWMGkZSnYHgVgv4eI8kMo4HiybxnRAhndM83CJ1EpOjkci1XMMksEWJYWPWJa2vWP%2BRrfIhzgIDHv3xwXJuwlwCVKNyxkBRoARYAQKEQjPXVhIE71kVTeeZL60fWQsWYmY6UFGHhk9NY0%2F85uwE%2BkG8QQ9bBdw6qA0oGhJZ9v5MzjcPeE8VH1zztF%2BpgakkyqPHC09qVxt%2FtJELvXtz49a0w%2BAHy4v%2FXQNTUNHER%2FsxIEZ4tGCbWqFVRgaAbqb6PxEqWqZGWthtIxL%2FXOLjUDUCPpR8ucVqZeSxUQmxim1hlNtj%2BGCqWFoXe3gEqoKN2AEGAFGgBGwEaieJ%2BvGPK5gF%2FZvV311YV%2FCMSb8DAnV0vVLhkpsDa%2BQYRbCE9A9GM2Ix5z%2ByCgZ6Gt3eTVc%2FVgnPWN6kmmr0PK%2B6Ht9bNrAumj9QdcvwMASfc1cRRaaPpYBd1YYXNQiQPdQOluTdT%2FwxRqAMHCSU1hpjmOnSypdR6viRh75WCWWAF0dhZ6IJVuxpO3sLQwlitiglnGJqCI3YwQYAUagLhCooidrCWPHrmE6M4eUBSXlXRsTXqwuHE41AuhFZrHXqqX9NuqBJZd%2FhkWNXm7iOYHj6V3I%2BPZHYRxSSGEKSdsoUeMrPWzDFt1KegrZRExVlv4b2B%2BxDNLPhMss%2BpNxDU%2FCZUJ%2BIXnDpLuBToRvOIOUUndoDrkhHe%2FS1fenNGFNHkTdwL2JdPIx7QvQWZxNJ53xtb1cjn65IavXKni2dH3IwKJE4K3epVC9UVHHmwOXolTmxowAI8AI1AECNZYgug5GhFVkBBgBRoARYAQYgZpHgHMX1vwQsgKMACPACDACjAAjsFERqN6erI2qMcvFCDACjAAjwAgwAozAOiDARtY6gMxdMAKMACPACDACjED9IcBGVv2NOWvMCDACjAAjwAgwAuuAABtZ6wAyd8EIMAKMACPACDAC9YcAG1n1N%2BasMSPACDACjAAjwAisAwJsZK0DyNwFI8AIMAKMACPACNQfAmxk1d%2BYs8aMACPACDACjAAjUGUE3vGOd4CNrCqDzOwZAUaAEWAEGAFGoP4Q%2BJ3f%2BR02supv2FljRoARYAQYAUaAEag2AmxkVRth5s8IMAKMACPACDACdYnA7%2F7u77Inqy5HnpVmBBgBRoARYAQYgaoiwEZWVeFl5owAI8AIMAKMACNQrwiQkfX%2FA%2BlhbcZMfwMcAAAAAElFTkSuQmCC)%0A%0A!%5B44173dd59fb82f5a5c614a704f3214d3.png%5D(en-resource%3A%2F%2Fdatabase%2F1137%3A0)%0A%0Agit%20reflog%20%E5%8F%AF%E4%BB%A5%E6%9F%A5%E7%9C%8B%E6%89%80%E6%9C%89%E5%88%86%E6%94%AF%E7%9A%84%E6%89%80%E6%9C%89%E6%93%8D%E4%BD%9C%E8%AE%B0%E5%BD%95%EF%BC%88%E5%8C%85%E6%8B%AC%E5%B7%B2%E7%BB%8F%E8%A2%AB%E5%88%A0%E9%99%A4%E7%9A%84%20commit%20%E8%AE%B0%E5%BD%95%E5%92%8C%20reset%20%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%89%0A%0A!%5B4d8781122926c136118c63309034ffb8.png%5D(en-resource%3A%2F%2Fdatabase%2F1145%3A0)%0A%0A%0Agit%20reset%20--hard%205306c99%20%2F%2F%E5%9B%9E%E6%BB%9A%E5%88%B0%E6%8C%87%E5%AE%9A%E7%89%88%E6%9C%AC%E5%90%8C%E8%BF%9B%E5%9B%9E%E6%BB%9Aindex%E5%92%8Cworking%E5%8C%BA%0Agit%20pull%20--rebase%20origin%20master%20%0A%0A!%5Bc1a0ef8498cf37e83ae47d3727141e5a.png%5D(en-resource%3A%2F%2Fdatabase%2F1141%3A0)%0A%0A!%5Bd0777cbf47700578b2d31d935b2c652b.png%5D(en-resource%3A%2F%2Fdatabase%2F1143%3A0)%0A%0A%0A%0A%0A%0A%0A

equals & hashcode

创建时间:2020/9/2 15:07
更新时间:2020/9/2 15:08
作者:Chris

1.overview

1.由object类提供
2.equals默认比较两个对象是否使用同一内存地址
3.hashcode返回随机唯一值来标识内存地址
4.相等的两个对象必须有相同的hashcode,
5.有相同hashcode的两个对象不一定相等,因为hashcode可以自定义。
6.覆盖equals方法时要同进覆盖hashcode方法,以避免在hashcode的数据结构如hashMap, HashTable, HashSet中比较对象时失败.

By default, the Java super class java.lang.Object provides two important methods for comparing objects: equals() and hashcode().

2.Method Definition and Default Implementation
3.The Contract Between equals() and hashcode()

The default implementation is not enough to satisfy business needs, especially if we're talking about a huge application that considers two objects as equal when some business fact happens. In some business scenarios, developers provide their own implementation in order to force their own equality mechanism regardless the memory addresses.

As per the Java documentation, developers should override both methods in order to achieve a fully working equality mechanism — it's not enough to just implement the equals() method. If two objects are equal according to the equals(Object) method, then calling the hashcode() method on each of the two objects must produce the same integer result.

In the following sections, we provide several examples that show the importance of overriding both methods and the drawbacks of overriding equals() without hashcode().

Practical Example**

We define a class called Student as the following:

package com.programmer.gate.beans;

public class Student {

​    private int id;
​    private String name;
​    public Student(int id, String name) {
​        this.name = name;
​        this.id = id;
​    }
​    public int getId() {
​        return id;
​    }
​    public void setId(int id) {
​        this.id = id;
​    }
​    public String getName() {
​        return name;
​    }
​    public void setName(String name) {
​        this.name = name;
​    }
}

For testing purposes, we define a main class HashcodeEquals that checks whether two instances of Student (who have the exact same attributes) are considered as equal.

public class HashcodeEquals {
​    public static void main(String[] args) {
​        Student alex1 = new Student(1, "Alex");
​        Student alex2 = new Student(1, "Alex");
​        System.out.println("alex1 hashcode = " + alex1.hashCode());
​        System.out.println("alex2 hashcode = " + alex2.hashCode());
​        System.out.println("Checking equality between alex1 and alex2 = " + alex1.equals(alex2));
​    }
}

Output:

alex1 hashcode = 1852704110
alex2 hashcode = 2032578917
Checking equality between alex1 and alex2 = false

Although the two instances have exactly the same attribute values, they are stored in different memory locations. Hence, they are not considered equal as per the default implementation of equals(). The same applies for hashcode() — a random unique code is generated for each instance.

Overriding equals()

For business purposes, we consider that two students are equal if they have the same ID, so we override the equals() method and provide our own implementation as the following:

@Override
public boolean equals(Object obj) {
​    if (obj == null) return false;
​    if (!(obj instanceof Student))
​        return false;
​    if (obj == this)
​        return true;
​    return this.getId() == ((Student) obj).getId();
}

In the above implementation, we are saying that two students are equal if and only if they are stored in the same memory address OR they have the same ID. Now if we try to run HashcodeEquals*,* we will get the following output:

alex1 hashcode = 2032578917
alex2 hashcode = 1531485190
Checking equality between alex1 and alex2 = true

As you noticed, overriding equals() with our custom business forces Java to consider the ID attribute when comparing two Student objects.

4.equals() With ArrayList

A very popular usage of equals() is defining an array list of Student and searching for a particular student inside it. So we modified our testing class in order the achieve this.

public class HashcodeEquals {
​    public static void main(String[] args) {
​        Student alex = new Student(1, "Alex");
​        List <Student> studentsLst = new ArrayList <Student> ();
​        studentsLst.add(alex);
​        System.out.println("Arraylist size = " + studentsLst.size());
​        System.out.println("Arraylist contains Alex = " + studentsLst.contains(new Student(1, "Alex")));
​    }
}

After running the above test, we get the following output:

Arraylist size = 1
Arraylist contains Alex = true
5.Overriding hashcode()

Okay, so we override equals() and we get the expected behavior — even though the hash code of the two objects are different. So, what's the purpose of overriding hashcode()?

equals() With HashSet

Let's consider a new test scenario. We want to store all the students in a HashSet, so we update HashcodeEquals as the following:

public class HashcodeEquals {
​    public static void main(String[] args) {
​        Student alex1 = new Student(1, "Alex");
​        Student alex2 = new Student(1, "Alex");
​        HashSet <Student> students = new HashSet <Student> ();
​        students.add(alex1);
​        students.add(alex2);
​        System.out.println("HashSet size = " + students.size());
​        System.out.println("HashSet contains Alex = " + students.contains(new Student(1, "Alex")));
​    }
}

If we run the above test, we get the following output:

HashSet size = 2

HashSet contains Alex = false

WAIT!! We already override equals() and verify that alex1 and alex2 are equal, and we all know that HashSet stores unique objects, so why did it consider them as different objects ?

HashSet stores its elements in memory buckets. Each bucket is linked to a particular hash code.

When calling students.add(alex1), Java stores alex1 inside a bucket and links it to the value of alex1.hashcode(). Now any time an element with the same hash code is inserted into the set, it will just replace *alex1.*However, since alex2 has a different hash code, it will be stored in a separate bucket and will be considered a totally different object.

Now when HashSet searches for an element inside it, it first generates the element's hash code and looks for a bucket which corresponds to this hash code.

Here comes the importance of overriding hashcode(), so let's override it in Student and set it to be equal to the ID so that students who have the same ID are stored in the same bucket:

@Override
public int hashCode() {
​    return id;
}

Now if we try to run the same test, we get the following output:

HashSet size = 1
HashSet contains Alex = true

See the magic of hashcode()! The two elements are now considered as equal and stored in the same memory bucket, so any time you call contains() and pass a student object holding the same hash code, the set will be able to find the element.

The same is applied for HashMap, HashTable, or any data structure that uses a hashing mechanism for storing elements.

6.Conclusion

In order to achieve a fully working custom equality mechanism, it is mandatory to override hashcode() each time you override equals(). Follow the tips below and you'll never have leaks in your custom equality mechanism:

  • If two objects are equal, they MUST have the same hash code.
  • If two objects have the same hash code, it doesn't mean that they are equal.
  • Overriding equals() alone will make your business fail with hashing data structures like: HashSet, HashMap, HashTable ... etc.
  • Overriding hashcode() alone doesn't force Java to ignore memory addresses when comparing two objects.
%5Btoc%5D%0A%0A%23%23%23%23%23%201.overview%0A%0A%3E1.%E7%94%B1object%E7%B1%BB%E6%8F%90%E4%BE%9B%0A2.equals%E9%BB%98%E8%AE%A4%E6%AF%94%E8%BE%83%E4%B8%A4%E4%B8%AA%E5%AF%B9%E8%B1%A1%E6%98%AF%E5%90%A6%E4%BD%BF%E7%94%A8%E5%90%8C%E4%B8%80%E5%86%85%E5%AD%98%E5%9C%B0%E5%9D%80%0A3.hashcode%E8%BF%94%E5%9B%9E%E9%9A%8F%E6%9C%BA%E5%94%AF%E4%B8%80%E5%80%BC%E6%9D%A5%E6%A0%87%E8%AF%86%E5%86%85%E5%AD%98%E5%9C%B0%E5%9D%80%0A4.%E7%9B%B8%E7%AD%89%E7%9A%84%E4%B8%A4%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%BF%85%E9%A1%BB%E6%9C%89%E7%9B%B8%E5%90%8C%E7%9A%84hashcode%2C%0A5.%E6%9C%89%E7%9B%B8%E5%90%8Chashcode%E7%9A%84%E4%B8%A4%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%B8%8D%E4%B8%80%E5%AE%9A%E7%9B%B8%E7%AD%89%EF%BC%8C%E5%9B%A0%E4%B8%BAhashcode%E5%8F%AF%E4%BB%A5%E8%87%AA%E5%AE%9A%E4%B9%89%E3%80%82%0A6.%E8%A6%86%E7%9B%96equals%E6%96%B9%E6%B3%95%E6%97%B6%E8%A6%81%E5%90%8C%E8%BF%9B%E8%A6%86%E7%9B%96hashcode%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BB%A5%E9%81%BF%E5%85%8D%E5%9C%A8hashcode%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%A6%82hashMap%2C%20HashTable%2C%20HashSet%E4%B8%AD%E6%AF%94%E8%BE%83%E5%AF%B9%E8%B1%A1%E6%97%B6%E5%A4%B1%E8%B4%A5.%0A%0A%0ABy%20default%2C%20the%20Java%20super%20class%20**java.lang.Object**%20provides%20two%20important%20methods%20for%20comparing%20objects%3A%20**equals()**%20and%20**hashcode()**.%20%0A%0A%23%23%23%23%23%202.Method%20Definition%20and%20Default%20Implementation%0A%0A-%20**equals(Object%20obj)%3A**%20a%20method%20provided%20by%20**java.lang.Object**%20that%20indicates%20whether%20some%20other%20object%20passed%20as%20an%20argument%20is%20**%22equal%20to%22**%20the%20current%20instance.%20The%20default%20implementation%20provided%20by%20the%20JDK%20is%20based%20on%20**memory%20location**%20%E2%80%94%20two%20objects%20are%20equal%20if%20and%20only%20if%20they%20are%20stored%20in%20the%20same%20memory%20address.%0A-%20**hashcode()%3A**%20a%20method%20provided%20by%20**java.lang.Object**%20that%20returns%20an%20integer%20representation%20of%20the%20object%20memory%20address.%20By%20default%2C%20this%20method%20returns%20**a%20random%20integer**%20that%20is%20unique%20for%20each%20instance.%20This%20integer%20might%20change%20between%20several%20executions%20of%20the%20application%20and%20won't%20stay%20the%20same.%0A%0A%23%23%23%23%23%20**3.The%20Contract%20Between%20equals()%20and%20hashcode()**%0A%0AThe%20default%20implementation%20is%20not%20enough%20to%20satisfy%20business%20needs%2C%20especially%20if%20we're%20talking%20about%20a%20huge%20application%20that%20considers%20two%20objects%20as%20equal%20when%20some%20business%20fact%20happens.%20In%20some%20business%20scenarios%2C%20developers%20provide%20their%20own%20implementation%20in%20order%20to%20force%20their%20own%20equality%20mechanism%20regardless%20the%20memory%20addresses.%0A%0AAs%20per%20the%20Java%20documentation%2C%20developers%20should%20override%20both%20methods%20in%20order%20to%20achieve%20a%20fully%20working%20equality%20mechanism%20%E2%80%94%20it's%20not%20enough%20to%20just%20implement%20the%20**equals()**%20method.%20If%20two%20objects%20are%20equal%20according%20to%20the%20**equals(Object)**%20method%2C%20then%20calling%20the%20**hashcode()**%20method%20on%20each%20of%20the%20two%20objects%20must%20produce%20the%20same%20integer%20result.%0A%0AIn%20the%20following%20sections%2C%20we%20provide%20several%20examples%20that%20show%20the%20importance%20of%20overriding%20both%20methods%20and%20the%20drawbacks%20of%20overriding%20**equals()**%20without%20**hashcode()**.%0A%0A%0A%0APractical%20Example**%0A%0AWe%20define%20a%20class%20called%20**Student**%20as%20the%20following%3A%0A%0A%60%60%60java%0Apackage%20com.programmer.gate.beans%3B%0A%0Apublic%20class%20Student%20%7B%0A%0A%E2%80%8B%20%20%20%20private%20int%20id%3B%0A%E2%80%8B%20%20%20%20private%20String%20name%3B%0A%E2%80%8B%20%20%20%20public%20Student(int%20id%2C%20String%20name)%20%7B%0A%E2%80%8B%20%20%20%20%20%20%20%20this.name%20%3D%20name%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20this.id%20%3D%20id%3B%0A%E2%80%8B%20%20%20%20%7D%0A%E2%80%8B%20%20%20%20public%20int%20getId()%20%7B%0A%E2%80%8B%20%20%20%20%20%20%20%20return%20id%3B%0A%E2%80%8B%20%20%20%20%7D%0A%E2%80%8B%20%20%20%20public%20void%20setId(int%20id)%20%7B%0A%E2%80%8B%20%20%20%20%20%20%20%20this.id%20%3D%20id%3B%0A%E2%80%8B%20%20%20%20%7D%0A%E2%80%8B%20%20%20%20public%20String%20getName()%20%7B%0A%E2%80%8B%20%20%20%20%20%20%20%20return%20name%3B%0A%E2%80%8B%20%20%20%20%7D%0A%E2%80%8B%20%20%20%20public%20void%20setName(String%20name)%20%7B%0A%E2%80%8B%20%20%20%20%20%20%20%20this.name%20%3D%20name%3B%0A%E2%80%8B%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0AFor%20testing%20purposes%2C%20we%20define%20a%20main%20class%20**HashcodeEquals**%20that%20checks%20whether%20two%20instances%20of%20**Student**%20(who%20have%20the%20exact%20same%20attributes)%20are%20considered%20as%20equal.%0A%0A%60%60%60java%0Apublic%20class%20HashcodeEquals%20%7B%0A%E2%80%8B%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%E2%80%8B%20%20%20%20%20%20%20%20Student%20alex1%20%3D%20new%20Student(1%2C%20%22Alex%22)%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20Student%20alex2%20%3D%20new%20Student(1%2C%20%22Alex%22)%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20System.out.println(%22alex1%20hashcode%20%3D%20%22%20%2B%20alex1.hashCode())%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20System.out.println(%22alex2%20hashcode%20%3D%20%22%20%2B%20alex2.hashCode())%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20System.out.println(%22Checking%20equality%20between%20alex1%20and%20alex2%20%3D%20%22%20%2B%20alex1.equals(alex2))%3B%0A%E2%80%8B%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0AOutput%3A%20%0A%0A%60%60%60%0Aalex1%20hashcode%20%3D%201852704110%0Aalex2%20hashcode%20%3D%202032578917%0AChecking%20equality%20between%20alex1%20and%20alex2%20%3D%20false%0A%60%60%60%0A%0AAlthough%20the%20two%20instances%20have%20exactly%20the%20same%20attribute%20values%2C%20they%20are%20stored%20in%20different%20memory%20locations.%20Hence%2C%20they%20are%20not%20considered%20equal%20as%20per%20the%20default%20implementation%20of%20**equals()**.%20The%20same%20applies%20for%20**hashcode()**%20%E2%80%94%20a%20random%20unique%20code%20is%20generated%20for%20each%20instance.%0A%0AOverriding%20equals()%0A%0AFor%20business%20purposes%2C%20we%20consider%20that%20two%20students%20are%20equal%20if%20they%20have%20the%20same%20*ID*%2C%20so%20we%20override%20the%20**equals()**%20method%20and%20provide%20our%20own%20implementation%20as%20the%20following%3A%0A%0A%60%60%60java%0A%40Override%0Apublic%20boolean%20equals(Object%20obj)%20%7B%0A%E2%80%8B%20%20%20%20if%20(obj%20%3D%3D%20null)%20return%20false%3B%0A%E2%80%8B%20%20%20%20if%20(!(obj%20instanceof%20Student))%0A%E2%80%8B%20%20%20%20%20%20%20%20return%20false%3B%0A%E2%80%8B%20%20%20%20if%20(obj%20%3D%3D%20this)%0A%E2%80%8B%20%20%20%20%20%20%20%20return%20true%3B%0A%E2%80%8B%20%20%20%20return%20this.getId()%20%3D%3D%20((Student)%20obj).getId()%3B%0A%7D%0A%60%60%60%0A%0AIn%20the%20above%20implementation%2C%20we%20are%20saying%20that%20two%20students%20are%20equal%20if%20and%20only%20if%20they%20are%20stored%20in%20the%20same%20memory%20address%20**OR**%20they%20have%20the%20same%20ID.%20Now%20if%20we%20try%20to%20run%20**HashcodeEquals***%2C*%20we%20will%20get%20the%20following%20output%3A%0A%0A%60%60%60%0Aalex1%20hashcode%20%3D%202032578917%0Aalex2%20hashcode%20%3D%201531485190%0AChecking%20equality%20between%20alex1%20and%20alex2%20%3D%20true%0A%60%60%60%0A%0AAs%20you%20noticed%2C%20overriding%20**equals()**%20with%20our%20custom%20business%20forces%20Java%20to%20consider%20the%20ID%20attribute%20when%20comparing%20two%20**Student**%20objects.%0A%0A%23%23%23%23%23%204.**equals()%20With%20ArrayList**%0A%0AA%20very%20popular%20usage%20of%20**equals()**%20%20is%20defining%20an%20array%20list%20of%20**Student**%20and%20searching%20for%20a%20particular%20student%20inside%20it.%20So%20we%20modified%20our%20testing%20class%20in%20order%20the%20achieve%20this.%0A%0A%60%60%60java%0Apublic%20class%20HashcodeEquals%20%7B%0A%E2%80%8B%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%E2%80%8B%20%20%20%20%20%20%20%20Student%20alex%20%3D%20new%20Student(1%2C%20%22Alex%22)%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20List%20%3CStudent%3E%20studentsLst%20%3D%20new%20ArrayList%20%3CStudent%3E%20()%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20studentsLst.add(alex)%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20System.out.println(%22Arraylist%20size%20%3D%20%22%20%2B%20studentsLst.size())%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20System.out.println(%22Arraylist%20contains%20Alex%20%3D%20%22%20%2B%20studentsLst.contains(new%20Student(1%2C%20%22Alex%22)))%3B%0A%E2%80%8B%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0AAfter%20running%20the%20above%20test%2C%20we%20get%20the%20following%20output%3A%0A%0A%60%60%60%0AArraylist%20size%20%3D%201%0AArraylist%20contains%20Alex%20%3D%20true%0A%60%60%60%0A%0A%23%23%23%23%23%205.**Overriding%20hashcode()**%0A%0AOkay%2C%20so%20we%20override%20**equals()**%20and%20we%20get%20the%20expected%20behavior%20%E2%80%94%20even%20though%20the%20hash%20code%20of%20the%20two%20objects%20are%20different.%20So%2C%20what's%20the%20purpose%20of%20overriding%20**hashcode()**%3F%0A%0Aequals()%20With%20HashSet%0A%0ALet's%20consider%20a%20new%20test%20scenario.%20We%20want%20to%20store%20all%20the%20students%20in%20a%20**HashSet**%2C%20so%20we%20update%20**HashcodeEquals**%20as%20the%20following%3A%0A%0A%60%60%60java%0Apublic%20class%20HashcodeEquals%20%7B%0A%E2%80%8B%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%E2%80%8B%20%20%20%20%20%20%20%20Student%20alex1%20%3D%20new%20Student(1%2C%20%22Alex%22)%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20Student%20alex2%20%3D%20new%20Student(1%2C%20%22Alex%22)%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20HashSet%20%3CStudent%3E%20students%20%3D%20new%20HashSet%20%3CStudent%3E%20()%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20students.add(alex1)%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20students.add(alex2)%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20System.out.println(%22HashSet%20size%20%3D%20%22%20%2B%20students.size())%3B%0A%E2%80%8B%20%20%20%20%20%20%20%20System.out.println(%22HashSet%20contains%20Alex%20%3D%20%22%20%2B%20students.contains(new%20Student(1%2C%20%22Alex%22)))%3B%0A%E2%80%8B%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0AIf%20we%20run%20the%20above%20test%2C%20we%20get%20the%20following%20output%3A%0A%0AHashSet%20size%20%3D%202%0A%0AHashSet%20contains%20Alex%20%3D%20false%0A%0AWAIT!!%20We%20already%20override%20**equals()**%20and%20verify%20that%20*alex1*%20and%20*alex2*%20are%20equal%2C%20and%20we%20all%20know%20that%20**HashSet**%20stores%20unique%20objects%2C%20so%20why%20did%20it%20consider%20them%20as%20different%20objects%20%3F%0A%0A**%60HashSet%60%20stores%20its%20elements%20in%20memory%20buckets.%20Each%20bucket%20is%20linked%20to%20a%20particular%20hash%20code.**%20%0A%0AWhen%20calling%20*students.add(alex1)*%2C%20Java%20stores%20*alex1*%20inside%20a%20bucket%20and%20links%20it%20to%20the%20value%20of%20*alex1.hashcode()*.%20Now%20any%20time%20an%20element%20with%20the%20same%20hash%20code%20is%20inserted%20into%20the%20set%2C%20it%20will%20just%20replace%20*alex1.*However%2C%20since%20*alex2*%20has%20a%20different%20hash%20code%2C%20it%20will%20be%20stored%20in%20a%20separate%20bucket%20and%20will%20be%20considered%20a%20totally%20different%20object.%0A%0ANow%20when%20**HashSet**%20searches%20for%20an%20element%20inside%20it%2C%20it%20first%20generates%20the%20element's%20hash%20code%20and%20looks%20for%20a%20bucket%20which%20corresponds%20to%20this%20hash%20code.%0A%0AHere%20comes%20the%20importance%20of%20overriding%20**hashcode()***%2C*%20so%20let's%20override%20it%20in%20**Student**%20and%20set%20it%20to%20be%20equal%20to%20the%20ID%20so%20that%20students%20who%20have%20the%20same%20ID%20are%20stored%20in%20the%20same%20bucket%3A%0A%0A%60%60%60java%0A%40Override%0Apublic%20int%20hashCode()%20%7B%0A%E2%80%8B%20%20%20%20return%20id%3B%0A%7D%0A%60%60%60%0A%0ANow%20if%20we%20try%20to%20run%20the%20same%20test%2C%20we%20get%20the%20following%20output%3A%0A%0A%60%60%60%0AHashSet%20size%20%3D%201%0AHashSet%20contains%20Alex%20%3D%20true%0A%60%60%60%0A%0ASee%20the%20magic%20of%20**hashcode()**!%20The%20two%20elements%20are%20now%20considered%20as%20equal%20and%20stored%20in%20the%20same%20memory%20bucket%2C%20so%20any%20time%20you%20call%20*contains()*%20and%20pass%20a%20student%20object%20holding%20the%20same%20hash%20code%2C%20the%20set%20will%20be%20able%20to%20find%20the%20element.%0A%0AThe%20same%20is%20applied%20for%20**HashMap%2C%20HashTable**%2C%20or%20any%20data%20structure%20that%20uses%20a%20hashing%20mechanism%20for%20storing%20elements.%0A%0A%23%23%23%23%23%206.Conclusion%0A%0AIn%20order%20to%20achieve%20a%20fully%20working%20custom%20equality%20mechanism%2C%20it%20is%20mandatory%20to%20override%20**hashcode()**%20each%20time%20you%20override%20**equals().**%20Follow%20the%20tips%20below%20and%20you'll%20never%20have%20leaks%20in%20your%20custom%20equality%20mechanism%3A%0A%3E%0A%3E-%20If%20two%20objects%20are%20equal%2C%20they%20MUST%20have%20the%20same%20hash%20code.%0A%3E-%20If%20two%20objects%20have%20the%20same%20hash%20code%2C%20it%20doesn't%20mean%20that%20they%20are%20equal.%0A%3E-%20Overriding%20**equals()**%20alone%20will%20make%20your%20business%20fail%20with%20hashing%20data%20structures%20like%3A%20**HashSet%2C%20HashMap%2C%20HashTable**%20...%20etc.%0A%3E-%20Overriding%20**hashcode()**%20alone%20doesn't%20force%20Java%20to%20ignore%20memory%20addresses%20when%20comparing%20two%20objects.%0A%0A

docker-elasticsearch

创建时间:2020/9/2 14:39
更新时间:2020/9/2 14:42
作者:Chris

ES启动问题

docker logs es2

删除容器
docker rm es2

重新创建容器ES_JAVA_OPTS=-Xms512m -Xmx512m

docker run -d --name es2 -e ES_JAVA_OPTS=-Xms512m -Xmx512m -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" 5c1e1ecfe33a

ES配置跨域

ElasticSearch默认的cluster.name为elasticsearch,所以,这里需要进行修改。

vi /usr/share/elasticsearch/config/elasticsearch.yml

cluster.name: "qfcwx-cluster"   
network.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"

cluster.name:自定义集群名称。
network.host:当前es节点绑定的ip地址,默认127.0.0.1,如果需要开放对外访问这个属性必须设置。
http.cors.enabled:是否支持跨域,默认为false。
http.cors.allow-origin:当设置允许跨域,默认为*,表示支持所有域名,如果我们只是允许某些网站能访问,那么可以使用正则表达式。

exit
docker restart es2

http://master:9200/

max virtual memory areas vm.max_map_count [65530] is too low, increase to at least

To make it persistent, you can add this line:
vm.max_map_count=262144
in your /etc/sysctl.conf and run
sudo sysctl -p

查看镜像内部信息

docker inspect image_id

%23%23%23%23%23%20ES%E5%90%AF%E5%8A%A8%E9%97%AE%E9%A2%98%0Adocker%20logs%20es2%0A%0A%0A%E5%88%A0%E9%99%A4%E5%AE%B9%E5%99%A8%0A%60docker%20rm%20es2%60%0A%0A%E9%87%8D%E6%96%B0%E5%88%9B%E5%BB%BA%E5%AE%B9%E5%99%A8ES_JAVA_OPTS%3D-Xms512m%20-Xmx512m%0A%0A%60docker%20run%20-d%20--name%20es2%20-e%20ES_JAVA_OPTS%3D-Xms512m%20-Xmx512m%20-p%209200%3A9200%20-p%209300%3A9300%20-e%20%22discovery.type%3Dsingle-node%22%205c1e1ecfe33a%60%0A%0A%0A%23%23%23%23%23%20ES%E9%85%8D%E7%BD%AE%E8%B7%A8%E5%9F%9F%0AElasticSearch%E9%BB%98%E8%AE%A4%E7%9A%84cluster.name%E4%B8%BAelasticsearch%EF%BC%8C%E6%89%80%E4%BB%A5%EF%BC%8C%E8%BF%99%E9%87%8C%E9%9C%80%E8%A6%81%E8%BF%9B%E8%A1%8C%E4%BF%AE%E6%94%B9%E3%80%82%0A%0A%60vi%20%2Fusr%2Fshare%2Felasticsearch%2Fconfig%2Felasticsearch.yml%60%0A%0A%60%60%60%0Acluster.name%3A%20%22qfcwx-cluster%22%20%20%20%0Anetwork.host%3A%200.0.0.0%0Ahttp.cors.enabled%3A%20true%0Ahttp.cors.allow-origin%3A%20%22*%22%0A%60%60%60%0A%0A%0A%3Ecluster.name%EF%BC%9A%E8%87%AA%E5%AE%9A%E4%B9%89%E9%9B%86%E7%BE%A4%E5%90%8D%E7%A7%B0%E3%80%82%0A%3Enetwork.host%EF%BC%9A%E5%BD%93%E5%89%8Des%E8%8A%82%E7%82%B9%E7%BB%91%E5%AE%9A%E7%9A%84ip%E5%9C%B0%E5%9D%80%EF%BC%8C%E9%BB%98%E8%AE%A4127.0.0.1%EF%BC%8C%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E5%BC%80%E6%94%BE%E5%AF%B9%E5%A4%96%E8%AE%BF%E9%97%AE%E8%BF%99%E4%B8%AA%E5%B1%9E%E6%80%A7%E5%BF%85%E9%A1%BB%E8%AE%BE%E7%BD%AE%E3%80%82%0A%3Ehttp.cors.enabled%EF%BC%9A%E6%98%AF%E5%90%A6%E6%94%AF%E6%8C%81%E8%B7%A8%E5%9F%9F%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BAfalse%E3%80%82%0A%3Ehttp.cors.allow-origin%EF%BC%9A%E5%BD%93%E8%AE%BE%E7%BD%AE%E5%85%81%E8%AE%B8%E8%B7%A8%E5%9F%9F%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA*%EF%BC%8C%E8%A1%A8%E7%A4%BA%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9F%9F%E5%90%8D%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%88%91%E4%BB%AC%E5%8F%AA%E6%98%AF%E5%85%81%E8%AE%B8%E6%9F%90%E4%BA%9B%E7%BD%91%E7%AB%99%E8%83%BD%E8%AE%BF%E9%97%AE%EF%BC%8C%E9%82%A3%E4%B9%88%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E3%80%82%0A%0A%60%60%60%0Aexit%0Adocker%20restart%20es2%0A%60%60%60%0A%0Ahttp%3A%2F%2Fmaster%3A9200%2F%0A!%5Bf6a3cbd4ade175395dabfc13b6f7b5d0.png%5D(en-resource%3A%2F%2Fdatabase%2F1069%3A1)%0A%0A%0A%0A%0A%23%23%23%23%23%20max%20virtual%20memory%20areas%20vm.max_map_count%20%5B65530%5D%20is%20too%20low%2C%20increase%20to%20at%20least%20%0A%0ATo%20make%20it%20persistent%2C%20you%20can%20add%20this%20line%3A%0A%60vm.max_map_count%3D262144%60%0Ain%20your%20%2Fetc%2Fsysctl.conf%20and%20run%0A%60sudo%20sysctl%20-p%60%20%20%0A%0A%0A%0A%23%23%23%23%23%20%E6%9F%A5%E7%9C%8B%E9%95%9C%E5%83%8F%E5%86%85%E9%83%A8%E4%BF%A1%E6%81%AF%0A%60docker%20inspect%20image_id%60%0A%0A!%5Bb514b50ccd278e42d5180bd5085069b8.png%5D(en-resource%3A%2F%2Fdatabase%2F1071%3A1)%0A

快捷操作

创建时间:2023/3/6 21:51
更新时间:2023/11/25 10:39
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzU2NDEyMzIzOA==&mid=2247498439&idx=1&sn=3c9adec7ce6f9f18efcb81878bd3f509&chksm=fc4d79cecb3af0d89a3e15122b531a13388ceb2b71d68e355e0fd7e8db7d778608e0d6942ab5&mpshare=1&scene=24&srcid=0130Fkl1988N34REmn8PmI7a&sharer_sharetime=1675073072446&sharer_shareid=8f247ffae0fc886917cba955f4d8c07b&key=e140a66dd4f32b5ef8d58d92bebbbc9454e36a509e9db23fbad2935e560d6b7ad27dc2982a4e553456af860dbb9499dcd4789efdeb8156b0fda097e2bc814fca9344173d81f9483bcabfd0241a461845f4e91d43fb9826c1b1c93b8280917b8275df9a631edfdb01b7b7697bb1e18a31620391bfa88f2a7464dcd6a7ff6c328d&ascene=14&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+11+x64&version=6309001c&lang=zh_CN&countrycode=CN&exportkey=n_ChQIAhIQ2ESVPbWGAMQir7CfpoUqKBL0AQIE97dBBAEAAAAAAB0fNyvwNr0AAAAOpnltbLcz9gKNyK89dVj0AeluYt90FZDj9NwAr9srbwNCregeL%2BPmles3HuadRQ5Fvv6tYH4O85ZjN%2B2g4TACbVKHpqMzLfG%2B8Px7EXbu%2BWHSS5m11%2B1Gz5zcfXGefjH8IMR%2FSohsF5Lh6dANFZr%2FjC8IsfDWak4BdJytGf7hBgt%2Bg0YOx0wcp8sYp6NmrDsQfjxmvXP%2BPQXQBhLc3d%2BI0nJLbyGQE21O11SrtyeQQLX%2B0nB%2BP0pgNMG8776ecVAcDoEnKhDXghPVtl97XvNwJVuEqVTPSXcG4u1jVhA%3D&acctmode=0&pass_ticket=eAjYiolMcRZQqrZ%2FzuS6dMuzCvWPAY2GgXuQeYktKHPEiyCxy3EKzFknwMA81RU0pbOHjWrSZt52%2FNWEZ0LHgg%3D%3D&wx_header=1&fontgear=2

重构

重构函数

Ctrl+Alt+M

可以正向操作也可以反向操作

方法重命名

Shift+F6

重构变量

Ctrl+Alt+C 快速提取常量(Constant)
Ctrl+Alt+V 快速提取变量(Variable)
Ctrl+Alt+F 快速提取成员变量(Filed Variable)
Ctrl+Shift+f6 重构变量的类型

提取方法到父类

优化导包配置

双斜杠注释改成紧跟代码头

显示行号和方法分割线

预览某个类的代码

ctrl+shift+i

查看方法在哪里被调用

alt+f7
或者
ctrl+alt+h

.idea全局设置(打开新窗口设置)

例如我们打开新窗口时,maven配置会恢复 这时就需要对打开新窗口的设置进行修改 达到一个全局的目的。

多行操作

  1. ctrl+shift+鼠标点点点或者
  2. 按下鼠标滚轮,移动鼠标
  3. 或者alt+鼠标左键,移动鼠标
%5Btoc%5D%0A%23%23%20%E9%87%8D%E6%9E%84%0A%0A%23%23%23%23%20%E9%87%8D%E6%9E%84%E5%87%BD%E6%95%B0%0A**Ctrl%2BAlt%2BM**%0A%0A%E5%8F%AF%E4%BB%A5%E6%AD%A3%E5%90%91%E6%93%8D%E4%BD%9C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%8F%8D%E5%90%91%E6%93%8D%E4%BD%9C%0A%0A!%5B1f5ac3bd05e5b978e7adcaf3efcd1788.png%5D(en-resource%3A%2F%2Fdatabase%2F1369%3A1)%0A%0A!%5B1b5fc06075b27307896c25f896b5418b.png%5D(en-resource%3A%2F%2Fdatabase%2F1367%3A1)%0A%0A%23%23%23%23%20%E6%96%B9%E6%B3%95%E9%87%8D%E5%91%BD%E5%90%8D%0A**Shift%2BF6**%0A%0A%0A%23%23%23%23%20%E9%87%8D%E6%9E%84%E5%8F%98%E9%87%8F%0A%0ACtrl%2BAlt%2BC%C2%A0%E5%BF%AB%E9%80%9F%E6%8F%90%E5%8F%96%E5%B8%B8%E9%87%8F%EF%BC%88Constant%EF%BC%89%0ACtrl%2BAlt%2BV%20%E5%BF%AB%E9%80%9F%E6%8F%90%E5%8F%96%E5%8F%98%E9%87%8F%EF%BC%88Variable%EF%BC%89%0ACtrl%2BAlt%2BF%20%E5%BF%AB%E9%80%9F%E6%8F%90%E5%8F%96%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%EF%BC%88Filed%20Variable%EF%BC%89%0ACtrl%2BShift%2Bf6%C2%A0%E9%87%8D%E6%9E%84%E5%8F%98%E9%87%8F%E7%9A%84%E7%B1%BB%E5%9E%8B%0A%0A%23%23%23%23%20%E6%8F%90%E5%8F%96%E6%96%B9%E6%B3%95%E5%88%B0%E7%88%B6%E7%B1%BB%0A%0A!%5B02c6d6be9ab1958aef27fd7858c572b0.png%5D(en-resource%3A%2F%2Fdatabase%2F1371%3A1)%0A%0A%0A%23%23%20%E4%BC%98%E5%8C%96%E5%AF%BC%E5%8C%85%E9%85%8D%E7%BD%AE%0A!%5B6b548f7b3abb3050f5055c16e5676cef.png%5D(en-resource%3A%2F%2Fdatabase%2F1373%3A1)%0A%0A%23%23%20%E5%8F%8C%E6%96%9C%E6%9D%A0%E6%B3%A8%E9%87%8A%E6%94%B9%E6%88%90%E7%B4%A7%E8%B7%9F%E4%BB%A3%E7%A0%81%E5%A4%B4%0A%0A!%5B813900574565842608b1d586f08132e8.png%5D(en-resource%3A%2F%2Fdatabase%2F1375%3A1)%0A%0A%23%23%20%E6%98%BE%E7%A4%BA%E8%A1%8C%E5%8F%B7%E5%92%8C%E6%96%B9%E6%B3%95%E5%88%86%E5%89%B2%E7%BA%BF%0A!%5B36b3a5aba0c59e17fc102741ebcc2a89.png%5D(en-resource%3A%2F%2Fdatabase%2F1377%3A1)%0A%0A%23%23%20%E9%A2%84%E8%A7%88%E6%9F%90%E4%B8%AA%E7%B1%BB%E7%9A%84%E4%BB%A3%E7%A0%81%0A%60%60%60%0Actrl%2Bshift%2Bi%0A%60%60%60%0A%0A%23%23%20%E6%9F%A5%E7%9C%8B%E6%96%B9%E6%B3%95%E5%9C%A8%E5%93%AA%E9%87%8C%E8%A2%AB%E8%B0%83%E7%94%A8%0A%60%60%60%0Aalt%2Bf7%0A%E6%88%96%E8%80%85%0Actrl%2Balt%2Bh%0A%60%60%60%0A%0A%0A%23%23%20.idea%E5%85%A8%E5%B1%80%E8%AE%BE%E7%BD%AE%EF%BC%88%E6%89%93%E5%BC%80%E6%96%B0%E7%AA%97%E5%8F%A3%E8%AE%BE%E7%BD%AE%EF%BC%89%0A%3E%20%E4%BE%8B%E5%A6%82%E6%88%91%E4%BB%AC%E6%89%93%E5%BC%80%E6%96%B0%E7%AA%97%E5%8F%A3%E6%97%B6%EF%BC%8Cmaven%E9%85%8D%E7%BD%AE%E4%BC%9A%E6%81%A2%E5%A4%8D%20%E8%BF%99%E6%97%B6%E5%B0%B1%E9%9C%80%E8%A6%81%E5%AF%B9%E6%89%93%E5%BC%80%E6%96%B0%E7%AA%97%E5%8F%A3%E7%9A%84%E8%AE%BE%E7%BD%AE%E8%BF%9B%E8%A1%8C%E4%BF%AE%E6%94%B9%20%E8%BE%BE%E5%88%B0%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E7%9A%84%E7%9B%AE%E7%9A%84%E3%80%82%0A%0A!%5B0ebbb594c326e07346d84c46ab6f1c01.png%5D(en-resource%3A%2F%2Fdatabase%2F1427%3A1)%0A%0A%0A%23%23%20%E5%A4%9A%E8%A1%8C%E6%93%8D%E4%BD%9C%0A1.%20ctrl%2Bshift%2B%E9%BC%A0%E6%A0%87%E7%82%B9%E7%82%B9%E7%82%B9%E6%88%96%E8%80%85%0A2.%20%E6%8C%89%E4%B8%8B%E9%BC%A0%E6%A0%87%E6%BB%9A%E8%BD%AE%EF%BC%8C%E7%A7%BB%E5%8A%A8%E9%BC%A0%E6%A0%87%0A3.%20%E6%88%96%E8%80%85alt%2B%E9%BC%A0%E6%A0%87%E5%B7%A6%E9%94%AE%EF%BC%8C%E7%A7%BB%E5%8A%A8%E9%BC%A0%E6%A0%87%0A%0A%0A

IDEA性能优化设置

创建时间:2023/3/19 20:44
更新时间:2023/3/19 20:53
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=Mzg5NDM1ODk4Mw==&mid=2247553770&idx=2&sn=6b0ddf7fb03bce2aab1da5b24e06c7e4&chksm=c0229642f7551f543c10368c1ebf6397fa5fe77db54f95c893318ded6fdbb5851da87f3f3719&mpshare=1&scene=24&srcid=03065AADJ2G0BKPZCBvWCAYJ&sharer_sharetime=1678063530571&sharer_shareid=8f247ffae0fc886917cba955f4d8c07b&key=639d057d7f1768ce732729ea2caf627ade721d21029314cefd7daa453a2d3203d080746a5cf943bb77012a8145c4573dcc2c77850956267ccf7ba376c19b9224d941c4a3d2f0d67ae7e39cb773a9b416e9df53921d1dd3541643ff6400849bf4b2744051a3fd05b6c8b32463d48de9d8a91e6166b5ecef6c001939c711d85f51&ascene=14&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+11+x64&version=6309001c&lang=en&countrycode=CN&exportkey=n_ChQIAhIQqtef5uZPIO8guFo17UjAcBLjAQIE97dBBAEAAAAAAOYYJTV8vicAAAAOpnltbLcz9gKNyK89dVj0axxNQft6Gxq7beqVbt5v2KE3SBM3GN8LzcoS5Idtv6dviHLSorDLz2Yxiyp2Gg3oo282euQDwPB3dwhmFBsiMDbQ26PaIEDH4WkSZvAZs3vde5vrqYONLqJZ0NAOzTa0JXMerqwY0ytwGBm9F6jt3%2BqscOzfg2aLPDfM1XRcTUkH8xHEwZBn7Ni6pGZWGldl9o4O5%2Bu5BTNOPVVd4JiLkb9RB0Rdh3PX0NmUpN4U9G4ax%2FswijGEGmki00gg&acctmode=0&pass_ticket=1k73x0bONgEtBVHlOYEO%2F3ktJSPM5%2FMwCW5plYai%2B3hIvQSPu2HnXn2VUM6kLqaPx3I06H%2BrLNTGJy5bEY%2B8jQ%3D%3D&wx_header=1&fontgear=2

1.Memory Indicator

通过显示内存使用情况来查看当前项目占用的内存大小

2.调整内存大小

选择顶部导航栏中的Help,然后点击Edit Custom VM Options

-Xmx1024m    // 最大内存上限为:1024MB(1GB)
-Xms256m     // 初始内存分配大小为:256MB
-XX:ReservedCodeCacheSize=128m    //代码缓冲区大小:128MB
-XX:+UseG1GC
-Xmx4096m
-Xms4096m
-XX:ReservedCodeCacheSize=256m
-XX:+UseG1GC

参数说明

-server:一定要作为第一个参数,在多个CPU时性能佳
-Xms:初始Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
-Xmx:java heap最大值,使用的最大内存
-XX:PermSize:设定内存的永久保存区域
-XX:MaxPermSize:设定最大内存的永久保存区域
-XX:MaxNewSize:
+XX:AggressiveHeap 使 Xms 失去意义。
-Xss:每个线程的Stack大小
-verbose:gc 现实垃圾收集信息
-Xloggc:gc.log 指定垃圾收集日志文件
-Xmn:young generation的heap大小,一般设置为Xmx的34分之一
-XX:+UseParNewGC :缩短minor收集的时间
-XX:+UseConcMarkSweepGC :缩短major收集的时间

提示:此选项在Heap Size 比较大而且Major收集时间较长的情况下使用更合适。

3.清理缓存

%5Btoc%5D%0A%23%23%201.Memory%20Indicator%0A%3E%20%E9%80%9A%E8%BF%87%E6%98%BE%E7%A4%BA%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E6%83%85%E5%86%B5%E6%9D%A5%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8D%E9%A1%B9%E7%9B%AE%E5%8D%A0%E7%94%A8%E7%9A%84%E5%86%85%E5%AD%98%E5%A4%A7%E5%B0%8F%0A!%5Ba4d48ae76fab26f757f034e736979642.png%5D(en-resource%3A%2F%2Fdatabase%2F1383%3A0)%0A%0A%0A%23%23%202.%E8%B0%83%E6%95%B4%E5%86%85%E5%AD%98%E5%A4%A7%E5%B0%8F%0A%3E%20%E9%80%89%E6%8B%A9%E9%A1%B6%E9%83%A8%E5%AF%BC%E8%88%AA%E6%A0%8F%E4%B8%AD%E7%9A%84Help%EF%BC%8C%E7%84%B6%E5%90%8E%E7%82%B9%E5%87%BBEdit%20Custom%20VM%20Options%0A%0A%0A%60%60%60java%0A-Xmx1024m%20%20%20%20%2F%2F%20%E6%9C%80%E5%A4%A7%E5%86%85%E5%AD%98%E4%B8%8A%E9%99%90%E4%B8%BA%EF%BC%9A1024MB%EF%BC%881GB%EF%BC%89%0A-Xms256m%20%20%20%20%20%2F%2F%20%E5%88%9D%E5%A7%8B%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E5%A4%A7%E5%B0%8F%E4%B8%BA%EF%BC%9A256MB%0A-XX%3AReservedCodeCacheSize%3D128m%20%20%20%20%2F%2F%E4%BB%A3%E7%A0%81%E7%BC%93%E5%86%B2%E5%8C%BA%E5%A4%A7%E5%B0%8F%EF%BC%9A128MB%0A-XX%3A%2BUseG1GC%0A%60%60%60%0A%0A%60%60%60java%0A-Xmx4096m%0A-Xms4096m%0A-XX%3AReservedCodeCacheSize%3D256m%0A-XX%3A%2BUseG1GC%0A%60%60%60%0A%3E%20%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E%0A%60%60%60java%0A-server%3A%E4%B8%80%E5%AE%9A%E8%A6%81%E4%BD%9C%E4%B8%BA%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E5%9C%A8%E5%A4%9A%E4%B8%AACPU%E6%97%B6%E6%80%A7%E8%83%BD%E4%BD%B3%0A-Xms%EF%BC%9A%E5%88%9D%E5%A7%8BHeap%E5%A4%A7%E5%B0%8F%EF%BC%8C%E4%BD%BF%E7%94%A8%E7%9A%84%E6%9C%80%E5%B0%8F%E5%86%85%E5%AD%98%2Ccpu%E6%80%A7%E8%83%BD%E9%AB%98%E6%97%B6%E6%AD%A4%E5%80%BC%E5%BA%94%E8%AE%BE%E7%9A%84%E5%A4%A7%E4%B8%80%E4%BA%9B%0A-Xmx%EF%BC%9Ajava%20heap%E6%9C%80%E5%A4%A7%E5%80%BC%EF%BC%8C%E4%BD%BF%E7%94%A8%E7%9A%84%E6%9C%80%E5%A4%A7%E5%86%85%E5%AD%98%0A-XX%3APermSize%3A%E8%AE%BE%E5%AE%9A%E5%86%85%E5%AD%98%E7%9A%84%E6%B0%B8%E4%B9%85%E4%BF%9D%E5%AD%98%E5%8C%BA%E5%9F%9F%0A-XX%3AMaxPermSize%3A%E8%AE%BE%E5%AE%9A%E6%9C%80%E5%A4%A7%E5%86%85%E5%AD%98%E7%9A%84%E6%B0%B8%E4%B9%85%E4%BF%9D%E5%AD%98%E5%8C%BA%E5%9F%9F%0A-XX%3AMaxNewSize%3A%0A%2BXX%3AAggressiveHeap%20%E4%BD%BF%20Xms%20%E5%A4%B1%E5%8E%BB%E6%84%8F%E4%B9%89%E3%80%82%0A-Xss%EF%BC%9A%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%9A%84Stack%E5%A4%A7%E5%B0%8F%0A-verbose%3Agc%20%E7%8E%B0%E5%AE%9E%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E4%BF%A1%E6%81%AF%0A-Xloggc%3Agc.log%20%E6%8C%87%E5%AE%9A%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%0A-Xmn%EF%BC%9Ayoung%20generation%E7%9A%84heap%E5%A4%A7%E5%B0%8F%EF%BC%8C%E4%B8%80%E8%88%AC%E8%AE%BE%E7%BD%AE%E4%B8%BAXmx%E7%9A%843%E3%80%814%E5%88%86%E4%B9%8B%E4%B8%80%0A-XX%3A%2BUseParNewGC%20%EF%BC%9A%E7%BC%A9%E7%9F%ADminor%E6%94%B6%E9%9B%86%E7%9A%84%E6%97%B6%E9%97%B4%0A-XX%3A%2BUseConcMarkSweepGC%20%EF%BC%9A%E7%BC%A9%E7%9F%ADmajor%E6%94%B6%E9%9B%86%E7%9A%84%E6%97%B6%E9%97%B4%0A%60%60%60%0A%3E%20%E6%8F%90%E7%A4%BA%EF%BC%9A%E6%AD%A4%E9%80%89%E9%A1%B9%E5%9C%A8Heap%20Size%20%E6%AF%94%E8%BE%83%E5%A4%A7%E8%80%8C%E4%B8%94Major%E6%94%B6%E9%9B%86%E6%97%B6%E9%97%B4%E8%BE%83%E9%95%BF%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E4%BD%BF%E7%94%A8%E6%9B%B4%E5%90%88%E9%80%82%E3%80%82%0A%0A%23%23%203.%E6%B8%85%E7%90%86%E7%BC%93%E5%AD%98%0A!%5B2df1294ed7f8e749ace7576cfe902e8b.png%5D(en-resource%3A%2F%2Fdatabase%2F1381%3A0)%0A

Runtime.addShutdownHook

创建时间:2023/3/25 13:40
更新时间:2023/3/25 13:43
作者:Chris

在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码。Java中得ShutdownHook提供了比较好的方案。

JDK在1.3之后提供了Runtime.addShutdownHook(Thread hook) 方法,可以注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用:

  • 1)程序正常退出
  • 2)使用System.exit()
  • 3)终端使用Ctrl+C触发的中断
  • 4)系统关闭5)使用Kill pid命令干掉进程

注:在使用kill -9 pid是不会JVM注册的钩子不会被调用。


package com.chris.thread.future.threadpool;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

public class TestShutdownHook {

    //简单模拟干活的
    static Timer timer = new Timer("job-timer");

    //计数干活次数
    static AtomicInteger count = new AtomicInteger(0);

    /**
     * hook线程
     */
    static class CleanWorkThread extends Thread {
        @Override
        public void run() {
            System.out.println("clean some work.");
            timer.cancel();
            try {
                Thread.sleep(2 * 1000);//sleep 2s
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //将hook线程添加到运行时环境中去
        Runtime.getRuntime().addShutdownHook(new CleanWorkThread());
        System.out.println("main class start ..... ");
        //简单模拟
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                count.getAndIncrement();
                //干了10次退出
                System.out.println("doing job " + count);
                if (count.get() == 10) {
                    System.exit(0);
                }
            }
        }, 0, 2 * 1000);
    }
}
%3E%20%E5%9C%A8%E7%BA%BF%E4%B8%8AJava%E7%A8%8B%E5%BA%8F%E4%B8%AD%E7%BB%8F%E5%B8%B8%E9%81%87%E5%88%B0%E8%BF%9B%E7%A8%8B%E7%A8%8B%E6%8C%82%E6%8E%89%EF%BC%8C%E4%B8%80%E4%BA%9B%E7%8A%B6%E6%80%81%E6%B2%A1%E6%9C%89%E6%AD%A3%E7%A1%AE%E7%9A%84%E4%BF%9D%E5%AD%98%E4%B8%8B%E6%9D%A5%EF%BC%8C%E8%BF%99%E6%97%B6%E5%80%99%E5%B0%B1%E9%9C%80%E8%A6%81%E5%9C%A8JVM%E5%85%B3%E6%8E%89%E7%9A%84%E6%97%B6%E5%80%99%E6%89%A7%E8%A1%8C%E4%B8%80%E4%BA%9B%E6%B8%85%E7%90%86%E7%8E%B0%E5%9C%BA%E7%9A%84%E4%BB%A3%E7%A0%81%E3%80%82Java%E4%B8%AD%E5%BE%97ShutdownHook%E6%8F%90%E4%BE%9B%E4%BA%86%E6%AF%94%E8%BE%83%E5%A5%BD%E7%9A%84%E6%96%B9%E6%A1%88%E3%80%82%0A%0A%3E%20JDK%E5%9C%A81.3%E4%B9%8B%E5%90%8E%E6%8F%90%E4%BE%9B%E4%BA%86%60Runtime.addShutdownHook(Thread%20hook)%60%20%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%B3%A8%E5%86%8C%E4%B8%80%E4%B8%AAJVM%E5%85%B3%E9%97%AD%E7%9A%84%E9%92%A9%E5%AD%90%EF%BC%8C%E8%BF%99%E4%B8%AA%E9%92%A9%E5%AD%90%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%BB%A5%E4%B8%8B%E5%87%A0%E7%A7%8D%E5%9C%BA%E6%99%AF%E8%A2%AB%E8%B0%83%E7%94%A8%EF%BC%9A%0A%3E%20%0A-%201%EF%BC%89%E7%A8%8B%E5%BA%8F%E6%AD%A3%E5%B8%B8%E9%80%80%E5%87%BA%0A-%202%EF%BC%89%E4%BD%BF%E7%94%A8System.exit()%0A-%203%EF%BC%89%E7%BB%88%E7%AB%AF%E4%BD%BF%E7%94%A8Ctrl%2BC%E8%A7%A6%E5%8F%91%E7%9A%84%E4%B8%AD%E6%96%AD%0A-%204%EF%BC%89%E7%B3%BB%E7%BB%9F%E5%85%B3%E9%97%AD5%EF%BC%89%E4%BD%BF%E7%94%A8Kill%20pid%E5%91%BD%E4%BB%A4%E5%B9%B2%E6%8E%89%E8%BF%9B%E7%A8%8B%0A%3E%20%E6%B3%A8%EF%BC%9A%E5%9C%A8%E4%BD%BF%E7%94%A8kill%20-9%20pid%E6%98%AF%E4%B8%8D%E4%BC%9AJVM%E6%B3%A8%E5%86%8C%E7%9A%84%E9%92%A9%E5%AD%90%E4%B8%8D%E4%BC%9A%E8%A2%AB%E8%B0%83%E7%94%A8%E3%80%82%0A%0A%0A%60%60%60java%0A%0Apackage%20com.chris.thread.future.threadpool%3B%0A%0Aimport%20java.util.Timer%3B%0Aimport%20java.util.TimerTask%3B%0Aimport%20java.util.concurrent.atomic.AtomicInteger%3B%0A%0Apublic%20class%20TestShutdownHook%20%7B%0A%0A%20%20%20%20%2F%2F%E7%AE%80%E5%8D%95%E6%A8%A1%E6%8B%9F%E5%B9%B2%E6%B4%BB%E7%9A%84%0A%20%20%20%20static%20Timer%20timer%20%3D%20new%20Timer(%22job-timer%22)%3B%0A%0A%20%20%20%20%2F%2F%E8%AE%A1%E6%95%B0%E5%B9%B2%E6%B4%BB%E6%AC%A1%E6%95%B0%0A%20%20%20%20static%20AtomicInteger%20count%20%3D%20new%20AtomicInteger(0)%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20hook%E7%BA%BF%E7%A8%8B%0A%20%20%20%20%20*%2F%0A%20%20%20%20static%20class%20CleanWorkThread%20extends%20Thread%20%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22clean%20some%20work.%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20timer.cancel()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(2%20*%201000)%3B%2F%2Fsleep%202s%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E5%B0%86hook%E7%BA%BF%E7%A8%8B%E6%B7%BB%E5%8A%A0%E5%88%B0%E8%BF%90%E8%A1%8C%E6%97%B6%E7%8E%AF%E5%A2%83%E4%B8%AD%E5%8E%BB%0A%20%20%20%20%20%20%20%20Runtime.getRuntime().addShutdownHook(new%20CleanWorkThread())%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22main%20class%20start%20.....%20%22)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E7%AE%80%E5%8D%95%E6%A8%A1%E6%8B%9F%0A%20%20%20%20%20%20%20%20timer.schedule(new%20TimerTask()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count.getAndIncrement()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%B9%B2%E4%BA%8610%E6%AC%A1%E9%80%80%E5%87%BA%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22doing%20job%20%22%20%2B%20count)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(count.get()%20%3D%3D%2010)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.exit(0)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%2C%200%2C%202%20*%201000)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60

LeetCode

创建时间:2023/3/25 13:55
更新时间:2023/3/25 13:55
作者:Chris

https://www.cspiration.com/#/leetcodeClassification


CountDownLatch

创建时间:2023/3/25 14:34
更新时间:2023/3/25 14:42
作者:Chris
来源:https://blog.csdn.net/warybee/article/details/122459493

1. 应用场景

一个线程等待多个线程完成给定任务后,然后执行后续的操作的场景

2. 构造函数

CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完 成,这里就传入N。这里所说的N个 点,可以是N个线程,也可以是1个线程里的N个执行步骤

 public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
 }

计数器参数count必须大于等于0,等于0的时候,调用await方法时不会 阻塞当前线程。
调用CountDownLatch的countDown()方法时,N就会减1,CountDownLatch的await()方法会阻塞当前线程,直到N变成零。

3. CountDownLatch方法

  1. await() 阻塞当前线程,直到计数器为零为止;
  2. await(long timeout, TimeUnit unit) await()的重载方法,可以指定阻塞时长;
  3. countDown() 计数器减1,如果计数达到零,释放所有等待的线程。
  4. getCount() 返回当前计数

4. 实现

public class DownLoadWorker implements Runnable{
    private String url;
    private  CountDownLatch countDownLatch;

    public DownLoadWorker(String url, CountDownLatch countDownLatch) {
        this.url = url;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        //省略无数业务代码
        System.out.println("线程" + Thread.currentThread().getName() + "开始下载完成");
        countDownLatch.countDown();
    }
}

public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch=new CountDownLatch(5);
        //使用Stream 生成5个线程
        List<Thread> workers = Stream
                .generate(() -> new Thread(new DownLoadWorker("https://image.baidu.com/", countDownLatch)))
                .limit(5)
                .collect(toList());
        //运行线程
        workers.forEach(Thread::start);
        //等待线程完成
        countDownLatch.await();
        System.out.println("图片已下载完~~~");
}

5. Thread.join()和CountDownLatch的区别

  1. Thread.join()是Thread类的一个方法,Thread.join()的实现是依靠Object的wait()和notifyAll()来完成的
  2. CountDownLatch是JUC包中的一个工具类。
  3. 调用join方法需要等待thread执行完毕才能继续向下执行。
  4. CountDownLatch只需要检查计数器的值为零就可以继续向下执行,相比之下,CountDownLatch更加灵活一些,可以实现一些更加复杂的业务场景
%5Btoc%5D%0A%23%23%201.%20%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%0A%3E%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%AD%89%E5%BE%85%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%AE%8C%E6%88%90%E7%BB%99%E5%AE%9A%E4%BB%BB%E5%8A%A1%E5%90%8E%EF%BC%8C%E7%84%B6%E5%90%8E%E6%89%A7%E8%A1%8C%E5%90%8E%E7%BB%AD%E7%9A%84%E6%93%8D%E4%BD%9C%E7%9A%84%E5%9C%BA%E6%99%AF%0A%0A!%5B1257987545fe838607736465fdb1062d.png%5D(en-resource%3A%2F%2Fdatabase%2F1399%3A0)%0A%0A%23%23%202.%20%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%0A%3E%20CountDownLatch%E7%9A%84%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E6%8E%A5%E6%94%B6%E4%B8%80%E4%B8%AAint%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%82%E6%95%B0%E4%BD%9C%E4%B8%BA%E8%AE%A1%E6%95%B0%E5%99%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%BD%A0%E6%83%B3%E7%AD%89%E5%BE%85N%E4%B8%AA%E7%82%B9%E5%AE%8C%20%E6%88%90%EF%BC%8C%E8%BF%99%E9%87%8C%E5%B0%B1%E4%BC%A0%E5%85%A5N%E3%80%82%E8%BF%99%E9%87%8C%E6%89%80%E8%AF%B4%E7%9A%84N%E4%B8%AA%20%E7%82%B9%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%98%AFN%E4%B8%AA%E7%BA%BF%E7%A8%8B%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%98%AF1%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%87%8C%E7%9A%84N%E4%B8%AA%E6%89%A7%E8%A1%8C%E6%AD%A5%E9%AA%A4%0A%0A%60%60%60java%0A%20public%20CountDownLatch(int%20count)%20%7B%0A%20%20%20%20%20%20%20%20if%20(count%20%3C%200)%20throw%20new%20IllegalArgumentException(%22count%20%3C%200%22)%3B%0A%20%20%20%20%20%20%20%20this.sync%20%3D%20new%20Sync(count)%3B%0A%20%7D%0A%60%60%60%0A%3E%20%E8%AE%A1%E6%95%B0%E5%99%A8%E5%8F%82%E6%95%B0count%E5%BF%85%E9%A1%BB%E5%A4%A7%E4%BA%8E%E7%AD%89%E4%BA%8E0%EF%BC%8C%E7%AD%89%E4%BA%8E0%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E8%B0%83%E7%94%A8await%E6%96%B9%E6%B3%95%E6%97%B6%E4%B8%8D%E4%BC%9A%20%E9%98%BB%E5%A1%9E%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E3%80%82%0A%3E%20%E8%B0%83%E7%94%A8CountDownLatch%E7%9A%84countDown()%E6%96%B9%E6%B3%95%E6%97%B6%EF%BC%8CN%E5%B0%B1%E4%BC%9A%E5%87%8F1%EF%BC%8CCountDownLatch%E7%9A%84await()%E6%96%B9%E6%B3%95%E4%BC%9A%E9%98%BB%E5%A1%9E%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%EF%BC%8C%E7%9B%B4%E5%88%B0N%E5%8F%98%E6%88%90%E9%9B%B6%E3%80%82%0A%0A%0A%23%23%203.%20CountDownLatch%E6%96%B9%E6%B3%95%0A1.%20await()%20%E9%98%BB%E5%A1%9E%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%EF%BC%8C%E7%9B%B4%E5%88%B0%E8%AE%A1%E6%95%B0%E5%99%A8%E4%B8%BA%E9%9B%B6%E4%B8%BA%E6%AD%A2%EF%BC%9B%0A2.%20await(long%20timeout%2C%20TimeUnit%20unit)%20await()%E7%9A%84%E9%87%8D%E8%BD%BD%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E9%98%BB%E5%A1%9E%E6%97%B6%E9%95%BF%EF%BC%9B%0A3.%20countDown()%20%E8%AE%A1%E6%95%B0%E5%99%A8%E5%87%8F1%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AE%A1%E6%95%B0%E8%BE%BE%E5%88%B0%E9%9B%B6%EF%BC%8C%E9%87%8A%E6%94%BE%E6%89%80%E6%9C%89%E7%AD%89%E5%BE%85%E7%9A%84%E7%BA%BF%E7%A8%8B%E3%80%82%0A4.%20getCount()%20%E8%BF%94%E5%9B%9E%E5%BD%93%E5%89%8D%E8%AE%A1%E6%95%B0%0A%0A%23%23%204.%20%E5%AE%9E%E7%8E%B0%0A%60%60%60java%0Apublic%20class%20DownLoadWorker%20implements%20Runnable%7B%0A%20%20%20%20private%20String%20url%3B%0A%20%20%20%20private%20%20CountDownLatch%20countDownLatch%3B%0A%0A%20%20%20%20public%20DownLoadWorker(String%20url%2C%20CountDownLatch%20countDownLatch)%20%7B%0A%20%20%20%20%20%20%20%20this.url%20%3D%20url%3B%0A%20%20%20%20%20%20%20%20this.countDownLatch%20%3D%20countDownLatch%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%E7%9C%81%E7%95%A5%E6%97%A0%E6%95%B0%E4%B8%9A%E5%8A%A1%E4%BB%A3%E7%A0%81%0A%20%20%20%20%20%20%20%20System.out.println(%22%E7%BA%BF%E7%A8%8B%22%20%2B%20Thread.currentThread().getName()%20%2B%20%22%E5%BC%80%E5%A7%8B%E4%B8%8B%E8%BD%BD%E5%AE%8C%E6%88%90%22)%3B%0A%20%20%20%20%20%20%20%20countDownLatch.countDown()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Apublic%20static%20void%20main(String%5B%5D%20args)%20throws%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20CountDownLatch%20countDownLatch%3Dnew%20CountDownLatch(5)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E4%BD%BF%E7%94%A8Stream%20%E7%94%9F%E6%88%905%E4%B8%AA%E7%BA%BF%E7%A8%8B%0A%20%20%20%20%20%20%20%20List%3CThread%3E%20workers%20%3D%20Stream%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.generate(()%20-%3E%20new%20Thread(new%20DownLoadWorker(%22https%3A%2F%2Fimage.baidu.com%2F%22%2C%20countDownLatch)))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.limit(5)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.collect(toList())%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E8%BF%90%E8%A1%8C%E7%BA%BF%E7%A8%8B%0A%20%20%20%20%20%20%20%20workers.forEach(Thread%3A%3Astart)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%E7%AD%89%E5%BE%85%E7%BA%BF%E7%A8%8B%E5%AE%8C%E6%88%90%0A%20%20%20%20%20%20%20%20countDownLatch.await()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22%E5%9B%BE%E7%89%87%E5%B7%B2%E4%B8%8B%E8%BD%BD%E5%AE%8C~~~%22)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%205.%20Thread.join()%E5%92%8CCountDownLatch%E7%9A%84%E5%8C%BA%E5%88%AB%0A1.%20Thread.join()%E6%98%AFThread%E7%B1%BB%E7%9A%84%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%EF%BC%8CThread.join()%E7%9A%84%E5%AE%9E%E7%8E%B0%E6%98%AF%E4%BE%9D%E9%9D%A0Object%E7%9A%84wait()%E5%92%8CnotifyAll()%E6%9D%A5%E5%AE%8C%E6%88%90%E7%9A%84%0A2.%20CountDownLatch%E6%98%AFJUC%E5%8C%85%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AA%E5%B7%A5%E5%85%B7%E7%B1%BB%E3%80%82%0A3.%20%E8%B0%83%E7%94%A8join%E6%96%B9%E6%B3%95%E9%9C%80%E8%A6%81%E7%AD%89%E5%BE%85thread%E6%89%A7%E8%A1%8C%E5%AE%8C%E6%AF%95%E6%89%8D%E8%83%BD%E7%BB%A7%E7%BB%AD%E5%90%91%E4%B8%8B%E6%89%A7%E8%A1%8C%E3%80%82%0A4.%20CountDownLatch%E5%8F%AA%E9%9C%80%E8%A6%81%E6%A3%80%E6%9F%A5%E8%AE%A1%E6%95%B0%E5%99%A8%E7%9A%84%E5%80%BC%E4%B8%BA%E9%9B%B6%E5%B0%B1%E5%8F%AF%E4%BB%A5%E7%BB%A7%E7%BB%AD%E5%90%91%E4%B8%8B%E6%89%A7%E8%A1%8C%EF%BC%8C%E7%9B%B8%E6%AF%94%E4%B9%8B%E4%B8%8B%EF%BC%8CCountDownLatch%E6%9B%B4%E5%8A%A0%E7%81%B5%E6%B4%BB%E4%B8%80%E4%BA%9B%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%BA%9B%E6%9B%B4%E5%8A%A0%E5%A4%8D%E6%9D%82%E7%9A%84%E4%B8%9A%E5%8A%A1%E5%9C%BA%E6%99%AF

jps不无显示jvm进程

创建时间:2023/3/26 14:29
更新时间:2023/3/26 14:39
作者:Chris

  1. 高级系统设置>环境变更>用户变量
  2. 打开对应文件路径,找到文件夹 hsperfdata_DELL
  3. 查看当前登录用户是存在且被授权,没有则添加且授权
  4. 添加完之后启动电脑




1.%20%E9%AB%98%E7%BA%A7%E7%B3%BB%E7%BB%9F%E8%AE%BE%E7%BD%AE%3E%E7%8E%AF%E5%A2%83%E5%8F%98%E6%9B%B4%3E%E7%94%A8%E6%88%B7%E5%8F%98%E9%87%8F%0A2.%20%E6%89%93%E5%BC%80%E5%AF%B9%E5%BA%94%E6%96%87%E4%BB%B6%E8%B7%AF%E5%BE%84%EF%BC%8C%E6%89%BE%E5%88%B0%E6%96%87%E4%BB%B6%E5%A4%B9%20hsperfdata_DELL%0A3.%20%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8D%E7%99%BB%E5%BD%95%E7%94%A8%E6%88%B7%E6%98%AF%E5%AD%98%E5%9C%A8%E4%B8%94%E8%A2%AB%E6%8E%88%E6%9D%83%EF%BC%8C%E6%B2%A1%E6%9C%89%E5%88%99%E6%B7%BB%E5%8A%A0%E4%B8%94%E6%8E%88%E6%9D%83%0A4.%20%E6%B7%BB%E5%8A%A0%E5%AE%8C%E4%B9%8B%E5%90%8E%E5%90%AF%E5%8A%A8%E7%94%B5%E8%84%91%0A%0A%0A%0A!%5B479ee54b41ebecb98c5c22199934b5ab.png%5D(en-resource%3A%2F%2Fdatabase%2F1407%3A0)%0A!%5B212a13e66ef5e478246aa0e8379c159a.png%5D(en-resource%3A%2F%2Fdatabase%2F1409%3A0)%0A!%5Bf3a084e340e77de15c43628333c93b69.png%5D(en-resource%3A%2F%2Fdatabase%2F1411%3A0)%0A!%5B45752a40598a26f3857ecb873f955aac.png%5D(en-resource%3A%2F%2Fdatabase%2F1413%3A0)%0A

重入锁-ReentrantLock

创建时间:2023/4/5 12:59
更新时间:2024/4/21 12:43
作者:Chris
来源:https://www.jianshu.com/p/7e2ec0eccd1e

参考文档

https://blog.csdn.net/bbj12345678/article/details/120458357
https://www.jianshu.com/p/7e2ec0eccd1e
https://baijiahao.baidu.com/s?id=1702822534980452383&wfr=spider&for=pc

1 是什么

一个持有锁的线程,在释放锁之前, 此线程如果再次访问了该同步锁的其他的方法,这个线程不需要再次竞争锁,只需要记录重入次数。

重入锁的设计目的是为了解决死锁的问题

lock() 获得锁
lockInterruptibly() 获得锁,但优先响应中断
tryLock() 尝试获得锁,成功返回true,否则false,该方法不等待,立即返回
tryLock(long time,TimeUnit unit) 在给定时间内尝试获得锁
unlock() 释放锁

2 原理

  1. 在多线程环境下如何实互斥的逻辑? 多线程环境下通过更改边界值state来实现获取锁与释放锁的逻辑。通过原子操作更改成员变量state,如果state=1则代表当前线程获取了锁其他线程阻塞。
  2. 获取锁失败的线程如何处理?获取锁失败的线程进行阻塞而不是循环。之所以阻塞是为了让这些获取锁失败的线程让出cpu资源
  3. 如何存储阻塞的线程呢?用一个双端列队存储线程
  4. 当前线程释放锁之后,如何唤醒阻塞的线程?释放锁的时候如果head节点的waitState= -1 那么通过LockSupport.unpark(thread) 唤醒header的后续waitState<= 0的节点
  5. 公平锁与公平锁什么区别? 阻塞列队中的阻塞线程按照先进先出的顺序被唤醒的,第一个进来的第一个被唤醒去抢占锁,但是这个时候新的线程T2获取锁,那么T2并不是先插入阻塞列队中,而是先尝试获取一个锁,那么这种行为对于那些先进入阻塞列队中排队的线程来说是不公平的,就好比说大家排队买票一样,一个新来的没有排队直接去窗口买票了,所以叫做非公平锁反之则是公平锁.

2.1 源码分析

private final Sync sync;  //内部类 实现类AbstractQueuedSynchronized抽象类
//默认实现是非公平锁
public ReentrantLock() {
    sync = new NonfairSync();
}
//true  公平锁 false 非公平锁
public ReentrantLock(boolean fair) {
     sync = fair ? new FairSync() : new NonfairSync();
}
//获取锁 
public void lock() {
    sync.lock();
}

2.1.1 获取锁

2.1.1.1 NonfairSync 非公平锁的核心实现
//中间态变量,通过更改state的值判断是否占有锁  state=0 代表无线程占用 
//state >= 1 代表有锁 state =1  代表有一个线程占用锁 state=5假如是重入锁那么代表这个线程获取了5次锁,相应的需要释放5次锁使得state=0从而达到释放的目的。
private volatile int state;
//当前占有锁的线程
private transient Thread exclusiveOwnerThread;
//尝试获取锁
final void lock() {
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

compareAndSetState 通过调用unsafe的提供的cas本地方法(调用c语言) 尝试把state=0的值更改为1,如果成功设置占有锁的线程为当前线程,如果获取失败则调用acquire尝试获取1次

public final void acquire(int arg) {
    //尝试获取一个锁,如果失败了添加线程到等待的双端队列中
    if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)){
        selfInterrupt();
    }
}
//尝试获取锁
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}

final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            //此处体现了nonfair非公平的意思
            if (c == 0) {
                //说明已经有线程释放了锁,那么当前线程尝试获取一次,如果获取成功返回true
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //次数体现了重入锁的逻辑
            //如果获取锁的线程是当前线程
            else if (current == getExclusiveOwnerThread()) {
                //获取锁的次数+acquires
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                //这里无需cas操作,因为必然已经获取锁了
                setState(nextc);
                return true;
            }
            return false;
}

2.1.2 释放锁

更新state的值如果为0则唤醒后续节点

public final boolean release(int arg) { 
  if (tryRelease(arg)) { 
       //释放锁成功
      Node h = head; //得到 aqs 中 head 节点
       if (h != null && h.waitStatus != 0)
         //如果 head 节点不 为空并且状态!=0.
         //调用 unparkSuccessor(h)唤醒后续节点
          unparkSuccessor(h); 
      return true;}return false;}

释放锁的业务逻辑不需要考虑多线程的问题,他还是被一个线程持有。因为重入锁的机制是 state>=1 释放就是 getState() - releases并更新state为最新值,如果state=0则返回。

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;}

3 案例

package com.chris.thread.future.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {
    private static final Lock lock = new ReentrantLock();
    private static int count = 0;
    private static void inrc() {
        try {
            // 加锁
            lock.lock();
            Thread.sleep(10);
            count++;
            System.out.println(Thread.currentThread().getName() + "+1=" + count);
            // 模拟重入锁
            dec();// 2
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private static void dec() {
        lock.lock();
        count--;
        System.out.println(Thread.currentThread().getName() + "-1=" + count);
        lock.unlock();
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            new Thread(ReentrantLockDemo::inrc).start();
        }
        TimeUnit.SECONDS.sleep(3);
        System.out.println(count);
    }
}

验证结果

Thread-0+1=1
Thread-0-1=0
Thread-1+1=1
Thread-1-1=0
Thread-2+1=1
Thread-2-1=0
Thread-8+1=1
Thread-8-1=0
Thread-4+1=1
Thread-4-1=0
Thread-5+1=1
Thread-5-1=0
Thread-6+1=1
Thread-6-1=0
Thread-7+1=1
Thread-7-1=0
Thread-3+1=1
Thread-3-1=0
Thread-9+1=1
Thread-9-1=0
Thread-10+1=1
Thread-10-1=0
%5Btoc%5D%0A%0A%0A%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3%0A%3E%20https%3A%2F%2Fblog.csdn.net%2Fbbj12345678%2Farticle%2Fdetails%2F120458357%0A%3E%20https%3A%2F%2Fwww.jianshu.com%2Fp%2F7e2ec0eccd1e%0A%3E%20https%3A%2F%2Fbaijiahao.baidu.com%2Fs%3Fid%3D1702822534980452383%26wfr%3Dspider%26for%3Dpc%0A%0A%23%23%201%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%3E%20%E4%B8%80%E4%B8%AA%E6%8C%81%E6%9C%89%E9%94%81%E7%9A%84%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%9C%A8%E9%87%8A%E6%94%BE%E9%94%81%E4%B9%8B%E5%89%8D%2C%20%E6%AD%A4%E7%BA%BF%E7%A8%8B%E5%A6%82%E6%9E%9C%E5%86%8D%E6%AC%A1%E8%AE%BF%E9%97%AE%E4%BA%86%E8%AF%A5%E5%90%8C%E6%AD%A5%E9%94%81%E7%9A%84%E5%85%B6%E4%BB%96%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E8%BF%99%E4%B8%AA%E7%BA%BF%E7%A8%8B%E4%B8%8D%E9%9C%80%E8%A6%81%E5%86%8D%E6%AC%A1%E7%AB%9E%E4%BA%89%E9%94%81%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E8%AE%B0%E5%BD%95%E9%87%8D%E5%85%A5%E6%AC%A1%E6%95%B0%E3%80%82%0A%3E%20%0A%3E%20%E9%87%8D%E5%85%A5%E9%94%81%E7%9A%84%E8%AE%BE%E8%AE%A1%E7%9B%AE%E7%9A%84%E6%98%AF%E4%B8%BA%E4%BA%86%E8%A7%A3%E5%86%B3%E6%AD%BB%E9%94%81%E7%9A%84%E9%97%AE%E9%A2%98%0A%0A%60%60%60%0Alock()%20%E8%8E%B7%E5%BE%97%E9%94%81%0AlockInterruptibly()%20%E8%8E%B7%E5%BE%97%E9%94%81%EF%BC%8C%E4%BD%86%E4%BC%98%E5%85%88%E5%93%8D%E5%BA%94%E4%B8%AD%E6%96%AD%0AtryLock()%20%E5%B0%9D%E8%AF%95%E8%8E%B7%E5%BE%97%E9%94%81%EF%BC%8C%E6%88%90%E5%8A%9F%E8%BF%94%E5%9B%9Etrue%2C%E5%90%A6%E5%88%99false%EF%BC%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E4%B8%8D%E7%AD%89%E5%BE%85%EF%BC%8C%E7%AB%8B%E5%8D%B3%E8%BF%94%E5%9B%9E%0AtryLock(long%20time%2CTimeUnit%20unit)%20%E5%9C%A8%E7%BB%99%E5%AE%9A%E6%97%B6%E9%97%B4%E5%86%85%E5%B0%9D%E8%AF%95%E8%8E%B7%E5%BE%97%E9%94%81%0Aunlock()%20%E9%87%8A%E6%94%BE%E9%94%81%0A%60%60%60%0A%0A%23%23%202%20%E5%8E%9F%E7%90%86%0A%0A1.%20%E5%9C%A8%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%8E%AF%E5%A2%83%E4%B8%8B%E5%A6%82%E4%BD%95%E5%AE%9E%E4%BA%92%E6%96%A5%E7%9A%84%E9%80%BB%E8%BE%91%EF%BC%9F%20%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%8E%AF%E5%A2%83%E4%B8%8B%E9%80%9A%E8%BF%87%E6%9B%B4%E6%94%B9%E8%BE%B9%E7%95%8C%E5%80%BCstate%E6%9D%A5%E5%AE%9E%E7%8E%B0%E8%8E%B7%E5%8F%96%E9%94%81%E4%B8%8E%E9%87%8A%E6%94%BE%E9%94%81%E7%9A%84%E9%80%BB%E8%BE%91%E3%80%82%E9%80%9A%E8%BF%87%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%E6%9B%B4%E6%94%B9%E6%88%90%E5%91%98%E5%8F%98%E9%87%8Fstate%EF%BC%8C%E5%A6%82%E6%9E%9Cstate%3D1%E5%88%99%E4%BB%A3%E8%A1%A8%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E8%8E%B7%E5%8F%96%E4%BA%86%E9%94%81%E5%85%B6%E4%BB%96%E7%BA%BF%E7%A8%8B%E9%98%BB%E5%A1%9E%E3%80%82%0A2.%20%E8%8E%B7%E5%8F%96%E9%94%81%E5%A4%B1%E8%B4%A5%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86%EF%BC%9F%E8%8E%B7%E5%8F%96%E9%94%81%E5%A4%B1%E8%B4%A5%E7%9A%84%E7%BA%BF%E7%A8%8B%E8%BF%9B%E8%A1%8C%E9%98%BB%E5%A1%9E%E8%80%8C%E4%B8%8D%E6%98%AF%E5%BE%AA%E7%8E%AF%E3%80%82%E4%B9%8B%E6%89%80%E4%BB%A5%E9%98%BB%E5%A1%9E%E6%98%AF%E4%B8%BA%E4%BA%86%E8%AE%A9%E8%BF%99%E4%BA%9B%E8%8E%B7%E5%8F%96%E9%94%81%E5%A4%B1%E8%B4%A5%E7%9A%84%E7%BA%BF%E7%A8%8B%E8%AE%A9%E5%87%BAcpu%E8%B5%84%E6%BA%90%0A3.%20%E5%A6%82%E4%BD%95%E5%AD%98%E5%82%A8%E9%98%BB%E5%A1%9E%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%91%A2%EF%BC%9F%E7%94%A8%E4%B8%80%E4%B8%AA%E5%8F%8C%E7%AB%AF%E5%88%97%E9%98%9F%E5%AD%98%E5%82%A8%E7%BA%BF%E7%A8%8B%0A4.%20%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E9%87%8A%E6%94%BE%E9%94%81%E4%B9%8B%E5%90%8E%EF%BC%8C%E5%A6%82%E4%BD%95%E5%94%A4%E9%86%92%E9%98%BB%E5%A1%9E%E7%9A%84%E7%BA%BF%E7%A8%8B%EF%BC%9F%E9%87%8A%E6%94%BE%E9%94%81%E7%9A%84%E6%97%B6%E5%80%99%E5%A6%82%E6%9E%9Chead%E8%8A%82%E7%82%B9%E7%9A%84waitState%3D%20-1%20%E9%82%A3%E4%B9%88%E9%80%9A%E8%BF%87%60LockSupport.unpark(thread)%20%60%20%E5%94%A4%E9%86%92header%E7%9A%84%E5%90%8E%E7%BB%ADwaitState%3C%3D%200%E7%9A%84%E8%8A%82%E7%82%B9%0A5.%20%E5%85%AC%E5%B9%B3%E9%94%81%E4%B8%8E%E5%85%AC%E5%B9%B3%E9%94%81%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%EF%BC%9F%20%E9%98%BB%E5%A1%9E%E5%88%97%E9%98%9F%E4%B8%AD%E7%9A%84%E9%98%BB%E5%A1%9E%E7%BA%BF%E7%A8%8B%E6%8C%89%E7%85%A7%E5%85%88%E8%BF%9B%E5%85%88%E5%87%BA%E7%9A%84%E9%A1%BA%E5%BA%8F%E8%A2%AB%E5%94%A4%E9%86%92%E7%9A%84%EF%BC%8C%E7%AC%AC%E4%B8%80%E4%B8%AA%E8%BF%9B%E6%9D%A5%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E8%A2%AB%E5%94%A4%E9%86%92%E5%8E%BB%E6%8A%A2%E5%8D%A0%E9%94%81%EF%BC%8C%E4%BD%86%E6%98%AF%E8%BF%99%E4%B8%AA%E6%97%B6%E5%80%99%E6%96%B0%E7%9A%84%E7%BA%BF%E7%A8%8BT2%E8%8E%B7%E5%8F%96%E9%94%81%EF%BC%8C%E9%82%A3%E4%B9%88T2%E5%B9%B6%E4%B8%8D%E6%98%AF%E5%85%88%E6%8F%92%E5%85%A5%E9%98%BB%E5%A1%9E%E5%88%97%E9%98%9F%E4%B8%AD%EF%BC%8C%E8%80%8C%E6%98%AF%E5%85%88%E5%B0%9D%E8%AF%95%E8%8E%B7%E5%8F%96%E4%B8%80%E4%B8%AA%E9%94%81%EF%BC%8C%E9%82%A3%E4%B9%88%E8%BF%99%E7%A7%8D%E8%A1%8C%E4%B8%BA%E5%AF%B9%E4%BA%8E%E9%82%A3%E4%BA%9B%E5%85%88%E8%BF%9B%E5%85%A5%E9%98%BB%E5%A1%9E%E5%88%97%E9%98%9F%E4%B8%AD%E6%8E%92%E9%98%9F%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%9D%A5%E8%AF%B4%E6%98%AF%E4%B8%8D%E5%85%AC%E5%B9%B3%E7%9A%84%EF%BC%8C%E5%B0%B1%E5%A5%BD%E6%AF%94%E8%AF%B4%E5%A4%A7%E5%AE%B6%E6%8E%92%E9%98%9F%E4%B9%B0%E7%A5%A8%E4%B8%80%E6%A0%B7%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%96%B0%E6%9D%A5%E7%9A%84%E6%B2%A1%E6%9C%89%E6%8E%92%E9%98%9F%E7%9B%B4%E6%8E%A5%E5%8E%BB%E7%AA%97%E5%8F%A3%E4%B9%B0%E7%A5%A8%E4%BA%86%EF%BC%8C%E6%89%80%E4%BB%A5%E5%8F%AB%E5%81%9A%E9%9D%9E%E5%85%AC%E5%B9%B3%E9%94%81%E5%8F%8D%E4%B9%8B%E5%88%99%E6%98%AF%E5%85%AC%E5%B9%B3%E9%94%81.%0A%0A%23%23%23%202.1%20%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%0A%60%60%60java%0Aprivate%20final%20Sync%20sync%3B%20%20%2F%2F%E5%86%85%E9%83%A8%E7%B1%BB%20%E5%AE%9E%E7%8E%B0%E7%B1%BBAbstractQueuedSynchronized%E6%8A%BD%E8%B1%A1%E7%B1%BB%0A%2F%2F%E9%BB%98%E8%AE%A4%E5%AE%9E%E7%8E%B0%E6%98%AF%E9%9D%9E%E5%85%AC%E5%B9%B3%E9%94%81%0Apublic%20ReentrantLock()%20%7B%0A%20%20%20%20sync%20%3D%20new%20NonfairSync()%3B%0A%7D%0A%2F%2Ftrue%20%20%E5%85%AC%E5%B9%B3%E9%94%81%20false%20%E9%9D%9E%E5%85%AC%E5%B9%B3%E9%94%81%0Apublic%20ReentrantLock(boolean%20fair)%20%7B%0A%20%20%20%20%20sync%20%3D%20fair%20%3F%20new%20FairSync()%20%3A%20new%20NonfairSync()%3B%0A%7D%0A%2F%2F%E8%8E%B7%E5%8F%96%E9%94%81%20%0Apublic%20void%20lock()%20%7B%0A%20%20%20%20sync.lock()%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%202.1.1%20%E8%8E%B7%E5%8F%96%E9%94%81%0A%23%23%23%23%23%202.1.1.1%20NonfairSync%20%E9%9D%9E%E5%85%AC%E5%B9%B3%E9%94%81%E7%9A%84%E6%A0%B8%E5%BF%83%E5%AE%9E%E7%8E%B0%0A%0A%60%60%60java%0A%2F%2F%E4%B8%AD%E9%97%B4%E6%80%81%E5%8F%98%E9%87%8F%EF%BC%8C%E9%80%9A%E8%BF%87%E6%9B%B4%E6%94%B9state%E7%9A%84%E5%80%BC%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E5%8D%A0%E6%9C%89%E9%94%81%20%20state%3D0%20%E4%BB%A3%E8%A1%A8%E6%97%A0%E7%BA%BF%E7%A8%8B%E5%8D%A0%E7%94%A8%20%0A%2F%2Fstate%20%3E%3D%201%20%E4%BB%A3%E8%A1%A8%E6%9C%89%E9%94%81%20state%20%3D1%20%20%E4%BB%A3%E8%A1%A8%E6%9C%89%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%8D%A0%E7%94%A8%E9%94%81%20state%3D5%E5%81%87%E5%A6%82%E6%98%AF%E9%87%8D%E5%85%A5%E9%94%81%E9%82%A3%E4%B9%88%E4%BB%A3%E8%A1%A8%E8%BF%99%E4%B8%AA%E7%BA%BF%E7%A8%8B%E8%8E%B7%E5%8F%96%E4%BA%865%E6%AC%A1%E9%94%81%EF%BC%8C%E7%9B%B8%E5%BA%94%E7%9A%84%E9%9C%80%E8%A6%81%E9%87%8A%E6%94%BE5%E6%AC%A1%E9%94%81%E4%BD%BF%E5%BE%97state%3D0%E4%BB%8E%E8%80%8C%E8%BE%BE%E5%88%B0%E9%87%8A%E6%94%BE%E7%9A%84%E7%9B%AE%E7%9A%84%E3%80%82%0Aprivate%20volatile%20int%20state%3B%0A%2F%2F%E5%BD%93%E5%89%8D%E5%8D%A0%E6%9C%89%E9%94%81%E7%9A%84%E7%BA%BF%E7%A8%8B%0Aprivate%20transient%20Thread%20exclusiveOwnerThread%3B%0A%2F%2F%E5%B0%9D%E8%AF%95%E8%8E%B7%E5%8F%96%E9%94%81%0Afinal%20void%20lock()%20%7B%0A%20%20%20%20if%20(compareAndSetState(0%2C%201))%0A%20%20%20%20%20%20%20%20setExclusiveOwnerThread(Thread.currentThread())%3B%0A%20%20%20%20else%0A%20%20%20%20%20%20%20%20acquire(1)%3B%0A%7D%0A%60%60%60%0A%0A%3E%20compareAndSetState%20%E9%80%9A%E8%BF%87%E8%B0%83%E7%94%A8unsafe%E7%9A%84%E6%8F%90%E4%BE%9B%E7%9A%84cas%E6%9C%AC%E5%9C%B0%E6%96%B9%E6%B3%95(%E8%B0%83%E7%94%A8c%E8%AF%AD%E8%A8%80)%20%E5%B0%9D%E8%AF%95%E6%8A%8Astate%3D0%E7%9A%84%E5%80%BC%E6%9B%B4%E6%94%B9%E4%B8%BA1%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%88%90%E5%8A%9F%E8%AE%BE%E7%BD%AE%E5%8D%A0%E6%9C%89%E9%94%81%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%B8%BA%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%8E%B7%E5%8F%96%E5%A4%B1%E8%B4%A5%E5%88%99%E8%B0%83%E7%94%A8acquire%E5%B0%9D%E8%AF%95%E8%8E%B7%E5%8F%961%E6%AC%A1%0A%0A%60%60%60java%0Apublic%20final%20void%20acquire(int%20arg)%20%7B%0A%20%20%20%20%2F%2F%E5%B0%9D%E8%AF%95%E8%8E%B7%E5%8F%96%E4%B8%80%E4%B8%AA%E9%94%81%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%A4%B1%E8%B4%A5%E4%BA%86%E6%B7%BB%E5%8A%A0%E7%BA%BF%E7%A8%8B%E5%88%B0%E7%AD%89%E5%BE%85%E7%9A%84%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97%E4%B8%AD%0A%20%20%20%20if%20(!tryAcquire(arg)%20%26%26%20acquireQueued(addWaiter(Node.EXCLUSIVE)%2C%20arg))%7B%0A%20%20%20%20%20%20%20%20selfInterrupt()%3B%0A%20%20%20%20%7D%0A%7D%0A%2F%2F%E5%B0%9D%E8%AF%95%E8%8E%B7%E5%8F%96%E9%94%81%0Aprotected%20final%20boolean%20tryAcquire(int%20acquires)%20%7B%0A%20%20%20%20return%20nonfairTryAcquire(acquires)%3B%0A%7D%0A%0Afinal%20boolean%20nonfairTryAcquire(int%20acquires)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20final%20Thread%20current%20%3D%20Thread.currentThread()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20c%20%3D%20getState()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E6%AD%A4%E5%A4%84%E4%BD%93%E7%8E%B0%E4%BA%86nonfair%E9%9D%9E%E5%85%AC%E5%B9%B3%E7%9A%84%E6%84%8F%E6%80%9D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(c%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E8%AF%B4%E6%98%8E%E5%B7%B2%E7%BB%8F%E6%9C%89%E7%BA%BF%E7%A8%8B%E9%87%8A%E6%94%BE%E4%BA%86%E9%94%81%EF%BC%8C%E9%82%A3%E4%B9%88%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E5%B0%9D%E8%AF%95%E8%8E%B7%E5%8F%96%E4%B8%80%E6%AC%A1%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%8E%B7%E5%8F%96%E6%88%90%E5%8A%9F%E8%BF%94%E5%9B%9Etrue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(compareAndSetState(0%2C%20acquires))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setExclusiveOwnerThread(current)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E6%AC%A1%E6%95%B0%E4%BD%93%E7%8E%B0%E4%BA%86%E9%87%8D%E5%85%A5%E9%94%81%E7%9A%84%E9%80%BB%E8%BE%91%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%A6%82%E6%9E%9C%E8%8E%B7%E5%8F%96%E9%94%81%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%98%AF%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%0A%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(current%20%3D%3D%20getExclusiveOwnerThread())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E8%8E%B7%E5%8F%96%E9%94%81%E7%9A%84%E6%AC%A1%E6%95%B0%2Bacquires%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20int%20nextc%20%3D%20c%20%2B%20acquires%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(nextc%20%3C%200)%20%2F%2F%20overflow%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Error(%22Maximum%20lock%20count%20exceeded%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E8%BF%99%E9%87%8C%E6%97%A0%E9%9C%80cas%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%BF%85%E7%84%B6%E5%B7%B2%E7%BB%8F%E8%8E%B7%E5%8F%96%E9%94%81%E4%BA%86%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setState(nextc)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%3B%0A%7D%0A%60%60%60%0A%0A!%5B98ea3923874c347d3a924eef620d35f1.png%5D(en-resource%3A%2F%2Fdatabase%2F1423%3A1)%0A%0A%0A%23%23%23%23%202.1.2%20%E9%87%8A%E6%94%BE%E9%94%81%0A%3E%20%20%E6%9B%B4%E6%96%B0state%E7%9A%84%E5%80%BC%E5%A6%82%E6%9E%9C%E4%B8%BA0%E5%88%99%E5%94%A4%E9%86%92%E5%90%8E%E7%BB%AD%E8%8A%82%E7%82%B9%0A%0A%60%60%60java%0Apublic%20final%20boolean%20release(int%20arg)%20%7B%20%0A%20%20if%20(tryRelease(arg))%20%7B%20%0A%20%20%20%20%20%20%20%2F%2F%E9%87%8A%E6%94%BE%E9%94%81%E6%88%90%E5%8A%9F%0A%20%20%20%20%20%20Node%20h%20%3D%20head%3B%20%2F%2F%E5%BE%97%E5%88%B0%20aqs%20%E4%B8%AD%20head%20%E8%8A%82%E7%82%B9%0A%20%20%20%20%20%20%20if%20(h%20!%3D%20null%20%26%26%20h.waitStatus%20!%3D%200)%0A%20%20%20%20%20%20%20%20%20%2F%2F%E5%A6%82%E6%9E%9C%20head%20%E8%8A%82%E7%82%B9%E4%B8%8D%20%E4%B8%BA%E7%A9%BA%E5%B9%B6%E4%B8%94%E7%8A%B6%E6%80%81!%3D0.%0A%20%20%20%20%20%20%20%20%20%2F%2F%E8%B0%83%E7%94%A8%20unparkSuccessor(h)%E5%94%A4%E9%86%92%E5%90%8E%E7%BB%AD%E8%8A%82%E7%82%B9%0A%20%20%20%20%20%20%20%20%20%20unparkSuccessor(h)%3B%20%0A%20%20%20%20%20%20return%20true%3B%7Dreturn%20false%3B%7D%0A%60%60%60%0A%3E%20%0A%E9%87%8A%E6%94%BE%E9%94%81%E7%9A%84%E4%B8%9A%E5%8A%A1%E9%80%BB%E8%BE%91%E4%B8%8D%E9%9C%80%E8%A6%81%E8%80%83%E8%99%91%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E4%BB%96%E8%BF%98%E6%98%AF%E8%A2%AB%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%8C%81%E6%9C%89%E3%80%82%E5%9B%A0%E4%B8%BA%E9%87%8D%E5%85%A5%E9%94%81%E7%9A%84%E6%9C%BA%E5%88%B6%E6%98%AF%20state%3E%3D1%20%E9%87%8A%E6%94%BE%E5%B0%B1%E6%98%AF%20getState()%20-%20releases%E5%B9%B6%E6%9B%B4%E6%96%B0state%E4%B8%BA%E6%9C%80%E6%96%B0%E5%80%BC%EF%BC%8C%E5%A6%82%E6%9E%9Cstate%3D0%E5%88%99%E8%BF%94%E5%9B%9E%E3%80%82%0A%0A%60%60%60java%0Aprotected%20final%20boolean%20tryRelease(int%20releases)%20%7B%0A%20%20%20%20int%20c%20%3D%20getState()%20-%20releases%3B%0A%20%20%20%20if%20(Thread.currentThread()%20!%3D%20getExclusiveOwnerThread())%0A%20%20%20%20%20%20%20%20throw%20new%20IllegalMonitorStateException()%3B%0A%20%20%20%20boolean%20free%20%3D%20false%3B%0A%20%20%20%20if%20(c%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20free%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20setExclusiveOwnerThread(null)%3B%0A%20%20%20%20%7D%0A%20%20%20%20setState(c)%3B%0A%20%20%20%20return%20free%3B%7D%0A%60%60%60%0A%0A%0A%23%23%203%20%E6%A1%88%E4%BE%8B%0A%60%60%60java%0Apackage%20com.chris.thread.future.lock%3B%0A%0Aimport%20java.util.concurrent.TimeUnit%3B%0Aimport%20java.util.concurrent.locks.Lock%3B%0Aimport%20java.util.concurrent.locks.ReentrantLock%3B%0A%0Apublic%20class%20ReentrantLockDemo%20%7B%0A%20%20%20%20private%20static%20final%20Lock%20lock%20%3D%20new%20ReentrantLock()%3B%0A%20%20%20%20private%20static%20int%20count%20%3D%200%3B%0A%20%20%20%20private%20static%20void%20inrc()%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E5%8A%A0%E9%94%81%0A%20%20%20%20%20%20%20%20%20%20%20%20lock.lock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Thread.sleep(10)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20count%2B%2B%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread().getName()%20%2B%20%22%2B1%3D%22%20%2B%20count)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E6%A8%A1%E6%8B%9F%E9%87%8D%E5%85%A5%E9%94%81%0A%20%20%20%20%20%20%20%20%20%20%20%20dec()%3B%2F%2F%202%0A%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20lock.unlock()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20private%20static%20void%20dec()%20%7B%0A%20%20%20%20%20%20%20%20lock.lock()%3B%0A%20%20%20%20%20%20%20%20count--%3B%0A%20%20%20%20%20%20%20%20System.out.println(Thread.currentThread().getName()%20%2B%20%22-1%3D%22%20%2B%20count)%3B%0A%20%20%20%20%20%20%20%20lock.unlock()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20new%20Thread(ReentrantLockDemo%3A%3Ainrc).start()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20TimeUnit.SECONDS.sleep(3)%3B%0A%20%20%20%20%20%20%20%20System.out.println(count)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%3E%20%E9%AA%8C%E8%AF%81%E7%BB%93%E6%9E%9C%0A%60%60%60%0AThread-0%2B1%3D1%0AThread-0-1%3D0%0AThread-1%2B1%3D1%0AThread-1-1%3D0%0AThread-2%2B1%3D1%0AThread-2-1%3D0%0AThread-8%2B1%3D1%0AThread-8-1%3D0%0AThread-4%2B1%3D1%0AThread-4-1%3D0%0AThread-5%2B1%3D1%0AThread-5-1%3D0%0AThread-6%2B1%3D1%0AThread-6-1%3D0%0AThread-7%2B1%3D1%0AThread-7-1%3D0%0AThread-3%2B1%3D1%0AThread-3-1%3D0%0AThread-9%2B1%3D1%0AThread-9-1%3D0%0AThread-10%2B1%3D1%0AThread-10-1%3D0%0A0%0A%60%60%60%0A%0A%0A

Condition

创建时间:2023/4/9 7:55
更新时间:2023/4/9 16:37
作者:Chris
来源:https://blog.csdn.net/bbj12345678/article/details/120458357

https://blog.csdn.net/bbj12345678/article/details/120458357

1 Condition是什么

  1. Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作
  2. 相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效
  3. 比较推荐使用Condition,阻塞队列实际上是使用了Condition来模拟线程间协作。
  1. Condition是个接口,基本的方法就是await()和signal()方法;
  2. Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
  3. 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
Conditon中的await() 对应 Object的wait();  
Condition中的signal() 对应 Object的notify();       
Condition中的signalAll() 对应 Object的notifyAll()

2. 工作原理

Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备( signal或者 signalAll方法被带调用)时 ,这些等待线程才会被唤醒,从而重新争夺锁。

3. 案例

3.1 ArrayBlockingQueue

package com.chris.thread.future.lock;

import com.chris.thread.ThreadUtil;
import org.junit.Test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionTest {

    final Lock lock = new ReentrantLock();
    final Condition condition = lock.newCondition();

    @Test
    public void test01() {
        Producer producer = new Producer();
        Consumer consumer1 = new Consumer();
        Consumer consumer2 = new Consumer();
        Consumer consumer3 = new Consumer();

        consumer1.start();
        consumer2.start();
        consumer3.start();
        producer.start();

        ThreadUtil.join(consumer1, consumer2, consumer3, producer);
    }

    class Consumer extends Thread {
        @Override
        public void run() {
            consume();
        }

        private void consume() {

            try {
                lock.lock();
                System.out.println("我在等一个新信号" + currentThread().getName());
                condition.await();

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println("拿到一个信号" + currentThread().getName());
                lock.unlock();
            }

        }
    }

    class Producer extends Thread {

        @Override
        public void run() {
            produce();
        }

        private void produce() {
            try {
                lock.lock();
                System.out.println("我拿到锁" + currentThread().getName());
                condition.signalAll();
                System.out.println("我发出了一个信号:" + currentThread().getName());
            } finally {
                lock.unlock();
            }
        }
    }
}

结果输出

我在等一个新信号Thread-1
我在等一个新信号Thread-2
我在等一个新信号Thread-3
我拿到锁Thread-0
我发出了一个信号:Thread-0
拿到一个信号Thread-1
拿到一个信号Thread-2
拿到一个信号Thread-3

Condition的执行方式,是当前线程在Consumer中调用await方法后,线程Consumer将释放锁,并且将自己放在等待队列中沉睡,等待唤醒,
线程Producer获取到锁后,开始做事,完毕后,调用Condition的signalall方法,唤醒所有的Consume线程,线程Consumer恢复执行。
condition.signalAll() 换成 condition.signal() 只是唤醒第一个被沉睡的线程,其它线程仍然等待被唤醒。

3.2 实现生产者、消费者模式

package com.chris.thread.future.lock;

import com.chris.thread.ThreadUtil;
import org.junit.Test;

import java.util.PriorityQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionTest2 {
    private final int queueSize = 10;
    private final PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
    private final Lock lock = new ReentrantLock();
    private final Condition canConsume = lock.newCondition();
    private final Condition canProduce = lock.newCondition();


    @Test
    public void test() throws InterruptedException {
        ConditionTest2 test = new ConditionTest2();
        Producer producer = test.new Producer();
        Consumer consumer = test.new Consumer();
        producer.start();
        consumer.start();
        Thread.sleep(0);

        ThreadUtil.join(producer, consumer);

       /* producer.interrupt();
        consumer.interrupt();*/
    }

    class Consumer extends Thread {
        @Override
        public void run() {
            consume();
        }

        volatile boolean flag = true;

        private void consume() {
            while (flag) {
                lock.lock();
                try {
                    if (queue.isEmpty()) {
                        try {
                            System.out.println("队列空,等待数据");
                            canConsume.await();
                        } catch (InterruptedException e) {
                            flag = false;
                        }
                    }
                    queue.poll();                // 每次移走队首元素
                    canProduce.signal();
                    System.out.println("从队列取走一个元素,队列剩余" + queue.size() + "个元素");
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    class Producer extends Thread {
        @Override
        public void run() {
            produce();
        }

        volatile boolean flag = true;

        private void produce() {
            while (flag) {
                lock.lock();
                try {
                    if (queue.size() == queueSize) {
                        try {
                            System.out.println("队列满,等待有空余空间");
                            canProduce.await();
                        } catch (InterruptedException e) {
                            flag = false;
                        }
                    }
                    queue.offer(1);        // 每次插入一个元素
                    canConsume.signal();
                    System.out.println("向队列取中插入一个元素,队列剩余空间:" + (queueSize - queue.size()));
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}

%0A%0A%5Btoc%5D%0A%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2Fbbj12345678%2Farticle%2Fdetails%2F120458357%0A%0A%23%23%201%20Condition%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%201.%20%20Condition%E6%98%AF%E5%9C%A8java%201.5%E4%B8%AD%E6%89%8D%E5%87%BA%E7%8E%B0%E7%9A%84%EF%BC%8C%E5%AE%83%E7%94%A8%E6%9D%A5%E6%9B%BF%E4%BB%A3%E4%BC%A0%E7%BB%9F%E7%9A%84Object%E7%9A%84wait()%E3%80%81notify()%E5%AE%9E%E7%8E%B0%E7%BA%BF%E7%A8%8B%E9%97%B4%E7%9A%84%E5%8D%8F%E4%BD%9C%0A%3E%202.%20%E7%9B%B8%E6%AF%94%E4%BD%BF%E7%94%A8Object%E7%9A%84wait()%E3%80%81notify()%EF%BC%8C%E4%BD%BF%E7%94%A8Condition%E7%9A%84await()%E3%80%81signal()%E8%BF%99%E7%A7%8D%E6%96%B9%E5%BC%8F%E5%AE%9E%E7%8E%B0%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%8D%8F%E4%BD%9C%60%E6%9B%B4%E5%8A%A0%E5%AE%89%E5%85%A8%E5%92%8C%E9%AB%98%E6%95%88%60%E3%80%82%0A%3E%203.%20%E6%AF%94%E8%BE%83%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8Condition%EF%BC%8C%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97%E5%AE%9E%E9%99%85%E4%B8%8A%E6%98%AF%E4%BD%BF%E7%94%A8%E4%BA%86Condition%E6%9D%A5%E6%A8%A1%E6%8B%9F%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%8D%8F%E4%BD%9C%E3%80%82%0A%0A%0A%0A%3E%201.%20Condition%E6%98%AF%E4%B8%AA%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%9F%BA%E6%9C%AC%E7%9A%84%E6%96%B9%E6%B3%95%E5%B0%B1%E6%98%AFawait()%E5%92%8Csignal()%E6%96%B9%E6%B3%95%EF%BC%9B%0A%3E%202.%20Condition%E4%BE%9D%E8%B5%96%E4%BA%8ELock%E6%8E%A5%E5%8F%A3%EF%BC%8C%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AACondition%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BB%A3%E7%A0%81%E6%98%AFlock.newCondition()%20%0A%3E%203.%20%E8%B0%83%E7%94%A8Condition%E7%9A%84await()%E5%92%8Csignal()%E6%96%B9%E6%B3%95%EF%BC%8C%E9%83%BD%E5%BF%85%E9%A1%BB%E5%9C%A8lock%E4%BF%9D%E6%8A%A4%E4%B9%8B%E5%86%85%EF%BC%8C%E5%B0%B1%E6%98%AF%E8%AF%B4%E5%BF%85%E9%A1%BB%E5%9C%A8lock.lock()%E5%92%8Clock.unlock%E4%B9%8B%E9%97%B4%E6%89%8D%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%0A%0A%60%60%60%0AConditon%E4%B8%AD%E7%9A%84await()%20%E5%AF%B9%E5%BA%94%20Object%E7%9A%84wait()%EF%BC%9B%E3%80%80%E3%80%80%0ACondition%E4%B8%AD%E7%9A%84signal()%20%E5%AF%B9%E5%BA%94%20Object%E7%9A%84notify()%EF%BC%9B%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%0ACondition%E4%B8%AD%E7%9A%84signalAll()%20%E5%AF%B9%E5%BA%94%20Object%E7%9A%84notifyAll()%0A%60%60%60%0A%23%23%202.%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%0A%0A%3E%20Condition%E6%98%AF%E4%B8%80%E4%B8%AA%E5%A4%9A%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%8D%8F%E8%B0%83%E9%80%9A%E4%BF%A1%E7%9A%84%E5%B7%A5%E5%85%B7%E7%B1%BB%EF%BC%8C%E4%BD%BF%E5%BE%97%E6%9F%90%E4%B8%AA%EF%BC%8C%E6%88%96%E8%80%85%E6%9F%90%E4%BA%9B%E7%BA%BF%E7%A8%8B%E4%B8%80%E8%B5%B7%E7%AD%89%E5%BE%85%E6%9F%90%E4%B8%AA%E6%9D%A1%E4%BB%B6%EF%BC%88Condition%EF%BC%89%2C%E5%8F%AA%E6%9C%89%E5%BD%93%E8%AF%A5%E6%9D%A1%E4%BB%B6%E5%85%B7%E5%A4%87(%20signal%E6%88%96%E8%80%85%20signalAll%E6%96%B9%E6%B3%95%E8%A2%AB%E5%B8%A6%E8%B0%83%E7%94%A8)%E6%97%B6%20%EF%BC%8C%E8%BF%99%E4%BA%9B%E7%AD%89%E5%BE%85%E7%BA%BF%E7%A8%8B%E6%89%8D%E4%BC%9A%E8%A2%AB%E5%94%A4%E9%86%92%EF%BC%8C%E4%BB%8E%E8%80%8C%E9%87%8D%E6%96%B0%E4%BA%89%E5%A4%BA%E9%94%81%E3%80%82%0A%0A%0A%0A%23%23%203.%20%E6%A1%88%E4%BE%8B%0A%0A%23%23%23%203.1%20%20%E5%AE%9E%E7%8E%B0%20ArrayBlockingQueue%0A%0A%60%60%60java%0Apackage%20com.chris.thread.future.lock%3B%0A%0Aimport%20com.chris.thread.ThreadUtil%3B%0Aimport%20org.junit.Test%3B%0A%0Aimport%20java.util.concurrent.locks.Condition%3B%0Aimport%20java.util.concurrent.locks.Lock%3B%0Aimport%20java.util.concurrent.locks.ReentrantLock%3B%0A%0Apublic%20class%20ConditionTest%20%7B%0A%0A%20%20%20%20final%20Lock%20lock%20%3D%20new%20ReentrantLock()%3B%0A%20%20%20%20final%20Condition%20condition%20%3D%20lock.newCondition()%3B%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test01()%20%7B%0A%20%20%20%20%20%20%20%20Producer%20producer%20%3D%20new%20Producer()%3B%0A%20%20%20%20%20%20%20%20Consumer%20consumer1%20%3D%20new%20Consumer()%3B%0A%20%20%20%20%20%20%20%20Consumer%20consumer2%20%3D%20new%20Consumer()%3B%0A%20%20%20%20%20%20%20%20Consumer%20consumer3%20%3D%20new%20Consumer()%3B%0A%0A%20%20%20%20%20%20%20%20consumer1.start()%3B%0A%20%20%20%20%20%20%20%20consumer2.start()%3B%0A%20%20%20%20%20%20%20%20consumer3.start()%3B%0A%20%20%20%20%20%20%20%20producer.start()%3B%0A%0A%20%20%20%20%20%20%20%20ThreadUtil.join(consumer1%2C%20consumer2%2C%20consumer3%2C%20producer)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Consumer%20extends%20Thread%20%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20consume()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20private%20void%20consume()%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lock.lock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E6%88%91%E5%9C%A8%E7%AD%89%E4%B8%80%E4%B8%AA%E6%96%B0%E4%BF%A1%E5%8F%B7%22%20%2B%20currentThread().getName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20condition.await()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E6%8B%BF%E5%88%B0%E4%B8%80%E4%B8%AA%E4%BF%A1%E5%8F%B7%22%20%2B%20currentThread().getName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lock.unlock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Producer%20extends%20Thread%20%7B%0A%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20produce()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20private%20void%20produce()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lock.lock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E6%88%91%E6%8B%BF%E5%88%B0%E9%94%81%22%20%2B%20currentThread().getName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20condition.signalAll()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E6%88%91%E5%8F%91%E5%87%BA%E4%BA%86%E4%B8%80%E4%B8%AA%E4%BF%A1%E5%8F%B7%EF%BC%9A%22%20%2B%20currentThread().getName())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lock.unlock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%20%E7%BB%93%E6%9E%9C%E8%BE%93%E5%87%BA%0A%60%60%60%0A%E6%88%91%E5%9C%A8%E7%AD%89%E4%B8%80%E4%B8%AA%E6%96%B0%E4%BF%A1%E5%8F%B7Thread-1%0A%E6%88%91%E5%9C%A8%E7%AD%89%E4%B8%80%E4%B8%AA%E6%96%B0%E4%BF%A1%E5%8F%B7Thread-2%0A%E6%88%91%E5%9C%A8%E7%AD%89%E4%B8%80%E4%B8%AA%E6%96%B0%E4%BF%A1%E5%8F%B7Thread-3%0A%E6%88%91%E6%8B%BF%E5%88%B0%E9%94%81Thread-0%0A%E6%88%91%E5%8F%91%E5%87%BA%E4%BA%86%E4%B8%80%E4%B8%AA%E4%BF%A1%E5%8F%B7%EF%BC%9AThread-0%0A%E6%8B%BF%E5%88%B0%E4%B8%80%E4%B8%AA%E4%BF%A1%E5%8F%B7Thread-1%0A%E6%8B%BF%E5%88%B0%E4%B8%80%E4%B8%AA%E4%BF%A1%E5%8F%B7Thread-2%0A%E6%8B%BF%E5%88%B0%E4%B8%80%E4%B8%AA%E4%BF%A1%E5%8F%B7Thread-3%0A%60%60%60%0A%0A%3E%20Condition%E7%9A%84%E6%89%A7%E8%A1%8C%E6%96%B9%E5%BC%8F%EF%BC%8C%E6%98%AF%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E5%9C%A8Consumer%E4%B8%AD%E8%B0%83%E7%94%A8await%E6%96%B9%E6%B3%95%E5%90%8E%EF%BC%8C%E7%BA%BF%E7%A8%8BConsumer%E5%B0%86%E9%87%8A%E6%94%BE%E9%94%81%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%B0%86%E8%87%AA%E5%B7%B1%E6%94%BE%E5%9C%A8%E7%AD%89%E5%BE%85%E9%98%9F%E5%88%97%E4%B8%AD%E6%B2%89%E7%9D%A1%EF%BC%8C%E7%AD%89%E5%BE%85%E5%94%A4%E9%86%92%EF%BC%8C%0A%3E%20%E7%BA%BF%E7%A8%8BProducer%E8%8E%B7%E5%8F%96%E5%88%B0%E9%94%81%E5%90%8E%EF%BC%8C%E5%BC%80%E5%A7%8B%E5%81%9A%E4%BA%8B%EF%BC%8C%E5%AE%8C%E6%AF%95%E5%90%8E%EF%BC%8C%E8%B0%83%E7%94%A8Condition%E7%9A%84signalall%E6%96%B9%E6%B3%95%EF%BC%8C%E5%94%A4%E9%86%92%E6%89%80%E6%9C%89%E7%9A%84Consume%E7%BA%BF%E7%A8%8B%EF%BC%8C%E7%BA%BF%E7%A8%8BConsumer%E6%81%A2%E5%A4%8D%E6%89%A7%E8%A1%8C%E3%80%82%0A%3E%20%60condition.signalAll()%60%20%E6%8D%A2%E6%88%90%20%20%60condition.signal()%60%20%E5%8F%AA%E6%98%AF%E5%94%A4%E9%86%92%E7%AC%AC%E4%B8%80%E4%B8%AA%E8%A2%AB%E6%B2%89%E7%9D%A1%E7%9A%84%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%85%B6%E5%AE%83%E7%BA%BF%E7%A8%8B%E4%BB%8D%E7%84%B6%E7%AD%89%E5%BE%85%E8%A2%AB%E5%94%A4%E9%86%92%E3%80%82%0A%0A%0A%23%23%23%203.2%20%E5%AE%9E%E7%8E%B0%E7%94%9F%E4%BA%A7%E8%80%85%E3%80%81%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%BC%8F%0A%60%60%60java%0Apackage%20com.chris.thread.future.lock%3B%0A%0Aimport%20com.chris.thread.ThreadUtil%3B%0Aimport%20org.junit.Test%3B%0A%0Aimport%20java.util.PriorityQueue%3B%0Aimport%20java.util.concurrent.TimeUnit%3B%0Aimport%20java.util.concurrent.locks.Condition%3B%0Aimport%20java.util.concurrent.locks.Lock%3B%0Aimport%20java.util.concurrent.locks.ReentrantLock%3B%0A%0Apublic%20class%20ConditionTest2%20%7B%0A%20%20%20%20private%20final%20int%20queueSize%20%3D%2010%3B%0A%20%20%20%20private%20final%20PriorityQueue%3CInteger%3E%20queue%20%3D%20new%20PriorityQueue%3CInteger%3E(queueSize)%3B%0A%20%20%20%20private%20final%20Lock%20lock%20%3D%20new%20ReentrantLock()%3B%0A%20%20%20%20private%20final%20Condition%20canConsume%20%3D%20lock.newCondition()%3B%0A%20%20%20%20private%20final%20Condition%20canProduce%20%3D%20lock.newCondition()%3B%0A%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test()%20throws%20InterruptedException%20%7B%0A%20%20%20%20%20%20%20%20ConditionTest2%20test%20%3D%20new%20ConditionTest2()%3B%0A%20%20%20%20%20%20%20%20Producer%20producer%20%3D%20test.new%20Producer()%3B%0A%20%20%20%20%20%20%20%20Consumer%20consumer%20%3D%20test.new%20Consumer()%3B%0A%20%20%20%20%20%20%20%20producer.start()%3B%0A%20%20%20%20%20%20%20%20consumer.start()%3B%0A%20%20%20%20%20%20%20%20Thread.sleep(0)%3B%0A%0A%20%20%20%20%20%20%20%20ThreadUtil.join(producer%2C%20consumer)%3B%0A%0A%20%20%20%20%20%20%20%2F*%20producer.interrupt()%3B%0A%20%20%20%20%20%20%20%20consumer.interrupt()%3B*%2F%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Consumer%20extends%20Thread%20%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20consume()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20volatile%20boolean%20flag%20%3D%20true%3B%0A%0A%20%20%20%20%20%20%20%20private%20void%20consume()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20while%20(flag)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lock.lock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(queue.isEmpty())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E9%98%9F%E5%88%97%E7%A9%BA%EF%BC%8C%E7%AD%89%E5%BE%85%E6%95%B0%E6%8D%AE%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canConsume.await()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20flag%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20queue.poll()%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%E6%AF%8F%E6%AC%A1%E7%A7%BB%E8%B5%B0%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canProduce.signal()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E4%BB%8E%E9%98%9F%E5%88%97%E5%8F%96%E8%B5%B0%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%EF%BC%8C%E9%98%9F%E5%88%97%E5%89%A9%E4%BD%99%22%20%2B%20queue.size()%20%2B%20%22%E4%B8%AA%E5%85%83%E7%B4%A0%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lock.unlock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Producer%20extends%20Thread%20%7B%0A%20%20%20%20%20%20%20%20%40Override%0A%20%20%20%20%20%20%20%20public%20void%20run()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20produce()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20volatile%20boolean%20flag%20%3D%20true%3B%0A%0A%20%20%20%20%20%20%20%20private%20void%20produce()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20while%20(flag)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lock.lock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(queue.size()%20%3D%3D%20queueSize)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E9%98%9F%E5%88%97%E6%BB%A1%EF%BC%8C%E7%AD%89%E5%BE%85%E6%9C%89%E7%A9%BA%E4%BD%99%E7%A9%BA%E9%97%B4%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canProduce.await()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(InterruptedException%20e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20flag%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20queue.offer(1)%3B%20%20%20%20%20%20%20%20%2F%2F%20%E6%AF%8F%E6%AC%A1%E6%8F%92%E5%85%A5%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canConsume.signal()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22%E5%90%91%E9%98%9F%E5%88%97%E5%8F%96%E4%B8%AD%E6%8F%92%E5%85%A5%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%EF%BC%8C%E9%98%9F%E5%88%97%E5%89%A9%E4%BD%99%E7%A9%BA%E9%97%B4%EF%BC%9A%22%20%2B%20(queueSize%20-%20queue.size()))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20finally%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lock.unlock()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%0A%60%60%60

accessibility

创建时间:2023/6/3 15:08
更新时间:2023/6/3 15:09
作者:Chris

https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

%0Ahttps%3A%2F%2Fdocs.oracle.com%2Fjavase%2Ftutorial%2Fjava%2FjavaOO%2Faccesscontrol.html%0A%0A%0A!%5Bbbf1a55d035af92cdefbd4c5dd271cf5.png%5D(en-resource%3A%2F%2Fdatabase%2F1447%3A1)%0A

spring cache

创建时间:2023/8/6 10:48
更新时间:2023/8/6 12:45
作者:Chris

1. 引言

Spring框架从4.1版本开始引入了缓存管理的支持,大大简化了在应用中集成缓存的过程

https://docs.spring.io/spring-framework/reference/integration/cache.html

https://blog.csdn.net/weixin_38972910/article/details/123275894

2. 缓存的基本概念

常见的缓存方案包括内存缓存、分布式缓存以及数据库缓存等

在Spring框架中,主要关注内存缓存的使用,Spring提供了对常见的内存缓存框架的集成支持,如Ehcache、Caffeine等

3. 使用Spring框架进行缓存管理

Spring框架通过提供缓存注解和配置来简化缓存操作。

可以通过在方法上添加缓存注解的方式来启用缓存功能,并可以根据需求配置不同的缓存策略和缓存管理器。

3.1 注解驱动的缓存

Spring提供了多个缓存注解,包括@Cacheable@CachePut@CacheEvict等。这些注解可以用于标记需要进行缓存操作的方法,并可以指定缓存的Key以及缓存的策略等。

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id")
    public User getUserById(String id) {
        // 查询数据库或其他操作
        return user;
    }

    @CachePut(value = "users", key = "#user.id")
    public User saveUser(User user) {
        // 保存用户到数据库或其他操作
        return user;
    }

    @CacheEvict(value = "users", key = "#id")
    public void deleteUserById(String id) {
        // 删除用户
    }
}
  1. @Cacheable注解用于标记getUserById方法,表示该方法的返回结果会被缓存起来,并且使用参数 id 作为缓存的Key。

  2. @CachePut注解用于标记saveUser方法,表示该方法的返回结果会被缓存起来或更新已存在的缓存。

  3. @CacheEvict注解用于标记deleteUserById方法,表示该方法会删除缓存中的相关数据。

3.2 缓存配置

除了在方法上使用缓存注解,我们还可以通过配置文件来进行缓存的配置。Spring提供了CacheManager接口和多个实现类,用于指定缓存的配置、策略以及缓存管理器的选择。

<bean >
    <property name="cacheManager" ref="ehcache"/>
</bean>

<bean >
    <property name="configLocation" value="classpath:ehcache.xml"/>
</bean>

在上述配置中,我们通过EhCacheCacheManager类来定义缓存管理器,同时指定了ehcache.xml作为Ehcache的配置文件。

4. 注解

4.1 @Cacheable

@Cacheable可以标记在一个方法上,也可以标记在一个类上。

当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。

对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。

Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略

需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。

@Cacheable可以指定三个属性,value、key和 condition。

4.1.1 value

value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。

@Cacheable(“cache1”)//Cache是发生在cache1上的
public User find(Integer id) {
	return null;
}
 
@Cacheable({“cache1”, “cache2”})//Cache是发生在cache1和cache2上的
public User find(Integer id) {
   return null;
}

4.1.2 key

key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key.

自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用 方法参数 及它们对应的属性。

使用方法参数时我们可以直接使用 “#参数名”或者“#p参数index” 。下面是几个使用参数作为key的示例。 r

@Cacheable(value=”users”, key=”#id”)
public User find(Integer id) {
	return null;
}
 
@Cacheable(value=”users”, key=”#p0”)
public User find(Integer id) {
	return null;
}
 
@Cacheable(value=”users”, key=”#user.id”)
public User find(User user) {
	return null;
}
 
@Cacheable(value=”users”, key=”#p0.id”)
public User find(User user) {
	return null;
}

除了上述使用方法参数作为key之外,Spring还为我们提供了一个root对象可以用来生成key。通过该root对象我们可以获取到以下信息。

属性名称描述示例
methodName当前方法名#root.methodName
method当前方法#root.method.name
target当前被调用的对象#root.target
targetClass当前被调用的对象的class#root.targetClass
args当前方法参数组成的数组#root.args[0]
caches当前被调用的方法使用的Cache#root.caches[0].name

当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。如:

@Cacheable(value={“users”, “xxx”}, key=”caches[1].name”)
public User find(User user) {
      return null;
}

1.2.3 condition

有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下示例表示只有当user的id为偶数时才会进行缓存。

@Cacheable(value={“users”}, key=”#user.id”, condition=”#user.id%2==0”)
public User find(User user) {
	System.out.println(“find user by user “ + user);
	return user;
}

4.2 @CachePut

@CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的

在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。

@CachePut也可以声明一个方法支持缓存功能。

与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

4.3@CacheEvict

@CacheEvict是用来标注在需要清除缓存元素的方法或类上的。

当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。

@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。

下面我们来介绍一下新出现的两个属性allEntries和beforeInvocation。

4.3.1 allEntries属性

allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。

当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。

@CacheEvict(value=”users”, allEntries=true)
public void delete(Integer id) {
   System.out.println(“delete user by id: “ + id);
}

4.3.2 beforeInvocation属性

清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。

使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

@CacheEvict(value=”users”, beforeInvocation=true)
public void delete(Integer id) {
      System.out.println(“delete user by id: “ + id);
 }

4.4 @Caching

  @Caching(cacheable = @Cacheable(“users”), 
    		  evict = { @CacheEvict(“cache2”),@CacheEvict(value = “cache3”, allEntries = true) })
   public User find(Integer id) {undefined
      returnnull;
   }

5. 使用

5.1 加入依赖

        <!-- SpringBoot WEB框架 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!--开启 cache 缓存 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
		</dependency>

5.2 启动类中加入注解开启缓存

@EnableCaching
%5Btoc%5D%0A%0A%23%23%201.%20%E5%BC%95%E8%A8%80%0A%0ASpring%E6%A1%86%E6%9E%B6%E4%BB%8E4.1%E7%89%88%E6%9C%AC%E5%BC%80%E5%A7%8B%E5%BC%95%E5%85%A5%E4%BA%86%E7%BC%93%E5%AD%98%E7%AE%A1%E7%90%86%E7%9A%84%E6%94%AF%E6%8C%81%EF%BC%8C%E5%A4%A7%E5%A4%A7%E7%AE%80%E5%8C%96%E4%BA%86%E5%9C%A8%E5%BA%94%E7%94%A8%E4%B8%AD%E9%9B%86%E6%88%90%E7%BC%93%E5%AD%98%E7%9A%84%E8%BF%87%E7%A8%8B%0A%0Ahttps%3A%2F%2Fdocs.spring.io%2Fspring-framework%2Freference%2Fintegration%2Fcache.html%0A%0Ahttps%3A%2F%2Fblog.csdn.net%2Fweixin_38972910%2Farticle%2Fdetails%2F123275894%0A%0A%0A%23%23%202.%20%E7%BC%93%E5%AD%98%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%0A%0A%E5%B8%B8%E8%A7%81%E7%9A%84%E7%BC%93%E5%AD%98%E6%96%B9%E6%A1%88%E5%8C%85%E6%8B%AC%E5%86%85%E5%AD%98%E7%BC%93%E5%AD%98%E3%80%81%5B%E5%88%86%E5%B8%83%E5%BC%8F%E7%BC%93%E5%AD%98%5D(https%3A%2F%2Fso.csdn.net%2Fso%2Fsearch%3Fq%3D%E5%88%86%E5%B8%83%E5%BC%8F%E7%BC%93%E5%AD%98%26spm%3D1001.2101.3001.7020)%E4%BB%A5%E5%8F%8A%E6%95%B0%E6%8D%AE%E5%BA%93%E7%BC%93%E5%AD%98%E7%AD%89%0A%0A%E5%9C%A8Spring%E6%A1%86%E6%9E%B6%E4%B8%AD%EF%BC%8C%E4%B8%BB%E8%A6%81%E5%85%B3%E6%B3%A8%E5%86%85%E5%AD%98%E7%BC%93%E5%AD%98%E7%9A%84%E4%BD%BF%E7%94%A8%EF%BC%8CSpring%E6%8F%90%E4%BE%9B%E4%BA%86%E5%AF%B9%E5%B8%B8%E8%A7%81%E7%9A%84%E5%86%85%E5%AD%98%E7%BC%93%E5%AD%98%E6%A1%86%E6%9E%B6%E7%9A%84%E9%9B%86%E6%88%90%E6%94%AF%E6%8C%81%EF%BC%8C%E5%A6%82Ehcache%E3%80%81Caffeine%E7%AD%89%0A%0A%0A%23%23%203.%20%E4%BD%BF%E7%94%A8Spring%E6%A1%86%E6%9E%B6%E8%BF%9B%E8%A1%8C%E7%BC%93%E5%AD%98%E7%AE%A1%E7%90%86%0A%0ASpring%E6%A1%86%E6%9E%B6%E9%80%9A%E8%BF%87%E6%8F%90%E4%BE%9B%E7%BC%93%E5%AD%98%E6%B3%A8%E8%A7%A3%E5%92%8C%E9%85%8D%E7%BD%AE%E6%9D%A5%E7%AE%80%E5%8C%96%E7%BC%93%E5%AD%98%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%8A%E6%B7%BB%E5%8A%A0%E7%BC%93%E5%AD%98%E6%B3%A8%E8%A7%A3%E7%9A%84%E6%96%B9%E5%BC%8F%E6%9D%A5%E5%90%AF%E7%94%A8%E7%BC%93%E5%AD%98%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%B9%B6%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E9%9C%80%E6%B1%82%E9%85%8D%E7%BD%AE%E4%B8%8D%E5%90%8C%E7%9A%84%E7%BC%93%E5%AD%98%E7%AD%96%E7%95%A5%E5%92%8C%E7%BC%93%E5%AD%98%E7%AE%A1%E7%90%86%E5%99%A8%E3%80%82%0A%0A%0A%23%23%23%203.1%20%E6%B3%A8%E8%A7%A3%E9%A9%B1%E5%8A%A8%E7%9A%84%E7%BC%93%E5%AD%98%0A%0ASpring%E6%8F%90%E4%BE%9B%E4%BA%86%E5%A4%9A%E4%B8%AA%E7%BC%93%E5%AD%98%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%8C%85%E6%8B%AC%60%40Cacheable%60%E3%80%81%60%40CachePut%60%E3%80%81%60%40CacheEvict%60%E7%AD%89%E3%80%82%E8%BF%99%E4%BA%9B%E6%B3%A8%E8%A7%A3%E5%8F%AF%E4%BB%A5%E7%94%A8%E4%BA%8E%E6%A0%87%E8%AE%B0%E9%9C%80%E8%A6%81%E8%BF%9B%E8%A1%8C%E7%BC%93%E5%AD%98%E6%93%8D%E4%BD%9C%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%B9%B6%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E7%BC%93%E5%AD%98%E7%9A%84Key%E4%BB%A5%E5%8F%8A%E7%BC%93%E5%AD%98%E7%9A%84%E7%AD%96%E7%95%A5%E7%AD%89%E3%80%82%0A%0A%60%60%60java%0A%40Service%0Apublic%20class%20UserService%20%7B%0A%0A%20%20%20%20%40Cacheable(value%20%3D%20%22users%22%2C%20key%20%3D%20%22%23id%22)%0A%20%20%20%20public%20User%20getUserById(String%20id)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%BA%93%E6%88%96%E5%85%B6%E4%BB%96%E6%93%8D%E4%BD%9C%0A%20%20%20%20%20%20%20%20return%20user%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40CachePut(value%20%3D%20%22users%22%2C%20key%20%3D%20%22%23user.id%22)%0A%20%20%20%20public%20User%20saveUser(User%20user)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E4%BF%9D%E5%AD%98%E7%94%A8%E6%88%B7%E5%88%B0%E6%95%B0%E6%8D%AE%E5%BA%93%E6%88%96%E5%85%B6%E4%BB%96%E6%93%8D%E4%BD%9C%0A%20%20%20%20%20%20%20%20return%20user%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40CacheEvict(value%20%3D%20%22users%22%2C%20key%20%3D%20%22%23id%22)%0A%20%20%20%20public%20void%20deleteUserById(String%20id)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E5%88%A0%E9%99%A4%E7%94%A8%E6%88%B7%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%3E%201.%20%40Cacheable%E6%B3%A8%E8%A7%A3%E7%94%A8%E4%BA%8E%E6%A0%87%E8%AE%B0getUserById%E6%96%B9%E6%B3%95%EF%BC%8C%E8%A1%A8%E7%A4%BA%E8%AF%A5%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E4%BC%9A%E8%A2%AB%E7%BC%93%E5%AD%98%E8%B5%B7%E6%9D%A5%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BD%BF%E7%94%A8%E5%8F%82%E6%95%B0%20id%20%E4%BD%9C%E4%B8%BA%E7%BC%93%E5%AD%98%E7%9A%84Key%E3%80%82%0A%3E%0A%3E%202.%20%40CachePut%E6%B3%A8%E8%A7%A3%E7%94%A8%E4%BA%8E%E6%A0%87%E8%AE%B0saveUser%E6%96%B9%E6%B3%95%EF%BC%8C%E8%A1%A8%E7%A4%BA%E8%AF%A5%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E4%BC%9A%E8%A2%AB%E7%BC%93%E5%AD%98%E8%B5%B7%E6%9D%A5%E6%88%96%E6%9B%B4%E6%96%B0%E5%B7%B2%E5%AD%98%E5%9C%A8%E7%9A%84%E7%BC%93%E5%AD%98%E3%80%82%0A%3E%0A%3E%203.%20%40CacheEvict%E6%B3%A8%E8%A7%A3%E7%94%A8%E4%BA%8E%E6%A0%87%E8%AE%B0deleteUserById%E6%96%B9%E6%B3%95%EF%BC%8C%E8%A1%A8%E7%A4%BA%E8%AF%A5%E6%96%B9%E6%B3%95%E4%BC%9A%E5%88%A0%E9%99%A4%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84%E7%9B%B8%E5%85%B3%E6%95%B0%E6%8D%AE%E3%80%82%0A%3E%20%20%20%20%0A%0A%23%23%23%203.2%20%E7%BC%93%E5%AD%98%E9%85%8D%E7%BD%AE%0A%0A%E9%99%A4%E4%BA%86%E5%9C%A8%E6%96%B9%E6%B3%95%E4%B8%8A%E4%BD%BF%E7%94%A8%E7%BC%93%E5%AD%98%E6%B3%A8%E8%A7%A3%EF%BC%8C%E6%88%91%E4%BB%AC%E8%BF%98%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E6%9D%A5%E8%BF%9B%E8%A1%8C%E7%BC%93%E5%AD%98%E7%9A%84%E9%85%8D%E7%BD%AE%E3%80%82Spring%E6%8F%90%E4%BE%9B%E4%BA%86%60CacheManager%60%E6%8E%A5%E5%8F%A3%E5%92%8C%E5%A4%9A%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%B1%BB%EF%BC%8C%E7%94%A8%E4%BA%8E%E6%8C%87%E5%AE%9A%E7%BC%93%E5%AD%98%E7%9A%84%E9%85%8D%E7%BD%AE%E3%80%81%E7%AD%96%E7%95%A5%E4%BB%A5%E5%8F%8A%E7%BC%93%E5%AD%98%E7%AE%A1%E7%90%86%E5%99%A8%E7%9A%84%E9%80%89%E6%8B%A9%E3%80%82%0A%0A%60%60%60java%0A%3Cbean%20id%3D%22cacheManager%22%20class%3D%22org.springframework.cache.ehcache.EhCacheCacheManager%22%3E%0A%20%20%20%20%3Cproperty%20name%3D%22cacheManager%22%20ref%3D%22ehcache%22%2F%3E%0A%3C%2Fbean%3E%0A%0A%3Cbean%20id%3D%22ehcache%22%20class%3D%22org.springframework.cache.ehcache.EhCacheManagerFactoryBean%22%3E%0A%20%20%20%20%3Cproperty%20name%3D%22configLocation%22%20value%3D%22classpath%3Aehcache.xml%22%2F%3E%0A%3C%2Fbean%3E%0A%60%60%60%0A%0A%E5%9C%A8%E4%B8%8A%E8%BF%B0%E9%85%8D%E7%BD%AE%E4%B8%AD%EF%BC%8C%E6%88%91%E4%BB%AC%E9%80%9A%E8%BF%87%60EhCacheCacheManager%60%E7%B1%BB%E6%9D%A5%E5%AE%9A%E4%B9%89%E7%BC%93%E5%AD%98%E7%AE%A1%E7%90%86%E5%99%A8%EF%BC%8C%E5%90%8C%E6%97%B6%E6%8C%87%E5%AE%9A%E4%BA%86%60ehcache.xml%60%E4%BD%9C%E4%B8%BAEhcache%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E3%80%82%0A%0A%0A%0A%23%23%204.%20%E6%B3%A8%E8%A7%A3%0A%0A%23%23%23%204.1%20%40Cacheable%0A%0A%3E%20%40Cacheable%E5%8F%AF%E4%BB%A5%E6%A0%87%E8%AE%B0%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%E4%B8%8A%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%A0%87%E8%AE%B0%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%8A%E3%80%82%0A%3E%0A%3E%20%E5%BD%93%E6%A0%87%E8%AE%B0%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%E4%B8%8A%E6%97%B6%E8%A1%A8%E7%A4%BA%E8%AF%A5%E6%96%B9%E6%B3%95%E6%98%AF%E6%94%AF%E6%8C%81%E7%BC%93%E5%AD%98%E7%9A%84%EF%BC%8C%E5%BD%93%E6%A0%87%E8%AE%B0%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%8A%E6%97%B6%E5%88%99%E8%A1%A8%E7%A4%BA%E8%AF%A5%E7%B1%BB%E6%89%80%E6%9C%89%E7%9A%84%E6%96%B9%E6%B3%95%E9%83%BD%E6%98%AF%E6%94%AF%E6%8C%81%E7%BC%93%E5%AD%98%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%E5%AF%B9%E4%BA%8E%E4%B8%80%E4%B8%AA%E6%94%AF%E6%8C%81%E7%BC%93%E5%AD%98%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8CSpring%E4%BC%9A%E5%9C%A8%E5%85%B6%E8%A2%AB%E8%B0%83%E7%94%A8%E5%90%8E%E5%B0%86%E5%85%B6%E8%BF%94%E5%9B%9E%E5%80%BC%E7%BC%93%E5%AD%98%E8%B5%B7%E6%9D%A5%EF%BC%8C%E4%BB%A5%E4%BF%9D%E8%AF%81%E4%B8%8B%E6%AC%A1%E5%88%A9%E7%94%A8%E5%90%8C%E6%A0%B7%E7%9A%84%E5%8F%82%E6%95%B0%E6%9D%A5%E6%89%A7%E8%A1%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E6%97%B6%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E4%BB%8E%E7%BC%93%E5%AD%98%E4%B8%AD%E8%8E%B7%E5%8F%96%E7%BB%93%E6%9E%9C%EF%BC%8C%E8%80%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E5%86%8D%E6%AC%A1%E6%89%A7%E8%A1%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E3%80%82%0A%3E%0A%3E%20Spring%E5%9C%A8%E7%BC%93%E5%AD%98%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E6%97%B6%E6%98%AF%E4%BB%A5%E9%94%AE%E5%80%BC%E5%AF%B9%E8%BF%9B%E8%A1%8C%E7%BC%93%E5%AD%98%E7%9A%84%EF%BC%8C%E5%80%BC%E5%B0%B1%E6%98%AF%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%EF%BC%8C%E8%87%B3%E4%BA%8E%E9%94%AE%E7%9A%84%E8%AF%9D%EF%BC%8CSpring%E5%8F%88%E6%94%AF%E6%8C%81%E4%B8%A4%E7%A7%8D%E7%AD%96%E7%95%A5%EF%BC%8C%60%E9%BB%98%E8%AE%A4%E7%AD%96%E7%95%A5%E5%92%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%AD%96%E7%95%A5%60%E3%80%82%0A%3E%0A%3E%20%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%E5%BD%93%E4%B8%80%E4%B8%AA%E6%94%AF%E6%8C%81%E7%BC%93%E5%AD%98%E7%9A%84%E6%96%B9%E6%B3%95%E5%9C%A8%E5%AF%B9%E8%B1%A1%E5%86%85%E9%83%A8%E8%A2%AB%E8%B0%83%E7%94%A8%E6%97%B6%E6%98%AF%E4%B8%8D%E4%BC%9A%E8%A7%A6%E5%8F%91%E7%BC%93%E5%AD%98%E5%8A%9F%E8%83%BD%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%40Cacheable%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E4%B8%89%E4%B8%AA%E5%B1%9E%E6%80%A7%EF%BC%8Cvalue%E3%80%81key%E5%92%8C%20condition%E3%80%82%0A%0A%23%23%23%23%204.1.1%20value%0A%0A%3E%20value%E5%B1%9E%E6%80%A7%E6%98%AF%E5%BF%85%E9%A1%BB%E6%8C%87%E5%AE%9A%E7%9A%84%EF%BC%8C%E5%85%B6%E8%A1%A8%E7%A4%BA%E5%BD%93%E5%89%8D%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC%E6%98%AF%E4%BC%9A%E8%A2%AB%E7%BC%93%E5%AD%98%E5%9C%A8%E5%93%AA%E4%B8%AACache%E4%B8%8A%E7%9A%84%EF%BC%8C%E5%AF%B9%E5%BA%94Cache%E7%9A%84%E5%90%8D%E7%A7%B0%E3%80%82%E5%85%B6%E5%8F%AF%E4%BB%A5%E6%98%AF%E4%B8%80%E4%B8%AACache%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%A4%9A%E4%B8%AACache%EF%BC%8C%E5%BD%93%E9%9C%80%E8%A6%81%E6%8C%87%E5%AE%9A%E5%A4%9A%E4%B8%AACache%E6%97%B6%E5%85%B6%E6%98%AF%E4%B8%80%E4%B8%AA%E6%95%B0%E7%BB%84%E3%80%82%0A%0A%60%60%60java%0A%40Cacheable(%E2%80%9Ccache1%E2%80%9D)%2F%2FCache%E6%98%AF%E5%8F%91%E7%94%9F%E5%9C%A8cache1%E4%B8%8A%E7%9A%84%0Apublic%20User%20find(Integer%20id)%20%7B%0A%09return%20null%3B%0A%7D%0A%20%0A%40Cacheable(%7B%E2%80%9Ccache1%E2%80%9D%2C%20%E2%80%9Ccache2%E2%80%9D%7D)%2F%2FCache%E6%98%AF%E5%8F%91%E7%94%9F%E5%9C%A8cache1%E5%92%8Ccache2%E4%B8%8A%E7%9A%84%0Apublic%20User%20find(Integer%20id)%20%7B%0A%20%20%20return%20null%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%204.1.2%20key%0A%0A%3E%20key%E5%B1%9E%E6%80%A7%E6%98%AF%E7%94%A8%E6%9D%A5%E6%8C%87%E5%AE%9ASpring%E7%BC%93%E5%AD%98%E6%96%B9%E6%B3%95%E7%9A%84%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E6%97%B6%E5%AF%B9%E5%BA%94%E7%9A%84key%E7%9A%84%E3%80%82%E8%AF%A5%E5%B1%9E%E6%80%A7%E6%94%AF%E6%8C%81SpringEL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E3%80%82%E5%BD%93%E6%88%91%E4%BB%AC%E6%B2%A1%E6%9C%89%E6%8C%87%E5%AE%9A%E8%AF%A5%E5%B1%9E%E6%80%A7%E6%97%B6%EF%BC%8CSpring%E5%B0%86%E4%BD%BF%E7%94%A8%E9%BB%98%E8%AE%A4%E7%AD%96%E7%95%A5%E7%94%9F%E6%88%90key.%0A%3E%0A%3E%20%E8%87%AA%E5%AE%9A%E4%B9%89%E7%AD%96%E7%95%A5%E6%98%AF%E6%8C%87%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87Spring%E7%9A%84EL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%9D%A5%E6%8C%87%E5%AE%9A%E6%88%91%E4%BB%AC%E7%9A%84key%E3%80%82%E8%BF%99%E9%87%8C%E7%9A%84EL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20**%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0**%20%E5%8F%8A%E5%AE%83%E4%BB%AC%E5%AF%B9%E5%BA%94%E7%9A%84%E5%B1%9E%E6%80%A7%E3%80%82%0A%3E%0A%3E%20%0A%3E%0A%3E%20%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E6%97%B6%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%20**%E2%80%9C%23%E5%8F%82%E6%95%B0%E5%90%8D%E2%80%9D%E6%88%96%E8%80%85%E2%80%9C%23p%E5%8F%82%E6%95%B0index%E2%80%9D**%20%E3%80%82%E4%B8%8B%E9%9D%A2%E6%98%AF%E5%87%A0%E4%B8%AA%E4%BD%BF%E7%94%A8%E5%8F%82%E6%95%B0%E4%BD%9C%E4%B8%BAkey%E7%9A%84%E7%A4%BA%E4%BE%8B%E3%80%82%20%20r%0A%0A%60%60%60java%0A%40Cacheable(value%3D%E2%80%9Dusers%E2%80%9D%2C%20key%3D%E2%80%9D%23id%E2%80%9D)%0Apublic%20User%20find(Integer%20id)%20%7B%0A%09return%20null%3B%0A%7D%0A%20%0A%40Cacheable(value%3D%E2%80%9Dusers%E2%80%9D%2C%20key%3D%E2%80%9D%23p0%E2%80%9D)%0Apublic%20User%20find(Integer%20id)%20%7B%0A%09return%20null%3B%0A%7D%0A%20%0A%40Cacheable(value%3D%E2%80%9Dusers%E2%80%9D%2C%20key%3D%E2%80%9D%23user.id%E2%80%9D)%0Apublic%20User%20find(User%20user)%20%7B%0A%09return%20null%3B%0A%7D%0A%20%0A%40Cacheable(value%3D%E2%80%9Dusers%E2%80%9D%2C%20key%3D%E2%80%9D%23p0.id%E2%80%9D)%0Apublic%20User%20find(User%20user)%20%7B%0A%09return%20null%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%3E%20%E9%99%A4%E4%BA%86%E4%B8%8A%E8%BF%B0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E4%BD%9C%E4%B8%BAkey%E4%B9%8B%E5%A4%96%EF%BC%8CSpring%E8%BF%98%E4%B8%BA%E6%88%91%E4%BB%AC%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E4%B8%AAroot%E5%AF%B9%E8%B1%A1%E5%8F%AF%E4%BB%A5%E7%94%A8%E6%9D%A5%E7%94%9F%E6%88%90key%E3%80%82%E9%80%9A%E8%BF%87%E8%AF%A5root%E5%AF%B9%E8%B1%A1%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%8F%96%E5%88%B0%E4%BB%A5%E4%B8%8B%E4%BF%A1%E6%81%AF%E3%80%82%0A%0A%7C%20%E5%B1%9E%E6%80%A7%E5%90%8D%E7%A7%B0%20%20%20%20%7C%20%E6%8F%8F%E8%BF%B0%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%E7%A4%BA%E4%BE%8B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20-----------%20%7C%20---------------------------%20%7C%20--------------------%20%7C%0A%7C%20methodName%20%20%7C%20%E5%BD%93%E5%89%8D%E6%96%B9%E6%B3%95%E5%90%8D%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%23root.methodName%20%20%20%20%20%7C%0A%7C%20method%20%20%20%20%20%20%7C%20%E5%BD%93%E5%89%8D%E6%96%B9%E6%B3%95%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%23root.method.name%20%20%20%20%7C%0A%7C%20target%20%20%20%20%20%20%7C%20%E5%BD%93%E5%89%8D%E8%A2%AB%E8%B0%83%E7%94%A8%E7%9A%84%E5%AF%B9%E8%B1%A1%20%20%20%20%20%20%20%20%20%20%20%20%7C%20%23root.target%20%20%20%20%20%20%20%20%20%7C%0A%7C%20targetClass%20%7C%20%E5%BD%93%E5%89%8D%E8%A2%AB%E8%B0%83%E7%94%A8%E7%9A%84%E5%AF%B9%E8%B1%A1%E7%9A%84class%20%20%20%20%20%7C%20%23root.targetClass%20%20%20%20%7C%0A%7C%20args%20%20%20%20%20%20%20%20%7C%20%E5%BD%93%E5%89%8D%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E7%BB%84%E6%88%90%E7%9A%84%E6%95%B0%E7%BB%84%20%20%20%20%20%20%7C%20%23root.args%5B0%5D%20%20%20%20%20%20%20%20%7C%0A%7C%20caches%20%20%20%20%20%20%7C%20%E5%BD%93%E5%89%8D%E8%A2%AB%E8%B0%83%E7%94%A8%E7%9A%84%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8%E7%9A%84Cache%20%7C%20%23root.caches%5B0%5D.name%20%7C%0A%0A%3E%20%E5%BD%93%E6%88%91%E4%BB%AC%E8%A6%81%E4%BD%BF%E7%94%A8root%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%B1%9E%E6%80%A7%E4%BD%9C%E4%B8%BAkey%E6%97%B6%E6%88%91%E4%BB%AC%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%B0%86%E2%80%9C%23root%E2%80%9D%E7%9C%81%E7%95%A5%EF%BC%8C%E5%9B%A0%E4%B8%BASpring%E9%BB%98%E8%AE%A4%E4%BD%BF%E7%94%A8%E7%9A%84%E5%B0%B1%E6%98%AFroot%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%B1%9E%E6%80%A7%E3%80%82%E5%A6%82%EF%BC%9A%20%20%0A%0A%60%60%60java%0A%40Cacheable(value%3D%7B%E2%80%9Cusers%E2%80%9D%2C%20%E2%80%9Cxxx%E2%80%9D%7D%2C%20key%3D%E2%80%9Dcaches%5B1%5D.name%E2%80%9D)%0Apublic%20User%20find(User%20user)%20%7B%0A%20%20%20%20%20%20return%20null%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%201.2.3%20condition%0A%3E%20%E6%9C%89%E7%9A%84%E6%97%B6%E5%80%99%E6%88%91%E4%BB%AC%E5%8F%AF%E8%83%BD%E5%B9%B6%E4%B8%8D%E5%B8%8C%E6%9C%9B%E7%BC%93%E5%AD%98%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%E6%89%80%E6%9C%89%E7%9A%84%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E3%80%82%E9%80%9A%E8%BF%87condition%E5%B1%9E%E6%80%A7%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%E8%BF%99%E4%B8%80%E5%8A%9F%E8%83%BD%E3%80%82condition%E5%B1%9E%E6%80%A7%E9%BB%98%E8%AE%A4%E4%B8%BA%E7%A9%BA%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%B0%86%E7%BC%93%E5%AD%98%E6%89%80%E6%9C%89%E7%9A%84%E8%B0%83%E7%94%A8%E6%83%85%E5%BD%A2%E3%80%82%E5%85%B6%E5%80%BC%E6%98%AF%E9%80%9A%E8%BF%87SpringEL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%9D%A5%E6%8C%87%E5%AE%9A%E7%9A%84%EF%BC%8C%E5%BD%93%E4%B8%BAtrue%E6%97%B6%E8%A1%A8%E7%A4%BA%E8%BF%9B%E8%A1%8C%E7%BC%93%E5%AD%98%E5%A4%84%E7%90%86%EF%BC%9B%E5%BD%93%E4%B8%BAfalse%E6%97%B6%E8%A1%A8%E7%A4%BA%E4%B8%8D%E8%BF%9B%E8%A1%8C%E7%BC%93%E5%AD%98%E5%A4%84%E7%90%86%EF%BC%8C%E5%8D%B3%E6%AF%8F%E6%AC%A1%E8%B0%83%E7%94%A8%E8%AF%A5%E6%96%B9%E6%B3%95%E6%97%B6%E8%AF%A5%E6%96%B9%E6%B3%95%E9%83%BD%E4%BC%9A%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%E3%80%82%E5%A6%82%E4%B8%8B%E7%A4%BA%E4%BE%8B%E8%A1%A8%E7%A4%BA%E5%8F%AA%E6%9C%89%E5%BD%93user%E7%9A%84id%E4%B8%BA%E5%81%B6%E6%95%B0%E6%97%B6%E6%89%8D%E4%BC%9A%E8%BF%9B%E8%A1%8C%E7%BC%93%E5%AD%98%E3%80%82%20%20%20%0A%0A%60%60%60java%0A%40Cacheable(value%3D%7B%E2%80%9Cusers%E2%80%9D%7D%2C%20key%3D%E2%80%9D%23user.id%E2%80%9D%2C%20condition%3D%E2%80%9D%23user.id%252%3D%3D0%E2%80%9D)%0Apublic%20User%20find(User%20user)%20%7B%0A%09System.out.println(%E2%80%9Cfind%20user%20by%20user%20%E2%80%9C%20%2B%20user)%3B%0A%09return%20user%3B%0A%7D%0A%60%60%60%0A%0A%0A%23%23%23%204.2%20%40CachePut%0A%0A%3E%20%40CachePut%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%A0%87%E6%B3%A8%E5%9C%A8%E7%B1%BB%E4%B8%8A%E5%92%8C%E6%96%B9%E6%B3%95%E4%B8%8A%E3%80%82%E4%BD%BF%E7%94%A8%40CachePut%E6%97%B6%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E7%9A%84%E5%B1%9E%E6%80%A7%E8%B7%9F%40Cacheable%E6%98%AF%E4%B8%80%E6%A0%B7%E7%9A%84%0A%3E%0A%3E%20%E5%9C%A8%E6%94%AF%E6%8C%81Spring%20Cache%E7%9A%84%E7%8E%AF%E5%A2%83%E4%B8%8B%EF%BC%8C%E5%AF%B9%E4%BA%8E%E4%BD%BF%E7%94%A8%40Cacheable%E6%A0%87%E6%B3%A8%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8CSpring%E5%9C%A8%E6%AF%8F%E6%AC%A1%E6%89%A7%E8%A1%8C%E5%89%8D%E9%83%BD%E4%BC%9A%E6%A3%80%E6%9F%A5Cache%E4%B8%AD%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E7%9B%B8%E5%90%8Ckey%E7%9A%84%E7%BC%93%E5%AD%98%E5%85%83%E7%B4%A0%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%AD%98%E5%9C%A8%E5%B0%B1%E4%B8%8D%E5%86%8D%E6%89%A7%E8%A1%8C%E8%AF%A5%E6%96%B9%E6%B3%95%EF%BC%8C%E8%80%8C%E6%98%AF%E7%9B%B4%E6%8E%A5%E4%BB%8E%E7%BC%93%E5%AD%98%E4%B8%AD%E8%8E%B7%E5%8F%96%E7%BB%93%E6%9E%9C%E8%BF%9B%E8%A1%8C%E8%BF%94%E5%9B%9E%EF%BC%8C%E5%90%A6%E5%88%99%E6%89%8D%E4%BC%9A%E6%89%A7%E8%A1%8C%E5%B9%B6%E5%B0%86%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E5%AD%98%E5%85%A5%E6%8C%87%E5%AE%9A%E7%9A%84%E7%BC%93%E5%AD%98%E4%B8%AD%E3%80%82%0A%3E%0A%3E%20%40CachePut%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%E6%94%AF%E6%8C%81%E7%BC%93%E5%AD%98%E5%8A%9F%E8%83%BD%E3%80%82%0A%3E%0A%3E%20%E4%B8%8E%40Cacheable%E4%B8%8D%E5%90%8C%E7%9A%84%E6%98%AF%E4%BD%BF%E7%94%A8%40CachePut%E6%A0%87%E6%B3%A8%E7%9A%84%E6%96%B9%E6%B3%95%E5%9C%A8%E6%89%A7%E8%A1%8C%E5%89%8D%E4%B8%8D%E4%BC%9A%E5%8E%BB%E6%A3%80%E6%9F%A5%E7%BC%93%E5%AD%98%E4%B8%AD%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E4%B9%8B%E5%89%8D%E6%89%A7%E8%A1%8C%E8%BF%87%E7%9A%84%E7%BB%93%E6%9E%9C%EF%BC%8C%E8%80%8C%E6%98%AF%E6%AF%8F%E6%AC%A1%E9%83%BD%E4%BC%9A%E6%89%A7%E8%A1%8C%E8%AF%A5%E6%96%B9%E6%B3%95%EF%BC%8C%E5%B9%B6%E5%B0%86%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%E4%BB%A5%E9%94%AE%E5%80%BC%E5%AF%B9%E7%9A%84%E5%BD%A2%E5%BC%8F%E5%AD%98%E5%85%A5%E6%8C%87%E5%AE%9A%E7%9A%84%E7%BC%93%E5%AD%98%E4%B8%AD%E3%80%82%0A%3E%20%0A%0A%20%0A%0A%23%23%23%204.3%40CacheEvict%0A%0A%3E%20%40CacheEvict%E6%98%AF%E7%94%A8%E6%9D%A5%E6%A0%87%E6%B3%A8%E5%9C%A8%E9%9C%80%E8%A6%81%E6%B8%85%E9%99%A4%E7%BC%93%E5%AD%98%E5%85%83%E7%B4%A0%E7%9A%84%E6%96%B9%E6%B3%95%E6%88%96%E7%B1%BB%E4%B8%8A%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%E5%BD%93%E6%A0%87%E8%AE%B0%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%8A%E6%97%B6%E8%A1%A8%E7%A4%BA%E5%85%B6%E4%B8%AD%E6%89%80%E6%9C%89%E7%9A%84%E6%96%B9%E6%B3%95%E7%9A%84%E6%89%A7%E8%A1%8C%E9%83%BD%E4%BC%9A%E8%A7%A6%E5%8F%91%E7%BC%93%E5%AD%98%E7%9A%84%E6%B8%85%E9%99%A4%E6%93%8D%E4%BD%9C%E3%80%82%0A%3E%0A%3E%20%40CacheEvict%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E7%9A%84%E5%B1%9E%E6%80%A7%E6%9C%89value%E3%80%81key%E3%80%81condition%E3%80%81allEntries%E5%92%8CbeforeInvocation%E3%80%82%E5%85%B6%E4%B8%ADvalue%E3%80%81key%E5%92%8Ccondition%E7%9A%84%E8%AF%AD%E4%B9%89%E4%B8%8E%40Cacheable%E5%AF%B9%E5%BA%94%E7%9A%84%E5%B1%9E%E6%80%A7%E7%B1%BB%E4%BC%BC%E3%80%82%E5%8D%B3value%E8%A1%A8%E7%A4%BA%E6%B8%85%E9%99%A4%E6%93%8D%E4%BD%9C%E6%98%AF%E5%8F%91%E7%94%9F%E5%9C%A8%E5%93%AA%E4%BA%9BCache%E4%B8%8A%E7%9A%84%EF%BC%88%E5%AF%B9%E5%BA%94Cache%E7%9A%84%E5%90%8D%E7%A7%B0%EF%BC%89%EF%BC%9Bkey%E8%A1%A8%E7%A4%BA%E9%9C%80%E8%A6%81%E6%B8%85%E9%99%A4%E7%9A%84%E6%98%AF%E5%93%AA%E4%B8%AAkey%EF%BC%8C%E5%A6%82%E6%9C%AA%E6%8C%87%E5%AE%9A%E5%88%99%E4%BC%9A%E4%BD%BF%E7%94%A8%E9%BB%98%E8%AE%A4%E7%AD%96%E7%95%A5%E7%94%9F%E6%88%90%E7%9A%84key%EF%BC%9Bcondition%E8%A1%A8%E7%A4%BA%E6%B8%85%E9%99%A4%E6%93%8D%E4%BD%9C%E5%8F%91%E7%94%9F%E7%9A%84%E6%9D%A1%E4%BB%B6%E3%80%82%0A%3E%0A%3E%20%E4%B8%8B%E9%9D%A2%E6%88%91%E4%BB%AC%E6%9D%A5%E4%BB%8B%E7%BB%8D%E4%B8%80%E4%B8%8B%E6%96%B0%E5%87%BA%E7%8E%B0%E7%9A%84%E4%B8%A4%E4%B8%AA%E5%B1%9E%E6%80%A7allEntries%E5%92%8CbeforeInvocation%E3%80%82%0A%3E%20%0A%0A%23%23%23%23%204.3.1%20allEntries%E5%B1%9E%E6%80%A7%0A%3E%20allEntries%E6%98%AFboolean%E7%B1%BB%E5%9E%8B%EF%BC%8C%E8%A1%A8%E7%A4%BA%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E6%B8%85%E9%99%A4%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E5%85%83%E7%B4%A0%E3%80%82%E9%BB%98%E8%AE%A4%E4%B8%BAfalse%EF%BC%8C%E8%A1%A8%E7%A4%BA%E4%B8%8D%E9%9C%80%E8%A6%81%E3%80%82%0A%3E%0A%3E%20%E5%BD%93%E6%8C%87%E5%AE%9A%E4%BA%86allEntries%E4%B8%BAtrue%E6%97%B6%EF%BC%8CSpring%20Cache%E5%B0%86%E5%BF%BD%E7%95%A5%E6%8C%87%E5%AE%9A%E7%9A%84key%E3%80%82%E6%9C%89%E7%9A%84%E6%97%B6%E5%80%99%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81Cache%E4%B8%80%E4%B8%8B%E6%B8%85%E9%99%A4%E6%89%80%E6%9C%89%E7%9A%84%E5%85%83%E7%B4%A0%EF%BC%8C%E8%BF%99%E6%AF%94%E4%B8%80%E4%B8%AA%E4%B8%80%E4%B8%AA%E6%B8%85%E9%99%A4%E5%85%83%E7%B4%A0%E6%9B%B4%E6%9C%89%E6%95%88%E7%8E%87%E3%80%82%20%20%0A%0A%60%60%60java%0A%40CacheEvict(value%3D%E2%80%9Dusers%E2%80%9D%2C%20allEntries%3Dtrue)%0Apublic%20void%20delete(Integer%20id)%20%7B%0A%20%20%20System.out.println(%E2%80%9Cdelete%20user%20by%20id%3A%20%E2%80%9C%20%2B%20id)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%23%204.3.2%20beforeInvocation%E5%B1%9E%E6%80%A7%0A%0A%3E%20%E6%B8%85%E9%99%A4%E6%93%8D%E4%BD%9C%E9%BB%98%E8%AE%A4%E6%98%AF%E5%9C%A8%E5%AF%B9%E5%BA%94%E6%96%B9%E6%B3%95%E6%88%90%E5%8A%9F%E6%89%A7%E8%A1%8C%E4%B9%8B%E5%90%8E%E8%A7%A6%E5%8F%91%E7%9A%84%EF%BC%8C%E5%8D%B3%E6%96%B9%E6%B3%95%E5%A6%82%E6%9E%9C%E5%9B%A0%E4%B8%BA%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E8%80%8C%E6%9C%AA%E8%83%BD%E6%88%90%E5%8A%9F%E8%BF%94%E5%9B%9E%E6%97%B6%E4%B9%9F%E4%B8%8D%E4%BC%9A%E8%A7%A6%E5%8F%91%E6%B8%85%E9%99%A4%E6%93%8D%E4%BD%9C%E3%80%82%0A%3E%0A%3E%20%E4%BD%BF%E7%94%A8beforeInvocation%E5%8F%AF%E4%BB%A5%E6%94%B9%E5%8F%98%E8%A7%A6%E5%8F%91%E6%B8%85%E9%99%A4%E6%93%8D%E4%BD%9C%E7%9A%84%E6%97%B6%E9%97%B4%EF%BC%8C%E5%BD%93%E6%88%91%E4%BB%AC%E6%8C%87%E5%AE%9A%E8%AF%A5%E5%B1%9E%E6%80%A7%E5%80%BC%E4%B8%BAtrue%E6%97%B6%EF%BC%8CSpring%E4%BC%9A%E5%9C%A8%E8%B0%83%E7%94%A8%E8%AF%A5%E6%96%B9%E6%B3%95%E4%B9%8B%E5%89%8D%E6%B8%85%E9%99%A4%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84%E6%8C%87%E5%AE%9A%E5%85%83%E7%B4%A0%E3%80%82%0A%0A%60%60%60java%0A%40CacheEvict(value%3D%E2%80%9Dusers%E2%80%9D%2C%20beforeInvocation%3Dtrue)%0Apublic%20void%20delete(Integer%20id)%20%7B%0A%20%20%20%20%20%20System.out.println(%E2%80%9Cdelete%20user%20by%20id%3A%20%E2%80%9C%20%2B%20id)%3B%0A%20%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%204.4%20%40Caching%0A%0A%60%60%60java%0A%20%20%40Caching(cacheable%20%3D%20%40Cacheable(%E2%80%9Cusers%E2%80%9D)%2C%20%0A%20%20%20%20%09%09%20%20evict%20%3D%20%7B%20%40CacheEvict(%E2%80%9Ccache2%E2%80%9D)%2C%40CacheEvict(value%20%3D%20%E2%80%9Ccache3%E2%80%9D%2C%20allEntries%20%3D%20true)%20%7D)%0A%20%20%20public%20User%20find(Integer%20id)%20%7Bundefined%0A%20%20%20%20%20%20returnnull%3B%0A%20%20%20%7D%0A%60%60%60%0A%0A%0A%0A%23%23%205.%20%E4%BD%BF%E7%94%A8%0A%0A%23%23%23%205.1%20%E5%8A%A0%E5%85%A5%E4%BE%9D%E8%B5%96%0A%0A%60%60%60xml%0A%20%20%20%20%20%20%20%20%3C!--%20SpringBoot%20WEB%E6%A1%86%E6%9E%B6%20--%3E%0A%20%20%20%20%20%20%20%20%3Cdependency%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CartifactId%3Espring-boot-starter-web%3C%2FartifactId%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdependency%3E%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%3C!--%E5%BC%80%E5%90%AF%20cache%20%E7%BC%93%E5%AD%98%20--%3E%0A%09%09%3Cdependency%3E%0A%09%09%09%3CgroupId%3Eorg.springframework.boot%3C%2FgroupId%3E%0A%09%09%09%3CartifactId%3Espring-boot-starter-cache%3C%2FartifactId%3E%0A%09%09%3C%2Fdependency%3E%0A%60%60%60%0A%0A%23%23%23%205.2%20%E5%90%AF%E5%8A%A8%E7%B1%BB%E4%B8%AD%E5%8A%A0%E5%85%A5%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%90%AF%E7%BC%93%E5%AD%98%0A%0A%60%60%60%0A%40EnableCaching%0A%60%60%60

JMH

创建时间:2023/8/22 21:40
更新时间:2023/11/19 15:44
作者:Chris

1. 什么是JMH

JMH(Java Microbenchmark Harness)

2. 能干什么

  1. if 快还是 switch 快?HashMap 的初始化size要不要指定,指定之后性能可以提高多少?各种序列化方法哪个耗时更短?

  2. 想准确地知道某个方法需要执行多长时间,以及执行时间和输入之间的相关性

  3. 对比接口不同实现在给定条件下的吞吐量

  4. 查看多少百分比的请求在多长时间内完成

    ......

无论出自何种原因需要进行性能评估,量化指标总是必要的。在大部分场合,简单地回答谁快谁慢是远远不够的,如何将程序性能量化呢?这就需要我们的主角JMH登场了!

3. 怎么玩

3.1 永远的HelloWorld

@Warmup(iterations = 5, time = 10) // 预热次数和时间
@Measurement(iterations = 5, time = 10) // 测试次数和时间
public class JMHSample_01_HelloWorld{
...
}

org.openjdk.jmh.samples.JMHSample_01_HelloWorld#main
    
# JMH version: 1.38-SNAPSHOT   -- JMH版本号
# VM version: JDK 1.8.0_361, Java HotSpot(TM) 64-Bit Server VM, 25.361-b09
# VM invoker: C:\Program Files\Java\jdk1.8.0_361\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3.2\lib\idea_rt.jar=63119:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3.2\bin -Dfile.encoding=UTF-8
# Blackhole mode: full + dont-inline hint (auto-detected, use -Djmh.blackhole.autoDetect=false to disable) -- 黑洞模式
# Warmup: 5 iterations, 10 s each       -- 测试前对测试对象进行5轮预热,每次执行10秒
# Measurement: 5 iterations, 10 s each  -- 真正时对测试对象进行5轮测试,每次执行10秒
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations  -- 默认只会在一个线程里面执行测试
# Benchmark mode: Throughput, ops/time		      -- 将输出结果打印成 Throughput【吞吐量】的模式来看输出结果
# Benchmark: org.openjdk.jmh.samples.JMHSample_01_HelloWorld.wellHelloThere  -- 此类中标识了 @Benchmark 的测试对象

# Run progress: 0.00% complete, ETA 00:01:40
# Fork: 1 of 1
# Warmup Iteration   1: 3760163825.594 ops/s   -- 一轮跑了10秒,每秒跑 3760163825.594 次, 
# Warmup Iteration   2: 4430889451.652 ops/s
# Warmup Iteration   3: 4439455072.862 ops/s
# Warmup Iteration   4: 4409147073.419 ops/s
# Warmup Iteration   5: 4409733220.347 ops/s
Iteration   1: 4389189990.659 ops/s
Iteration   2: 4437504114.906 ops/s
Iteration   3: 4413845865.828 ops/s
Iteration   4: 4401591543.047 ops/s
Iteration   5: 4432448561.087 ops/s

Result "org.openjdk.jmh.samples.JMHSample_01_HelloWorld.wellHelloThere":
  4414916015.106 ±(99.9%) 78399326.229 ops/s [Average]
  (min, avg, max) = (4389189990.659, 4414916015.106, 4437504114.906), stdev = 20360056.054  -- 最小值,平均值,最大值,标准差
  CI (99.9%): [4336516688.876, 4493315341.335] (assumes normal distribution) -- 围住区间

# Run complete. Total time: 00:01:40

REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.

Benchmark                                Mode  Cnt           Score          Error  Units
JMHSample_01_HelloWorld.wellHelloThere  thrpt    5  4414916015.106 ± 78399326.229  ops/s 

Process finished with exit code 0

Warmup Iteration 该部分为每一次热身中的性能指标,预热测试不会作为最终的统计结果。预热的目的是让 JVM 对被测代码进行足够多的优化,比如,在预热后,被测代码应该得到了充分的 JIT 编译和优化。

3.2 @BenchmarkMode

3.2.1 Throughput 吞吐量

@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public void measureThroughput() throws InterruptedException {
	TimeUnit.MILLISECONDS.sleep(100);
}

Benchmark                                       Mode  Cnt  Score   Error  Units
JMHSample_02_BenchmarkModes.measureThroughput  thrpt    5  9.201 ± 0.031  ops/s  -- ops/s表示每秒多少次操作

3.2.2 AverageTime 平均时间

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureAvgTime() throws InterruptedException {
	TimeUnit.MILLISECONDS.sleep(100);
}

Benchmark                                   Mode  Cnt       Score     Error  Units
JMHSample_02_BenchmarkModes.measureAvgTime  avgt    5  108758.884 ± 494.750  us/op --us/op 表示一次操作耗时多
 
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.SECONDS)
public void measureAvgTime() throws InterruptedException {
	TimeUnit.MILLISECONDS.sleep(100);
}    
Benchmark                                   Mode  Cnt  Score   Error  Units
JMHSample_02_BenchmarkModes.measureAvgTime  avgt       0.108           s/op    

3.2.3 SampleTime 抽样

和 AverageTime 一样表示的是每次操作需要消耗多少秒

通过抽样可以直观感受到耗时的波动和算法的稳定性, 如果稳定性不高,随着抽样的增加耗时会出现比较大的波动

只是进行采样比对来统计耗时,不像吞吐量和平均值测试将每次运行都计算在内。

@Benchmark
@BenchmarkMode(Mode.SampleTime)
@OutputTimeUnit(TimeUnit.SECONDS)
public void measureSamples() throws InterruptedException {
    TimeUnit.MILLISECONDS.sleep(100);
}

Benchmark                                             Mode  Cnt  Score   Error  Units
JMHSample_02_BenchmarkModes.measureSamples          sample   10  0.108 ± 0.003   s/op
JMHSample_02_BenchmarkModes.measureSamples:p0.00    sample       0.103           s/op -- 最少耗时
JMHSample_02_BenchmarkModes.measureSamples:p0.50    sample       0.108           s/op -- 50% 的操作是在0.108s内完成
JMHSample_02_BenchmarkModes.measureSamples:p0.90    sample       0.110           s/op
JMHSample_02_BenchmarkModes.measureSamples:p0.95    sample       0.110           s/op
JMHSample_02_BenchmarkModes.measureSamples:p0.99    sample       0.110           s/op -- 99% 的操作是在0.11s内完成
JMHSample_02_BenchmarkModes.measureSamples:p0.999   sample       0.110           s/op -- 99.9% 的操作是在0.11s内完成
JMHSample_02_BenchmarkModes.measureSamples:p0.9999  sample       0.110           s/op -- 99.99% 的操作是在0.11s内完成
JMHSample_02_BenchmarkModes.measureSamples:p1.00    sample       0.110           s/op -- 所有操作在 0.11s内完成

3.2.4 SingleShotTime 单次执行耗时

  1. 冷启动测试,此方法在JMH一轮测试中只会执行一次,这个模式主要是为了测试冷启动的性能

  2. 云原生时代,Java是落后后其它语言的,因为java有一个预热的过程,java代码是越执行越快,它通过JIT的方式会让自己的执行效率越来越高, 而其它语言,比如GO语言,编译完后就已经最高执行效率的机器码

    所以对于java代码来说,如何提高自己的冷启动的效率也是一个比较重要优化项

@Benchmark
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureSingleShot() throws InterruptedException {
	TimeUnit.MILLISECONDS.sleep(100);
}
Benchmark                                      Mode  Cnt       Score   Error  Units
JMHSample_02_BenchmarkModes.measureSingleShot    ss       102272.200          us/op

3.2.5 Mode.All 全部测试

@BenchmarkMode(Mode.All) 
等同于
@BenchmarkMode({Mode.Throughput, Mode.AverageTime, Mode.SampleTime, Mode.SingleShotTime})    
@Benchmark
@BenchmarkMode({Mode.Throughput, Mode.AverageTime, Mode.SampleTime, Mode.SingleShotTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureMultiple() throws InterruptedException {
	TimeUnit.MILLISECONDS.sleep(100);
}

Benchmark                                              Mode  Cnt       Score      Error   Units
JMHSample_02_BenchmarkModes.measureMultiple           thrpt           ≈ 10⁻⁵             ops/us -- 吞吐量测试
JMHSample_02_BenchmarkModes.measureMultiple            avgt       107870.110              us/op -- 平均值测试
JMHSample_02_BenchmarkModes.measureMultiple          sample   10  109169.869 ± 2678.978   us/op -- 抽样测试
JMHSample_02_BenchmarkModes.measureMultiple:p0.00    sample       107610.112              us/op
JMHSample_02_BenchmarkModes.measureMultiple:p0.50    sample       108724.224              us/op
JMHSample_02_BenchmarkModes.measureMultiple:p0.90    sample       113390.387              us/op
JMHSample_02_BenchmarkModes.measureMultiple:p0.95    sample       113770.496              us/op
JMHSample_02_BenchmarkModes.measureMultiple:p0.99    sample       113770.496              us/op
JMHSample_02_BenchmarkModes.measureMultiple:p0.999   sample       113770.496              us/op
JMHSample_02_BenchmarkModes.measureMultiple:p0.9999  sample       113770.496              us/op
JMHSample_02_BenchmarkModes.measureMultiple:p1.00    sample       113770.496              us/op
JMHSample_02_BenchmarkModes.measureMultiple              ss       101059.700              us/op	-- 冷启动测试

3.3 @State

@State 会标记在一个类上面,这个类会由JMH管理并初始化

在执行 @Benchmark 方法时会注入到方法中

3.3.1 Scope

3.3.1.1 Scope.Thread
// 这个静态内部类会在Benchmark各线程执行前初始化, 作为入参,且每个线程的入参都是不一样的
@State(Scope.Thread)
public static class ThreadState {
    volatile double x = Math.PI;
}

@Benchmark
public void measureUnshared(ThreadState state) {
    state.x++;
}
3.3.1.2 Scope.Beanchmark
// 这个静态内部类会在整个Benchmark启动时初始化, 作为入参,且所有测试线程共享一个实例,用于测试有状态实例在多线程共享下的性能
@State(Scope.Benchmark)
public static class BenchmarkState {
	volatile double x = Math.PI;
}

@Benchmark
public void measureShared(BenchmarkState state) {
    state.x++;
}

public static void main(String[] args) throws RunnerException {
    Options opt = new OptionsBuilder()
        .include(JMHSample_03_States.class.getSimpleName())
        .threads(4) // 在执行每一个benchmark时会创建4个线程
        .forks(1)
        .build();

    new Runner(opt).run();
}

Benchmark                             Mode  Cnt          Score   Error  Units
JMHSample_03_States.measureShared    thrpt        56734444.884          ops/s
JMHSample_03_States.measureUnshared  thrpt       569412894.729          ops/s
3.3.1.3 Scope.Group

当多个的benchmark标记为同一个组,标记为同一个组的benchmark会放在一起执行

inc方法和get方法会被放到同一个benckmark里面去执行,并创建3个线程执行ink方法,创建一个线程执行get方法

如果需要测试一个方法在多线程下的执行效率时,可以使用@Group创造多线程下的竞争环境来衡量真实的执行效率

@State(Scope.Group)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class JMHSample_15_Asymmetric {

    private AtomicInteger counter;

    @Setup
    public void up() {
        counter = new AtomicInteger();
    }

    @Benchmark
    @Group("g")
    @GroupThreads(3) //启动3个线程去执行inc方法对变量counter进行自增
    public int inc() {
        return counter.incrementAndGet();
    }

    @Benchmark
    @Group("g")
    @GroupThreads(1) //启动一个线程去执行get方法获取counter里面的变量值
    public int get() {
        return counter.get();
    }


    @Benchmark
    @Group("g_single_get")
    public int single_get() {
        return counter.get();
    }


    @Benchmark
    @Group("g_single_ink_1")
    @GroupThreads(1)
    public int single_ink_1() {
        return counter.get();
    }

    @Benchmark
    @Group("g_single_ink_3")
    @GroupThreads(3)
    public int single_ink_3() {
        return counter.get();
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_15_Asymmetric.class.getSimpleName())
                .warmupIterations(1)
                .warmupTime(TimeValue.seconds(2))
                .measurementIterations(1)
                .measurementTime(TimeValue.seconds(1))
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}
Benchmark                                Mode  Cnt  Score   Error   Units
JMHSample_15_Asymmetric.g               thrpt       0.144          ops/ns
JMHSample_15_Asymmetric.g:get           thrpt       0.090          ops/ns
JMHSample_15_Asymmetric.g:inc           thrpt       0.054          ops/ns
JMHSample_15_Asymmetric.g_single_get    thrpt       0.721          ops/ns
JMHSample_15_Asymmetric.g_single_ink_1  thrpt       0.704          ops/ns
JMHSample_15_Asymmetric.g_single_ink_3  thrpt       1.940          ops/ns

3.3.2 default state

@State(Scope.Thread) // 相当于将当前类作为一个静态内部类,并在Benchmark各线程执行前初始化, 作为入参,且每个线程的入参都是不一样的, 这样会方便测试,不用声明一个类并将这个类作为参数传入Benchmark方法中
public class JMHSample_04_DefaultState{
 	double x = Math.PI;

	@Benchmark
	public void measure() {
		x++;
	}
}

Benchmark                           Mode  Cnt          Score   Error  Units
JMHSample_04_DefaultState.measure  thrpt       545266394.109          ops/s

3.4 @Setup & @TearDown

@Setup // 启动Benchmark 之前做准备工作, 必须在@State标识的类中使用,实际上是@State标识类的生命周期的一部分
public void prepare() {
	x = Math.PI;
    System.out.println("----- do Setup");
}

@TearDown // Benchmark 结束之后做收尾工作, 必须在@State标识的类中使用,实际上是@State标识类的生命周期的一部分
public void check() {
    System.out.println("----- do TearDown");
}

@Benchmark
public void measureRight() {
    x++;
}

@Benchmark
public void measureWrong() {
    double x = 0;
    x++;
}


 public static void main(String[] args) throws RunnerException {
     Options opt = new OptionsBuilder()
         .include(JMHSample_05_StateFixtures.class.getSimpleName())
         .forks(1)
         .jvmArgs("-ea")
         .build();

     new Runner(opt).run();
 }
# Benchmark: org.openjdk.jmh.samples.JMHSample_05_StateFixtures.measureRight

# Run progress: 0.00% complete, ETA 00:00:04
# Fork: 1 of 1
# Warmup Iteration   1: ----- do Setup
531640672.812 ops/s
Iteration   1: ----- do TearDown
554361599.723 ops/s

    
# Benchmark: org.openjdk.jmh.samples.JMHSample_05_StateFixtures.measureWrong

# Run progress: 50.00% complete, ETA 00:00:02
# Fork: 1 of 1
# Warmup Iteration   1: ----- do Setup
4497489243.589 ops/s
Iteration   1: ----- do TearDown
4526285173.485 ops/s
    
Benchmark                                 Mode  Cnt           Score   Error  Units
JMHSample_05_StateFixtures.measureRight  thrpt        529834411.876          ops/s
JMHSample_05_StateFixtures.measureWrong  thrpt       3867906327.891          ops/s

3.4.1 Level.Trial

@Setup(Level.Trial) // 整个Benchmark测试开始前会被执行一次,后面不再执行
@TearDown(Level.Trial) // 整个Benchmark测试完成后才会被执行一次,后面不再执行
@Setup(Level.Trial)
public void init() {
	System.out.println("----- do Setup");
}

@TearDown(Level.Trial)
public void check() {
	System.out.println("----- do TearDown");
}

# Warmup Iteration   1: ----- do Setup
4421937429.452 ops/s
# Warmup Iteration   2: 4485015612.898 ops/s
# Warmup Iteration   3: 4458406467.342 ops/s
Iteration   1: 4490684681.514 ops/s
Iteration   2: 4480366157.457 ops/s
Iteration   3: ----- do TearDown
4491445447.792 ops/s

3.4.2 Level.Iteration

@Setup(Level.Iteration) // 每一轮Benchmark测试开始前会被执行一次
@TearDown(Level.Iteration) // 每一轮Benchmark测试完成后才会被执行一次
@Setup(Level.Iteration)
public void init() {
	System.out.println("----- do Setup");
}

@TearDown(Level.Iteration)
public void check() {
	System.out.println("----- do TearDown");
}

# Warmup Iteration   1: ----- do Setup
----- do TearDown
498103233.061 ops/s
# Warmup Iteration   2: ----- do Setup
----- do TearDown
519591601.900 ops/s
# Warmup Iteration   3: ----- do Setup
----- do TearDown
547577377.973 ops/s
Iteration   1: ----- do Setup
----- do TearDown
553250593.661 ops/s
Iteration   2: ----- do Setup
----- do TearDown
551605708.992 ops/s
Iteration   3: ----- do Setup
----- do TearDown
553137249.413 ops/s

3.4.3 Level.Invocation

@Setup(Level.Invocation) // 每次方法被调用,都会被执行一次
@TearDown(Level.Invocation) // 每次方法被调用完后,都会被执行一次
@Setup(Level.Invocation)
public void init() {
	System.out.println("----- do Setup");
}

@TearDown(Level.Invocation)
public void check() {
	System.out.println("----- do TearDown");
}

3.5 @Param

指定某项参数的多种情况,特别适合用来测试一个函数在不同的参数输入的情况下的性能,只能作用在字段上,使用该注解必须定义 @State 注解。

@Param(value = {"10", "50", "100"})
private int length;

3.6 冷启动和热启动

// 模拟线程池的冷启动和热启动, 线程池启动是需要耗时的,这里面假设耗时为10ms
org.openjdk.jmh.samples.JMHSample_07_FixtureLevelInvocation


Benchmark                                        Mode  Cnt    Score   Error  Units
JMHSample_07_FixtureLevelInvocation.measureCold  avgt    2  122.002          us/op
JMHSample_07_FixtureLevelInvocation.measureHot   avgt    2    6.787          us/op

3.7 DeadCode

org.openjdk.jmh.samples.JMHSample_08_DeadCode

因为JMH使用不当,导致一些Benchmark被JVM优化掉,测试不出真实执行效率

// 这个方法因为没有返回值会被JVM优化掉
// JVM通过方法内联和逃逸检测,发现没有使用方法返回值,所以compute(x); 这行代码就会被优化掉,导致和空方法的执行效率基本一致
@Benchmark
public void measureWrong() {
    compute(x);
}

public static void main(String[] args) throws RunnerException {
     Options opt = new OptionsBuilder()
     	.include(JMHSample_08_DeadCode.class.getSimpleName())
     	.forks(1)
     	.jvmArgs("-server") // 这里设置为server模式,以充分使用JIT
     	.build();

    new Runner(opt).run();
}

Benchmark                           Mode  Cnt  Score   Error  Units
JMHSample_08_DeadCode.baseline      avgt    2  0.231          ns/op
JMHSample_08_DeadCode.measureRight  avgt    2  8.931          ns/op
JMHSample_08_DeadCode.measureWrong  avgt    2  0.299          ns/op
 public static void main(String[] args) throws RunnerException {
     Options opt = new OptionsBuilder()
     	.include(JMHSample_08_DeadCode.class.getSimpleName())
     	.forks(1)
     	.build();

    new Runner(opt).run();
}

Benchmark                           Mode  Cnt  Score   Error  Units
JMHSample_08_DeadCode.baseline      avgt    2  0.225          ns/op
JMHSample_08_DeadCode.measureRight  avgt    2  8.909          ns/op
JMHSample_08_DeadCode.measureWrong  avgt    2  0.223          ns/op

3.8 blackhole

只有在jdk8下才有意义

@Benchmark
public double baseline() {
    return compute(x1);
}

@Benchmark
public double measureWrong() {
    compute(x1); // JVM通过方法内联和逃逸检测,发现没有使用方法返回值,所以compute(x1); 这行代码就会进行JIT优化被优化掉,导致和空方法的执行效率基本一致
    return compute(x2);
}

// 可能把两个参数的方法相加,这样这两个参数都会在computer方法中计算
@Benchmark
public double measureRight_1() {
    return compute(x1) + compute(x2);
}

// 可以通过黑洞操作,这样JVM就认为这两个方法都是需要执行不能优化掉
@Benchmark
public void measureRight_2(Blackhole bh) {
    bh.consume(compute(x1));
    bh.consume(compute(x2));
}

Benchmark                               Mode  Cnt   Score   Error  Units
JMHSample_09_Blackholes.baseline        avgt        9.947          ns/op
JMHSample_09_Blackholes.measureRight_1  avgt       18.611          ns/op
JMHSample_09_Blackholes.measureRight_2  avgt       18.246          ns/op
JMHSample_09_Blackholes.measureWrong    avgt        9.267          ns/op

3.9 constant fold 常量折叠

org.openjdk.jmh.samples.JMHSample_10_ConstantFold

编译时简化常数的过程

这三方法测试时间基本一致,是因为在运行时进行了常量折叠

  • 返回值是常量的方法
  • 对常量进行一通计算仍得到一个常量
  • 入参是final类型的成员变量

Benchmark                                 Mode  Cnt  Score   Error  Units
JMHSample_10_ConstantFold.baseline        avgt       1.666          ns/op
JMHSample_10_ConstantFold.measureWrong_1  avgt       1.647          ns/op
JMHSample_10_ConstantFold.measureWrong_2  avgt       1.545          ns/op
JMHSample_10_ConstantFold.measureRight    avgt       9.117          ns/op

3.10 Loops

@Benchmark
@OperationsPerInvocation(10) //告诉JMH 这个Benchmark运行一次相当于运行了10次;也就是说这个Benckmark虽然只被JVM运行了一次,但是JMH在计算报表时会把这一次当作10次来算
public int measureWrong_10() {
    return reps(10);
}

可以看出后面计算一次的耗时越来越快,最后执行一次只要0.017ns,JVM把多次计算进行了合并通过别的方式快速计算出来结果,这样在循环里面得到两个数相加的耗时是不正确的

我们只需要在代码里面正常写Benchmark,不需要自作聪明的加循环,JMH在执行Benckmark时后通过Annotation Processor一套规范生成执行代码,会自动进行循环,不需要自己特意地在Benchmark里面自己做循环,JMH已经帮你做好的

control.announceWarmdownReady();
try {
    while (control.warmdownShouldWait) {
        blackhole.consume(l_jmhsample_11_loops0_0.measureRight());
        if (control.shouldYield) Thread.yield();
        res.allOps++;
    }
} catch (Throwable e) {
    if (!(e instanceof InterruptedException)) throw e;
}
Benchmark                               Mode  Cnt  Score   Error  Units
JMHSample_11_Loops.measureRight         avgt       1.555          ns/op
JMHSample_11_Loops.measureWrong_1       avgt       1.287          ns/op
JMHSample_11_Loops.measureWrong_10      avgt       0.156          ns/op
JMHSample_11_Loops.measureWrong_100     avgt       0.016          ns/op
JMHSample_11_Loops.measureWrong_1000    avgt       0.024          ns/op
JMHSample_11_Loops.measureWrong_10000   avgt       0.018          ns/op
JMHSample_11_Loops.measureWrong_100000  avgt       0.017          ns/op

3.11 Fork

3.11.1 fork(0)

fork(0) 启动JMH的JVM进程和执行Benchmark的JVM进程是在同一个进程

@Benchmark
@Fork(0)
public int measure1_c1(){
    return 1;
}

public static void printProcessID(String name) {
    System.out.println("----------------------------------------------------------------");
    System.out.println(name + " pid is " + ManagementFactory.getRuntimeMXBean().getName());
    System.out.println("----------------------------------------------------------------");
}

----------------------------------------------------------------
main pid is 20864@Chris
----------------------------------------------------------------

# Warmup Iteration   1: 
----------------------------------------------------------------
setup pid is 20864@Chris
----------------------------------------------------------------
0.518 ns/op
Iteration   1: 0.457 ns/op

Benchmark                           Mode  Cnt  Score   Error  Units
JMHSample_12_Forking_0.measure1_c1  avgt       0.457          ns/op

3.11.2 fork(1)

fork(1) 启动JMH的JVM进程和执行Benchmark的JVM进程是在不同进程

JMH在执行Benchmar测试时会fork出一个全新的JVM进程进行测试

@Benchmark
@Fork(1)
public int measure1_c1(){
    return 1;
}

----------------------------------------------------------------
main pid is 13352@Chris
----------------------------------------------------------------

# Fork: 1 of 1
# Warmup Iteration   1: 
----------------------------------------------------------------
setup pid is 11976@Chris
----------------------------------------------------------------
1.676 ns/op
Iteration   1: 1.681 ns/op


Benchmark                           Mode  Cnt  Score   Error  Units
JMHSample_12_Forking_0.measure1_c1  avgt       1.681          ns/op

3.11.3 fork(10)

fork(10) 表示整个JMH fork出了10个JVM进行依次去执行Benchmark测试,

不是并行去执行Benchmark测试,而是创建一个JVM进程执行完Benchmark测试后再销毁这个JVM,再创建再执行再销毁这么一个过程,总共将benchmark测试在不同的JVM进程中测试10次

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 2,time = 1)
@Measurement(iterations = 2, time = 1)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class JMHSample_12_Forking_1 {

    @Setup(Level.Trial)
    public void setup(){
        printProcessID("setup");
    }

    @Benchmark
    @Fork(10)
    public int measure1_c1(){
        return 1;
    }
    public static void printProcessID(String name) {
        System.out.println("----------------------------------------------------------------");
        System.out.println(name + " pid is " + ManagementFactory.getRuntimeMXBean().getName());
        System.out.println("----------------------------------------------------------------");
    }

    public static void main(String[] args) throws RunnerException {
        printProcessID("main");
        Options opt = new OptionsBuilder()
                .include(JMHSample_12_Forking_1.class.getSimpleName())
                .build();

        new Runner(opt).run();
    }

}



org.openjdk.jmh.samples.JMHSample_12_Forking_1
----------------------------------------------------------------
main pid is 8368@Chris
----------------------------------------------------------------
# JMH version: 1.38-SNAPSHOT
# VM version: JDK 1.8.0_361, Java HotSpot(TM) 64-Bit Server VM, 25.361-b09
# VM invoker: C:\Program Files\Java\jdk1.8.0_361\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3.2\lib\idea_rt.jar=52902:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3.2\bin -Dfile.encoding=UTF-8
# Blackhole mode: full + dont-inline hint (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 2 iterations, 1 s each
# Measurement: 2 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: org.openjdk.jmh.samples.JMHSample_12_Forking_1.measure1_c1

# Run progress: 0.00% complete, ETA 00:00:40
# Fork: 1 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 14660@Chris
----------------------------------------------------------------
1.578 ns/op
# Warmup Iteration   2: 1.673 ns/op
Iteration   1: 1.241 ns/op
Iteration   2: 1.110 ns/op

# Run progress: 10.00% complete, ETA 00:00:43
# Fork: 2 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 11336@Chris
----------------------------------------------------------------
1.421 ns/op
# Warmup Iteration   2: 1.440 ns/op
Iteration   1: 1.147 ns/op
Iteration   2: 1.068 ns/op

# Run progress: 20.00% complete, ETA 00:00:38
# Fork: 3 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 4904@Chris
----------------------------------------------------------------
1.400 ns/op
# Warmup Iteration   2: 1.434 ns/op
Iteration   1: 1.062 ns/op
Iteration   2: 1.079 ns/op

# Run progress: 30.00% complete, ETA 00:00:33
# Fork: 4 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 18992@Chris
----------------------------------------------------------------
1.383 ns/op
# Warmup Iteration   2: 1.444 ns/op
Iteration   1: 1.074 ns/op
Iteration   2: 1.073 ns/op

# Run progress: 40.00% complete, ETA 00:00:28
# Fork: 5 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 15644@Chris
----------------------------------------------------------------
1.396 ns/op
# Warmup Iteration   2: 1.481 ns/op
Iteration   1: 1.067 ns/op
Iteration   2: 1.067 ns/op

# Run progress: 50.00% complete, ETA 00:00:23
# Fork: 6 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 20944@Chris
----------------------------------------------------------------
1.421 ns/op
# Warmup Iteration   2: 1.435 ns/op
Iteration   1: 1.070 ns/op
Iteration   2: 1.071 ns/op

# Run progress: 60.00% complete, ETA 00:00:19
# Fork: 7 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 20208@Chris
----------------------------------------------------------------
1.370 ns/op
# Warmup Iteration   2: 1.440 ns/op
Iteration   1: 1.068 ns/op
Iteration   2: 1.062 ns/op

# Run progress: 70.00% complete, ETA 00:00:14
# Fork: 8 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 1656@Chris
----------------------------------------------------------------
1.386 ns/op
# Warmup Iteration   2: 1.437 ns/op
Iteration   1: 1.082 ns/op
Iteration   2: 1.066 ns/op

# Run progress: 80.00% complete, ETA 00:00:09
# Fork: 9 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 12804@Chris
----------------------------------------------------------------
1.395 ns/op
# Warmup Iteration   2: 1.444 ns/op
Iteration   1: 1.067 ns/op
Iteration   2: 1.087 ns/op

# Run progress: 90.00% complete, ETA 00:00:04
# Fork: 10 of 10
# Warmup Iteration   1: ----------------------------------------------------------------
setup pid is 14188@Chris
----------------------------------------------------------------
1.396 ns/op
# Warmup Iteration   2: 1.455 ns/op
Iteration   1: 1.067 ns/op
Iteration   2: 1.067 ns/op


Result "org.openjdk.jmh.samples.JMHSample_12_Forking_1.measure1_c1":
  1.085 ±(99.9%) 0.036 ns/op [Average]
  (min, avg, max) = (1.062, 1.085, 1.241), stdev = 0.042
  CI (99.9%): [1.049, 1.121] (assumes normal distribution)


# Run complete. Total time: 00:00:47	

Benchmark                           Mode  Cnt  Score   Error  Units
JMHSample_12_Forking_1.measure1_c1  avgt   20  1.085 ± 0.036  ns/op

3.11.4 fork()

fork() fork里面为空,默认表示fork出5个进程,但不建议使用默认值,这样会降低代码的可读性,别人看你代码或者过两天你看自己的代码不知道是想干啥

3.11.5 同一进程中的干扰问题

Benchmark                                 Mode  Cnt  Score   Error  Units
JMHSample_12_Forking.measure_1_c1         avgt       1.213          ns/op
JMHSample_12_Forking.measure_2_c2         avgt       4.182          ns/op
JMHSample_12_Forking.measure_3_c1_again   avgt       4.851          ns/op
JMHSample_12_Forking.measure_4_forked_c1  avgt       1.997          ns/op
JMHSample_12_Forking.measure_5_forked_c2  avgt       1.987          ns/op
public static class Counter1 implements Counter {
    private int x;

    @Override
    public int inc() {
        return x++;
    }
}

public int measure(Counter c) {
    int s = 0;
    for (int i = 0; i < 10; i++) {
        s += c.inc();
    }
    return s;
}

在调用每个c1的benckmark时传入的是c1,这时 c.inc() 就是 c1.inc(), JVM解释执行它需要先找到c1的对象,再执行c1的 inc()方法,这个在我们的代码里面是体现不出来的,但是JVM的确又是这么做的。

第一个传入的参数是c1,JVM就会假设这个类型参数都是c1,再进行一些激进的优化,比如方法内联,在运行时JIT把c.inc()变为x++, 这样 int inc() 这个方法就没有了,第一次执行时这个方法的效率会非常高。

当执行到第二个benchmark时,因为此时都是在同一个JVM里面,JVM记录的Counter实例都是c1,这时我们传入了一个c2,导致我们的 JIT 优化失效,JVM优化降级又转为了解释执行,放弃了方法内联的方式,在执行c2时,会先找到c2这个对象,再去c2对象里面到 int inc() 方法后再执行

因此,在同个JVM里面多个benchmark是可以相互影响的, 有的时候JVM会优化,有时又因为你的benchmark写的有问题又不优化,所以在进行benchmark测试时尽量放到不同的JVM进程中

《Java虚拟机规范》 字节码指令invokeinterface

《深入了解Java虚拟机》第8章 8.4.2

《深入理解Java虚拟机》第11章 11.4.2

3.11.6 什么时候用fork

可以看到在JMH启动时这个随机值是已经确认在,在整个Benchmark测试过程中使用的都是一个确定的值

但每次执行得到的随机数都是不一样的,的这就带来一个问题,如何得到一个偏差较小,更接近我们期望值的数据,这时就要使用到fork

@State(Scope.Thread)
public static class SleepyState {
    public long sleepTime;

    @Setup
    public void setup() {
        sleepTime = (long) (Math.random() * 1000);
        System.out.println("----------------------");
        System.out.println("sleepTime:" + sleepTime);
        System.out.println("----------------------");
    }
}

Benchmark                       Mode  Cnt    Score     Error  Units
JMHSample_13_RunToRun.baseline  avgt    3  118.507 ±   0.884  ms/op
JMHSample_13_RunToRun.fork_1    avgt   15  696.184 ± 187.366  ms/op

如果使用到的算法有一定的随机性,比如会生成一个随机值,然后在后面的执行中都会使用到这个随机值,这个随机值是如何分布的,一次或多次的测试是体现不出来的,

比如我们会有一些随机算法,在启动的时候生成一个种子,在整个执行过程的生成的随机数都会基于这个种子,为了使结果尽可能的平均,接近我们的期望值,减少偏差,就要多测试几轮

每轮测试都放到一个新的JVM进程中独立的执行

4 编写基准测试

4.1 字符串拼

判断 +StringBuilder.append() 两种字符串拼接哪个耗时更短

/**
 * @Author: 80393617
 * @Date: 2023-10-23  14:57
 * @Description: String Connect Test
 */
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 2, time = 1)
@Measurement(iterations = 3, time = 1)
@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class StrConnectTest {
    @Param(value = {"10", "50", "100"})
    private int length;

    @Benchmark
    public void testStringAdd(Blackhole blackhole) {
        String a = "";
        for (int i = 0; i < length; i++) {
            a += i;
        }
        blackhole.consume(a);
    }

    @Benchmark
    public void testStringBuilderAdd(Blackhole blackhole) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(i);
        }
        blackhole.consume(sb.toString());
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(StrConnectTest.class.getSimpleName())
                .threads(4)
                .forks(1)
                .result("result.json")
                .resultFormat(ResultFormatType.JSON).build();
        new Runner(opt).run();
    }
}

Benchmark                            (length)  Mode  Cnt     Score      Error  Units
StrConnectTest.testStringAdd               10  avgt    3   210.344 ±  542.752  ns/op
StrConnectTest.testStringAdd               50  avgt    3  1689.224 ±  496.450  ns/op
StrConnectTest.testStringAdd              100  avgt    3  6102.150 ± 4193.507  ns/op
StrConnectTest.testStringBuilderAdd        10  avgt    3    75.982 ±   62.798  ns/op
StrConnectTest.testStringBuilderAdd        50  avgt    3   512.804 ±  304.180  ns/op
StrConnectTest.testStringBuilderAdd       100  avgt    3  1014.121 ±  477.335  ns/op
  • Warmup Iteration 该部分为每一次热身中的性能指标,预热测试不会作为最终的统计结果。预热的目的是让 JVM 对被测代码进行足够多的优化,比如,在预热后,被测代码应该得到了充分的 JIT 编译和优化。

  • 该部分显示测量迭代的情况,每一次迭代都显示了当前的执行速率,即一个操作所花费的时间。在进行 5 次迭代后,进行统计,在本例中,length 为 100 的情况下 testStringBuilderAdd 方法的平均执行花费时间为 1014.121 ns,误差为 477.335 ns

4.2 list.sort与Stream().sorted


@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 2, time = 1)
@Measurement(iterations = 5, time = 5)
@Fork(1)
@State(Scope.Thread)
public class SortBenchmark {
    @Param(value = {"100", "10000", "100000"})
    private int operationSize; 
    private static List<Integer> arrayList;
    
    @Setup
    public void init() {
        arrayList = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < operationSize; i++) {
            arrayList.add(random.nextInt(10000));
        }
    }
    @Benchmark
    public void sort(Blackhole blackhole) {
        arrayList.sort(Comparator.comparing(e -> e));
        blackhole.consume(arrayList);
    }
    @Benchmark
    public void streamSorted(Blackhole blackhole) {
        arrayList = arrayList.stream().sorted(Comparator.comparing(e -> e)).collect(Collectors.toList());
        blackhole.consume(arrayList);
    }
    
    public static void main(String[] args) throws RunnerException {
        // 启动基准测试
        Options opt = new OptionsBuilder()
            .include(SortBenchmark.class.getSimpleName()) 
            .result("SortBenchmark.json")
            .mode(Mode.All)
            .resultFormat(ResultFormatType.JSON)
            .build();
        new Runner(opt).run(); 
    }
}
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 2, time = 1)
@Measurement(iterations = 5, time = 5)
@Fork(1)
@State(Scope.Thread)
public class SortBenchmark3 {
    @Param(value = {"100", "10000"})
    private int operationSize; // 操作次数
    private static List<Integer> arrayList;
    public static void main(String[] args) throws RunnerException {
        // 启动基准测试
        Options opt = new OptionsBuilder()
            .include(SortBenchmark3.class.getSimpleName()) // 要导入的测试类
            .result("SortBenchmark3.json")
            .mode(Mode.All)
            .resultFormat(ResultFormatType.JSON)
            .build();
        new Runner(opt).run(); // 执行测试
    }

    @Setup
    public void init() {
        // 启动执行事件
        arrayList = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < operationSize; i++) {
            arrayList.add(random.nextInt(10000));
        }
    }

    @Benchmark
    public void stream(Blackhole blackhole) {
        arrayList.stream().collect(Collectors.toList());
        blackhole.consume(arrayList);
    }

    @Benchmark
    public void sort(Blackhole blackhole) {
        arrayList.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList());
        blackhole.consume(arrayList);
    }
}
%23%23%201.%20%E4%BB%80%E4%B9%88%E6%98%AFJMH%0A%0A%3E%20JMH(Java%20Microbenchmark%20Harness)%0A%3E%0A%3E%20-%20%E6%98%AF%E7%94%A8%E4%BA%8E%E4%BB%A3%E7%A0%81%E5%BE%AE%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%E7%9A%84%E5%B7%A5%E5%85%B7%E5%A5%97%E4%BB%B6%EF%BC%8C%E4%B8%BB%E8%A6%81%E6%98%AF%E5%9F%BA%E4%BA%8E%E6%96%B9%E6%B3%95%E5%B1%82%E9%9D%A2%E7%9A%84%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%EF%BC%8C%E7%B2%BE%E5%BA%A6%E5%8F%AF%E4%BB%A5%E8%BE%BE%E5%88%B0%E7%BA%B3%E7%A7%92%E7%BA%A7%E3%80%82%0A%3E-%20%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%E6%98%AF%E6%8C%87%E9%80%9A%E8%BF%87%E8%AE%BE%E8%AE%A1%E7%A7%91%E5%AD%A6%E7%9A%84%E6%B5%8B%E8%AF%95%E6%96%B9%E6%B3%95%E3%80%81%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7%E5%92%8C%E6%B5%8B%E8%AF%95%E7%B3%BB%E7%BB%9F%EF%BC%8C%E5%AE%9E%E7%8E%B0%E5%AF%B9%E4%B8%80%E7%B1%BB%E6%B5%8B%E8%AF%95%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%9F%90%E9%A1%B9%E6%80%A7%E8%83%BD%E6%8C%87%E6%A0%87%E8%BF%9B%E8%A1%8C%E5%AE%9A%E9%87%8F%E7%9A%84%E5%92%8C%E5%8F%AF%E5%AF%B9%E6%AF%94%E7%9A%84%E6%B5%8B%E8%AF%95%E3%80%82%0A%3E%20-%20%E8%AF%A5%E5%B7%A5%E5%85%B7%E6%98%AF%E7%94%B1%20Oracle%20%E5%86%85%E9%83%A8%E5%AE%9E%E7%8E%B0%20JIT%20%E7%9A%84%E5%B7%A8%E4%BD%AC%E4%BB%AC%E7%BC%96%E5%86%99%E7%9A%84%EF%BC%8C%E4%BB%96%E4%BB%AC%E5%BA%94%E8%AF%A5%E6%AF%94%E4%BB%BB%E4%BD%95%E4%BA%BA%E9%83%BD%E4%BA%86%E8%A7%A3%20JIT%20%E4%BB%A5%E5%8F%8A%20JVM%20%E5%AF%B9%E4%BA%8E%5B%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%5D(https%3A%2F%2Fwww.zhihu.com%2Fsearch%3Fq%3D%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%26search_source%3DEntity%26hybrid_search_source%3DEntity%26hybrid_search_extra%3D%7B%22sourceType%22%253A%22answer%22%252C%22sourceId%22%253A1259967560%7D)%E7%9A%84%E5%BD%B1%E5%93%8D%E3%80%82%0A%3E%20-%20https%3A%2F%2Fgithub.com%2Fopenjdk%2Fjmh.git%0A%0A%0A%0A%23%23%202.%20%E8%83%BD%E5%B9%B2%E4%BB%80%E4%B9%88%0A%0A%3E%201.%20if%20%E5%BF%AB%E8%BF%98%E6%98%AF%20switch%20%E5%BF%AB%EF%BC%9FHashMap%20%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96size%E8%A6%81%E4%B8%8D%E8%A6%81%E6%8C%87%E5%AE%9A%EF%BC%8C%E6%8C%87%E5%AE%9A%E4%B9%8B%E5%90%8E%E6%80%A7%E8%83%BD%E5%8F%AF%E4%BB%A5%E6%8F%90%E9%AB%98%E5%A4%9A%E5%B0%91%EF%BC%9F%E5%90%84%E7%A7%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%96%B9%E6%B3%95%E5%93%AA%E4%B8%AA%E8%80%97%E6%97%B6%E6%9B%B4%E7%9F%AD%EF%BC%9F%0A%3E%0A%3E%202.%20%E6%83%B3%E5%87%86%E7%A1%AE%E5%9C%B0%E7%9F%A5%E9%81%93%E6%9F%90%E4%B8%AA%E6%96%B9%E6%B3%95%E9%9C%80%E8%A6%81%E6%89%A7%E8%A1%8C%E5%A4%9A%E9%95%BF%E6%97%B6%E9%97%B4%EF%BC%8C%E4%BB%A5%E5%8F%8A%E6%89%A7%E8%A1%8C%E6%97%B6%E9%97%B4%E5%92%8C%E8%BE%93%E5%85%A5%E4%B9%8B%E9%97%B4%E7%9A%84%E7%9B%B8%E5%85%B3%E6%80%A7%0A%3E%0A%3E%203.%20%E5%AF%B9%E6%AF%94%E6%8E%A5%E5%8F%A3%E4%B8%8D%E5%90%8C%E5%AE%9E%E7%8E%B0%E5%9C%A8%E7%BB%99%E5%AE%9A%E6%9D%A1%E4%BB%B6%E4%B8%8B%E7%9A%84%E5%90%9E%E5%90%90%E9%87%8F%0A%3E%0A%3E%204.%20%E6%9F%A5%E7%9C%8B%E5%A4%9A%E5%B0%91%E7%99%BE%E5%88%86%E6%AF%94%E7%9A%84%E8%AF%B7%E6%B1%82%E5%9C%A8%E5%A4%9A%E9%95%BF%E6%97%B6%E9%97%B4%E5%86%85%E5%AE%8C%E6%88%90%0A%3E%0A%3E%20%20%20%20......%0A%3E%0A%3E%20%E6%97%A0%E8%AE%BA%E5%87%BA%E8%87%AA%E4%BD%95%E7%A7%8D%E5%8E%9F%E5%9B%A0%E9%9C%80%E8%A6%81%E8%BF%9B%E8%A1%8C%E6%80%A7%E8%83%BD%E8%AF%84%E4%BC%B0%EF%BC%8C%E9%87%8F%E5%8C%96%E6%8C%87%E6%A0%87%E6%80%BB%E6%98%AF%E5%BF%85%E8%A6%81%E7%9A%84%E3%80%82%E5%9C%A8%E5%A4%A7%E9%83%A8%E5%88%86%E5%9C%BA%E5%90%88%EF%BC%8C%E7%AE%80%E5%8D%95%E5%9C%B0%E5%9B%9E%E7%AD%94%E8%B0%81%E5%BF%AB%E8%B0%81%E6%85%A2%E6%98%AF%E8%BF%9C%E8%BF%9C%E4%B8%8D%E5%A4%9F%E7%9A%84%EF%BC%8C%E5%A6%82%E4%BD%95%E5%B0%86%E7%A8%8B%E5%BA%8F%E6%80%A7%E8%83%BD%E9%87%8F%E5%8C%96%E5%91%A2%EF%BC%9F%E8%BF%99%E5%B0%B1%E9%9C%80%E8%A6%81%E6%88%91%E4%BB%AC%E7%9A%84%E4%B8%BB%E8%A7%92JMH%E7%99%BB%E5%9C%BA%E4%BA%86%EF%BC%81%0A%0A%0A%0A%23%23%203.%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%23%23%23%203.1%20%E6%B0%B8%E8%BF%9C%E7%9A%84HelloWorld%0A%0A%60%60%60java%0A%40Warmup(iterations%20%3D%205%2C%20time%20%3D%2010)%20%2F%2F%20%E9%A2%84%E7%83%AD%E6%AC%A1%E6%95%B0%E5%92%8C%E6%97%B6%E9%97%B4%0A%40Measurement(iterations%20%3D%205%2C%20time%20%3D%2010)%20%2F%2F%20%E6%B5%8B%E8%AF%95%E6%AC%A1%E6%95%B0%E5%92%8C%E6%97%B6%E9%97%B4%0Apublic%20class%20JMHSample_01_HelloWorld%7B%0A...%0A%7D%0A%0Aorg.openjdk.jmh.samples.JMHSample_01_HelloWorld%23main%0A%20%20%20%20%0A%23%20JMH%20version%3A%201.38-SNAPSHOT%20%20%20--%20JMH%E7%89%88%E6%9C%AC%E5%8F%B7%0A%23%20VM%20version%3A%20JDK%201.8.0_361%2C%20Java%20HotSpot(TM)%2064-Bit%20Server%20VM%2C%2025.361-b09%0A%23%20VM%20invoker%3A%20C%3A%5CProgram%20Files%5CJava%5Cjdk1.8.0_361%5Cjre%5Cbin%5Cjava.exe%0A%23%20VM%20options%3A%20-javaagent%3AC%3A%5CProgram%20Files%5CJetBrains%5CIntelliJ%20IDEA%202022.3.2%5Clib%5Cidea_rt.jar%3D63119%3AC%3A%5CProgram%20Files%5CJetBrains%5CIntelliJ%20IDEA%202022.3.2%5Cbin%20-Dfile.encoding%3DUTF-8%0A%23%20Blackhole%20mode%3A%20full%20%2B%20dont-inline%20hint%20(auto-detected%2C%20use%20-Djmh.blackhole.autoDetect%3Dfalse%20to%20disable)%20--%20%E9%BB%91%E6%B4%9E%E6%A8%A1%E5%BC%8F%0A%23%20Warmup%3A%205%20iterations%2C%2010%20s%20each%20%20%20%20%20%20%20--%20%E6%B5%8B%E8%AF%95%E5%89%8D%E5%AF%B9%E6%B5%8B%E8%AF%95%E5%AF%B9%E8%B1%A1%E8%BF%9B%E8%A1%8C5%E8%BD%AE%E9%A2%84%E7%83%AD%EF%BC%8C%E6%AF%8F%E6%AC%A1%E6%89%A7%E8%A1%8C10%E7%A7%92%0A%23%20Measurement%3A%205%20iterations%2C%2010%20s%20each%20%20--%20%E7%9C%9F%E6%AD%A3%E6%97%B6%E5%AF%B9%E6%B5%8B%E8%AF%95%E5%AF%B9%E8%B1%A1%E8%BF%9B%E8%A1%8C5%E8%BD%AE%E6%B5%8B%E8%AF%95%EF%BC%8C%E6%AF%8F%E6%AC%A1%E6%89%A7%E8%A1%8C10%E7%A7%92%0A%23%20Timeout%3A%2010%20min%20per%20iteration%0A%23%20Threads%3A%201%20thread%2C%20will%20synchronize%20iterations%20%20--%20%E9%BB%98%E8%AE%A4%E5%8F%AA%E4%BC%9A%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%87%8C%E9%9D%A2%E6%89%A7%E8%A1%8C%E6%B5%8B%E8%AF%95%0A%23%20Benchmark%20mode%3A%20Throughput%2C%20ops%2Ftime%09%09%20%20%20%20%20%20--%20%E5%B0%86%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%E6%89%93%E5%8D%B0%E6%88%90%20Throughput%E3%80%90%E5%90%9E%E5%90%90%E9%87%8F%E3%80%91%E7%9A%84%E6%A8%A1%E5%BC%8F%E6%9D%A5%E7%9C%8B%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%0A%23%20Benchmark%3A%20org.openjdk.jmh.samples.JMHSample_01_HelloWorld.wellHelloThere%20%20--%20%E6%AD%A4%E7%B1%BB%E4%B8%AD%E6%A0%87%E8%AF%86%E4%BA%86%20%40Benchmark%20%E7%9A%84%E6%B5%8B%E8%AF%95%E5%AF%B9%E8%B1%A1%0A%0A%23%20Run%20progress%3A%200.00%25%20complete%2C%20ETA%2000%3A01%3A40%0A%23%20Fork%3A%201%20of%201%0A%23%20Warmup%20Iteration%20%20%201%3A%203760163825.594%20ops%2Fs%20%20%20--%20%E4%B8%80%E8%BD%AE%E8%B7%91%E4%BA%8610%E7%A7%92%EF%BC%8C%E6%AF%8F%E7%A7%92%E8%B7%91%203760163825.594%20%E6%AC%A1%2C%20%0A%23%20Warmup%20Iteration%20%20%202%3A%204430889451.652%20ops%2Fs%0A%23%20Warmup%20Iteration%20%20%203%3A%204439455072.862%20ops%2Fs%0A%23%20Warmup%20Iteration%20%20%204%3A%204409147073.419%20ops%2Fs%0A%23%20Warmup%20Iteration%20%20%205%3A%204409733220.347%20ops%2Fs%0AIteration%20%20%201%3A%204389189990.659%20ops%2Fs%0AIteration%20%20%202%3A%204437504114.906%20ops%2Fs%0AIteration%20%20%203%3A%204413845865.828%20ops%2Fs%0AIteration%20%20%204%3A%204401591543.047%20ops%2Fs%0AIteration%20%20%205%3A%204432448561.087%20ops%2Fs%0A%0AResult%20%22org.openjdk.jmh.samples.JMHSample_01_HelloWorld.wellHelloThere%22%3A%0A%20%204414916015.106%20%C2%B1(99.9%25)%2078399326.229%20ops%2Fs%20%5BAverage%5D%0A%20%20(min%2C%20avg%2C%20max)%20%3D%20(4389189990.659%2C%204414916015.106%2C%204437504114.906)%2C%20stdev%20%3D%2020360056.054%20%20--%20%E6%9C%80%E5%B0%8F%E5%80%BC%EF%BC%8C%E5%B9%B3%E5%9D%87%E5%80%BC%EF%BC%8C%E6%9C%80%E5%A4%A7%E5%80%BC%EF%BC%8C%E6%A0%87%E5%87%86%E5%B7%AE%0A%20%20CI%20(99.9%25)%3A%20%5B4336516688.876%2C%204493315341.335%5D%20(assumes%20normal%20distribution)%20--%20%E5%9B%B4%E4%BD%8F%E5%8C%BA%E9%97%B4%0A%0A%23%20Run%20complete.%20Total%20time%3A%2000%3A01%3A40%0A%0AREMEMBER%3A%20The%20numbers%20below%20are%20just%20data.%20To%20gain%20reusable%20insights%2C%20you%20need%20to%20follow%20up%20on%0Awhy%20the%20numbers%20are%20the%20way%20they%20are.%20Use%20profilers%20(see%20-prof%2C%20-lprof)%2C%20design%20factorial%0Aexperiments%2C%20perform%20baseline%20and%20negative%20tests%20that%20provide%20experimental%20control%2C%20make%20sure%0Athe%20benchmarking%20environment%20is%20safe%20on%20JVM%2FOS%2FHW%20level%2C%20ask%20for%20reviews%20from%20the%20domain%20experts.%0ADo%20not%20assume%20the%20numbers%20tell%20you%20what%20you%20want%20them%20to%20tell.%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20%20%20%20%20%20%20%20Score%20%20%20%20%20%20%20%20%20%20Error%20%20Units%0AJMHSample_01_HelloWorld.wellHelloThere%20%20thrpt%20%20%20%205%20%204414916015.106%20%C2%B1%2078399326.229%20%20ops%2Fs%20%0A%0AProcess%20finished%20with%20exit%20code%200%0A%60%60%60%0A%0A%0A%0A%3E%20%60Warmup%20Iteration%60%20%E8%AF%A5%E9%83%A8%E5%88%86%E4%B8%BA%E6%AF%8F%E4%B8%80%E6%AC%A1%E7%83%AD%E8%BA%AB%E4%B8%AD%E7%9A%84%E6%80%A7%E8%83%BD%E6%8C%87%E6%A0%87%EF%BC%8C%E9%A2%84%E7%83%AD%E6%B5%8B%E8%AF%95%E4%B8%8D%E4%BC%9A%E4%BD%9C%E4%B8%BA%E6%9C%80%E7%BB%88%E7%9A%84%E7%BB%9F%E8%AE%A1%E7%BB%93%E6%9E%9C%E3%80%82%E9%A2%84%E7%83%AD%E7%9A%84%E7%9B%AE%E7%9A%84%E6%98%AF**%E8%AE%A9%20JVM%20%E5%AF%B9%E8%A2%AB%E6%B5%8B%E4%BB%A3%E7%A0%81%E8%BF%9B%E8%A1%8C%E8%B6%B3%E5%A4%9F%E5%A4%9A%E7%9A%84%E4%BC%98%E5%8C%96**%EF%BC%8C%E6%AF%94%E5%A6%82%EF%BC%8C%E5%9C%A8%E9%A2%84%E7%83%AD%E5%90%8E%EF%BC%8C%E8%A2%AB%E6%B5%8B%E4%BB%A3%E7%A0%81%E5%BA%94%E8%AF%A5%E5%BE%97%E5%88%B0%E4%BA%86%E5%85%85%E5%88%86%E7%9A%84%20JIT%20%E7%BC%96%E8%AF%91%E5%92%8C%E4%BC%98%E5%8C%96%E3%80%82%0A%0A%0A%0A%23%23%23%203.2%20%40BenchmarkMode%20%0A%0A%23%23%23%23%203.2.1%20Throughput%20%20%E5%90%9E%E5%90%90%E9%87%8F%0A%0A%60%60%60java%0A%40Benchmark%0A%40BenchmarkMode(Mode.Throughput)%0A%40OutputTimeUnit(TimeUnit.SECONDS)%0Apublic%20void%20measureThroughput()%20throws%20InterruptedException%20%7B%0A%09TimeUnit.MILLISECONDS.sleep(100)%3B%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_02_BenchmarkModes.measureThroughput%20%20thrpt%20%20%20%205%20%209.201%20%C2%B1%200.031%20%20ops%2Fs%20%20--%20ops%2Fs%E8%A1%A8%E7%A4%BA%E6%AF%8F%E7%A7%92%E5%A4%9A%E5%B0%91%E6%AC%A1%E6%93%8D%E4%BD%9C%0A%60%60%60%0A%0A%23%23%23%23%203.2.2%20AverageTime%20%20%E5%B9%B3%E5%9D%87%E6%97%B6%E9%97%B4%0A%0A%60%60%60java%0A%40Benchmark%0A%40BenchmarkMode(Mode.AverageTime)%0A%40OutputTimeUnit(TimeUnit.MICROSECONDS)%0Apublic%20void%20measureAvgTime()%20throws%20InterruptedException%20%7B%0A%09TimeUnit.MILLISECONDS.sleep(100)%3B%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20%20%20%20Score%20%20%20%20%20Error%20%20Units%0AJMHSample_02_BenchmarkModes.measureAvgTime%20%20avgt%20%20%20%205%20%20108758.884%20%C2%B1%20494.750%20%20us%2Fop%20--us%2Fop%20%E8%A1%A8%E7%A4%BA%E4%B8%80%E6%AC%A1%E6%93%8D%E4%BD%9C%E8%80%97%E6%97%B6%E5%A4%9A%0A%20%0A%40Benchmark%0A%40BenchmarkMode(Mode.AverageTime)%0A%40OutputTimeUnit(TimeUnit.SECONDS)%0Apublic%20void%20measureAvgTime()%20throws%20InterruptedException%20%7B%0A%09TimeUnit.MILLISECONDS.sleep(100)%3B%0A%7D%20%20%20%20%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_02_BenchmarkModes.measureAvgTime%20%20avgt%20%20%20%20%20%20%200.108%20%20%20%20%20%20%20%20%20%20%20s%2Fop%20%20%20%20%0A%60%60%60%0A%0A%23%23%23%23%203.2.3%20SampleTime%20%E6%8A%BD%E6%A0%B7%0A%0A%3E%20%E5%92%8C%20AverageTime%20%20%E4%B8%80%E6%A0%B7%E8%A1%A8%E7%A4%BA%E7%9A%84%E6%98%AF%E6%AF%8F%E6%AC%A1%E6%93%8D%E4%BD%9C%E9%9C%80%E8%A6%81%E6%B6%88%E8%80%97%E5%A4%9A%E5%B0%91%E7%A7%92%0A%3E%0A%3E%20%E9%80%9A%E8%BF%87%E6%8A%BD%E6%A0%B7%E5%8F%AF%E4%BB%A5%E7%9B%B4%E8%A7%82%E6%84%9F%E5%8F%97%E5%88%B0%E8%80%97%E6%97%B6%E7%9A%84%E6%B3%A2%E5%8A%A8%E5%92%8C%E7%AE%97%E6%B3%95%E7%9A%84%E7%A8%B3%E5%AE%9A%E6%80%A7%EF%BC%8C%20%E5%A6%82%E6%9E%9C%E7%A8%B3%E5%AE%9A%E6%80%A7%E4%B8%8D%E9%AB%98%EF%BC%8C%E9%9A%8F%E7%9D%80%E6%8A%BD%E6%A0%B7%E7%9A%84%E5%A2%9E%E5%8A%A0%E8%80%97%E6%97%B6%E4%BC%9A%E5%87%BA%E7%8E%B0%E6%AF%94%E8%BE%83%E5%A4%A7%E7%9A%84%E6%B3%A2%E5%8A%A8%0A%3E%0A%3E%20%E5%8F%AA%E6%98%AF%E8%BF%9B%E8%A1%8C%E9%87%87%E6%A0%B7%E6%AF%94%E5%AF%B9%E6%9D%A5%E7%BB%9F%E8%AE%A1%E8%80%97%E6%97%B6%EF%BC%8C%E4%B8%8D%E5%83%8F%E5%90%9E%E5%90%90%E9%87%8F%E5%92%8C%E5%B9%B3%E5%9D%87%E5%80%BC%E6%B5%8B%E8%AF%95%E5%B0%86%E6%AF%8F%E6%AC%A1%E8%BF%90%E8%A1%8C%E9%83%BD%E8%AE%A1%E7%AE%97%E5%9C%A8%E5%86%85%E3%80%82%0A%0A%60%60%60java%0A%40Benchmark%0A%40BenchmarkMode(Mode.SampleTime)%0A%40OutputTimeUnit(TimeUnit.SECONDS)%0Apublic%20void%20measureSamples()%20throws%20InterruptedException%20%7B%0A%20%20%20%20TimeUnit.MILLISECONDS.sleep(100)%3B%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_02_BenchmarkModes.measureSamples%20%20%20%20%20%20%20%20%20%20sample%20%20%2010%20%200.108%20%C2%B1%200.003%20%20%20s%2Fop%0AJMHSample_02_BenchmarkModes.measureSamples%3Ap0.00%20%20%20%20sample%20%20%20%20%20%20%200.103%20%20%20%20%20%20%20%20%20%20%20s%2Fop%20--%20%E6%9C%80%E5%B0%91%E8%80%97%E6%97%B6%0AJMHSample_02_BenchmarkModes.measureSamples%3Ap0.50%20%20%20%20sample%20%20%20%20%20%20%200.108%20%20%20%20%20%20%20%20%20%20%20s%2Fop%20--%2050%25%20%E7%9A%84%E6%93%8D%E4%BD%9C%E6%98%AF%E5%9C%A80.108s%E5%86%85%E5%AE%8C%E6%88%90%0AJMHSample_02_BenchmarkModes.measureSamples%3Ap0.90%20%20%20%20sample%20%20%20%20%20%20%200.110%20%20%20%20%20%20%20%20%20%20%20s%2Fop%0AJMHSample_02_BenchmarkModes.measureSamples%3Ap0.95%20%20%20%20sample%20%20%20%20%20%20%200.110%20%20%20%20%20%20%20%20%20%20%20s%2Fop%0AJMHSample_02_BenchmarkModes.measureSamples%3Ap0.99%20%20%20%20sample%20%20%20%20%20%20%200.110%20%20%20%20%20%20%20%20%20%20%20s%2Fop%20--%2099%25%20%E7%9A%84%E6%93%8D%E4%BD%9C%E6%98%AF%E5%9C%A80.11s%E5%86%85%E5%AE%8C%E6%88%90%0AJMHSample_02_BenchmarkModes.measureSamples%3Ap0.999%20%20%20sample%20%20%20%20%20%20%200.110%20%20%20%20%20%20%20%20%20%20%20s%2Fop%20--%2099.9%25%20%E7%9A%84%E6%93%8D%E4%BD%9C%E6%98%AF%E5%9C%A80.11s%E5%86%85%E5%AE%8C%E6%88%90%0AJMHSample_02_BenchmarkModes.measureSamples%3Ap0.9999%20%20sample%20%20%20%20%20%20%200.110%20%20%20%20%20%20%20%20%20%20%20s%2Fop%20--%2099.99%25%20%E7%9A%84%E6%93%8D%E4%BD%9C%E6%98%AF%E5%9C%A80.11s%E5%86%85%E5%AE%8C%E6%88%90%0AJMHSample_02_BenchmarkModes.measureSamples%3Ap1.00%20%20%20%20sample%20%20%20%20%20%20%200.110%20%20%20%20%20%20%20%20%20%20%20s%2Fop%20--%20%E6%89%80%E6%9C%89%E6%93%8D%E4%BD%9C%E5%9C%A8%200.11s%E5%86%85%E5%AE%8C%E6%88%90%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.2.4%20SingleShotTime%20%20%E5%8D%95%E6%AC%A1%E6%89%A7%E8%A1%8C%E8%80%97%E6%97%B6%0A%0A%3E%201.%20%E5%86%B7%E5%90%AF%E5%8A%A8%E6%B5%8B%E8%AF%95%EF%BC%8C%E6%AD%A4%E6%96%B9%E6%B3%95%E5%9C%A8JMH%E4%B8%80%E8%BD%AE%E6%B5%8B%E8%AF%95%E4%B8%AD%E5%8F%AA%E4%BC%9A%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%A8%A1%E5%BC%8F%E4%B8%BB%E8%A6%81%E6%98%AF%E4%B8%BA%E4%BA%86%E6%B5%8B%E8%AF%95%E5%86%B7%E5%90%AF%E5%8A%A8%E7%9A%84%E6%80%A7%E8%83%BD%0A%3E%0A%3E%202.%20%E4%BA%91%E5%8E%9F%E7%94%9F%E6%97%B6%E4%BB%A3%EF%BC%8CJava%E6%98%AF%E8%90%BD%E5%90%8E%E5%90%8E%E5%85%B6%E5%AE%83%E8%AF%AD%E8%A8%80%E7%9A%84%EF%BC%8C%E5%9B%A0%E4%B8%BAjava%E6%9C%89%E4%B8%80%E4%B8%AA%E9%A2%84%E7%83%AD%E7%9A%84%E8%BF%87%E7%A8%8B%EF%BC%8Cjava%E4%BB%A3%E7%A0%81%E6%98%AF%E8%B6%8A%E6%89%A7%E8%A1%8C%E8%B6%8A%E5%BF%AB%EF%BC%8C%E5%AE%83%E9%80%9A%E8%BF%87JIT%E7%9A%84%E6%96%B9%E5%BC%8F%E4%BC%9A%E8%AE%A9%E8%87%AA%E5%B7%B1%E7%9A%84%E6%89%A7%E8%A1%8C%E6%95%88%E7%8E%87%E8%B6%8A%E6%9D%A5%E8%B6%8A%E9%AB%98%2C%20%E8%80%8C%E5%85%B6%E5%AE%83%E8%AF%AD%E8%A8%80%EF%BC%8C%E6%AF%94%E5%A6%82GO%E8%AF%AD%E8%A8%80%EF%BC%8C%E7%BC%96%E8%AF%91%E5%AE%8C%E5%90%8E%E5%B0%B1%E5%B7%B2%E7%BB%8F%E6%9C%80%E9%AB%98%E6%89%A7%E8%A1%8C%E6%95%88%E7%8E%87%E7%9A%84%E6%9C%BA%E5%99%A8%E7%A0%81%0A%3E%0A%3E%20%20%20%20%E6%89%80%E4%BB%A5%E5%AF%B9%E4%BA%8Ejava%E4%BB%A3%E7%A0%81%E6%9D%A5%E8%AF%B4%EF%BC%8C%E5%A6%82%E4%BD%95%E6%8F%90%E9%AB%98%E8%87%AA%E5%B7%B1%E7%9A%84%E5%86%B7%E5%90%AF%E5%8A%A8%E7%9A%84%E6%95%88%E7%8E%87%E4%B9%9F%E6%98%AF%E4%B8%80%E4%B8%AA%E6%AF%94%E8%BE%83%E9%87%8D%E8%A6%81%E4%BC%98%E5%8C%96%E9%A1%B9%0A%0A%60%60%60java%0A%40Benchmark%0A%40BenchmarkMode(Mode.SingleShotTime)%0A%40OutputTimeUnit(TimeUnit.MICROSECONDS)%0Apublic%20void%20measureSingleShot()%20throws%20InterruptedException%20%7B%0A%09TimeUnit.MILLISECONDS.sleep(100)%3B%0A%7D%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20%20%20%20Score%20%20%20Error%20%20Units%0AJMHSample_02_BenchmarkModes.measureSingleShot%20%20%20%20ss%20%20%20%20%20%20%20102272.200%20%20%20%20%20%20%20%20%20%20us%2Fop%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.2.5%20Mode.All%20%E5%85%A8%E9%83%A8%E6%B5%8B%E8%AF%95%0A%0A%60%60%60java%0A%40BenchmarkMode(Mode.All)%20%0A%E7%AD%89%E5%90%8C%E4%BA%8E%0A%40BenchmarkMode(%7BMode.Throughput%2C%20Mode.AverageTime%2C%20Mode.SampleTime%2C%20Mode.SingleShotTime%7D)%20%20%20%20%0A%60%60%60%0A%0A%0A%0A%60%60%60java%0A%40Benchmark%0A%40BenchmarkMode(%7BMode.Throughput%2C%20Mode.AverageTime%2C%20Mode.SampleTime%2C%20Mode.SingleShotTime%7D)%0A%40OutputTimeUnit(TimeUnit.MICROSECONDS)%0Apublic%20void%20measureMultiple()%20throws%20InterruptedException%20%7B%0A%09TimeUnit.MILLISECONDS.sleep(100)%3B%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20%20%20%20Score%20%20%20%20%20%20Error%20%20%20Units%0AJMHSample_02_BenchmarkModes.measureMultiple%20%20%20%20%20%20%20%20%20%20%20thrpt%20%20%20%20%20%20%20%20%20%20%20%E2%89%88%2010%E2%81%BB%E2%81%B5%20%20%20%20%20%20%20%20%20%20%20%20%20ops%2Fus%20--%20%E5%90%9E%E5%90%90%E9%87%8F%E6%B5%8B%E8%AF%95%0AJMHSample_02_BenchmarkModes.measureMultiple%20%20%20%20%20%20%20%20%20%20%20%20avgt%20%20%20%20%20%20%20107870.110%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%20--%20%E5%B9%B3%E5%9D%87%E5%80%BC%E6%B5%8B%E8%AF%95%0AJMHSample_02_BenchmarkModes.measureMultiple%20%20%20%20%20%20%20%20%20%20sample%20%20%2010%20%20109169.869%20%C2%B1%202678.978%20%20%20us%2Fop%20--%20%E6%8A%BD%E6%A0%B7%E6%B5%8B%E8%AF%95%0AJMHSample_02_BenchmarkModes.measureMultiple%3Ap0.00%20%20%20%20sample%20%20%20%20%20%20%20107610.112%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_02_BenchmarkModes.measureMultiple%3Ap0.50%20%20%20%20sample%20%20%20%20%20%20%20108724.224%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_02_BenchmarkModes.measureMultiple%3Ap0.90%20%20%20%20sample%20%20%20%20%20%20%20113390.387%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_02_BenchmarkModes.measureMultiple%3Ap0.95%20%20%20%20sample%20%20%20%20%20%20%20113770.496%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_02_BenchmarkModes.measureMultiple%3Ap0.99%20%20%20%20sample%20%20%20%20%20%20%20113770.496%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_02_BenchmarkModes.measureMultiple%3Ap0.999%20%20%20sample%20%20%20%20%20%20%20113770.496%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_02_BenchmarkModes.measureMultiple%3Ap0.9999%20%20sample%20%20%20%20%20%20%20113770.496%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_02_BenchmarkModes.measureMultiple%3Ap1.00%20%20%20%20sample%20%20%20%20%20%20%20113770.496%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_02_BenchmarkModes.measureMultiple%20%20%20%20%20%20%20%20%20%20%20%20%20%20ss%20%20%20%20%20%20%20101059.700%20%20%20%20%20%20%20%20%20%20%20%20%20%20us%2Fop%09--%20%E5%86%B7%E5%90%AF%E5%8A%A8%E6%B5%8B%E8%AF%95%0A%60%60%60%0A%0A%0A%0A%23%23%23%203.3%20%40State%0A%0A%0A%0A%3E%20%40State%20%E4%BC%9A%E6%A0%87%E8%AE%B0%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%8A%E9%9D%A2%EF%BC%8C%E8%BF%99%E4%B8%AA%E7%B1%BB%E4%BC%9A%E7%94%B1JMH%E7%AE%A1%E7%90%86%E5%B9%B6%E5%88%9D%E5%A7%8B%E5%8C%96%0A%3E%0A%3E%20%E5%9C%A8%E6%89%A7%E8%A1%8C%20%40Benchmark%20%E6%96%B9%E6%B3%95%E6%97%B6%E4%BC%9A%E6%B3%A8%E5%85%A5%E5%88%B0%E6%96%B9%E6%B3%95%E4%B8%AD%0A%0A%23%23%23%23%203.3.1%20Scope%0A%0A%23%23%23%23%23%203.3.1.1%20Scope.Thread%0A%0A%60%60%60java%0A%2F%2F%20%E8%BF%99%E4%B8%AA%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB%E4%BC%9A%E5%9C%A8Benchmark%E5%90%84%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E5%89%8D%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%20%E4%BD%9C%E4%B8%BA%E5%85%A5%E5%8F%82%EF%BC%8C%E4%B8%94%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%85%A5%E5%8F%82%E9%83%BD%E6%98%AF%E4%B8%8D%E4%B8%80%E6%A0%B7%E7%9A%84%0A%40State(Scope.Thread)%0Apublic%20static%20class%20ThreadState%20%7B%0A%20%20%20%20volatile%20double%20x%20%3D%20Math.PI%3B%0A%7D%0A%0A%40Benchmark%0Apublic%20void%20measureUnshared(ThreadState%20state)%20%7B%0A%20%20%20%20state.x%2B%2B%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%203.3.1.2%20Scope.Beanchmark%0A%0A%60%60%60java%0A%2F%2F%20%E8%BF%99%E4%B8%AA%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB%E4%BC%9A%E5%9C%A8%E6%95%B4%E4%B8%AABenchmark%E5%90%AF%E5%8A%A8%E6%97%B6%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%20%E4%BD%9C%E4%B8%BA%E5%85%A5%E5%8F%82%EF%BC%8C%E4%B8%94%E6%89%80%E6%9C%89%E6%B5%8B%E8%AF%95%E7%BA%BF%E7%A8%8B%E5%85%B1%E4%BA%AB%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E7%94%A8%E4%BA%8E%E6%B5%8B%E8%AF%95%E6%9C%89%E7%8A%B6%E6%80%81%E5%AE%9E%E4%BE%8B%E5%9C%A8%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%85%B1%E4%BA%AB%E4%B8%8B%E7%9A%84%E6%80%A7%E8%83%BD%0A%40State(Scope.Benchmark)%0Apublic%20static%20class%20BenchmarkState%20%7B%0A%09volatile%20double%20x%20%3D%20Math.PI%3B%0A%7D%0A%0A%40Benchmark%0Apublic%20void%20measureShared(BenchmarkState%20state)%20%7B%0A%20%20%20%20state.x%2B%2B%3B%0A%7D%0A%0A%60%60%60%0A%0A%60%60%60java%0Apublic%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%20%20%20.include(JMHSample_03_States.class.getSimpleName())%0A%20%20%20%20%20%20%20%20.threads(4)%20%2F%2F%20%E5%9C%A8%E6%89%A7%E8%A1%8C%E6%AF%8F%E4%B8%80%E4%B8%AAbenchmark%E6%97%B6%E4%BC%9A%E5%88%9B%E5%BB%BA4%E4%B8%AA%E7%BA%BF%E7%A8%8B%0A%20%20%20%20%20%20%20%20.forks(1)%0A%20%20%20%20%20%20%20%20.build()%3B%0A%0A%20%20%20%20new%20Runner(opt).run()%3B%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20%20%20%20%20%20%20Score%20%20%20Error%20%20Units%0AJMHSample_03_States.measureShared%20%20%20%20thrpt%20%20%20%20%20%20%20%2056734444.884%20%20%20%20%20%20%20%20%20%20ops%2Fs%0AJMHSample_03_States.measureUnshared%20%20thrpt%20%20%20%20%20%20%20569412894.729%20%20%20%20%20%20%20%20%20%20ops%2Fs%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%203.3.1.3%20Scope.Group%0A%0A%3E%20%E5%BD%93%E5%A4%9A%E4%B8%AA%E7%9A%84benchmark%E6%A0%87%E8%AE%B0%E4%B8%BA%E5%90%8C%E4%B8%80%E4%B8%AA%E7%BB%84%EF%BC%8C%E6%A0%87%E8%AE%B0%E4%B8%BA%E5%90%8C%E4%B8%80%E4%B8%AA%E7%BB%84%E7%9A%84benchmark%E4%BC%9A%E6%94%BE%E5%9C%A8%E4%B8%80%E8%B5%B7%E6%89%A7%E8%A1%8C%0A%3E%0A%3E%20inc%E6%96%B9%E6%B3%95%E5%92%8Cget%E6%96%B9%E6%B3%95%E4%BC%9A%E8%A2%AB%E6%94%BE%E5%88%B0%E5%90%8C%E4%B8%80%E4%B8%AAbenckmark%E9%87%8C%E9%9D%A2%E5%8E%BB%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%B9%B6%E5%88%9B%E5%BB%BA3%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8Cink%E6%96%B9%E6%B3%95%EF%BC%8C%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8Cget%E6%96%B9%E6%B3%95%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%E5%9C%A8%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%8B%E7%9A%84%E6%89%A7%E8%A1%8C%E6%95%88%E7%8E%87%E6%97%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%40Group%E5%88%9B%E9%80%A0%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%8B%E7%9A%84%E7%AB%9E%E4%BA%89%E7%8E%AF%E5%A2%83%E6%9D%A5%E8%A1%A1%E9%87%8F%E7%9C%9F%E5%AE%9E%E7%9A%84%E6%89%A7%E8%A1%8C%E6%95%88%E7%8E%87%0A%0A%0A%0A%60%60%60java%0A%40State(Scope.Group)%0A%40BenchmarkMode(Mode.Throughput)%0A%40OutputTimeUnit(TimeUnit.NANOSECONDS)%0Apublic%20class%20JMHSample_15_Asymmetric%20%7B%0A%0A%20%20%20%20private%20AtomicInteger%20counter%3B%0A%0A%20%20%20%20%40Setup%0A%20%20%20%20public%20void%20up()%20%7B%0A%20%20%20%20%20%20%20%20counter%20%3D%20new%20AtomicInteger()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20%40Group(%22g%22)%0A%20%20%20%20%40GroupThreads(3)%20%2F%2F%E5%90%AF%E5%8A%A83%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%8E%BB%E6%89%A7%E8%A1%8Cinc%E6%96%B9%E6%B3%95%E5%AF%B9%E5%8F%98%E9%87%8Fcounter%E8%BF%9B%E8%A1%8C%E8%87%AA%E5%A2%9E%0A%20%20%20%20public%20int%20inc()%20%7B%0A%20%20%20%20%20%20%20%20return%20counter.incrementAndGet()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20%40Group(%22g%22)%0A%20%20%20%20%40GroupThreads(1)%20%2F%2F%E5%90%AF%E5%8A%A8%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%8E%BB%E6%89%A7%E8%A1%8Cget%E6%96%B9%E6%B3%95%E8%8E%B7%E5%8F%96counter%E9%87%8C%E9%9D%A2%E7%9A%84%E5%8F%98%E9%87%8F%E5%80%BC%0A%20%20%20%20public%20int%20get()%20%7B%0A%20%20%20%20%20%20%20%20return%20counter.get()%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20%40Group(%22g_single_get%22)%0A%20%20%20%20public%20int%20single_get()%20%7B%0A%20%20%20%20%20%20%20%20return%20counter.get()%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20%40Group(%22g_single_ink_1%22)%0A%20%20%20%20%40GroupThreads(1)%0A%20%20%20%20public%20int%20single_ink_1()%20%7B%0A%20%20%20%20%20%20%20%20return%20counter.get()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20%40Group(%22g_single_ink_3%22)%0A%20%20%20%20%40GroupThreads(3)%0A%20%20%20%20public%20int%20single_ink_3()%20%7B%0A%20%20%20%20%20%20%20%20return%20counter.get()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.include(JMHSample_15_Asymmetric.class.getSimpleName())%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.warmupIterations(1)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.warmupTime(TimeValue.seconds(2))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.measurementIterations(1)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.measurementTime(TimeValue.seconds(1))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.forks(1)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%0A%20%20%20%20%20%20%20%20new%20Runner(opt).run()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%60%60%60java%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20%20Units%0AJMHSample_15_Asymmetric.g%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20thrpt%20%20%20%20%20%20%200.144%20%20%20%20%20%20%20%20%20%20ops%2Fns%0AJMHSample_15_Asymmetric.g%3Aget%20%20%20%20%20%20%20%20%20%20%20thrpt%20%20%20%20%20%20%200.090%20%20%20%20%20%20%20%20%20%20ops%2Fns%0AJMHSample_15_Asymmetric.g%3Ainc%20%20%20%20%20%20%20%20%20%20%20thrpt%20%20%20%20%20%20%200.054%20%20%20%20%20%20%20%20%20%20ops%2Fns%0AJMHSample_15_Asymmetric.g_single_get%20%20%20%20thrpt%20%20%20%20%20%20%200.721%20%20%20%20%20%20%20%20%20%20ops%2Fns%0AJMHSample_15_Asymmetric.g_single_ink_1%20%20thrpt%20%20%20%20%20%20%200.704%20%20%20%20%20%20%20%20%20%20ops%2Fns%0AJMHSample_15_Asymmetric.g_single_ink_3%20%20thrpt%20%20%20%20%20%20%201.940%20%20%20%20%20%20%20%20%20%20ops%2Fns%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.3.2%20default%20state%0A%0A%60%60%60java%0A%40State(Scope.Thread)%20%2F%2F%20%E7%9B%B8%E5%BD%93%E4%BA%8E%E5%B0%86%E5%BD%93%E5%89%8D%E7%B1%BB%E4%BD%9C%E4%B8%BA%E4%B8%80%E4%B8%AA%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB%EF%BC%8C%E5%B9%B6%E5%9C%A8Benchmark%E5%90%84%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E5%89%8D%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%20%E4%BD%9C%E4%B8%BA%E5%85%A5%E5%8F%82%EF%BC%8C%E4%B8%94%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%85%A5%E5%8F%82%E9%83%BD%E6%98%AF%E4%B8%8D%E4%B8%80%E6%A0%B7%E7%9A%84%2C%20%E8%BF%99%E6%A0%B7%E4%BC%9A%E6%96%B9%E4%BE%BF%E6%B5%8B%E8%AF%95%EF%BC%8C%E4%B8%8D%E7%94%A8%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%B9%B6%E5%B0%86%E8%BF%99%E4%B8%AA%E7%B1%BB%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0%E4%BC%A0%E5%85%A5Benchmark%E6%96%B9%E6%B3%95%E4%B8%AD%0Apublic%20class%20JMHSample_04_DefaultState%7B%0A%20%09double%20x%20%3D%20Math.PI%3B%0A%0A%09%40Benchmark%0A%09public%20void%20measure()%20%7B%0A%09%09x%2B%2B%3B%0A%09%7D%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20%20%20%20%20%20%20Score%20%20%20Error%20%20Units%0AJMHSample_04_DefaultState.measure%20%20thrpt%20%20%20%20%20%20%20545266394.109%20%20%20%20%20%20%20%20%20%20ops%2Fs%0A%60%60%60%0A%0A%0A%0A%23%23%23%203.4%20%40Setup%20%26%20%40TearDown%0A%0A%60%60%60java%0A%40Setup%20%2F%2F%20%E5%90%AF%E5%8A%A8Benchmark%20%E4%B9%8B%E5%89%8D%E5%81%9A%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C%2C%20%E5%BF%85%E9%A1%BB%E5%9C%A8%40State%E6%A0%87%E8%AF%86%E7%9A%84%E7%B1%BB%E4%B8%AD%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%AE%9E%E9%99%85%E4%B8%8A%E6%98%AF%40State%E6%A0%87%E8%AF%86%E7%B1%BB%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%0Apublic%20void%20prepare()%20%7B%0A%09x%20%3D%20Math.PI%3B%0A%20%20%20%20System.out.println(%22-----%20do%20Setup%22)%3B%0A%7D%0A%0A%40TearDown%20%2F%2F%20Benchmark%20%E7%BB%93%E6%9D%9F%E4%B9%8B%E5%90%8E%E5%81%9A%E6%94%B6%E5%B0%BE%E5%B7%A5%E4%BD%9C%2C%20%E5%BF%85%E9%A1%BB%E5%9C%A8%40State%E6%A0%87%E8%AF%86%E7%9A%84%E7%B1%BB%E4%B8%AD%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%AE%9E%E9%99%85%E4%B8%8A%E6%98%AF%40State%E6%A0%87%E8%AF%86%E7%B1%BB%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%0Apublic%20void%20check()%20%7B%0A%20%20%20%20System.out.println(%22-----%20do%20TearDown%22)%3B%0A%7D%0A%0A%40Benchmark%0Apublic%20void%20measureRight()%20%7B%0A%20%20%20%20x%2B%2B%3B%0A%7D%0A%0A%40Benchmark%0Apublic%20void%20measureWrong()%20%7B%0A%20%20%20%20double%20x%20%3D%200%3B%0A%20%20%20%20x%2B%2B%3B%0A%7D%0A%0A%0A%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%20%20%20%20.include(JMHSample_05_StateFixtures.class.getSimpleName())%0A%20%20%20%20%20%20%20%20%20.forks(1)%0A%20%20%20%20%20%20%20%20%20.jvmArgs(%22-ea%22)%0A%20%20%20%20%20%20%20%20%20.build()%3B%0A%0A%20%20%20%20%20new%20Runner(opt).run()%3B%0A%20%7D%0A%60%60%60%0A%0A%0A%0A%60%60%60java%0A%23%20Benchmark%3A%20org.openjdk.jmh.samples.JMHSample_05_StateFixtures.measureRight%0A%0A%23%20Run%20progress%3A%200.00%25%20complete%2C%20ETA%2000%3A00%3A04%0A%23%20Fork%3A%201%20of%201%0A%23%20Warmup%20Iteration%20%20%201%3A%20-----%20do%20Setup%0A531640672.812%20ops%2Fs%0AIteration%20%20%201%3A%20-----%20do%20TearDown%0A554361599.723%20ops%2Fs%0A%0A%20%20%20%20%0A%23%20Benchmark%3A%20org.openjdk.jmh.samples.JMHSample_05_StateFixtures.measureWrong%0A%0A%23%20Run%20progress%3A%2050.00%25%20complete%2C%20ETA%2000%3A00%3A02%0A%23%20Fork%3A%201%20of%201%0A%23%20Warmup%20Iteration%20%20%201%3A%20-----%20do%20Setup%0A4497489243.589%20ops%2Fs%0AIteration%20%20%201%3A%20-----%20do%20TearDown%0A4526285173.485%20ops%2Fs%0A%20%20%20%20%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20%20%20%20%20%20%20%20Score%20%20%20Error%20%20Units%0AJMHSample_05_StateFixtures.measureRight%20%20thrpt%20%20%20%20%20%20%20%20529834411.876%20%20%20%20%20%20%20%20%20%20ops%2Fs%0AJMHSample_05_StateFixtures.measureWrong%20%20thrpt%20%20%20%20%20%20%203867906327.891%20%20%20%20%20%20%20%20%20%20ops%2Fs%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.4.1%20Level.Trial%0A%0A%3E%20%60%60%60%0A%3E%20%40Setup(Level.Trial)%20%2F%2F%20%E6%95%B4%E4%B8%AABenchmark%E6%B5%8B%E8%AF%95%E5%BC%80%E5%A7%8B%E5%89%8D%E4%BC%9A%E8%A2%AB%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%EF%BC%8C%E5%90%8E%E9%9D%A2%E4%B8%8D%E5%86%8D%E6%89%A7%E8%A1%8C%0A%3E%20%40TearDown(Level.Trial)%20%2F%2F%20%E6%95%B4%E4%B8%AABenchmark%E6%B5%8B%E8%AF%95%E5%AE%8C%E6%88%90%E5%90%8E%E6%89%8D%E4%BC%9A%E8%A2%AB%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%EF%BC%8C%E5%90%8E%E9%9D%A2%E4%B8%8D%E5%86%8D%E6%89%A7%E8%A1%8C%0A%3E%20%60%60%60%0A%0A%60%60%60java%0A%40Setup(Level.Trial)%0Apublic%20void%20init()%20%7B%0A%09System.out.println(%22-----%20do%20Setup%22)%3B%0A%7D%0A%0A%40TearDown(Level.Trial)%0Apublic%20void%20check()%20%7B%0A%09System.out.println(%22-----%20do%20TearDown%22)%3B%0A%7D%0A%0A%23%20Warmup%20Iteration%20%20%201%3A%20-----%20do%20Setup%0A4421937429.452%20ops%2Fs%0A%23%20Warmup%20Iteration%20%20%202%3A%204485015612.898%20ops%2Fs%0A%23%20Warmup%20Iteration%20%20%203%3A%204458406467.342%20ops%2Fs%0AIteration%20%20%201%3A%204490684681.514%20ops%2Fs%0AIteration%20%20%202%3A%204480366157.457%20ops%2Fs%0AIteration%20%20%203%3A%20-----%20do%20TearDown%0A4491445447.792%20ops%2Fs%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.4.2%20Level.Iteration%0A%0A%3E%20%60%60%60%0A%3E%20%40Setup(Level.Iteration)%20%2F%2F%20%E6%AF%8F%E4%B8%80%E8%BD%AEBenchmark%E6%B5%8B%E8%AF%95%E5%BC%80%E5%A7%8B%E5%89%8D%E4%BC%9A%E8%A2%AB%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%0A%3E%20%40TearDown(Level.Iteration)%20%2F%2F%20%E6%AF%8F%E4%B8%80%E8%BD%AEBenchmark%E6%B5%8B%E8%AF%95%E5%AE%8C%E6%88%90%E5%90%8E%E6%89%8D%E4%BC%9A%E8%A2%AB%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%0A%3E%20%60%60%60%0A%0A%60%60%60java%0A%40Setup(Level.Iteration)%0Apublic%20void%20init()%20%7B%0A%09System.out.println(%22-----%20do%20Setup%22)%3B%0A%7D%0A%0A%40TearDown(Level.Iteration)%0Apublic%20void%20check()%20%7B%0A%09System.out.println(%22-----%20do%20TearDown%22)%3B%0A%7D%0A%0A%23%20Warmup%20Iteration%20%20%201%3A%20-----%20do%20Setup%0A-----%20do%20TearDown%0A498103233.061%20ops%2Fs%0A%23%20Warmup%20Iteration%20%20%202%3A%20-----%20do%20Setup%0A-----%20do%20TearDown%0A519591601.900%20ops%2Fs%0A%23%20Warmup%20Iteration%20%20%203%3A%20-----%20do%20Setup%0A-----%20do%20TearDown%0A547577377.973%20ops%2Fs%0AIteration%20%20%201%3A%20-----%20do%20Setup%0A-----%20do%20TearDown%0A553250593.661%20ops%2Fs%0AIteration%20%20%202%3A%20-----%20do%20Setup%0A-----%20do%20TearDown%0A551605708.992%20ops%2Fs%0AIteration%20%20%203%3A%20-----%20do%20Setup%0A-----%20do%20TearDown%0A553137249.413%20ops%2Fs%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.4.3%20Level.Invocation%0A%0A%3E%20%60%60%60%0A%3E%20%40Setup(Level.Invocation)%20%2F%2F%20%E6%AF%8F%E6%AC%A1%E6%96%B9%E6%B3%95%E8%A2%AB%E8%B0%83%E7%94%A8%EF%BC%8C%E9%83%BD%E4%BC%9A%E8%A2%AB%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%0A%3E%20%40TearDown(Level.Invocation)%20%2F%2F%20%E6%AF%8F%E6%AC%A1%E6%96%B9%E6%B3%95%E8%A2%AB%E8%B0%83%E7%94%A8%E5%AE%8C%E5%90%8E%EF%BC%8C%E9%83%BD%E4%BC%9A%E8%A2%AB%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%0A%3E%20%60%60%60%0A%0A%60%60%60java%0A%40Setup(Level.Invocation)%0Apublic%20void%20init()%20%7B%0A%09System.out.println(%22-----%20do%20Setup%22)%3B%0A%7D%0A%0A%40TearDown(Level.Invocation)%0Apublic%20void%20check()%20%7B%0A%09System.out.println(%22-----%20do%20TearDown%22)%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%203.5%20%40Param%0A%0A%3E%20%E6%8C%87%E5%AE%9A%E6%9F%90%E9%A1%B9%E5%8F%82%E6%95%B0%E7%9A%84%E5%A4%9A%E7%A7%8D%E6%83%85%E5%86%B5%EF%BC%8C%E7%89%B9%E5%88%AB%E9%80%82%E5%90%88%E7%94%A8%E6%9D%A5%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E5%8F%82%E6%95%B0%E8%BE%93%E5%85%A5%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E7%9A%84%E6%80%A7%E8%83%BD%EF%BC%8C%E5%8F%AA%E8%83%BD%E4%BD%9C%E7%94%A8%E5%9C%A8%E5%AD%97%E6%AE%B5%E4%B8%8A%EF%BC%8C%E4%BD%BF%E7%94%A8%E8%AF%A5%E6%B3%A8%E8%A7%A3%E5%BF%85%E9%A1%BB%E5%AE%9A%E4%B9%89%20%60%40State%60%20%E6%B3%A8%E8%A7%A3%E3%80%82%0A%3E%0A%3E%20%60%60%60java%0A%3E%20%40Param(value%20%3D%20%7B%2210%22%2C%20%2250%22%2C%20%22100%22%7D)%0A%3E%20private%20int%20length%3B%0A%3E%20%60%60%60%0A%0A%0A%0A%23%23%23%203.6%20%E5%86%B7%E5%90%AF%E5%8A%A8%E5%92%8C%E7%83%AD%E5%90%AF%E5%8A%A8%0A%0A%60%60%60java%0A%2F%2F%20%E6%A8%A1%E6%8B%9F%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E5%86%B7%E5%90%AF%E5%8A%A8%E5%92%8C%E7%83%AD%E5%90%AF%E5%8A%A8%2C%20%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%90%AF%E5%8A%A8%E6%98%AF%E9%9C%80%E8%A6%81%E8%80%97%E6%97%B6%E7%9A%84%EF%BC%8C%E8%BF%99%E9%87%8C%E9%9D%A2%E5%81%87%E8%AE%BE%E8%80%97%E6%97%B6%E4%B8%BA10ms%0Aorg.openjdk.jmh.samples.JMHSample_07_FixtureLevelInvocation%0A%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20Score%20%20%20Error%20%20Units%0AJMHSample_07_FixtureLevelInvocation.measureCold%20%20avgt%20%20%20%202%20%20122.002%20%20%20%20%20%20%20%20%20%20us%2Fop%0AJMHSample_07_FixtureLevelInvocation.measureHot%20%20%20avgt%20%20%20%202%20%20%20%206.787%20%20%20%20%20%20%20%20%20%20us%2Fop%0A%60%60%60%0A%0A%0A%0A%23%23%23%203.7%20DeadCode%0A%0A%3E%20org.openjdk.jmh.samples.JMHSample_08_DeadCode%0A%3E%0A%3E%20%E5%9B%A0%E4%B8%BAJMH%E4%BD%BF%E7%94%A8%E4%B8%8D%E5%BD%93%EF%BC%8C%E5%AF%BC%E8%87%B4%E4%B8%80%E4%BA%9BBenchmark%E8%A2%ABJVM%E4%BC%98%E5%8C%96%E6%8E%89%EF%BC%8C%E6%B5%8B%E8%AF%95%E4%B8%8D%E5%87%BA%E7%9C%9F%E5%AE%9E%E6%89%A7%E8%A1%8C%E6%95%88%E7%8E%87%0A%0A%60%60%60java%0A%2F%2F%20%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E5%9B%A0%E4%B8%BA%E6%B2%A1%E6%9C%89%E8%BF%94%E5%9B%9E%E5%80%BC%E4%BC%9A%E8%A2%ABJVM%E4%BC%98%E5%8C%96%E6%8E%89%0A%2F%2F%20JVM%E9%80%9A%E8%BF%87%E6%96%B9%E6%B3%95%E5%86%85%E8%81%94%E5%92%8C%E9%80%83%E9%80%B8%E6%A3%80%E6%B5%8B%EF%BC%8C%E5%8F%91%E7%8E%B0%E6%B2%A1%E6%9C%89%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%80%BC%EF%BC%8C%E6%89%80%E4%BB%A5compute(x)%3B%20%E8%BF%99%E8%A1%8C%E4%BB%A3%E7%A0%81%E5%B0%B1%E4%BC%9A%E8%A2%AB%E4%BC%98%E5%8C%96%E6%8E%89%EF%BC%8C%E5%AF%BC%E8%87%B4%E5%92%8C%E7%A9%BA%E6%96%B9%E6%B3%95%E7%9A%84%E6%89%A7%E8%A1%8C%E6%95%88%E7%8E%87%E5%9F%BA%E6%9C%AC%E4%B8%80%E8%87%B4%0A%40Benchmark%0Apublic%20void%20measureWrong()%20%7B%0A%20%20%20%20compute(x)%3B%0A%7D%0A%0Apublic%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%09.include(JMHSample_08_DeadCode.class.getSimpleName())%0A%20%20%20%20%20%09.forks(1)%0A%20%20%20%20%20%09.jvmArgs(%22-server%22)%20%2F%2F%20%E8%BF%99%E9%87%8C%E8%AE%BE%E7%BD%AE%E4%B8%BAserver%E6%A8%A1%E5%BC%8F%EF%BC%8C%E4%BB%A5%E5%85%85%E5%88%86%E4%BD%BF%E7%94%A8JIT%0A%20%20%20%20%20%09.build()%3B%0A%0A%20%20%20%20new%20Runner(opt).run()%3B%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_08_DeadCode.baseline%20%20%20%20%20%20avgt%20%20%20%202%20%200.231%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_08_DeadCode.measureRight%20%20avgt%20%20%20%202%20%208.931%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_08_DeadCode.measureWrong%20%20avgt%20%20%20%202%20%200.299%20%20%20%20%20%20%20%20%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%0A%0A%60%60%60java%0A%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%09.include(JMHSample_08_DeadCode.class.getSimpleName())%0A%20%20%20%20%20%09.forks(1)%0A%20%20%20%20%20%09.build()%3B%0A%0A%20%20%20%20new%20Runner(opt).run()%3B%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_08_DeadCode.baseline%20%20%20%20%20%20avgt%20%20%20%202%20%200.225%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_08_DeadCode.measureRight%20%20avgt%20%20%20%202%20%208.909%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_08_DeadCode.measureWrong%20%20avgt%20%20%20%202%20%200.223%20%20%20%20%20%20%20%20%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%23%203.8%20blackhole%0A%0A%3E%E5%8F%AA%E6%9C%89%E5%9C%A8jdk8%E4%B8%8B%E6%89%8D%E6%9C%89%E6%84%8F%E4%B9%89%0A%0A%0A%0A%60%60%60java%0A%40Benchmark%0Apublic%20double%20baseline()%20%7B%0A%20%20%20%20return%20compute(x1)%3B%0A%7D%0A%0A%40Benchmark%0Apublic%20double%20measureWrong()%20%7B%0A%20%20%20%20compute(x1)%3B%20%2F%2F%20JVM%E9%80%9A%E8%BF%87%E6%96%B9%E6%B3%95%E5%86%85%E8%81%94%E5%92%8C%E9%80%83%E9%80%B8%E6%A3%80%E6%B5%8B%EF%BC%8C%E5%8F%91%E7%8E%B0%E6%B2%A1%E6%9C%89%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%80%BC%EF%BC%8C%E6%89%80%E4%BB%A5compute(x1)%3B%20%E8%BF%99%E8%A1%8C%E4%BB%A3%E7%A0%81%E5%B0%B1%E4%BC%9A%E8%BF%9B%E8%A1%8CJIT%E4%BC%98%E5%8C%96%E8%A2%AB%E4%BC%98%E5%8C%96%E6%8E%89%EF%BC%8C%E5%AF%BC%E8%87%B4%E5%92%8C%E7%A9%BA%E6%96%B9%E6%B3%95%E7%9A%84%E6%89%A7%E8%A1%8C%E6%95%88%E7%8E%87%E5%9F%BA%E6%9C%AC%E4%B8%80%E8%87%B4%0A%20%20%20%20return%20compute(x2)%3B%0A%7D%0A%0A%2F%2F%20%E5%8F%AF%E8%83%BD%E6%8A%8A%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%E7%9A%84%E6%96%B9%E6%B3%95%E7%9B%B8%E5%8A%A0%EF%BC%8C%E8%BF%99%E6%A0%B7%E8%BF%99%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%E9%83%BD%E4%BC%9A%E5%9C%A8computer%E6%96%B9%E6%B3%95%E4%B8%AD%E8%AE%A1%E7%AE%97%0A%40Benchmark%0Apublic%20double%20measureRight_1()%20%7B%0A%20%20%20%20return%20compute(x1)%20%2B%20compute(x2)%3B%0A%7D%0A%0A%2F%2F%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E9%BB%91%E6%B4%9E%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%BF%99%E6%A0%B7JVM%E5%B0%B1%E8%AE%A4%E4%B8%BA%E8%BF%99%E4%B8%A4%E4%B8%AA%E6%96%B9%E6%B3%95%E9%83%BD%E6%98%AF%E9%9C%80%E8%A6%81%E6%89%A7%E8%A1%8C%E4%B8%8D%E8%83%BD%E4%BC%98%E5%8C%96%E6%8E%89%0A%40Benchmark%0Apublic%20void%20measureRight_2(Blackhole%20bh)%20%7B%0A%20%20%20%20bh.consume(compute(x1))%3B%0A%20%20%20%20bh.consume(compute(x2))%3B%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20Score%20%20%20Error%20%20Units%0AJMHSample_09_Blackholes.baseline%20%20%20%20%20%20%20%20avgt%20%20%20%20%20%20%20%209.947%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_09_Blackholes.measureRight_1%20%20avgt%20%20%20%20%20%20%2018.611%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_09_Blackholes.measureRight_2%20%20avgt%20%20%20%20%20%20%2018.246%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_09_Blackholes.measureWrong%20%20%20%20avgt%20%20%20%20%20%20%20%209.267%20%20%20%20%20%20%20%20%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%23%23%23%203.9%20constant%20fold%20%E5%B8%B8%E9%87%8F%E6%8A%98%E5%8F%A0%0A%0A%3E%20org.openjdk.jmh.samples.JMHSample_10_ConstantFold%0A%3E%0A%3E%20%E7%BC%96%E8%AF%91%E6%97%B6%E7%AE%80%E5%8C%96%E5%B8%B8%E6%95%B0%E7%9A%84%E8%BF%87%E7%A8%8B%0A%3E%0A%3E%20%E8%BF%99%E4%B8%89%E6%96%B9%E6%B3%95%E6%B5%8B%E8%AF%95%E6%97%B6%E9%97%B4%E5%9F%BA%E6%9C%AC%E4%B8%80%E8%87%B4%EF%BC%8C%E6%98%AF%E5%9B%A0%E4%B8%BA%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E8%BF%9B%E8%A1%8C%E4%BA%86%E5%B8%B8%E9%87%8F%E6%8A%98%E5%8F%A0%0A%3E%0A%3E%20-%20%E8%BF%94%E5%9B%9E%E5%80%BC%E6%98%AF%E5%B8%B8%E9%87%8F%E7%9A%84%E6%96%B9%E6%B3%95%0A%3E%20-%20%E5%AF%B9%E5%B8%B8%E9%87%8F%E8%BF%9B%E8%A1%8C%E4%B8%80%E9%80%9A%E8%AE%A1%E7%AE%97%E4%BB%8D%E5%BE%97%E5%88%B0%E4%B8%80%E4%B8%AA%E5%B8%B8%E9%87%8F%0A%3E%20-%20%E5%85%A5%E5%8F%82%E6%98%AFfinal%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%0A%0A%60%60%60%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_10_ConstantFold.baseline%20%20%20%20%20%20%20%20avgt%20%20%20%20%20%20%201.666%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_10_ConstantFold.measureWrong_1%20%20avgt%20%20%20%20%20%20%201.647%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_10_ConstantFold.measureWrong_2%20%20avgt%20%20%20%20%20%20%201.545%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_10_ConstantFold.measureRight%20%20%20%20avgt%20%20%20%20%20%20%209.117%20%20%20%20%20%20%20%20%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%23%23%23%203.10%20Loops%0A%0A%60%60%60java%0A%40Benchmark%0A%40OperationsPerInvocation(10)%20%2F%2F%E5%91%8A%E8%AF%89JMH%20%E8%BF%99%E4%B8%AABenchmark%E8%BF%90%E8%A1%8C%E4%B8%80%E6%AC%A1%E7%9B%B8%E5%BD%93%E4%BA%8E%E8%BF%90%E8%A1%8C%E4%BA%8610%E6%AC%A1%EF%BC%9B%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%E8%BF%99%E4%B8%AABenckmark%E8%99%BD%E7%84%B6%E5%8F%AA%E8%A2%ABJVM%E8%BF%90%E8%A1%8C%E4%BA%86%E4%B8%80%E6%AC%A1%EF%BC%8C%E4%BD%86%E6%98%AFJMH%E5%9C%A8%E8%AE%A1%E7%AE%97%E6%8A%A5%E8%A1%A8%E6%97%B6%E4%BC%9A%E6%8A%8A%E8%BF%99%E4%B8%80%E6%AC%A1%E5%BD%93%E4%BD%9C10%E6%AC%A1%E6%9D%A5%E7%AE%97%0Apublic%20int%20measureWrong_10()%20%7B%0A%20%20%20%20return%20reps(10)%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BA%E5%90%8E%E9%9D%A2%E8%AE%A1%E7%AE%97%E4%B8%80%E6%AC%A1%E7%9A%84%E8%80%97%E6%97%B6%E8%B6%8A%E6%9D%A5%E8%B6%8A%E5%BF%AB%EF%BC%8C%E6%9C%80%E5%90%8E%E6%89%A7%E8%A1%8C%E4%B8%80%E6%AC%A1%E5%8F%AA%E8%A6%810.017ns%EF%BC%8CJVM%E6%8A%8A%E5%A4%9A%E6%AC%A1%E8%AE%A1%E7%AE%97%E8%BF%9B%E8%A1%8C%E4%BA%86%E5%90%88%E5%B9%B6%E9%80%9A%E8%BF%87%E5%88%AB%E7%9A%84%E6%96%B9%E5%BC%8F%E5%BF%AB%E9%80%9F%E8%AE%A1%E7%AE%97%E5%87%BA%E6%9D%A5%E7%BB%93%E6%9E%9C%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%9C%A8%E5%BE%AA%E7%8E%AF%E9%87%8C%E9%9D%A2%E5%BE%97%E5%88%B0%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%9B%B8%E5%8A%A0%E7%9A%84%E8%80%97%E6%97%B6%E6%98%AF%E4%B8%8D%E6%AD%A3%E7%A1%AE%E7%9A%84%0A%3E%0A%3E%20%E6%88%91%E4%BB%AC%E5%8F%AA%E9%9C%80%E8%A6%81%E5%9C%A8%E4%BB%A3%E7%A0%81%E9%87%8C%E9%9D%A2%E6%AD%A3%E5%B8%B8%E5%86%99Benchmark%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E8%87%AA%E4%BD%9C%E8%81%AA%E6%98%8E%E7%9A%84%E5%8A%A0%E5%BE%AA%E7%8E%AF%EF%BC%8CJMH%E5%9C%A8%E6%89%A7%E8%A1%8CBenckmark%E6%97%B6%E5%90%8E%E9%80%9A%E8%BF%87Annotation%20Processor%E4%B8%80%E5%A5%97%E8%A7%84%E8%8C%83%E7%94%9F%E6%88%90%E6%89%A7%E8%A1%8C%E4%BB%A3%E7%A0%81%2C%E4%BC%9A%E8%87%AA%E5%8A%A8%E8%BF%9B%E8%A1%8C%E5%BE%AA%E7%8E%AF%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E8%87%AA%E5%B7%B1%E7%89%B9%E6%84%8F%E5%9C%B0%E5%9C%A8Benchmark%E9%87%8C%E9%9D%A2%E8%87%AA%E5%B7%B1%E5%81%9A%E5%BE%AA%E7%8E%AF%EF%BC%8CJMH%E5%B7%B2%E7%BB%8F%E5%B8%AE%E4%BD%A0%E5%81%9A%E5%A5%BD%E7%9A%84%0A%0A%60%60%60java%0Acontrol.announceWarmdownReady()%3B%0Atry%20%7B%0A%20%20%20%20while%20(control.warmdownShouldWait)%20%7B%0A%20%20%20%20%20%20%20%20blackhole.consume(l_jmhsample_11_loops0_0.measureRight())%3B%0A%20%20%20%20%20%20%20%20if%20(control.shouldYield)%20Thread.yield()%3B%0A%20%20%20%20%20%20%20%20res.allOps%2B%2B%3B%0A%20%20%20%20%7D%0A%7D%20catch%20(Throwable%20e)%20%7B%0A%20%20%20%20if%20(!(e%20instanceof%20InterruptedException))%20throw%20e%3B%0A%7D%0A%60%60%60%0A%0A%60%60%60%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_11_Loops.measureRight%20%20%20%20%20%20%20%20%20avgt%20%20%20%20%20%20%201.555%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_11_Loops.measureWrong_1%20%20%20%20%20%20%20avgt%20%20%20%20%20%20%201.287%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_11_Loops.measureWrong_10%20%20%20%20%20%20avgt%20%20%20%20%20%20%200.156%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_11_Loops.measureWrong_100%20%20%20%20%20avgt%20%20%20%20%20%20%200.016%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_11_Loops.measureWrong_1000%20%20%20%20avgt%20%20%20%20%20%20%200.024%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_11_Loops.measureWrong_10000%20%20%20avgt%20%20%20%20%20%20%200.018%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_11_Loops.measureWrong_100000%20%20avgt%20%20%20%20%20%20%200.017%20%20%20%20%20%20%20%20%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%23%23%23%203.11%20Fork%0A%0A%23%23%23%23%203.11.1%20fork(0)%0A%0A%3E%20fork(0)%20%E5%90%AF%E5%8A%A8JMH%E7%9A%84JVM%E8%BF%9B%E7%A8%8B%E5%92%8C%E6%89%A7%E8%A1%8CBenchmark%E7%9A%84JVM%E8%BF%9B%E7%A8%8B%E6%98%AF%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AA%E8%BF%9B%E7%A8%8B%0A%0A%60%60%60java%0A%40Benchmark%0A%40Fork(0)%0Apublic%20int%20measure1_c1()%7B%0A%20%20%20%20return%201%3B%0A%7D%0A%0Apublic%20static%20void%20printProcessID(String%20name)%20%7B%0A%20%20%20%20System.out.println(%22----------------------------------------------------------------%22)%3B%0A%20%20%20%20System.out.println(name%20%2B%20%22%20pid%20is%20%22%20%2B%20ManagementFactory.getRuntimeMXBean().getName())%3B%0A%20%20%20%20System.out.println(%22----------------------------------------------------------------%22)%3B%0A%7D%0A%0A----------------------------------------------------------------%0Amain%20pid%20is%2020864%40Chris%0A----------------------------------------------------------------%0A%0A%23%20Warmup%20Iteration%20%20%201%3A%20%0A----------------------------------------------------------------%0Asetup%20pid%20is%2020864%40Chris%0A----------------------------------------------------------------%0A0.518%20ns%2Fop%0AIteration%20%20%201%3A%200.457%20ns%2Fop%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_12_Forking_0.measure1_c1%20%20avgt%20%20%20%20%20%20%200.457%20%20%20%20%20%20%20%20%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.11.2%20fork(1)%0A%0A%0A%0A%3Efork(1)%20%E5%90%AF%E5%8A%A8JMH%E7%9A%84JVM%E8%BF%9B%E7%A8%8B%E5%92%8C%E6%89%A7%E8%A1%8CBenchmark%E7%9A%84JVM%E8%BF%9B%E7%A8%8B%E6%98%AF%E5%9C%A8%E4%B8%8D%E5%90%8C%E8%BF%9B%E7%A8%8B%0A%3E%0A%3EJMH%E5%9C%A8%E6%89%A7%E8%A1%8CBenchmar%E6%B5%8B%E8%AF%95%E6%97%B6%E4%BC%9Afork%E5%87%BA%E4%B8%80%E4%B8%AA%E5%85%A8%E6%96%B0%E7%9A%84JVM%E8%BF%9B%E7%A8%8B%E8%BF%9B%E8%A1%8C%E6%B5%8B%E8%AF%95%0A%0A%60%60%60java%0A%40Benchmark%0A%40Fork(1)%0Apublic%20int%20measure1_c1()%7B%0A%20%20%20%20return%201%3B%0A%7D%0A%0A----------------------------------------------------------------%0Amain%20pid%20is%2013352%40Chris%0A----------------------------------------------------------------%0A%0A%23%20Fork%3A%201%20of%201%0A%23%20Warmup%20Iteration%20%20%201%3A%20%0A----------------------------------------------------------------%0Asetup%20pid%20is%2011976%40Chris%0A----------------------------------------------------------------%0A1.676%20ns%2Fop%0AIteration%20%20%201%3A%201.681%20ns%2Fop%0A%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_12_Forking_0.measure1_c1%20%20avgt%20%20%20%20%20%20%201.681%20%20%20%20%20%20%20%20%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.11.3%20fork(10)%0A%0A%3E%20fork(10)%20%E8%A1%A8%E7%A4%BA%E6%95%B4%E4%B8%AAJMH%20fork%E5%87%BA%E4%BA%8610%E4%B8%AAJVM%E8%BF%9B%E8%A1%8C%E4%BE%9D%E6%AC%A1%E5%8E%BB%E6%89%A7%E8%A1%8CBenchmark%E6%B5%8B%E8%AF%95%EF%BC%8C%0A%3E%0A%3E%20%E4%B8%8D%E6%98%AF%E5%B9%B6%E8%A1%8C%E5%8E%BB%E6%89%A7%E8%A1%8CBenchmark%E6%B5%8B%E8%AF%95%EF%BC%8C%E8%80%8C%E6%98%AF%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAJVM%E8%BF%9B%E7%A8%8B%E6%89%A7%E8%A1%8C%E5%AE%8CBenchmark%E6%B5%8B%E8%AF%95%E5%90%8E%E5%86%8D%E9%94%80%E6%AF%81%E8%BF%99%E4%B8%AAJVM%EF%BC%8C%E5%86%8D%E5%88%9B%E5%BB%BA%E5%86%8D%E6%89%A7%E8%A1%8C%E5%86%8D%E9%94%80%E6%AF%81%E8%BF%99%E4%B9%88%E4%B8%80%E4%B8%AA%E8%BF%87%E7%A8%8B%EF%BC%8C%E6%80%BB%E5%85%B1%E5%B0%86benchmark%E6%B5%8B%E8%AF%95%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84JVM%E8%BF%9B%E7%A8%8B%E4%B8%AD%E6%B5%8B%E8%AF%9510%E6%AC%A1%0A%0A%60%60%60java%0A%40State(Scope.Thread)%0A%40BenchmarkMode(Mode.AverageTime)%0A%40Warmup(iterations%20%3D%202%2Ctime%20%3D%201)%0A%40Measurement(iterations%20%3D%202%2C%20time%20%3D%201)%0A%40OutputTimeUnit(TimeUnit.NANOSECONDS)%0Apublic%20class%20JMHSample_12_Forking_1%20%7B%0A%0A%20%20%20%20%40Setup(Level.Trial)%0A%20%20%20%20public%20void%20setup()%7B%0A%20%20%20%20%20%20%20%20printProcessID(%22setup%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20%40Fork(10)%0A%20%20%20%20public%20int%20measure1_c1()%7B%0A%20%20%20%20%20%20%20%20return%201%3B%0A%20%20%20%20%7D%0A%20%20%20%20public%20static%20void%20printProcessID(String%20name)%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(%22----------------------------------------------------------------%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(name%20%2B%20%22%20pid%20is%20%22%20%2B%20ManagementFactory.getRuntimeMXBean().getName())%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22----------------------------------------------------------------%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20%20%20%20%20printProcessID(%22main%22)%3B%0A%20%20%20%20%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.include(JMHSample_12_Forking_1.class.getSimpleName())%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%0A%20%20%20%20%20%20%20%20new%20Runner(opt).run()%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%0A%0A%0Aorg.openjdk.jmh.samples.JMHSample_12_Forking_1%0A----------------------------------------------------------------%0Amain%20pid%20is%208368%40Chris%0A----------------------------------------------------------------%0A%23%20JMH%20version%3A%201.38-SNAPSHOT%0A%23%20VM%20version%3A%20JDK%201.8.0_361%2C%20Java%20HotSpot(TM)%2064-Bit%20Server%20VM%2C%2025.361-b09%0A%23%20VM%20invoker%3A%20C%3A%5CProgram%20Files%5CJava%5Cjdk1.8.0_361%5Cjre%5Cbin%5Cjava.exe%0A%23%20VM%20options%3A%20-javaagent%3AC%3A%5CProgram%20Files%5CJetBrains%5CIntelliJ%20IDEA%202022.3.2%5Clib%5Cidea_rt.jar%3D52902%3AC%3A%5CProgram%20Files%5CJetBrains%5CIntelliJ%20IDEA%202022.3.2%5Cbin%20-Dfile.encoding%3DUTF-8%0A%23%20Blackhole%20mode%3A%20full%20%2B%20dont-inline%20hint%20(auto-detected%2C%20use%20-Djmh.blackhole.autoDetect%3Dfalse%20to%20disable)%0A%23%20Warmup%3A%202%20iterations%2C%201%20s%20each%0A%23%20Measurement%3A%202%20iterations%2C%201%20s%20each%0A%23%20Timeout%3A%2010%20min%20per%20iteration%0A%23%20Threads%3A%201%20thread%2C%20will%20synchronize%20iterations%0A%23%20Benchmark%20mode%3A%20Average%20time%2C%20time%2Fop%0A%23%20Benchmark%3A%20org.openjdk.jmh.samples.JMHSample_12_Forking_1.measure1_c1%0A%0A%23%20Run%20progress%3A%200.00%25%20complete%2C%20ETA%2000%3A00%3A40%0A%23%20Fork%3A%201%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%2014660%40Chris%0A----------------------------------------------------------------%0A1.578%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.673%20ns%2Fop%0AIteration%20%20%201%3A%201.241%20ns%2Fop%0AIteration%20%20%202%3A%201.110%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2010.00%25%20complete%2C%20ETA%2000%3A00%3A43%0A%23%20Fork%3A%202%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%2011336%40Chris%0A----------------------------------------------------------------%0A1.421%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.440%20ns%2Fop%0AIteration%20%20%201%3A%201.147%20ns%2Fop%0AIteration%20%20%202%3A%201.068%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2020.00%25%20complete%2C%20ETA%2000%3A00%3A38%0A%23%20Fork%3A%203%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%204904%40Chris%0A----------------------------------------------------------------%0A1.400%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.434%20ns%2Fop%0AIteration%20%20%201%3A%201.062%20ns%2Fop%0AIteration%20%20%202%3A%201.079%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2030.00%25%20complete%2C%20ETA%2000%3A00%3A33%0A%23%20Fork%3A%204%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%2018992%40Chris%0A----------------------------------------------------------------%0A1.383%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.444%20ns%2Fop%0AIteration%20%20%201%3A%201.074%20ns%2Fop%0AIteration%20%20%202%3A%201.073%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2040.00%25%20complete%2C%20ETA%2000%3A00%3A28%0A%23%20Fork%3A%205%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%2015644%40Chris%0A----------------------------------------------------------------%0A1.396%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.481%20ns%2Fop%0AIteration%20%20%201%3A%201.067%20ns%2Fop%0AIteration%20%20%202%3A%201.067%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2050.00%25%20complete%2C%20ETA%2000%3A00%3A23%0A%23%20Fork%3A%206%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%2020944%40Chris%0A----------------------------------------------------------------%0A1.421%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.435%20ns%2Fop%0AIteration%20%20%201%3A%201.070%20ns%2Fop%0AIteration%20%20%202%3A%201.071%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2060.00%25%20complete%2C%20ETA%2000%3A00%3A19%0A%23%20Fork%3A%207%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%2020208%40Chris%0A----------------------------------------------------------------%0A1.370%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.440%20ns%2Fop%0AIteration%20%20%201%3A%201.068%20ns%2Fop%0AIteration%20%20%202%3A%201.062%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2070.00%25%20complete%2C%20ETA%2000%3A00%3A14%0A%23%20Fork%3A%208%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%201656%40Chris%0A----------------------------------------------------------------%0A1.386%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.437%20ns%2Fop%0AIteration%20%20%201%3A%201.082%20ns%2Fop%0AIteration%20%20%202%3A%201.066%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2080.00%25%20complete%2C%20ETA%2000%3A00%3A09%0A%23%20Fork%3A%209%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%2012804%40Chris%0A----------------------------------------------------------------%0A1.395%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.444%20ns%2Fop%0AIteration%20%20%201%3A%201.067%20ns%2Fop%0AIteration%20%20%202%3A%201.087%20ns%2Fop%0A%0A%23%20Run%20progress%3A%2090.00%25%20complete%2C%20ETA%2000%3A00%3A04%0A%23%20Fork%3A%2010%20of%2010%0A%23%20Warmup%20Iteration%20%20%201%3A%20----------------------------------------------------------------%0Asetup%20pid%20is%2014188%40Chris%0A----------------------------------------------------------------%0A1.396%20ns%2Fop%0A%23%20Warmup%20Iteration%20%20%202%3A%201.455%20ns%2Fop%0AIteration%20%20%201%3A%201.067%20ns%2Fop%0AIteration%20%20%202%3A%201.067%20ns%2Fop%0A%0A%0AResult%20%22org.openjdk.jmh.samples.JMHSample_12_Forking_1.measure1_c1%22%3A%0A%20%201.085%20%C2%B1(99.9%25)%200.036%20ns%2Fop%20%5BAverage%5D%0A%20%20(min%2C%20avg%2C%20max)%20%3D%20(1.062%2C%201.085%2C%201.241)%2C%20stdev%20%3D%200.042%0A%20%20CI%20(99.9%25)%3A%20%5B1.049%2C%201.121%5D%20(assumes%20normal%20distribution)%0A%0A%0A%23%20Run%20complete.%20Total%20time%3A%2000%3A00%3A47%09%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_12_Forking_1.measure1_c1%20%20avgt%20%20%2020%20%201.085%20%C2%B1%200.036%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%203.11.4%20fork()%0A%0A%3E%20fork()%20%20fork%E9%87%8C%E9%9D%A2%E4%B8%BA%E7%A9%BA%EF%BC%8C%E9%BB%98%E8%AE%A4%E8%A1%A8%E7%A4%BAfork%E5%87%BA5%E4%B8%AA%E8%BF%9B%E7%A8%8B%2C%E4%BD%86%E4%B8%8D%E5%BB%BA%E8%AE%AE%E4%BD%BF%E7%94%A8%E9%BB%98%E8%AE%A4%E5%80%BC%EF%BC%8C%E8%BF%99%E6%A0%B7%E4%BC%9A%E9%99%8D%E4%BD%8E%E4%BB%A3%E7%A0%81%E7%9A%84%E5%8F%AF%E8%AF%BB%E6%80%A7%EF%BC%8C%E5%88%AB%E4%BA%BA%E7%9C%8B%E4%BD%A0%E4%BB%A3%E7%A0%81%E6%88%96%E8%80%85%E8%BF%87%E4%B8%A4%E5%A4%A9%E4%BD%A0%E7%9C%8B%E8%87%AA%E5%B7%B1%E7%9A%84%E4%BB%A3%E7%A0%81%E4%B8%8D%E7%9F%A5%E9%81%93%E6%98%AF%E6%83%B3%E5%B9%B2%E5%95%A5%0A%0A%0A%0A%0A%0A%23%23%23%23%203.11.5%20%E5%90%8C%E4%B8%80%E8%BF%9B%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%B9%B2%E6%89%B0%E9%97%AE%E9%A2%98%0A%0A%60%60%60java%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20Score%20%20%20Error%20%20Units%0AJMHSample_12_Forking.measure_1_c1%20%20%20%20%20%20%20%20%20avgt%20%20%20%20%20%20%201.213%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_12_Forking.measure_2_c2%20%20%20%20%20%20%20%20%20avgt%20%20%20%20%20%20%204.182%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_12_Forking.measure_3_c1_again%20%20%20avgt%20%20%20%20%20%20%204.851%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_12_Forking.measure_4_forked_c1%20%20avgt%20%20%20%20%20%20%201.997%20%20%20%20%20%20%20%20%20%20ns%2Fop%0AJMHSample_12_Forking.measure_5_forked_c2%20%20avgt%20%20%20%20%20%20%201.987%20%20%20%20%20%20%20%20%20%20ns%2Fop%0A%60%60%60%0A%0A%0A%0A%60%60%60java%0Apublic%20static%20class%20Counter1%20implements%20Counter%20%7B%0A%20%20%20%20private%20int%20x%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20int%20inc()%20%7B%0A%20%20%20%20%20%20%20%20return%20x%2B%2B%3B%0A%20%20%20%20%7D%0A%7D%0A%0Apublic%20int%20measure(Counter%20c)%20%7B%0A%20%20%20%20int%20s%20%3D%200%3B%0A%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20s%20%2B%3D%20c.inc()%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20s%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%3E%20%E5%9C%A8%E8%B0%83%E7%94%A8%E6%AF%8F%E4%B8%AAc1%E7%9A%84benckmark%E6%97%B6%E4%BC%A0%E5%85%A5%E7%9A%84%E6%98%AFc1%EF%BC%8C%E8%BF%99%E6%97%B6%20%60c.inc()%60%20%E5%B0%B1%E6%98%AF%20%60c1.inc()%60%2C%20JVM%E8%A7%A3%E9%87%8A%E6%89%A7%E8%A1%8C%E5%AE%83%E9%9C%80%E8%A6%81%E5%85%88%E6%89%BE%E5%88%B0c1%E7%9A%84%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%86%8D%E6%89%A7%E8%A1%8Cc1%E7%9A%84%20%60inc()%60%E6%96%B9%E6%B3%95%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%9C%A8%E6%88%91%E4%BB%AC%E7%9A%84%E4%BB%A3%E7%A0%81%E9%87%8C%E9%9D%A2%E6%98%AF%E4%BD%93%E7%8E%B0%E4%B8%8D%E5%87%BA%E6%9D%A5%E7%9A%84%EF%BC%8C%E4%BD%86%E6%98%AFJVM%E7%9A%84%E7%A1%AE%E5%8F%88%E6%98%AF%E8%BF%99%E4%B9%88%E5%81%9A%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%E7%AC%AC%E4%B8%80%E4%B8%AA%E4%BC%A0%E5%85%A5%E7%9A%84%E5%8F%82%E6%95%B0%E6%98%AFc1%EF%BC%8CJVM%E5%B0%B1%E4%BC%9A%E5%81%87%E8%AE%BE%E8%BF%99%E4%B8%AA%E7%B1%BB%E5%9E%8B%E5%8F%82%E6%95%B0%E9%83%BD%E6%98%AFc1%EF%BC%8C%E5%86%8D%E8%BF%9B%E8%A1%8C%E4%B8%80%E4%BA%9B%E6%BF%80%E8%BF%9B%E7%9A%84%E4%BC%98%E5%8C%96%EF%BC%8C%E6%AF%94%E5%A6%82%E6%96%B9%E6%B3%95%E5%86%85%E8%81%94%EF%BC%8C%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6JIT%E6%8A%8Ac.inc()%E5%8F%98%E4%B8%BAx%2B%2B%EF%BC%8C%20%E8%BF%99%E6%A0%B7%20%60int%20inc()%60%20%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E5%B0%B1%E6%B2%A1%E6%9C%89%E4%BA%86%EF%BC%8C%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%89%A7%E8%A1%8C%E6%97%B6%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E7%9A%84%E6%95%88%E7%8E%87%E4%BC%9A%E9%9D%9E%E5%B8%B8%E9%AB%98%E3%80%82%0A%3E%0A%3E%20%E5%BD%93%E6%89%A7%E8%A1%8C%E5%88%B0%E7%AC%AC%E4%BA%8C%E4%B8%AAbenchmark%E6%97%B6%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%AD%A4%E6%97%B6%E9%83%BD%E6%98%AF%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AAJVM%E9%87%8C%E9%9D%A2%EF%BC%8CJVM%E8%AE%B0%E5%BD%95%E7%9A%84Counter%E5%AE%9E%E4%BE%8B%E9%83%BD%E6%98%AFc1%EF%BC%8C%E8%BF%99%E6%97%B6%E6%88%91%E4%BB%AC%E4%BC%A0%E5%85%A5%E4%BA%86%E4%B8%80%E4%B8%AAc2%2C%E5%AF%BC%E8%87%B4%E6%88%91%E4%BB%AC%E7%9A%84%20JIT%20%E4%BC%98%E5%8C%96%E5%A4%B1%E6%95%88%EF%BC%8CJVM%E4%BC%98%E5%8C%96%E9%99%8D%E7%BA%A7%E5%8F%88%E8%BD%AC%E4%B8%BA%E4%BA%86%E8%A7%A3%E9%87%8A%E6%89%A7%E8%A1%8C%EF%BC%8C%E6%94%BE%E5%BC%83%E4%BA%86%E6%96%B9%E6%B3%95%E5%86%85%E8%81%94%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%9C%A8%E6%89%A7%E8%A1%8Cc2%E6%97%B6%EF%BC%8C%E4%BC%9A%E5%85%88%E6%89%BE%E5%88%B0c2%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%86%8D%E5%8E%BBc2%E5%AF%B9%E8%B1%A1%E9%87%8C%E9%9D%A2%E5%88%B0%20%60int%20inc()%60%20%E6%96%B9%E6%B3%95%E5%90%8E%E5%86%8D%E6%89%A7%E8%A1%8C%0A%3E%0A%3E%20%E5%9B%A0%E6%AD%A4%EF%BC%8C%E5%9C%A8%E5%90%8C%E4%B8%AAJVM%E9%87%8C%E9%9D%A2%E5%A4%9A%E4%B8%AAbenchmark%E6%98%AF%E5%8F%AF%E4%BB%A5%E7%9B%B8%E4%BA%92%E5%BD%B1%E5%93%8D%E7%9A%84%EF%BC%8C%20%E6%9C%89%E7%9A%84%E6%97%B6%E5%80%99JVM%E4%BC%9A%E4%BC%98%E5%8C%96%EF%BC%8C%E6%9C%89%E6%97%B6%E5%8F%88%E5%9B%A0%E4%B8%BA%E4%BD%A0%E7%9A%84benchmark%E5%86%99%E7%9A%84%E6%9C%89%E9%97%AE%E9%A2%98%E5%8F%88%E4%B8%8D%E4%BC%98%E5%8C%96%EF%BC%8C%E6%89%80%E4%BB%A5%E5%9C%A8%E8%BF%9B%E8%A1%8Cbenchmark%E6%B5%8B%E8%AF%95%E6%97%B6%E5%B0%BD%E9%87%8F%E6%94%BE%E5%88%B0%E4%B8%8D%E5%90%8C%E7%9A%84JVM%E8%BF%9B%E7%A8%8B%E4%B8%AD%0A%0A%0A%0A%3E%20%E3%80%8AJava%E8%99%9A%E6%8B%9F%E6%9C%BA%E8%A7%84%E8%8C%83%E3%80%8B%20%E5%AD%97%E8%8A%82%E7%A0%81%E6%8C%87%E4%BB%A4invokeinterface%0A%3E%0A%3E%20%E3%80%8A%E6%B7%B1%E5%85%A5%E4%BA%86%E8%A7%A3Java%E8%99%9A%E6%8B%9F%E6%9C%BA%E3%80%8B%E7%AC%AC8%E7%AB%A0%208.4.2%0A%3E%0A%3E%20%E3%80%8A%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Java%E8%99%9A%E6%8B%9F%E6%9C%BA%E3%80%8B%E7%AC%AC11%E7%AB%A0%2011.4.2%0A%0A%0A%0A%23%23%23%23%203.11.6%20%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E7%94%A8fork%0A%0A%3E%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E5%9C%A8JMH%E5%90%AF%E5%8A%A8%E6%97%B6%E8%BF%99%E4%B8%AA%E9%9A%8F%E6%9C%BA%E5%80%BC%E6%98%AF%E5%B7%B2%E7%BB%8F%E7%A1%AE%E8%AE%A4%E5%9C%A8%EF%BC%8C%E5%9C%A8%E6%95%B4%E4%B8%AABenchmark%E6%B5%8B%E8%AF%95%E8%BF%87%E7%A8%8B%E4%B8%AD%E4%BD%BF%E7%94%A8%E7%9A%84%E9%83%BD%E6%98%AF%E4%B8%80%E4%B8%AA%E7%A1%AE%E5%AE%9A%E7%9A%84%E5%80%BC%0A%3E%0A%3E%20%E4%BD%86%E6%AF%8F%E6%AC%A1%E6%89%A7%E8%A1%8C%E5%BE%97%E5%88%B0%E7%9A%84%E9%9A%8F%E6%9C%BA%E6%95%B0%E9%83%BD%E6%98%AF%E4%B8%8D%E4%B8%80%E6%A0%B7%E7%9A%84%EF%BC%8C%E7%9A%84%E8%BF%99%E5%B0%B1%E5%B8%A6%E6%9D%A5%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%8C%E5%A6%82%E4%BD%95%E5%BE%97%E5%88%B0%E4%B8%80%E4%B8%AA%E5%81%8F%E5%B7%AE%E8%BE%83%E5%B0%8F%EF%BC%8C%E6%9B%B4%E6%8E%A5%E8%BF%91%E6%88%91%E4%BB%AC%E6%9C%9F%E6%9C%9B%E5%80%BC%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%BF%99%E6%97%B6%E5%B0%B1%E8%A6%81%E4%BD%BF%E7%94%A8%E5%88%B0fork%0A%0A%60%60%60java%0A%40State(Scope.Thread)%0Apublic%20static%20class%20SleepyState%20%7B%0A%20%20%20%20public%20long%20sleepTime%3B%0A%0A%20%20%20%20%40Setup%0A%20%20%20%20public%20void%20setup()%20%7B%0A%20%20%20%20%20%20%20%20sleepTime%20%3D%20(long)%20(Math.random()%20*%201000)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22----------------------%22)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22sleepTime%3A%22%20%2B%20sleepTime)%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22----------------------%22)%3B%0A%20%20%20%20%7D%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Mode%20%20Cnt%20%20%20%20Score%20%20%20%20%20Error%20%20Units%0AJMHSample_13_RunToRun.baseline%20%20avgt%20%20%20%203%20%20118.507%20%C2%B1%20%20%200.884%20%20ms%2Fop%0AJMHSample_13_RunToRun.fork_1%20%20%20%20avgt%20%20%2015%20%20696.184%20%C2%B1%20187.366%20%20ms%2Fop%0A%60%60%60%0A%0A%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E4%BD%BF%E7%94%A8%E5%88%B0%E7%9A%84%E7%AE%97%E6%B3%95%E6%9C%89%E4%B8%80%E5%AE%9A%E7%9A%84%E9%9A%8F%E6%9C%BA%E6%80%A7%EF%BC%8C%E6%AF%94%E5%A6%82%E4%BC%9A%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E9%9A%8F%E6%9C%BA%E5%80%BC%EF%BC%8C%E7%84%B6%E5%90%8E%E5%9C%A8%E5%90%8E%E9%9D%A2%E7%9A%84%E6%89%A7%E8%A1%8C%E4%B8%AD%E9%83%BD%E4%BC%9A%E4%BD%BF%E7%94%A8%E5%88%B0%E8%BF%99%E4%B8%AA%E9%9A%8F%E6%9C%BA%E5%80%BC%EF%BC%8C%E8%BF%99%E4%B8%AA%E9%9A%8F%E6%9C%BA%E5%80%BC%E6%98%AF%E5%A6%82%E4%BD%95%E5%88%86%E5%B8%83%E7%9A%84%EF%BC%8C%E4%B8%80%E6%AC%A1%E6%88%96%E5%A4%9A%E6%AC%A1%E7%9A%84%E6%B5%8B%E8%AF%95%E6%98%AF%E4%BD%93%E7%8E%B0%E4%B8%8D%E5%87%BA%E6%9D%A5%E7%9A%84%EF%BC%8C%0A%3E%0A%3E%20%E6%AF%94%E5%A6%82%E6%88%91%E4%BB%AC%E4%BC%9A%E6%9C%89%E4%B8%80%E4%BA%9B%E9%9A%8F%E6%9C%BA%E7%AE%97%E6%B3%95%EF%BC%8C%E5%9C%A8%E5%90%AF%E5%8A%A8%E7%9A%84%E6%97%B6%E5%80%99%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E7%A7%8D%E5%AD%90%EF%BC%8C%E5%9C%A8%E6%95%B4%E4%B8%AA%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%E7%9A%84%E7%94%9F%E6%88%90%E7%9A%84%E9%9A%8F%E6%9C%BA%E6%95%B0%E9%83%BD%E4%BC%9A%E5%9F%BA%E4%BA%8E%E8%BF%99%E4%B8%AA%E7%A7%8D%E5%AD%90%EF%BC%8C%E4%B8%BA%E4%BA%86%E4%BD%BF%E7%BB%93%E6%9E%9C%E5%B0%BD%E5%8F%AF%E8%83%BD%E7%9A%84%E5%B9%B3%E5%9D%87%EF%BC%8C%E6%8E%A5%E8%BF%91%E6%88%91%E4%BB%AC%E7%9A%84%E6%9C%9F%E6%9C%9B%E5%80%BC%EF%BC%8C%E5%87%8F%E5%B0%91%E5%81%8F%E5%B7%AE%EF%BC%8C%E5%B0%B1%E8%A6%81%E5%A4%9A%E6%B5%8B%E8%AF%95%E5%87%A0%E8%BD%AE%0A%3E%0A%3E%20%E6%AF%8F%E8%BD%AE%E6%B5%8B%E8%AF%95%E9%83%BD%E6%94%BE%E5%88%B0%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84JVM%E8%BF%9B%E7%A8%8B%E4%B8%AD%E7%8B%AC%E7%AB%8B%E7%9A%84%E6%89%A7%E8%A1%8C%0A%0A%0A%0A%0A%0A%0A%0A%23%23%204%20%E7%BC%96%E5%86%99%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%0A%0A%23%23%23%204.1%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8B%BC%0A%0A%3E%20%E5%88%A4%E6%96%AD%20%60%2B%60%20%E5%92%8C%20%60StringBuilder.append()%60%20%E4%B8%A4%E7%A7%8D%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8B%BC%E6%8E%A5%E5%93%AA%E4%B8%AA%E8%80%97%E6%97%B6%E6%9B%B4%E7%9F%AD%0A%0A%60%60%60java%0A%2F**%0A%20*%20%40Author%3A%2080393617%0A%20*%20%40Date%3A%202023-10-23%20%2014%3A57%0A%20*%20%40Description%3A%20String%20Connect%20Test%0A%20*%2F%0A%40BenchmarkMode(Mode.AverageTime)%0A%40Warmup(iterations%20%3D%202%2C%20time%20%3D%201)%0A%40Measurement(iterations%20%3D%203%2C%20time%20%3D%201)%0A%40State(Scope.Benchmark)%0A%40OutputTimeUnit(TimeUnit.NANOSECONDS)%0Apublic%20class%20StrConnectTest%20%7B%0A%20%20%20%20%40Param(value%20%3D%20%7B%2210%22%2C%20%2250%22%2C%20%22100%22%7D)%0A%20%20%20%20private%20int%20length%3B%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20public%20void%20testStringAdd(Blackhole%20blackhole)%20%7B%0A%20%20%20%20%20%20%20%20String%20a%20%3D%20%22%22%3B%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%2B%3D%20i%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20blackhole.consume(a)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20public%20void%20testStringBuilderAdd(Blackhole%20blackhole)%20%7B%0A%20%20%20%20%20%20%20%20StringBuilder%20sb%20%3D%20new%20StringBuilder()%3B%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sb.append(i)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20blackhole.consume(sb.toString())%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.include(StrConnectTest.class.getSimpleName())%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.threads(4)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.forks(1)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.result(%22result.json%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.resultFormat(ResultFormatType.JSON).build()%3B%0A%20%20%20%20%20%20%20%20new%20Runner(opt).run()%3B%0A%20%20%20%20%7D%0A%7D%0A%0ABenchmark%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(length)%20%20Mode%20%20Cnt%20%20%20%20%20Score%20%20%20%20%20%20Error%20%20Units%0AStrConnectTest.testStringAdd%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2010%20%20avgt%20%20%20%203%20%20%20210.344%20%C2%B1%20%20542.752%20%20ns%2Fop%0AStrConnectTest.testStringAdd%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2050%20%20avgt%20%20%20%203%20%201689.224%20%C2%B1%20%20496.450%20%20ns%2Fop%0AStrConnectTest.testStringAdd%20%20%20%20%20%20%20%20%20%20%20%20%20%20100%20%20avgt%20%20%20%203%20%206102.150%20%C2%B1%204193.507%20%20ns%2Fop%0AStrConnectTest.testStringBuilderAdd%20%20%20%20%20%20%20%2010%20%20avgt%20%20%20%203%20%20%20%2075.982%20%C2%B1%20%20%2062.798%20%20ns%2Fop%0AStrConnectTest.testStringBuilderAdd%20%20%20%20%20%20%20%2050%20%20avgt%20%20%20%203%20%20%20512.804%20%C2%B1%20%20304.180%20%20ns%2Fop%0AStrConnectTest.testStringBuilderAdd%20%20%20%20%20%20%20100%20%20avgt%20%20%20%203%20%201014.121%20%C2%B1%20%20477.335%20%20ns%2Fop%0A%60%60%60%0A%0A%3E%20-%20%60Warmup%20Iteration%60%20%E8%AF%A5%E9%83%A8%E5%88%86%E4%B8%BA%E6%AF%8F%E4%B8%80%E6%AC%A1%E7%83%AD%E8%BA%AB%E4%B8%AD%E7%9A%84%E6%80%A7%E8%83%BD%E6%8C%87%E6%A0%87%EF%BC%8C%E9%A2%84%E7%83%AD%E6%B5%8B%E8%AF%95%E4%B8%8D%E4%BC%9A%E4%BD%9C%E4%B8%BA%E6%9C%80%E7%BB%88%E7%9A%84%E7%BB%9F%E8%AE%A1%E7%BB%93%E6%9E%9C%E3%80%82%E9%A2%84%E7%83%AD%E7%9A%84%E7%9B%AE%E7%9A%84%E6%98%AF**%E8%AE%A9%20JVM%20%E5%AF%B9%E8%A2%AB%E6%B5%8B%E4%BB%A3%E7%A0%81%E8%BF%9B%E8%A1%8C%E8%B6%B3%E5%A4%9F%E5%A4%9A%E7%9A%84%E4%BC%98%E5%8C%96**%EF%BC%8C%E6%AF%94%E5%A6%82%EF%BC%8C%E5%9C%A8%E9%A2%84%E7%83%AD%E5%90%8E%EF%BC%8C%E8%A2%AB%E6%B5%8B%E4%BB%A3%E7%A0%81%E5%BA%94%E8%AF%A5%E5%BE%97%E5%88%B0%E4%BA%86%E5%85%85%E5%88%86%E7%9A%84%20JIT%20%E7%BC%96%E8%AF%91%E5%92%8C%E4%BC%98%E5%8C%96%E3%80%82%0A%3E%0A%3E%20-%20%E8%AF%A5%E9%83%A8%E5%88%86%E6%98%BE%E7%A4%BA%E6%B5%8B%E9%87%8F%E8%BF%AD%E4%BB%A3%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%8C%E6%AF%8F%E4%B8%80%E6%AC%A1%E8%BF%AD%E4%BB%A3%E9%83%BD%E6%98%BE%E7%A4%BA%E4%BA%86%E5%BD%93%E5%89%8D%E7%9A%84%E6%89%A7%E8%A1%8C%E9%80%9F%E7%8E%87%EF%BC%8C%E5%8D%B3%E4%B8%80%E4%B8%AA%E6%93%8D%E4%BD%9C%E6%89%80%E8%8A%B1%E8%B4%B9%E7%9A%84%E6%97%B6%E9%97%B4%E3%80%82%E5%9C%A8%E8%BF%9B%E8%A1%8C%205%20%E6%AC%A1%E8%BF%AD%E4%BB%A3%E5%90%8E%EF%BC%8C%E8%BF%9B%E8%A1%8C%E7%BB%9F%E8%AE%A1%EF%BC%8C%E5%9C%A8%E6%9C%AC%E4%BE%8B%E4%B8%AD%EF%BC%8Clength%20%E4%B8%BA%20100%20%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%20%60testStringBuilderAdd%60%20%E6%96%B9%E6%B3%95%E7%9A%84%E5%B9%B3%E5%9D%87%E6%89%A7%E8%A1%8C%E8%8A%B1%E8%B4%B9%E6%97%B6%E9%97%B4%E4%B8%BA%20%601014.121%20ns%60%EF%BC%8C%E8%AF%AF%E5%B7%AE%E4%B8%BA%20%60477.335%20ns%60%E3%80%82%0A%0A%0A%0A%23%23%23%204.2%20list.sort%E4%B8%8EStream().sorted%0A%0A%0A%0A%60%60%60java%0A%0A%40BenchmarkMode(Mode.AverageTime)%0A%40OutputTimeUnit(TimeUnit.MICROSECONDS)%0A%40Warmup(iterations%20%3D%202%2C%20time%20%3D%201)%0A%40Measurement(iterations%20%3D%205%2C%20time%20%3D%205)%0A%40Fork(1)%0A%40State(Scope.Thread)%0Apublic%20class%20SortBenchmark%20%7B%0A%20%20%20%20%40Param(value%20%3D%20%7B%22100%22%2C%20%2210000%22%2C%20%22100000%22%7D)%0A%20%20%20%20private%20int%20operationSize%3B%20%0A%20%20%20%20private%20static%20List%3CInteger%3E%20arrayList%3B%0A%20%20%20%20%0A%20%20%20%20%40Setup%0A%20%20%20%20public%20void%20init()%20%7B%0A%20%20%20%20%20%20%20%20arrayList%20%3D%20new%20ArrayList%3C%3E()%3B%0A%20%20%20%20%20%20%20%20Random%20random%20%3D%20new%20Random()%3B%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20operationSize%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20arrayList.add(random.nextInt(10000))%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20%40Benchmark%0A%20%20%20%20public%20void%20sort(Blackhole%20blackhole)%20%7B%0A%20%20%20%20%20%20%20%20arrayList.sort(Comparator.comparing(e%20-%3E%20e))%3B%0A%20%20%20%20%20%20%20%20blackhole.consume(arrayList)%3B%0A%20%20%20%20%7D%0A%20%20%20%20%40Benchmark%0A%20%20%20%20public%20void%20streamSorted(Blackhole%20blackhole)%20%7B%0A%20%20%20%20%20%20%20%20arrayList%20%3D%20arrayList.stream().sorted(Comparator.comparing(e%20-%3E%20e)).collect(Collectors.toList())%3B%0A%20%20%20%20%20%20%20%20blackhole.consume(arrayList)%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E5%90%AF%E5%8A%A8%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%0A%20%20%20%20%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20.include(SortBenchmark.class.getSimpleName())%20%0A%20%20%20%20%20%20%20%20%20%20%20%20.result(%22SortBenchmark.json%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20.mode(Mode.All)%0A%20%20%20%20%20%20%20%20%20%20%20%20.resultFormat(ResultFormatType.JSON)%0A%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%20%20%20%20%20%20%20%20new%20Runner(opt).run()%3B%20%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%0A%0A%0A%0A%60%60%60java%0A%40BenchmarkMode(Mode.AverageTime)%0A%40OutputTimeUnit(TimeUnit.MICROSECONDS)%0A%40Warmup(iterations%20%3D%202%2C%20time%20%3D%201)%0A%40Measurement(iterations%20%3D%205%2C%20time%20%3D%205)%0A%40Fork(1)%0A%40State(Scope.Thread)%0Apublic%20class%20SortBenchmark3%20%7B%0A%20%20%20%20%40Param(value%20%3D%20%7B%22100%22%2C%20%2210000%22%7D)%0A%20%20%20%20private%20int%20operationSize%3B%20%2F%2F%20%E6%93%8D%E4%BD%9C%E6%AC%A1%E6%95%B0%0A%20%20%20%20private%20static%20List%3CInteger%3E%20arrayList%3B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20throws%20RunnerException%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E5%90%AF%E5%8A%A8%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%0A%20%20%20%20%20%20%20%20Options%20opt%20%3D%20new%20OptionsBuilder()%0A%20%20%20%20%20%20%20%20%20%20%20%20.include(SortBenchmark3.class.getSimpleName())%20%2F%2F%20%E8%A6%81%E5%AF%BC%E5%85%A5%E7%9A%84%E6%B5%8B%E8%AF%95%E7%B1%BB%0A%20%20%20%20%20%20%20%20%20%20%20%20.result(%22SortBenchmark3.json%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20.mode(Mode.All)%0A%20%20%20%20%20%20%20%20%20%20%20%20.resultFormat(ResultFormatType.JSON)%0A%20%20%20%20%20%20%20%20%20%20%20%20.build()%3B%0A%20%20%20%20%20%20%20%20new%20Runner(opt).run()%3B%20%2F%2F%20%E6%89%A7%E8%A1%8C%E6%B5%8B%E8%AF%95%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Setup%0A%20%20%20%20public%20void%20init()%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E5%90%AF%E5%8A%A8%E6%89%A7%E8%A1%8C%E4%BA%8B%E4%BB%B6%0A%20%20%20%20%20%20%20%20arrayList%20%3D%20new%20ArrayList%3C%3E()%3B%0A%20%20%20%20%20%20%20%20Random%20random%20%3D%20new%20Random()%3B%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20operationSize%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20arrayList.add(random.nextInt(10000))%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20public%20void%20stream(Blackhole%20blackhole)%20%7B%0A%20%20%20%20%20%20%20%20arrayList.stream().collect(Collectors.toList())%3B%0A%20%20%20%20%20%20%20%20blackhole.consume(arrayList)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Benchmark%0A%20%20%20%20public%20void%20sort(Blackhole%20blackhole)%20%7B%0A%20%20%20%20%20%20%20%20arrayList.stream().sorted(Comparator.comparing(Integer%3A%3AintValue)).collect(Collectors.toList())%3B%0A%20%20%20%20%20%20%20%20blackhole.consume(arrayList)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A

诗词

创建时间:2023/9/21 10:24
更新时间:2023/9/21 10:27

原文

王国维蝶恋花·阅尽天涯离别苦

阅尽天涯离别苦,不道归来,零落花如许。花底相看无一语,绿窗春与天俱莫。 待把相思灯下诉,一缕新欢,旧恨千千缕。最是人间留不住,朱颜辞镜花辞树。

译文及注释

译文 我早已历尽天涯离别的痛苦,想不到重回故地时,却看到百花如此零落的情景。忆当时与她花下别离,相对无言,只有离愁别绪噎胸间,现在只剩绿窗青天如故,却已非当时风景了。 想在这萤萤孤灯下细诉相思,细诉别后的相思。可是,一点点新的欢愉,又勾起了无穷的旧恨。在人世间最留不住的,是那在镜中一去不复返的青春和离树飘零的落花。


二十四节气的小满
古人有云:花未全开月未圆,半山微醉尽余欢。何须多虑盈亏事,终归小满胜万全。
小满时节,物产开始灌浆,万物逐渐发展为饱满状态并走向成熟。值此小满之际,我们当从“小满”中感悟“大成”之道,助力人生小满之时胜万全。

Spring plugin 实现策略模式

创建时间:2023/11/26 10:04
更新时间:2023/12/17 10:11
作者:Chris
来源:file:///E:/Program%20Files/Apifox/resources/app/dist/renderer/index.html#/project/1878323

public interface ISmsPlugin extends Plugin<SmsRequestBean> {
    SmsResponseBean sendSms(SmsRequestBean smsRequestBean);
}

@Slf4j
@Component
public class TencentSmsPlugin implements ISmsPlugin {
    @Override
    public SmsResponseBean sendSms(SmsRequestBean smsRequestBean) {
        log.info("tencent sms:{}", JSONUtil.toJsonStr(smsRequestBean));
        return SmsResponseBean.builder().code("200").message("send success").success(true).result("tencent sms response").build();

    }

    @Override
    public boolean supports(SmsRequestBean smsRequestBean) {
        return SmsTypeEnum.TENCENT == smsRequestBean.getSmsType();
    }
}

public interface ISmsService {
    SmsResponseBean sendSms(SmsRequestBean  smsRequestBean);
}

@Service
@RequiredArgsConstructor
public class SmsService implements ISmsService {

    private final PluginRegistry<ISmsPlugin, SmsRequestBean> pluginRegistry;

    @Override
    public SmsResponseBean sendSms(SmsRequestBean smsRequestBean) {
        return pluginRegistry.getPluginFor(smsRequestBean)
                .orElseThrow(() -> new RuntimeException("sms plugin is not binder with type:" + smsRequestBean.getSmsType()))
                .sendSms(smsRequestBean);

    }
}


public enum SmsTypeEnum {
    ALIYUN, TENCENT;
}


@PostMapping("/send")
public SmsResponseBean smsReuqest(@RequestBody SmsRequestBean smsRequestBean) {
    return smsService.sendSms(smsRequestBean);
}

@SpringBootApplication
@EnableRetry
@EnablePluginRegistries({ISmsPlugin.class})
public class Cloud2022Application {

    public static void main(String[] args) {
        SpringApplication.run(Cloud2022Application.class, args);
    }

}
POST http://127.0.0.1:8081/smsReqeust/send
{
    "smsType": "TENCENT"
}
%0A!%5Bc801d14a70f9d36569d16fc7a0c79300.png%5D(en-resource%3A%2F%2Fdatabase%2F1461%3A1)%0A%0A%60%60%60java%0Apublic%20interface%20ISmsPlugin%20extends%20Plugin%3CSmsRequestBean%3E%20%7B%0A%20%20%20%20SmsResponseBean%20sendSms(SmsRequestBean%20smsRequestBean)%3B%0A%7D%0A%0A%40Slf4j%0A%40Component%0Apublic%20class%20TencentSmsPlugin%20implements%20ISmsPlugin%20%7B%0A%20%20%20%20%40Override%0A%20%20%20%20public%20SmsResponseBean%20sendSms(SmsRequestBean%20smsRequestBean)%20%7B%0A%20%20%20%20%20%20%20%20log.info(%22tencent%20sms%3A%7B%7D%22%2C%20JSONUtil.toJsonStr(smsRequestBean))%3B%0A%20%20%20%20%20%20%20%20return%20SmsResponseBean.builder().code(%22200%22).message(%22send%20success%22).success(true).result(%22tencent%20sms%20response%22).build()%3B%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20boolean%20supports(SmsRequestBean%20smsRequestBean)%20%7B%0A%20%20%20%20%20%20%20%20return%20SmsTypeEnum.TENCENT%20%3D%3D%20smsRequestBean.getSmsType()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Apublic%20interface%20ISmsService%20%7B%0A%20%20%20%20SmsResponseBean%20sendSms(SmsRequestBean%20%20smsRequestBean)%3B%0A%7D%0A%0A%40Service%0A%40RequiredArgsConstructor%0Apublic%20class%20SmsService%20implements%20ISmsService%20%7B%0A%0A%20%20%20%20private%20final%20PluginRegistry%3CISmsPlugin%2C%20SmsRequestBean%3E%20pluginRegistry%3B%0A%0A%20%20%20%20%40Override%0A%20%20%20%20public%20SmsResponseBean%20sendSms(SmsRequestBean%20smsRequestBean)%20%7B%0A%20%20%20%20%20%20%20%20return%20pluginRegistry.getPluginFor(smsRequestBean)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.orElseThrow(()%20-%3E%20new%20RuntimeException(%22sms%20plugin%20is%20not%20binder%20with%20type%3A%22%20%2B%20smsRequestBean.getSmsType()))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.sendSms(smsRequestBean)%3B%0A%0A%20%20%20%20%7D%0A%7D%0A%0A%0Apublic%20enum%20SmsTypeEnum%20%7B%0A%20%20%20%20ALIYUN%2C%20TENCENT%3B%0A%7D%0A%0A%0A%40PostMapping(%22%2Fsend%22)%0Apublic%20SmsResponseBean%20smsReuqest(%40RequestBody%20SmsRequestBean%20smsRequestBean)%20%7B%0A%20%20%20%20return%20smsService.sendSms(smsRequestBean)%3B%0A%7D%0A%0A%40SpringBootApplication%0A%40EnableRetry%0A%40EnablePluginRegistries(%7BISmsPlugin.class%7D)%0Apublic%20class%20Cloud2022Application%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20SpringApplication.run(Cloud2022Application.class%2C%20args)%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%60%60%60%0A%0A%60%60%60%0APOST%20http%3A%2F%2F127.0.0.1%3A8081%2FsmsReqeust%2Fsend%0A%7B%0A%20%20%20%20%22smsType%22%3A%20%22TENCENT%22%0A%7D%0A%60%60%60

20231102

创建时间:2023/12/7 22:41
更新时间:2023/12/7 22:42
作者:Chris

honest
polish a little bit
certain kind of
marital status
body checkups
records
stipulate
discrimination
law article
hold against a job compliants
strike balance between
comply with Federal laws / compliance with
uncontrollable
dispit
a gifted teacher
privacy
disability
proper
truthful / untruthful
risk losing this opportunity
affect vt: Does television affect children’s behaviour?
effect n: Does television have an effect on children's behaviour.
conducting a background check
mutual
mature
additionalc
additionally
confidential
crime
criminal
tricky question
survey
socialize with peers
size up
experience
retract
complement
supervisor
instead of
popularity
compliment vt & n: / praise
compliment sb on sth

honest%0Apolish%20a%20little%20bit%0Acertain%20kind%20of%20%0Amarital%20status%0Abody%20checkups%0Arecords%0Astipulate%0Adiscrimination%0Alaw%20article%0Ahold%20against%20a%20job%20compliants%0Astrike%20balance%20between%0Acomply%20with%20Federal%20laws%20%2F%20compliance%20with%0Auncontrollable%0Adispit%0Aa%20gifted%20teacher%0Aprivacy%0Adisability%0Aproper%0Atruthful%20%2F%20untruthful%0Arisk%20losing%20this%20opportunity%0Aaffect%20vt%3A%20Does%20television%20affect%20children%E2%80%99s%20behaviour%3F%0Aeffect%20%20n%3A%20Does%20television%20have%20an%20effect%20on%20children's%20behaviour.%0Aconducting%20a%20background%20check%0Amutual%0Amature%0Aadditionalc%0Aadditionally%0Aconfidential%0Acrime%0Acriminal%0Atricky%20question%0Asurvey%0Asocialize%20with%20peers%0Asize%20up%0Aexperience%0Aretract%0Acomplement%0Asupervisor%0Ainstead%20of%0Apopularity%0Acompliment%20vt%20%26%20n%3A%20%2F%20praise%0Acompliment%20sb%20on%20sth

20231122

创建时间:2023/12/7 22:43
更新时间:2023/12/7 22:43
作者:Chris
来源:file:///E:/Program%20Files/Apifox/resources/app/dist/renderer/index.html#/project/451843

count as outdoor activity
as long as you're going out
a huge load of garbage
innovate | innovator | innovative | innovationlet's get down to the real business
mountaineering
pickleball
entire year
outdoor area
conducting outdoor activities
gear
in the meantime
the number of people
transport | transportation
bungee jumping
engage in outdoor activities such as hiking and camping
high-end sport
compete | competitive | competitively | competition
reflect people's personality
tree-hugging
extroverted
introverted
a wide range of interest
observe /əbˈzɜːv/
the pandemic area
campaign /kæmˈpeɪn/
trend
lifestyle sharing experience
increase
on-par with

%0Acount%20as%20outdoor%20activity%0Aas%20long%20as%20you're%20going%20out%0Aa%20huge%20load%20of%20garbage%0Ainnovate%20%7C%20innovator%20%7C%20innovative%20%7C%20innovationlet's%20get%20down%20to%20the%20real%20business%0Amountaineering%0Apickleball%0Aentire%20year%0Aoutdoor%20area%0Aconducting%20outdoor%20activities%0Agear%0Ain%20the%20meantime%0Athe%20number%20of%20people%0Atransport%20%7C%20transportation%0Abungee%20jumping%0Aengage%20in%20outdoor%20activities%20such%20as%20hiking%20and%20camping%0Ahigh-end%20sport%0Acompete%20%7C%20competitive%20%7C%20competitively%20%7C%20competition%0Areflect%20people's%20personality%0Atree-hugging%0Aextroverted%0Aintroverted%0Aa%20wide%20range%20of%20interest%0Aobserve%20%2F%C9%99b%CB%88z%C9%9C%CB%90v%2F%0Athe%20pandemic%20area%0Acampaign%20%2Fk%C3%A6m%CB%88pe%C9%AAn%2F%0Atrend%0Alifestyle%20sharing%20experience%0Aincrease%0Aon-par%20with

20231206

创建时间:2023/12/7 22:43
更新时间:2023/12/7 22:44
作者:Chris

music score
soundtrack
complament
standalone
playlist
quick example
intimate song
emotional
motive | motivate | motivation
impact
main character
literal | ilterally
enhance
can't help falling in love
go on notice
direct | indirect
can't be settle in the background

[new devide]
give up any pretence

music%20score%0Asoundtrack%0Acomplament%0Astandalone%0Aplaylist%0Aquick%20example%0Aintimate%20song%0Aemotional%0Amotive%20%7C%20motivate%20%7C%20motivation%0Aimpact%0Amain%20character%0Aliteral%20%7C%20ilterally%0Aenhance%0Acan't%20help%20falling%20in%20love%0Ago%20on%20notice%20%0Adirect%20%7C%20indirect%0Acan't%20be%20settle%20in%20the%20background%0A%5Bnew%20devide%5D%0Agive%20up%20any%20pretence

The Brothers Karamazov

创建时间:2023/12/7 22:44
更新时间:2023/12/7 22:44
作者:Chris

https://en.wikipedia.org/wiki/Fyodor_Dostoevsky

Dostoevsky /ˌdɒstɔɪˈɛfski/
Karamazov

literature
literary /ˈlɪtərəri/
literal | literally

human conditon

The human condition can be defined as the characteristics and key events of human life, including birth, learning, emotion, aspiration, morality, conflict, and death. This is a very broad topic that has been and continues to be pondered and analyzed from many perspectives, including those of anthropology, art, biology, history, literature, philosophy, psychology, and religion.

compulsory military service
compulsory subject
compulsory education/schooling
exile
gambling addiction
a lavish lifestyle/scale
lavish with/in sth
she lavishs most of her attention on her youngest son
The work was acclaimed as a masterpiece.
philosophy | philosophical /ˌfɪləˈsɒfɪk(ə)l/
The company needs to engage with its customers to understand their needs.
troubled society
anthropology /ˌænθrəˈpɒlədʒi/
perspectives /pəˈ spektɪvz/

She pondered over/about his words
The senator pondered the question for a moment.
I didn't realize you had political aspirations.

She is one of the most influential /ˌɪnfluˈenʃl/
figures in local politics.
financial journalist
essayist
I make no pretence to being an expert on the subject.
She was unable to keep up the pretence that she loved him
crane /kreɪn/

oblige /əˈblaɪdʒ/
I felt obliged to ask them to dinner.
Parents are obliged by law to send their children to school.

a barren /ˈbærən/ landscape | infertile

the hat had become limp /lɪmp/ and shapeless
She had twisted her ankle and was limping.

genocide /ˈdʒenəsaɪd/
colonists /ˈkɑːlənɪsts/
Most of the house remains intact /ɪnˈtækt/ even after two hundred years.

He's a crafty /ˈkrɑːfti/ old devil | tricky
a ban on the ivory /ˈaɪvəri/ trade
a jade /dʒeɪd/ necklace
They rejoiced /rɪˈdʒɔɪs/ to see their son well again.
rejoice (at/in/over sth)

https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FFyodor_Dostoevsky%0A%0ADostoevsky%20%2F%CB%8Cd%C9%92st%C9%94%C9%AA%CB%88%C9%9Bfski%2F%0AKaramazov%0A%0Aliterature%0Aliterary%20%2F%CB%88l%C9%AAt%C9%99r%C9%99ri%2F%0Aliteral%20%7C%20literally%0A%0Ahuman%20conditon%20%0A%3E%20The%20human%20condition%20can%20be%20defined%20as%20the%20characteristics%20and%20key%20events%20of%20human%20life%2C%20including%20birth%2C%20learning%2C%20emotion%2C%20aspiration%2C%20morality%2C%20conflict%2C%20and%20death.%20This%20is%20a%20very%20broad%20topic%20that%20has%20been%20and%20continues%20to%20be%20pondered%20and%20analyzed%20from%20many%20perspectives%2C%20including%20those%20of%20anthropology%2C%20art%2C%20biology%2C%20history%2C%20literature%2C%20philosophy%2C%20psychology%2C%20and%20religion.%20%0A%0Acompulsory%20military%20service%0Acompulsory%20subject%20%0Acompulsory%20education%2Fschooling%0Aexile%0Agambling%20addiction%0Aa%20lavish%20lifestyle%2Fscale%0Alavish%20with%2Fin%20sth%0Ashe%20lavishs%20most%20of%20her%20attention%20on%20her%20youngest%20son%0AThe%20work%20was%20acclaimed%20as%20a%20masterpiece.%20%0Aphilosophy%20%7C%20philosophical%20%2F%CB%8Cf%C9%AAl%C9%99%CB%88s%C9%92f%C9%AAk(%C9%99)l%2F%0AThe%20company%20needs%20to%20%60engage%20with%60%20its%20customers%20to%20understand%20their%20needs.%0Atroubled%20society%0Aanthropology%20%2F%CB%8C%C3%A6n%CE%B8r%C9%99%CB%88p%C9%92l%C9%99d%CA%92i%2F%0Aperspectives%20%2Fp%C9%99%CB%88%20spekt%C9%AAvz%2F%0A%0AShe%20pondered%20over%2Fabout%20his%20words%0AThe%20senator%20pondered%20the%20question%20for%20a%20moment.%0AI%20didn't%20realize%20you%20had%20political%20aspirations.%20%0A%0AShe%20is%20one%20of%20the%20most%20%60influential%20%20%2F%CB%8C%C9%AAnflu%CB%88en%CA%83l%2F%60%0Afigures%20in%20local%20politics.%0Afinancial%20journalist%20%0Aessayist%0AI%20%60make%20no%20pretence%20to%60%20being%20an%20expert%20on%20the%20subject.%0AShe%20was%20unable%20to%20%60keep%20up%20the%20pretence%60%20that%20she%20loved%20him%0Acrane%20%2Fkre%C9%AAn%2F%0A%0A%0Aoblige%20%2F%C9%99%CB%88bla%C9%AAd%CA%92%2F%0AI%20felt%20obliged%20to%20ask%20them%20to%20dinner.%0AParents%20are%20obliged%20by%20law%20to%20send%20their%20children%20to%20school.%20%0A%0Aa%20%60barren%20%2F%CB%88b%C3%A6r%C9%99n%2F%60%20landscape%20%7C%20infertile%0A%0Athe%20hat%20had%20become%20%60limp%20%2Fl%C9%AAmp%2F%60%20and%20shapeless%0AShe%20had%20twisted%20her%20ankle%20and%20was%20limping.%20%0A%0Agenocide%20%2F%CB%88d%CA%92en%C9%99sa%C9%AAd%2F%0Acolonists%20%2F%CB%88k%C9%91%CB%90l%C9%99n%C9%AAsts%2F%0AMost%20of%20the%20house%20remains%20%60intact%20%2F%C9%AAn%CB%88t%C3%A6kt%2F%60%20even%20after%20two%20hundred%20years.%20%0A%0AHe's%20a%20%60crafty%20%2F%CB%88kr%C9%91%CB%90fti%2F%60%20old%20devil%20%7C%20tricky%0Aa%20ban%20on%20the%20%60ivory%20%2F%CB%88a%C9%AAv%C9%99ri%2F%60%20trade%0Aa%20%60jade%20%2Fd%CA%92e%C9%AAd%2F%60%20necklace%0AThey%20%60rejoiced%20%20%2Fr%C9%AA%CB%88d%CA%92%C9%94%C9%AAs%2F%60%20to%20see%20their%20son%20well%20again.%0Arejoice%20(at%2Fin%2Fover%20sth)

CentOS7

创建时间:2020/9/8 20:13
更新时间:2024/9/21 13:39
作者:Chris
来源:https://blog.csdn.net/rentian1/article/details/93768557

1. 安装

1.1 下载

https://mirrors.tuna.tsinghua.edu.cn/centos/7.8.2003/isos/x86_64/CentOS-7-x86_64-Everything-2003.iso

1.2 安装

去勾选

调整参数

调整时区时间

软件选择

安装目的地

kdump 内核崩溃转储机制,会占用一部分内存,且这部分内存对于其它进程是不用的,测试安装时建议去勾选

打开网络开关

创建root用户








1.3 修改密码
[root@localhost chris]# sudo vi /etc/pam.d/system-auth
#password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password    sufficient    pam_unix.so sha512 shadow nullok #try_first_pass use_authtok
#password    required      pam_deny.so
//修改当前用户密码
passwd
//修改root用户密码
sudo passwd root

2 配置主机名

配置主机名

vi /etc/hostname
master

vi /etc/sysconfig/network
HOSTNAME=master

配置hosts列表

vi /etc/hosts
192.168.101.127 master

3 修改静态IP

参考VMware NAT配置

cd /etc/sysconfig/network-scripts
cp ifcfg-ens33 ifcfg-ens33.bak
vi ifcfg-ens33

ens33是网卡的名字,这个在每台机器上可能是不同的。
修改内容如下:

ONBOOT="yes"
BOOTPROTO=static
IPADDR=192.168.174.127  #静态IP
GATEWAY=192.168.174.2  #默认网关, 与NAT设置中的网关一致
NETMASK=255.255.255.0  #子网掩码
DNS1=192.168.174.2        #DNS 配置与GATEWAY一致
DNS2=8.8.8.8                 #DNS 配置
systemctl restart network

5.软件包管理

开发者直接在已知的环境中编译好,使用者可以直接下载安装升级卸载

Linux中能够提供这些功能的软件有两种,一个是RPM ,另一个是DPCK,而在centos中使用RPM

5.1 RPM

red head package manager

5.1.1 优点

将软件提前编译打包,然后在rpm里面存放在用以记录软件依赖关系到的相关数据。

在安装时优先查看这些依赖关系数据,如果系统满足这些依赖关系则安装,否则不安装

安装完成之后会将安装数据记录到自己的数据库中,以便后继升级或卸载等。

5.1.2 缺点

只能在指定的系统中使用,所以不同厂商的rpm包,甚至同一厂商不同版本的操作系统的rpm包都不能通用

5.1.3 命名

5.1.4 使用

包安装完成后,rpm包的相关文件一般会放在对应的目录下,比如

rpm包的配置文件一般会放在/etc下

执行文件会放在/usr/bin下

链接库文件会放在/usr/lib下

帮助和说明文档一般会放在/usr/share/man和/usr/share/doc目录下

rpm -ivh dhcp-server-4.3.6-30.el8.x86_64.rpm

-i 安装
-v 显示详细信息
-h 显示安装进度
-qf 查询一个文件归属于哪个已安装的软件包
--force 强制
-U 升级,如果系统中有低版本的就会升级,如果系统中没有安装对应的软件包则安装
-F 有条件的升级,会检测用户指定的软件包是否已安装到linux中
-q 查询指定的软件包是否安装 
-ql 查询指定的软件包里面所包含的文件列表
-qi 查询指定的软件包的信息,包括开发商,版本,说明
-qa 查询本机已安装的所有软件包
[root@master chris]# rpm -q dhcp-server
package dhcp-server is not installed
5.2 YUM

yum yellow dog updater, modified 是一个基于rpm却更胜于rpm的软件包管理工具

可以使用yum安装,升级,卸载软件包,yum会自动解决软件包之间的依赖关系

5.2.1 yum 源

如果把所有的rpm文件都放在同一个目录下,那这个目录就称为yum下载源
/etc/yum.repos.d/

5.2.2 yum 插件

yum允许第三方厂商开发yum插件,让用户可以方便的扩展yum功能,比如说有的yum插件可以选择最快的yum源

插件存放位置:etc/yum/pluginconf.d/xxx.conf

启用或停用插件:配置文件xxx.conf 中 enable 字段 1:启动,0:不启用

5.2.3 yum cache

yum运行时会获取yum下载源中的软件信息与文件,暂存放在本机的硬盘中,这个暂存的本机的目录称为yum cache

yum缓存的目录为: /var/cache/yum

5.2.4 配置 yum 源
cd /etc/yum.repos.d/
mkdir repo.bak
mv *.repo repo.bak
vi server.repo
[base]
name=CentOS-$releasever - Base
# 定义软件包的位置,这里使用清华源
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
enabled=1   # 1:启动,0:不启用
gpgcheck=1  # 下载软件包时是否检查数字签名
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-7

样例:

[base]
name=CentOS-$releasever - Base
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-7

#released updates
[updates]
name=CentOS-$releasever - Updates
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/updates/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-7



#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/extras/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-7



#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/centosplus/$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-7
~                                               
5.2.5 yum 命令
yum install httpd
-y 如果遇到问题自动回答yes
--installroot=/path 指定软件包安装时的根目录

yum install 'package-group-name' -y 安装一组软件包,建议用引号将组名引起来
yum clean all
有时yum运行不正常,很可能是因为缓存数据导致的,所以需要清理一下缓存
yum makecache fast
yum list 查看yum源中已包含的软件包, 会列出所有的软件包 yum list | more 按空格翻页 按q退出
yum grouplist 以组的形式查看yum源中有哪些软件包组

yum info java-1.8.0-openjdk.x86_64  查看软件包信息

yum search java-1.8.0-openjdk.x86_64 查看某个软件包是否包含在yum源中,等同于 yum list | grep package-name

yum remove package-name    卸载一个软件包
yum groupremove  'package-group-name' 卸载一组软件包

yum list updates 列出所有可更新的软件包 
yum list installed 列出所有已安装的软件包 
yum list extras  列出所有已安装但不在 Yum Repository 内的软件包
5.2.6 更新Ali yum源
[root@master yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@master yum.repos.d]# mv server.repo repo.bak/
[root@master yum.repos.d]# mv CentOS-Base.repo server.repo
5.3 epel源

EPEL是一个开源的附加软件包仓库,可用于centos 和 REHL 服务器,它提供了些在默认软件包仓库中不存在的软件包

5.3.1 安装 epel源

yum install epel源的下载地址

5.3.2 查看已安装的epel源

安装成功后会在 /etc/yum.repos.d/目录下多出来一些epel文件

或者使用如下命令查看系统中的软件源个数

yum repolist

6.服务管理

6.1 systemV 与 init

systemV中有一个init命令,可以让service命令去调用/etc/ini.d目录下的服务脚本

6.1.1 服务的启停操作
/etc/init.d/service-name start/stop/status/restart
service service-name  start/stop/status/restart
6.1.2 服务的启停级别
0 关机
1 单用户
2 无网络多用户
3 字符模式
4 保留
5 图形模式
6 重启
#关闭系统启动3级别中的sshd服务
chkconfig --level 3 sshd off 

#forbid the start of firewall when restart system
chkconfig iptables off

chkconfig - updates and queries runlevel information for system services

#查看一个服务在哪个级别启动
chkconfig --list iptables
6.1.3 对服务的分类
  1. 按功能分类

    系统服务:这类服务所服务的对象是系统本身或使用系统的用户

    网络服务:这类服务所服务的对象是网络中的其它客户端

  2. 按启动方法分类

    独立系统服务:

    这类服务一旦启动,除非系统关闭或者管理员手动结束,否则会一直在系统后台运行,不管是否会被系统使用到,所以响应快但是占用资源

    临时服务:用到的时候启动,使用完后停止,响应速度慢但是节省资源

6.2 systemD 与 unit

从centos7开始,systemV和与其对应的init命令被效率更高的systemD及其对应的systemctl命令代替
并且systemctl兼容之前的servicer命令

6.2.1 优点

并且处理所有服务,缩短开机时间

类似于yum,自动解决服务之间的依赖

方便记忆,按照类型对服务分类

兼容init和service命令

6.2.2 相关文件
/usr/lib/systemd/system/ 服务启动脚本,包含已安装的服务设置文件
/run/systemd/system/  	 系统运行过程中的服务脚本,优先级高于上一个文件
/etc/systemd/system/	 管理员手动建立的服务启动脚本,优先级最高
/etc/sysconfig/*		 系统功能的默认设置
6.2.3 单元unit分类

systemctl -t help

6.3 systemctl 命令
6.3.1 服务启动和停用

systemctl start sevice-name

status 详解

[root@master chris]# systemctl status atd
 atd.service - Job spooling tools
   Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2020-09-21 10:19:24 CST; 2min 58s ago
 Main PID: 1143 (atd)
    Tasks: 1
   CGroup: /system.slice/atd.service
             1143 /usr/sbin/atd -f

Loaded:加需成功,失败会显示error
Active:服务当前状态
Main PID:服务的主进程号
Tasks:服务的进程个数和线程个数
Memory:当前占用的内存大小

不想让某些服务加入systemctl, mask之后如果使用systemctl 操作就会报错

[root@master chris]# systemctl mask atd
Created symlink from /etc/systemd/system/atd.service to /dev/null.
[root@master chris]# systemctl status atd
● atd.service
   Loaded: masked (/dev/null; bad)
   Active: active (running) since Mon 2020-09-21 10:19:24 CST; 13min ago
 Main PID: 1143 (atd)
   CGroup: /system.slice/atd.service
           └─1143 /usr/sbin/atd -f

想让某些服务加入systemctl

systemctl unmask atd
6.3.2 查看服务
systemctl  list-units 查看加载到内存中的单元
systemctl  list-units --type service | grep mysql  查看mysql服务是否启动

systemctl  list-unit-files 查看系统中所有安装的单元文件(存放在/usr/lib/systemd/system/)的启 状态

--type 单元类型
--all  不管状态是什么,列出系统中加载的
systemctl --type service --all
systemctl --type=service --all
#查看一个服务依赖于哪些其它服务
systemctl list-dependencies atd.service

#查看哪些服务依赖于这个服务
systemctl list-dependencies atd.service --reverse
6.3.3 设置启动单元

systemctl list-units --type target --all

graphical.target
multi-user.target
shutdown.target
#查看系统默认使用的启动单元
systemctl  get-default
#设置系统默认使用的启动单元
systemctl  set-default multi-user.target
6.3.4 开关机
  1. 关机

    systemctl poweroff  
    等同于
    	init 0 
    	shutdown -h now
    
  2. 重启

    systemctl reboot  
    等同于
    	init 6
    	shutdown -r now
    
  3. 挂起

    systemctl suspend 
    
  4. 休眠

    systemctl hibernate
    
6.3.5 查看端口号

6.3.6 firewall
systemctl enable firewalld.service
systemctl restart firewalld.service

firewall-cmd --state     查看状态
firewall-cmd --list-all   查看过滤的列表信息

firewall-cmd --add-service=http --permanent 设置开放的服务
firewall-cmd --add-port=8001 --permanent   设置开放的端口号
firewall-cmd --reload   重新加载防火墙
%0A%5Btoc%5D%0A%0A%23%23%23%23%201.%20%E5%AE%89%E8%A3%85%0A%0A%23%23%23%23%23%201.1%20%E4%B8%8B%E8%BD%BD%0A%0Ahttps%3A%2F%2Fmirrors.tuna.tsinghua.edu.cn%2Fcentos%2F7.8.2003%2Fisos%2Fx86_64%2FCentOS-7-x86_64-Everything-2003.iso%0A%0A%23%23%23%23%23%201.2%20%E5%AE%89%E8%A3%85%0A!%5Bde41ea69aa96faff7519e52f64ec7b78.png%5D(en-resource%3A%2F%2Fdatabase%2F1479%3A1)%0A%0A%E5%8E%BB%E5%8B%BE%E9%80%89%0A!%5B97aa9a06287a060546d73abf394fb9a9.png%5D(en-resource%3A%2F%2Fdatabase%2F1485%3A1)%0A%0A%0A%E8%B0%83%E6%95%B4%E5%8F%82%E6%95%B0%0A!%5B556295196d1b9050c233d37c281eb658.png%5D(en-resource%3A%2F%2Fdatabase%2F1481%3A1)%0A%0A%E8%B0%83%E6%95%B4%E6%97%B6%E5%8C%BA%E6%97%B6%E9%97%B4%0A!%5B1038acc61579e49086f12bf71f7c932e.png%5D(en-resource%3A%2F%2Fdatabase%2F1480%3A1)%0A%0A%E8%BD%AF%E4%BB%B6%E9%80%89%E6%8B%A9%0A!%5B5d19cf224f17108ccbcabf4df166a659.png%5D(en-resource%3A%2F%2Fdatabase%2F1483%3A1)%0A%0A%E5%AE%89%E8%A3%85%E7%9B%AE%E7%9A%84%E5%9C%B0%0A!%5B9dc05922975eed981f5fd3fd827110ff.png%5D(en-resource%3A%2F%2Fdatabase%2F1486%3A1)%0A%0A%0Akdump%20%E5%86%85%E6%A0%B8%E5%B4%A9%E6%BA%83%E8%BD%AC%E5%82%A8%E6%9C%BA%E5%88%B6%EF%BC%8C%E4%BC%9A%E5%8D%A0%E7%94%A8%E4%B8%80%E9%83%A8%E5%88%86%E5%86%85%E5%AD%98%EF%BC%8C%E4%B8%94%E8%BF%99%E9%83%A8%E5%88%86%E5%86%85%E5%AD%98%E5%AF%B9%E4%BA%8E%E5%85%B6%E5%AE%83%E8%BF%9B%E7%A8%8B%E6%98%AF%E4%B8%8D%E7%94%A8%E7%9A%84%EF%BC%8C%E6%B5%8B%E8%AF%95%E5%AE%89%E8%A3%85%E6%97%B6%E5%BB%BA%E8%AE%AE%E5%8E%BB%E5%8B%BE%E9%80%89%0A!%5Bf4fc9f1d0179eab352bc3a5e0982da9f.png%5D(en-resource%3A%2F%2Fdatabase%2F1491%3A1)%0A%0A%0A%E6%89%93%E5%BC%80%E7%BD%91%E7%BB%9C%E5%BC%80%E5%85%B3%0A!%5Bd230fbd8becf0f8ab36433217d9d3131.png%5D(en-resource%3A%2F%2Fdatabase%2F1489%3A1)%0A%0A!%5B5ef85b765d7fb8909fb1ffbfd9d948c5.png%5D(en-resource%3A%2F%2Fdatabase%2F1484%3A1)%0A%0A%E5%88%9B%E5%BB%BAroot%E7%94%A8%E6%88%B7%0A!%5Bf3c426f0e183e8d78901db4064245310.png%5D(en-resource%3A%2F%2Fdatabase%2F1490%3A1)%0A%0A!%5Bb24e3e62758c8b3a5b6d9936ea57fe49.png%5D(en-resource%3A%2F%2Fdatabase%2F1488%3A1)%0A%0A!%5Bb0a64a031a2cea3ec740a165575a60a5.png%5D(en-resource%3A%2F%2Fdatabase%2F1487%3A1)%0A!%5B55d60105e08fc90aa8c1945e06449c81.png%5D(en-resource%3A%2F%2Fdatabase%2F1482%3A1)%0A!%5Baa7ca7bcae8487bad1f78fd3d0fb15e8.png%5D(en-resource%3A%2F%2Fdatabase%2F1494%3A1)%0A!%5Bf57562bb2eb1fdaff8a563ffcd29ce76.png%5D(en-resource%3A%2F%2Fdatabase%2F1497%3A1)%0A!%5Ba31fc6e5f3e1224d819ae609364d0096.png%5D(en-resource%3A%2F%2Fdatabase%2F1493%3A1)%0A!%5Be58bbcfe47adaeefbd5ba7b32a9d68ec.png%5D(en-resource%3A%2F%2Fdatabase%2F1496%3A1)%0A!%5B76c56d2da3e0df03198d056f5e0a7ac6.png%5D(en-resource%3A%2F%2Fdatabase%2F1492%3A1)%0A!%5Bc3381bea6031bd205608c1aa11a61bd7.png%5D(en-resource%3A%2F%2Fdatabase%2F1495%3A1)%0A%0A%0A%0A%23%23%23%23%23%201.3%20%E4%BF%AE%E6%94%B9%E5%AF%86%E7%A0%81%0A%0A%60%60%60%0A%5Broot%40localhost%20chris%5D%23%20sudo%20vi%20%2Fetc%2Fpam.d%2Fsystem-auth%0A%23password%20%20%20%20requisite%20%20%20%20%20pam_pwquality.so%20try_first_pass%20local_users_only%20retry%3D3%20authtok_type%3D%0Apassword%20%20%20%20sufficient%20%20%20%20pam_unix.so%20sha512%20shadow%20nullok%20%23try_first_pass%20use_authtok%0A%23password%20%20%20%20required%20%20%20%20%20%20pam_deny.so%0A%60%60%60%0A%0A%60%60%60%0A%2F%2F%E4%BF%AE%E6%94%B9%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7%E5%AF%86%E7%A0%81%0Apasswd%0A%2F%2F%E4%BF%AE%E6%94%B9root%E7%94%A8%E6%88%B7%E5%AF%86%E7%A0%81%0Asudo%20passwd%20root%0A%60%60%60%0A%0A%23%23%23%23%202%20%E9%85%8D%E7%BD%AE%E4%B8%BB%E6%9C%BA%E5%90%8D%0A%0A%3E%20%E9%85%8D%E7%BD%AE%E4%B8%BB%E6%9C%BA%E5%90%8D%0A%60%60%60%0Avi%20%2Fetc%2Fhostname%0Amaster%0A%0Avi%20%2Fetc%2Fsysconfig%2Fnetwork%0AHOSTNAME%3Dmaster%0A%60%60%60%0A%0A%3E%20%E9%85%8D%E7%BD%AEhosts%E5%88%97%E8%A1%A8%0A%60%60%60%0Avi%20%2Fetc%2Fhosts%0A192.168.101.127%20master%0A%60%60%60%0A%0A%23%23%23%23%203%20%E4%BF%AE%E6%94%B9%E9%9D%99%E6%80%81IP%0A%3E%20%E5%8F%82%E8%80%83VMware%20NAT%E9%85%8D%E7%BD%AE%0A%60%60%60%0Acd%20%2Fetc%2Fsysconfig%2Fnetwork-scripts%0Acp%20ifcfg-ens33%20ifcfg-ens33.bak%0Avi%20ifcfg-ens33%0A%60%60%60%0A%3E%20ens33%E6%98%AF%E7%BD%91%E5%8D%A1%E7%9A%84%E5%90%8D%E5%AD%97%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%9C%A8%E6%AF%8F%E5%8F%B0%E6%9C%BA%E5%99%A8%E4%B8%8A%E5%8F%AF%E8%83%BD%E6%98%AF%E4%B8%8D%E5%90%8C%E7%9A%84%E3%80%82%0A%3E%20%E4%BF%AE%E6%94%B9%E5%86%85%E5%AE%B9%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A!%5Bb2110495875ee972404db184399105bf.png%5D(en-resource%3A%2F%2Fdatabase%2F1502%3A1)%0A%0A%60%60%60%0AONBOOT%3D%22yes%22%0ABOOTPROTO%3Dstatic%0AIPADDR%3D192.168.174.127%20%20%23%E9%9D%99%E6%80%81IP%0AGATEWAY%3D192.168.174.2%20%20%23%E9%BB%98%E8%AE%A4%E7%BD%91%E5%85%B3%2C%20%E4%B8%8ENAT%E8%AE%BE%E7%BD%AE%E4%B8%AD%E7%9A%84%E7%BD%91%E5%85%B3%E4%B8%80%E8%87%B4%0ANETMASK%3D255.255.255.0%20%20%23%E5%AD%90%E7%BD%91%E6%8E%A9%E7%A0%81%0ADNS1%3D192.168.174.2%20%20%20%20%20%20%20%20%23DNS%20%E9%85%8D%E7%BD%AE%E4%B8%8EGATEWAY%E4%B8%80%E8%87%B4%0ADNS2%3D8.8.8.8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23DNS%20%E9%85%8D%E7%BD%AE%0A%60%60%60%0A%60%60%60shell%0Asystemctl%20restart%20network%0A%60%60%60%0A%0A%23%23%23%23%205.%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%AE%A1%E7%90%86%0A%0A%3E%20%E5%BC%80%E5%8F%91%E8%80%85%E7%9B%B4%E6%8E%A5%E5%9C%A8%E5%B7%B2%E7%9F%A5%E7%9A%84%E7%8E%AF%E5%A2%83%E4%B8%AD%E7%BC%96%E8%AF%91%E5%A5%BD%EF%BC%8C%E4%BD%BF%E7%94%A8%E8%80%85%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%E5%8D%87%E7%BA%A7%E5%8D%B8%E8%BD%BD%0A%3E%0A%3E%20Linux%E4%B8%AD%E8%83%BD%E5%A4%9F%E6%8F%90%E4%BE%9B%E8%BF%99%E4%BA%9B%E5%8A%9F%E8%83%BD%E7%9A%84%E8%BD%AF%E4%BB%B6%E6%9C%89%E4%B8%A4%E7%A7%8D%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%98%AFRPM%20%EF%BC%8C%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%98%AFDPCK%EF%BC%8C%E8%80%8C%E5%9C%A8centos%E4%B8%AD%E4%BD%BF%E7%94%A8RPM%0A%0A%23%23%23%23%23%205.1%20RPM%0A%0A%3E%20red%20head%20package%20manager%0A%0A%23%23%23%23%23%23%205.1.1%20%E4%BC%98%E7%82%B9%0A%0A%3E%20%E5%B0%86%E8%BD%AF%E4%BB%B6%E6%8F%90%E5%89%8D%E7%BC%96%E8%AF%91%E6%89%93%E5%8C%85%EF%BC%8C%E7%84%B6%E5%90%8E%E5%9C%A8rpm%E9%87%8C%E9%9D%A2%E5%AD%98%E6%94%BE%E5%9C%A8%E7%94%A8%E4%BB%A5%E8%AE%B0%E5%BD%95%E8%BD%AF%E4%BB%B6%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E5%88%B0%E7%9A%84%E7%9B%B8%E5%85%B3%E6%95%B0%E6%8D%AE%E3%80%82%0A%3E%0A%3E%20%E5%9C%A8%E5%AE%89%E8%A3%85%E6%97%B6%E4%BC%98%E5%85%88%E6%9F%A5%E7%9C%8B%E8%BF%99%E4%BA%9B%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%B3%BB%E7%BB%9F%E6%BB%A1%E8%B6%B3%E8%BF%99%E4%BA%9B%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E5%88%99%E5%AE%89%E8%A3%85%EF%BC%8C%E5%90%A6%E5%88%99%E4%B8%8D%E5%AE%89%E8%A3%85%20%0A%3E%0A%3E%20%E5%AE%89%E8%A3%85%E5%AE%8C%E6%88%90%E4%B9%8B%E5%90%8E%E4%BC%9A%E5%B0%86%E5%AE%89%E8%A3%85%E6%95%B0%E6%8D%AE%E8%AE%B0%E5%BD%95%E5%88%B0%E8%87%AA%E5%B7%B1%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%EF%BC%8C%E4%BB%A5%E4%BE%BF%E5%90%8E%E7%BB%A7%E5%8D%87%E7%BA%A7%E6%88%96%E5%8D%B8%E8%BD%BD%E7%AD%89%E3%80%82%0A%0A%23%23%23%23%23%23%205.1.2%20%E7%BC%BA%E7%82%B9%0A%0A%3E%20%E5%8F%AA%E8%83%BD%E5%9C%A8%E6%8C%87%E5%AE%9A%E7%9A%84%E7%B3%BB%E7%BB%9F%E4%B8%AD%E4%BD%BF%E7%94%A8%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%8D%E5%90%8C%E5%8E%82%E5%95%86%E7%9A%84rpm%E5%8C%85%EF%BC%8C%E7%94%9A%E8%87%B3%E5%90%8C%E4%B8%80%E5%8E%82%E5%95%86%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%E7%9A%84%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84rpm%E5%8C%85%E9%83%BD%E4%B8%8D%E8%83%BD%E9%80%9A%E7%94%A8%0A%0A%0A%0A%23%23%23%23%23%23%205.1.3%20%E5%91%BD%E5%90%8D%0A!%5B2ede2bbfcd73429a8d437e2d2b1f5b0a.png%5D(en-resource%3A%2F%2Fdatabase%2F1501%3A1)%0A%0A%23%23%23%23%23%23%205.1.4%20%E4%BD%BF%E7%94%A8%0A%0A%3E%20%E5%8C%85%E5%AE%89%E8%A3%85%E5%AE%8C%E6%88%90%E5%90%8E%EF%BC%8Crpm%E5%8C%85%E7%9A%84%E7%9B%B8%E5%85%B3%E6%96%87%E4%BB%B6%E4%B8%80%E8%88%AC%E4%BC%9A%E6%94%BE%E5%9C%A8%E5%AF%B9%E5%BA%94%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%8B%EF%BC%8C%E6%AF%94%E5%A6%82%0A%3E%0A%3E%20rpm%E5%8C%85%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%80%E8%88%AC%E4%BC%9A%E6%94%BE%E5%9C%A8%2Fetc%E4%B8%8B%0A%3E%0A%3E%20%E6%89%A7%E8%A1%8C%E6%96%87%E4%BB%B6%E4%BC%9A%E6%94%BE%E5%9C%A8%2Fusr%2Fbin%E4%B8%8B%20%0A%3E%0A%3E%20%E9%93%BE%E6%8E%A5%E5%BA%93%E6%96%87%E4%BB%B6%E4%BC%9A%E6%94%BE%E5%9C%A8%2Fusr%2Flib%E4%B8%8B%0A%3E%0A%3E%20%E5%B8%AE%E5%8A%A9%E5%92%8C%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E4%B8%80%E8%88%AC%E4%BC%9A%E6%94%BE%E5%9C%A8%2Fusr%2Fshare%2Fman%E5%92%8C%2Fusr%2Fshare%2Fdoc%E7%9B%AE%E5%BD%95%E4%B8%8B%0A%0A%60%60%60%0Arpm%20-ivh%20dhcp-server-4.3.6-30.el8.x86_64.rpm%0A%0A-i%20%E5%AE%89%E8%A3%85%0A-v%20%E6%98%BE%E7%A4%BA%E8%AF%A6%E7%BB%86%E4%BF%A1%E6%81%AF%0A-h%20%E6%98%BE%E7%A4%BA%E5%AE%89%E8%A3%85%E8%BF%9B%E5%BA%A6%0A-qf%20%E6%9F%A5%E8%AF%A2%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E5%BD%92%E5%B1%9E%E4%BA%8E%E5%93%AA%E4%B8%AA%E5%B7%B2%E5%AE%89%E8%A3%85%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%0A--force%20%E5%BC%BA%E5%88%B6%0A-U%20%E5%8D%87%E7%BA%A7%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E6%9C%89%E4%BD%8E%E7%89%88%E6%9C%AC%E7%9A%84%E5%B0%B1%E4%BC%9A%E5%8D%87%E7%BA%A7%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E6%B2%A1%E6%9C%89%E5%AE%89%E8%A3%85%E5%AF%B9%E5%BA%94%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%E5%88%99%E5%AE%89%E8%A3%85%0A-F%20%E6%9C%89%E6%9D%A1%E4%BB%B6%E7%9A%84%E5%8D%87%E7%BA%A7%EF%BC%8C%E4%BC%9A%E6%A3%80%E6%B5%8B%E7%94%A8%E6%88%B7%E6%8C%87%E5%AE%9A%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%E6%98%AF%E5%90%A6%E5%B7%B2%E5%AE%89%E8%A3%85%E5%88%B0linux%E4%B8%AD%0A-q%20%E6%9F%A5%E8%AF%A2%E6%8C%87%E5%AE%9A%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%E6%98%AF%E5%90%A6%E5%AE%89%E8%A3%85%20%0A-ql%20%E6%9F%A5%E8%AF%A2%E6%8C%87%E5%AE%9A%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%E9%87%8C%E9%9D%A2%E6%89%80%E5%8C%85%E5%90%AB%E7%9A%84%E6%96%87%E4%BB%B6%E5%88%97%E8%A1%A8%0A-qi%20%E6%9F%A5%E8%AF%A2%E6%8C%87%E5%AE%9A%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%9A%84%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%8C%85%E6%8B%AC%E5%BC%80%E5%8F%91%E5%95%86%EF%BC%8C%E7%89%88%E6%9C%AC%EF%BC%8C%E8%AF%B4%E6%98%8E%0A-qa%20%E6%9F%A5%E8%AF%A2%E6%9C%AC%E6%9C%BA%E5%B7%B2%E5%AE%89%E8%A3%85%E7%9A%84%E6%89%80%E6%9C%89%E8%BD%AF%E4%BB%B6%E5%8C%85%0A%60%60%60%0A%0A%60%60%60shell%0A%5Broot%40master%20chris%5D%23%20rpm%20-q%20dhcp-server%0Apackage%20dhcp-server%20is%20not%20installed%0A%60%60%60%0A%0A%23%23%23%23%23%205.2%20YUM%0A%0A%3E%20yum%20yellow%20dog%20updater%2C%20modified%20%E6%98%AF%E4%B8%80%E4%B8%AA%E5%9F%BA%E4%BA%8Erpm%E5%8D%B4%E6%9B%B4%E8%83%9C%E4%BA%8Erpm%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7%0A%3E%0A%3E%20%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8yum%E5%AE%89%E8%A3%85%EF%BC%8C%E5%8D%87%E7%BA%A7%EF%BC%8C%E5%8D%B8%E8%BD%BD%E8%BD%AF%E4%BB%B6%E5%8C%85%EF%BC%8Cyum%E4%BC%9A%E8%87%AA%E5%8A%A8%E8%A7%A3%E5%86%B3%E8%BD%AF%E4%BB%B6%E5%8C%85%E4%B9%8B%E9%97%B4%E7%9A%84%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%0A%0A%23%23%23%23%23%23%205.2.1%20yum%20%E6%BA%90%0A%0A%3E%20%E5%A6%82%E6%9E%9C%E6%8A%8A%E6%89%80%E6%9C%89%E7%9A%84rpm%E6%96%87%E4%BB%B6%E9%83%BD%E6%94%BE%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%8B%EF%BC%8C%E9%82%A3%E8%BF%99%E4%B8%AA%E7%9B%AE%E5%BD%95%E5%B0%B1%E7%A7%B0%E4%B8%BAyum%E4%B8%8B%E8%BD%BD%E6%BA%90%0A%3E%20%2Fetc%2Fyum.repos.d%2F%0A%0A%0A%23%23%23%23%23%23%205.2.2%20yum%20%E6%8F%92%E4%BB%B6%0A%0A%3E%20yum%E5%85%81%E8%AE%B8%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8E%82%E5%95%86%E5%BC%80%E5%8F%91yum%E6%8F%92%E4%BB%B6%EF%BC%8C%E8%AE%A9%E7%94%A8%E6%88%B7%E5%8F%AF%E4%BB%A5%E6%96%B9%E4%BE%BF%E7%9A%84%E6%89%A9%E5%B1%95yum%E5%8A%9F%E8%83%BD%EF%BC%8C%E6%AF%94%E5%A6%82%E8%AF%B4%E6%9C%89%E7%9A%84yum%E6%8F%92%E4%BB%B6%E5%8F%AF%E4%BB%A5%E9%80%89%E6%8B%A9%E6%9C%80%E5%BF%AB%E7%9A%84yum%E6%BA%90%0A%3E%0A%3E%20%E6%8F%92%E4%BB%B6%E5%AD%98%E6%94%BE%E4%BD%8D%E7%BD%AE%EF%BC%9Aetc%2Fyum%2Fpluginconf.d%2Fxxx.conf%0A%3E%0A%3E%20%E5%90%AF%E7%94%A8%E6%88%96%E5%81%9C%E7%94%A8%E6%8F%92%E4%BB%B6%EF%BC%9A%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6xxx.conf%20%E4%B8%AD%20enable%20%E5%AD%97%E6%AE%B5%201%3A%E5%90%AF%E5%8A%A8%EF%BC%8C0%3A%E4%B8%8D%E5%90%AF%E7%94%A8%0A%0A%23%23%23%23%23%23%205.2.3%20yum%20cache%20%0A%0A%3E%20yum%E8%BF%90%E8%A1%8C%E6%97%B6%E4%BC%9A%E8%8E%B7%E5%8F%96yum%E4%B8%8B%E8%BD%BD%E6%BA%90%E4%B8%AD%E7%9A%84%E8%BD%AF%E4%BB%B6%E4%BF%A1%E6%81%AF%E4%B8%8E%E6%96%87%E4%BB%B6%EF%BC%8C%E6%9A%82%E5%AD%98%E6%94%BE%E5%9C%A8%E6%9C%AC%E6%9C%BA%E7%9A%84%E7%A1%AC%E7%9B%98%E4%B8%AD%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%9A%82%E5%AD%98%E7%9A%84%E6%9C%AC%E6%9C%BA%E7%9A%84%E7%9B%AE%E5%BD%95%E7%A7%B0%E4%B8%BAyum%20cache%20%0A%3E%0A%3E%20yum%E7%BC%93%E5%AD%98%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%BA%3A%20%2Fvar%2Fcache%2Fyum%0A%0A%23%23%23%23%23%23%205.2.4%20%E9%85%8D%E7%BD%AE%20yum%20%E6%BA%90%0A%0A%60%60%60shell%0Acd%20%2Fetc%2Fyum.repos.d%2F%0Amkdir%20repo.bak%0Amv%20*.repo%20repo.bak%0Avi%20server.repo%0A%60%60%60%0A%0A%60%60%60%0A%5Bbase%5D%0Aname%3DCentOS-%24releasever%20-%20Base%0A%23%20%E5%AE%9A%E4%B9%89%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%9A%84%E4%BD%8D%E7%BD%AE%EF%BC%8C%E8%BF%99%E9%87%8C%E4%BD%BF%E7%94%A8%E6%B8%85%E5%8D%8E%E6%BA%90%0Abaseurl%3Dhttps%3A%2F%2Fmirrors.tuna.tsinghua.edu.cn%2Fcentos%2F%24releasever%2Fos%2F%24basearch%2F%0A%23mirrorlist%3Dhttp%3A%2F%2Fmirrorlist.centos.org%2F%3Frelease%3D%24releasever%26arch%3D%24basearch%26repo%3Dos%0Aenabled%3D1%20%20%20%23%201%3A%E5%90%AF%E5%8A%A8%EF%BC%8C0%3A%E4%B8%8D%E5%90%AF%E7%94%A8%0Agpgcheck%3D1%20%20%23%20%E4%B8%8B%E8%BD%BD%E8%BD%AF%E4%BB%B6%E5%8C%85%E6%97%B6%E6%98%AF%E5%90%A6%E6%A3%80%E6%9F%A5%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D%0Agpgkey%3Dfile%3A%2F%2F%2Fetc%2Fpki%2Frpm-gpg%2FRPM-GPG-KEY-7%0A%60%60%60%0A%0A%E6%A0%B7%E4%BE%8B%EF%BC%9A%0A%0A%60%60%60%0A%5Bbase%5D%0Aname%3DCentOS-%24releasever%20-%20Base%0Abaseurl%3Dhttps%3A%2F%2Fmirrors.tuna.tsinghua.edu.cn%2Fcentos%2F%24releasever%2Fos%2F%24basearch%2F%0A%23mirrorlist%3Dhttp%3A%2F%2Fmirrorlist.centos.org%2F%3Frelease%3D%24releasever%26arch%3D%24basearch%26repo%3Dos%0Aenabled%3D1%0Agpgcheck%3D1%0Agpgkey%3Dfile%3A%2F%2F%2Fetc%2Fpki%2Frpm-gpg%2FRPM-GPG-KEY-7%0A%0A%23released%20updates%0A%5Bupdates%5D%0Aname%3DCentOS-%24releasever%20-%20Updates%0Abaseurl%3Dhttps%3A%2F%2Fmirrors.tuna.tsinghua.edu.cn%2Fcentos%2F%24releasever%2Fupdates%2F%24basearch%2F%0A%23mirrorlist%3Dhttp%3A%2F%2Fmirrorlist.centos.org%2F%3Frelease%3D%24releasever%26arch%3D%24basearch%26repo%3Dupdates%0Aenabled%3D1%0Agpgcheck%3D1%0Agpgkey%3Dfile%3A%2F%2F%2Fetc%2Fpki%2Frpm-gpg%2FRPM-GPG-KEY-7%0A%0A%0A%0A%23additional%20packages%20that%20may%20be%20useful%0A%5Bextras%5D%0Aname%3DCentOS-%24releasever%20-%20Extras%0Abaseurl%3Dhttps%3A%2F%2Fmirrors.tuna.tsinghua.edu.cn%2Fcentos%2F%24releasever%2Fextras%2F%24basearch%2F%0A%23mirrorlist%3Dhttp%3A%2F%2Fmirrorlist.centos.org%2F%3Frelease%3D%24releasever%26arch%3D%24basearch%26repo%3Dextras%0Aenabled%3D1%0Agpgcheck%3D1%0Agpgkey%3Dfile%3A%2F%2F%2Fetc%2Fpki%2Frpm-gpg%2FRPM-GPG-KEY-7%0A%0A%0A%0A%23additional%20packages%20that%20extend%20functionality%20of%20existing%20packages%0A%5Bcentosplus%5D%0Aname%3DCentOS-%24releasever%20-%20Plus%0Abaseurl%3Dhttps%3A%2F%2Fmirrors.tuna.tsinghua.edu.cn%2Fcentos%2F%24releasever%2Fcentosplus%2F%24basearch%2F%0A%23mirrorlist%3Dhttp%3A%2F%2Fmirrorlist.centos.org%2F%3Frelease%3D%24releasever%26arch%3D%24basearch%26repo%3Dcentosplus%0Agpgcheck%3D1%0Aenabled%3D0%0Agpgkey%3Dfile%3A%2F%2F%2Fetc%2Fpki%2Frpm-gpg%2FRPM-GPG-KEY-7%0A~%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%60%60%60%0A%23%23%23%23%23%23%205.2.5%20yum%20%20%E5%91%BD%E4%BB%A4%0A%0A%60%60%60%0Ayum%20install%20httpd%0A-y%20%E5%A6%82%E6%9E%9C%E9%81%87%E5%88%B0%E9%97%AE%E9%A2%98%E8%87%AA%E5%8A%A8%E5%9B%9E%E7%AD%94yes%0A--installroot%3D%2Fpath%20%E6%8C%87%E5%AE%9A%E8%BD%AF%E4%BB%B6%E5%8C%85%E5%AE%89%E8%A3%85%E6%97%B6%E7%9A%84%E6%A0%B9%E7%9B%AE%E5%BD%95%0A%0Ayum%20install%20'package-group-name'%20-y%20%E5%AE%89%E8%A3%85%E4%B8%80%E7%BB%84%E8%BD%AF%E4%BB%B6%E5%8C%85%EF%BC%8C%E5%BB%BA%E8%AE%AE%E7%94%A8%E5%BC%95%E5%8F%B7%E5%B0%86%E7%BB%84%E5%90%8D%E5%BC%95%E8%B5%B7%E6%9D%A5%0A%60%60%60%0A%0A%60%60%60%0Ayum%20clean%20all%0A%E6%9C%89%E6%97%B6yum%E8%BF%90%E8%A1%8C%E4%B8%8D%E6%AD%A3%E5%B8%B8%EF%BC%8C%E5%BE%88%E5%8F%AF%E8%83%BD%E6%98%AF%E5%9B%A0%E4%B8%BA%E7%BC%93%E5%AD%98%E6%95%B0%E6%8D%AE%E5%AF%BC%E8%87%B4%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E6%B8%85%E7%90%86%E4%B8%80%E4%B8%8B%E7%BC%93%E5%AD%98%0Ayum%20makecache%20fast%0A%60%60%60%0A%0A%60%60%60%20shell%0Ayum%20list%20%E6%9F%A5%E7%9C%8Byum%E6%BA%90%E4%B8%AD%E5%B7%B2%E5%8C%85%E5%90%AB%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%EF%BC%8C%20%E4%BC%9A%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%20yum%20list%20%7C%20more%20%E6%8C%89%E7%A9%BA%E6%A0%BC%E7%BF%BB%E9%A1%B5%20%E6%8C%89q%E9%80%80%E5%87%BA%0Ayum%20grouplist%20%E4%BB%A5%E7%BB%84%E7%9A%84%E5%BD%A2%E5%BC%8F%E6%9F%A5%E7%9C%8Byum%E6%BA%90%E4%B8%AD%E6%9C%89%E5%93%AA%E4%BA%9B%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%BB%84%0A%0Ayum%20info%20java-1.8.0-openjdk.x86_64%20%20%E6%9F%A5%E7%9C%8B%E8%BD%AF%E4%BB%B6%E5%8C%85%E4%BF%A1%E6%81%AF%0A%0Ayum%20search%20java-1.8.0-openjdk.x86_64%20%E6%9F%A5%E7%9C%8B%E6%9F%90%E4%B8%AA%E8%BD%AF%E4%BB%B6%E5%8C%85%E6%98%AF%E5%90%A6%E5%8C%85%E5%90%AB%E5%9C%A8yum%E6%BA%90%E4%B8%AD%2C%E7%AD%89%E5%90%8C%E4%BA%8E%20yum%20list%20%7C%20grep%20package-name%0A%0Ayum%20remove%20package-name%20%20%20%20%E5%8D%B8%E8%BD%BD%E4%B8%80%E4%B8%AA%E8%BD%AF%E4%BB%B6%E5%8C%85%0Ayum%20groupremove%20%20'package-group-name'%20%E5%8D%B8%E8%BD%BD%E4%B8%80%E7%BB%84%E8%BD%AF%E4%BB%B6%E5%8C%85%0A%0Ayum%20list%20updates%20%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E5%8F%AF%E6%9B%B4%E6%96%B0%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%C2%A0%0Ayum%20list%20installed%C2%A0%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E5%B7%B2%E5%AE%89%E8%A3%85%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%C2%A0%0Ayum%20list%20extras%C2%A0%20%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E5%B7%B2%E5%AE%89%E8%A3%85%E4%BD%86%E4%B8%8D%E5%9C%A8%20Yum%20Repository%20%E5%86%85%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%0A%60%60%60%0A%0A%23%23%23%23%23%23%205.2.6%20%E6%9B%B4%E6%96%B0Ali%20yum%E6%BA%90%0A%0A%60%60%60%0A%5Broot%40master%20yum.repos.d%5D%23%20wget%20-O%20%2Fetc%2Fyum.repos.d%2FCentOS-Base.repo%20http%3A%2F%2Fmirrors.aliyun.com%2Frepo%2FCentos-7.repo%0A%5Broot%40master%20yum.repos.d%5D%23%20mv%20server.repo%20repo.bak%2F%0A%5Broot%40master%20yum.repos.d%5D%23%20mv%20CentOS-Base.repo%20server.repo%0A%60%60%60%0A%0A%0A%23%23%23%23%23%205.3%20epel%E6%BA%90%0A%0A%3E%20EPEL%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BC%80%E6%BA%90%E7%9A%84%E9%99%84%E5%8A%A0%E8%BD%AF%E4%BB%B6%E5%8C%85%E4%BB%93%E5%BA%93%EF%BC%8C%E5%8F%AF%E7%94%A8%E4%BA%8Ecentos%20%E5%92%8C%20REHL%20%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%AE%83%E6%8F%90%E4%BE%9B%E4%BA%86%E4%BA%9B%E5%9C%A8%E9%BB%98%E8%AE%A4%E8%BD%AF%E4%BB%B6%E5%8C%85%E4%BB%93%E5%BA%93%E4%B8%AD%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%0A%0A%0A%0A%23%23%23%23%23%23%205.3.1%20%E5%AE%89%E8%A3%85%20epel%E6%BA%90%0A%0A%3E%20yum%20install%20epel%E6%BA%90%E7%9A%84%E4%B8%8B%E8%BD%BD%E5%9C%B0%E5%9D%80%0A%0A%0A%0A%23%23%23%23%23%23%205.3.2%20%E6%9F%A5%E7%9C%8B%E5%B7%B2%E5%AE%89%E8%A3%85%E7%9A%84epel%E6%BA%90%0A%0A%E5%AE%89%E8%A3%85%E6%88%90%E5%8A%9F%E5%90%8E%E4%BC%9A%E5%9C%A8%20%2Fetc%2Fyum.repos.d%2F%E7%9B%AE%E5%BD%95%E4%B8%8B%E5%A4%9A%E5%87%BA%E6%9D%A5%E4%B8%80%E4%BA%9Bepel%E6%96%87%E4%BB%B6%0A%0A%E6%88%96%E8%80%85%E4%BD%BF%E7%94%A8%E5%A6%82%E4%B8%8B%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E8%BD%AF%E4%BB%B6%E6%BA%90%E4%B8%AA%E6%95%B0%0A%0A%60%60%60%0Ayum%20repolist%0A%60%60%60%0A%0A%23%23%23%23%206.%E6%9C%8D%E5%8A%A1%E7%AE%A1%E7%90%86%0A%0A%23%23%23%23%23%206.1%20systemV%20%E4%B8%8E%20init%0A%0AsystemV%E4%B8%AD%E6%9C%89%E4%B8%80%E4%B8%AAinit%E5%91%BD%E4%BB%A4%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%AE%A9service%E5%91%BD%E4%BB%A4%E5%8E%BB%E8%B0%83%E7%94%A8%2Fetc%2Fini.d%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E6%9C%8D%E5%8A%A1%E8%84%9A%E6%9C%AC%0A%0A%23%23%23%23%23%23%206.1.1%20%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%81%9C%E6%93%8D%E4%BD%9C%0A%0A%60%60%60%0A%2Fetc%2Finit.d%2Fservice-name%20start%2Fstop%2Fstatus%2Frestart%0Aservice%20service-name%20%20start%2Fstop%2Fstatus%2Frestart%0A%60%60%60%0A%0A%23%23%23%23%23%23%206.1.2%20%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%81%9C%E7%BA%A7%E5%88%AB%0A%0A%60%60%60%0A0%20%E5%85%B3%E6%9C%BA%0A1%20%E5%8D%95%E7%94%A8%E6%88%B7%0A2%20%E6%97%A0%E7%BD%91%E7%BB%9C%E5%A4%9A%E7%94%A8%E6%88%B7%0A3%20%E5%AD%97%E7%AC%A6%E6%A8%A1%E5%BC%8F%0A4%20%E4%BF%9D%E7%95%99%0A5%20%E5%9B%BE%E5%BD%A2%E6%A8%A1%E5%BC%8F%0A6%20%E9%87%8D%E5%90%AF%0A%60%60%60%0A%0A%0A%0A%60%60%60%0A%23%E5%85%B3%E9%97%AD%E7%B3%BB%E7%BB%9F%E5%90%AF%E5%8A%A83%E7%BA%A7%E5%88%AB%E4%B8%AD%E7%9A%84sshd%E6%9C%8D%E5%8A%A1%0Achkconfig%20--level%203%20sshd%20off%20%0A%0A%23forbid%20the%20start%20of%20firewall%20when%20restart%20system%0Achkconfig%20iptables%20off%0A%0Achkconfig%20-%20updates%20and%20queries%20runlevel%20information%20for%20system%20services%0A%0A%23%E6%9F%A5%E7%9C%8B%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%9C%A8%E5%93%AA%E4%B8%AA%E7%BA%A7%E5%88%AB%E5%90%AF%E5%8A%A8%0Achkconfig%20--list%20iptables%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%206.1.3%20%E5%AF%B9%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%88%86%E7%B1%BB%0A%0A1.%20%E6%8C%89%E5%8A%9F%E8%83%BD%E5%88%86%E7%B1%BB%0A%0A%20%20%20%3E%20%E7%B3%BB%E7%BB%9F%E6%9C%8D%E5%8A%A1%EF%BC%9A%E8%BF%99%E7%B1%BB%E6%9C%8D%E5%8A%A1%E6%89%80%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%98%AF%E7%B3%BB%E7%BB%9F%E6%9C%AC%E8%BA%AB%E6%88%96%E4%BD%BF%E7%94%A8%E7%B3%BB%E7%BB%9F%E7%9A%84%E7%94%A8%E6%88%B7%0A%20%20%20%3E%0A%20%20%20%3E%20%E7%BD%91%E7%BB%9C%E6%9C%8D%E5%8A%A1%EF%BC%9A%E8%BF%99%E7%B1%BB%E6%9C%8D%E5%8A%A1%E6%89%80%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%98%AF%E7%BD%91%E7%BB%9C%E4%B8%AD%E7%9A%84%E5%85%B6%E5%AE%83%E5%AE%A2%E6%88%B7%E7%AB%AF%0A%0A2.%20%E6%8C%89%E5%90%AF%E5%8A%A8%E6%96%B9%E6%B3%95%E5%88%86%E7%B1%BB%0A%0A%20%20%20%3E%20%E7%8B%AC%E7%AB%8B%E7%B3%BB%E7%BB%9F%E6%9C%8D%E5%8A%A1%EF%BC%9A%0A%20%20%20%3E%0A%20%20%20%3E%20%E8%BF%99%E7%B1%BB%E6%9C%8D%E5%8A%A1%E4%B8%80%E6%97%A6%E5%90%AF%E5%8A%A8%EF%BC%8C%E9%99%A4%E9%9D%9E%E7%B3%BB%E7%BB%9F%E5%85%B3%E9%97%AD%E6%88%96%E8%80%85%E7%AE%A1%E7%90%86%E5%91%98%E6%89%8B%E5%8A%A8%E7%BB%93%E6%9D%9F%EF%BC%8C%E5%90%A6%E5%88%99%E4%BC%9A%E4%B8%80%E7%9B%B4%E5%9C%A8%E7%B3%BB%E7%BB%9F%E5%90%8E%E5%8F%B0%E8%BF%90%E8%A1%8C%EF%BC%8C%E4%B8%8D%E7%AE%A1%E6%98%AF%E5%90%A6%E4%BC%9A%E8%A2%AB%E7%B3%BB%E7%BB%9F%E4%BD%BF%E7%94%A8%E5%88%B0%EF%BC%8C%E6%89%80%E4%BB%A5%E5%93%8D%E5%BA%94%E5%BF%AB%E4%BD%86%E6%98%AF%E5%8D%A0%E7%94%A8%E8%B5%84%E6%BA%90%0A%20%20%20%3E%0A%20%20%20%3E%20%0A%20%20%20%3E%0A%20%20%20%3E%20%E4%B8%B4%E6%97%B6%E6%9C%8D%E5%8A%A1%EF%BC%9A%E7%94%A8%E5%88%B0%E7%9A%84%E6%97%B6%E5%80%99%E5%90%AF%E5%8A%A8%EF%BC%8C%E4%BD%BF%E7%94%A8%E5%AE%8C%E5%90%8E%E5%81%9C%E6%AD%A2%EF%BC%8C%E5%93%8D%E5%BA%94%E9%80%9F%E5%BA%A6%E6%85%A2%E4%BD%86%E6%98%AF%E8%8A%82%E7%9C%81%E8%B5%84%E6%BA%90%0A%0A%20%20%20%0A%0A%23%23%23%23%23%206.2%20systemD%20%E4%B8%8E%20unit%0A%0A%3E%20%E4%BB%8Ecentos7%E5%BC%80%E5%A7%8B%EF%BC%8CsystemV%E5%92%8C%E4%B8%8E%E5%85%B6%E5%AF%B9%E5%BA%94%E7%9A%84init%E5%91%BD%E4%BB%A4%E8%A2%AB%E6%95%88%E7%8E%87%E6%9B%B4%E9%AB%98%E7%9A%84systemD%E5%8F%8A%E5%85%B6%E5%AF%B9%E5%BA%94%E7%9A%84systemctl%E5%91%BD%E4%BB%A4%E4%BB%A3%E6%9B%BF%0A%3E%20%E5%B9%B6%E4%B8%94systemctl%E5%85%BC%E5%AE%B9%E4%B9%8B%E5%89%8D%E7%9A%84servicer%E5%91%BD%E4%BB%A4%0A%0A%23%23%23%23%23%23%206.2.1%20%E4%BC%98%E7%82%B9%0A%0A%3E%20%E5%B9%B6%E4%B8%94%E5%A4%84%E7%90%86%E6%89%80%E6%9C%89%E6%9C%8D%E5%8A%A1%EF%BC%8C%E7%BC%A9%E7%9F%AD%E5%BC%80%E6%9C%BA%E6%97%B6%E9%97%B4%0A%3E%0A%3E%20%E7%B1%BB%E4%BC%BC%E4%BA%8Eyum%EF%BC%8C%E8%87%AA%E5%8A%A8%E8%A7%A3%E5%86%B3%E6%9C%8D%E5%8A%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E4%BE%9D%E8%B5%96%0A%3E%0A%3E%20%E6%96%B9%E4%BE%BF%E8%AE%B0%E5%BF%86%EF%BC%8C%E6%8C%89%E7%85%A7%E7%B1%BB%E5%9E%8B%E5%AF%B9%E6%9C%8D%E5%8A%A1%E5%88%86%E7%B1%BB%0A%3E%0A%3E%20%E5%85%BC%E5%AE%B9init%E5%92%8Cservice%E5%91%BD%E4%BB%A4%0A%0A%23%23%23%23%23%23%206.2.2%20%E7%9B%B8%E5%85%B3%E6%96%87%E4%BB%B6%0A%0A%60%60%60shell%0A%2Fusr%2Flib%2Fsystemd%2Fsystem%2F%20%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E8%84%9A%E6%9C%AC%EF%BC%8C%E5%8C%85%E5%90%AB%E5%B7%B2%E5%AE%89%E8%A3%85%E7%9A%84%E6%9C%8D%E5%8A%A1%E8%AE%BE%E7%BD%AE%E6%96%87%E4%BB%B6%0A%2Frun%2Fsystemd%2Fsystem%2F%20%20%09%20%E7%B3%BB%E7%BB%9F%E8%BF%90%E8%A1%8C%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%9A%84%E6%9C%8D%E5%8A%A1%E8%84%9A%E6%9C%AC%EF%BC%8C%E4%BC%98%E5%85%88%E7%BA%A7%E9%AB%98%E4%BA%8E%E4%B8%8A%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%0A%2Fetc%2Fsystemd%2Fsystem%2F%09%20%E7%AE%A1%E7%90%86%E5%91%98%E6%89%8B%E5%8A%A8%E5%BB%BA%E7%AB%8B%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E8%84%9A%E6%9C%AC%EF%BC%8C%E4%BC%98%E5%85%88%E7%BA%A7%E6%9C%80%E9%AB%98%0A%2Fetc%2Fsysconfig%2F*%09%09%20%E7%B3%BB%E7%BB%9F%E5%8A%9F%E8%83%BD%E7%9A%84%E9%BB%98%E8%AE%A4%E8%AE%BE%E7%BD%AE%0A%60%60%60%0A%0A%23%23%23%23%23%23%206.2.3%20%E5%8D%95%E5%85%83unit%E5%88%86%E7%B1%BB%0A%0A%3E%20systemctl%20-t%20help%0A%0A!%5B3bb233473e608b1c1501da8a1fab2bf0.png%5D(en-resource%3A%2F%2Fdatabase%2F1499%3A1)%0A%0A%0A%0A%0A%23%23%23%23%23%206.3%20systemctl%20%E5%91%BD%E4%BB%A4%0A%0A%23%23%23%23%23%23%206.3.1%20%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E5%92%8C%E5%81%9C%E7%94%A8%0A%0A%3E%20systemctl%20start%20sevice-name%0A%0A!%5B6a579fb5ab1dc7e96e2ae689951515e9.png%5D(en-resource%3A%2F%2Fdatabase%2F1500%3A1)%0A%0A%0A%3E%20status%20%E8%AF%A6%E8%A7%A3%0A%0A%60%60%60%0A%5Broot%40master%20chris%5D%23%20systemctl%20status%20atd%0A%20atd.service%20-%20Job%20spooling%20tools%0A%20%20%20Loaded%3A%20loaded%20(%2Fusr%2Flib%2Fsystemd%2Fsystem%2Fatd.service%3B%20enabled%3B%20vendor%20preset%3A%20enabled)%0A%20%20%20Active%3A%20active%20(running)%20since%20Mon%202020-09-21%2010%3A19%3A24%20CST%3B%202min%2058s%20ago%0A%20Main%20PID%3A%201143%20(atd)%0A%20%20%20%20Tasks%3A%201%0A%20%20%20CGroup%3A%20%2Fsystem.slice%2Fatd.service%0A%20%20%20%20%20%20%20%20%20%20%20%20%201143%20%2Fusr%2Fsbin%2Fatd%20-f%0A%0A%60%60%60%0A%0A%60%60%60%0ALoaded%3A%E5%8A%A0%E9%9C%80%E6%88%90%E5%8A%9F%EF%BC%8C%E5%A4%B1%E8%B4%A5%E4%BC%9A%E6%98%BE%E7%A4%BAerror%0AActive%3A%E6%9C%8D%E5%8A%A1%E5%BD%93%E5%89%8D%E7%8A%B6%E6%80%81%0AMain%20PID%EF%BC%9A%E6%9C%8D%E5%8A%A1%E7%9A%84%E4%B8%BB%E8%BF%9B%E7%A8%8B%E5%8F%B7%0ATasks%EF%BC%9A%E6%9C%8D%E5%8A%A1%E7%9A%84%E8%BF%9B%E7%A8%8B%E4%B8%AA%E6%95%B0%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%AA%E6%95%B0%0AMemory%EF%BC%9A%E5%BD%93%E5%89%8D%E5%8D%A0%E7%94%A8%E7%9A%84%E5%86%85%E5%AD%98%E5%A4%A7%E5%B0%8F%0A%60%60%60%0A%0A%0A%0A%3E%20%E4%B8%8D%E6%83%B3%E8%AE%A9%E6%9F%90%E4%BA%9B%E6%9C%8D%E5%8A%A1%E5%8A%A0%E5%85%A5systemctl%2C%20mask%E4%B9%8B%E5%90%8E%E5%A6%82%E6%9E%9C%E4%BD%BF%E7%94%A8systemctl%20%E6%93%8D%E4%BD%9C%E5%B0%B1%E4%BC%9A%E6%8A%A5%E9%94%99%0A%0A%60%60%60%0A%5Broot%40master%20chris%5D%23%20systemctl%20mask%20atd%0ACreated%20symlink%20from%20%2Fetc%2Fsystemd%2Fsystem%2Fatd.service%20to%20%2Fdev%2Fnull.%0A%5Broot%40master%20chris%5D%23%20systemctl%20status%20atd%0A%E2%97%8F%20atd.service%0A%20%20%20Loaded%3A%20masked%20(%2Fdev%2Fnull%3B%20bad)%0A%20%20%20Active%3A%20active%20(running)%20since%20Mon%202020-09-21%2010%3A19%3A24%20CST%3B%2013min%20ago%0A%20Main%20PID%3A%201143%20(atd)%0A%20%20%20CGroup%3A%20%2Fsystem.slice%2Fatd.service%0A%20%20%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%801143%20%2Fusr%2Fsbin%2Fatd%20-f%0A%60%60%60%0A%0A%3E%20%E6%83%B3%E8%AE%A9%E6%9F%90%E4%BA%9B%E6%9C%8D%E5%8A%A1%E5%8A%A0%E5%85%A5systemctl%0A%0A%60%60%60%0Asystemctl%20unmask%20atd%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%206.3.2%20%E6%9F%A5%E7%9C%8B%E6%9C%8D%E5%8A%A1%0A%0A%60%60%60shell%0Asystemctl%20%20list-units%20%E6%9F%A5%E7%9C%8B%E5%8A%A0%E8%BD%BD%E5%88%B0%E5%86%85%E5%AD%98%E4%B8%AD%E7%9A%84%E5%8D%95%E5%85%83%0Asystemctl%20%20list-units%20--type%20service%20%7C%20grep%20mysql%20%20%E6%9F%A5%E7%9C%8Bmysql%E6%9C%8D%E5%8A%A1%E6%98%AF%E5%90%A6%E5%90%AF%E5%8A%A8%0A%0Asystemctl%20%20list-unit-files%20%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E4%B8%AD%E6%89%80%E6%9C%89%E5%AE%89%E8%A3%85%E7%9A%84%E5%8D%95%E5%85%83%E6%96%87%E4%BB%B6%EF%BC%88%E5%AD%98%E6%94%BE%E5%9C%A8%2Fusr%2Flib%2Fsystemd%2Fsystem%2F%EF%BC%89%E7%9A%84%E5%90%AF%20%E7%8A%B6%E6%80%81%0A%0A--type%20%E5%8D%95%E5%85%83%E7%B1%BB%E5%9E%8B%0A--all%20%20%E4%B8%8D%E7%AE%A1%E7%8A%B6%E6%80%81%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%8C%E5%88%97%E5%87%BA%E7%B3%BB%E7%BB%9F%E4%B8%AD%E5%8A%A0%E8%BD%BD%E7%9A%84%0A%60%60%60%0A%0A%60%60%60shell%0Asystemctl%20--type%20service%20--all%0Asystemctl%20--type%3Dservice%20--all%0A%60%60%60%0A%0A%60%60%60shell%0A%23%E6%9F%A5%E7%9C%8B%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E4%BE%9D%E8%B5%96%E4%BA%8E%E5%93%AA%E4%BA%9B%E5%85%B6%E5%AE%83%E6%9C%8D%E5%8A%A1%0Asystemctl%20list-dependencies%20atd.service%0A%0A%23%E6%9F%A5%E7%9C%8B%E5%93%AA%E4%BA%9B%E6%9C%8D%E5%8A%A1%E4%BE%9D%E8%B5%96%E4%BA%8E%E8%BF%99%E4%B8%AA%E6%9C%8D%E5%8A%A1%0Asystemctl%20list-dependencies%20atd.service%20--reverse%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%206.3.3%20%E8%AE%BE%E7%BD%AE%E5%90%AF%E5%8A%A8%E5%8D%95%E5%85%83%0A%0Asystemctl%20%20list-units%20--type%20target%20--all%0A%0A%60%60%60shell%0Agraphical.target%0Amulti-user.target%0Ashutdown.target%0A%60%60%60%0A%0A%60%60%60shell%0A%23%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E9%BB%98%E8%AE%A4%E4%BD%BF%E7%94%A8%E7%9A%84%E5%90%AF%E5%8A%A8%E5%8D%95%E5%85%83%0Asystemctl%20%20get-default%0A%23%E8%AE%BE%E7%BD%AE%E7%B3%BB%E7%BB%9F%E9%BB%98%E8%AE%A4%E4%BD%BF%E7%94%A8%E7%9A%84%E5%90%AF%E5%8A%A8%E5%8D%95%E5%85%83%0Asystemctl%20%20set-default%20multi-user.target%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%23%23%206.3.4%20%E5%BC%80%E5%85%B3%E6%9C%BA%0A%0A1.%20%E5%85%B3%E6%9C%BA%0A%0A%20%20%20%60%60%60shell%0A%20%20%20systemctl%20poweroff%20%20%0A%20%20%20%E7%AD%89%E5%90%8C%E4%BA%8E%0A%20%20%20%09init%200%20%0A%20%20%20%09shutdown%20-h%20now%0A%20%20%20%60%60%60%0A%0A2.%20%E9%87%8D%E5%90%AF%0A%0A%20%20%20%60%60%60shell%0A%20%20%20systemctl%20reboot%20%20%0A%20%20%20%E7%AD%89%E5%90%8C%E4%BA%8E%0A%20%20%20%09init%206%0A%20%20%20%09shutdown%20-r%20now%0A%20%20%20%60%60%60%0A%0A3.%20%E6%8C%82%E8%B5%B7%0A%0A%20%20%20%60%60%60shell%0A%20%20%20systemctl%20suspend%20%0A%20%20%20%60%60%60%0A%0A4.%20%E4%BC%91%E7%9C%A0%0A%0A%20%20%20%60%60%60shell%0A%20%20%20systemctl%20hibernate%0A%20%20%20%60%60%60%0A%0A%20%20%20%0A%0A%23%23%23%23%23%23%206.3.5%20%E6%9F%A5%E7%9C%8B%E7%AB%AF%E5%8F%A3%E5%8F%B7%0A!%5B3217561b55d18b5a92e108ba4871d1cd.png%5D(en-resource%3A%2F%2Fdatabase%2F1498%3A1)%0A%0A%0A%0A%0A%23%23%23%23%23%23%206.3.6%20%20firewall%0A%0A%60%60%60%0Asystemctl%20enable%20firewalld.service%0Asystemctl%20restart%20firewalld.service%0A%0Afirewall-cmd%20--state%20%20%20%20%20%E6%9F%A5%E7%9C%8B%E7%8A%B6%E6%80%81%0Afirewall-cmd%20--list-all%20%20%20%E6%9F%A5%E7%9C%8B%E8%BF%87%E6%BB%A4%E7%9A%84%E5%88%97%E8%A1%A8%E4%BF%A1%E6%81%AF%0A%0Afirewall-cmd%20--add-service%3Dhttp%20--permanent%20%E8%AE%BE%E7%BD%AE%E5%BC%80%E6%94%BE%E7%9A%84%E6%9C%8D%E5%8A%A1%0Afirewall-cmd%20--add-port%3D8001%20--permanent%20%20%20%E8%AE%BE%E7%BD%AE%E5%BC%80%E6%94%BE%E7%9A%84%E7%AB%AF%E5%8F%A3%E5%8F%B7%0Afirewall-cmd%20--reload%20%20%20%E9%87%8D%E6%96%B0%E5%8A%A0%E8%BD%BD%E9%98%B2%E7%81%AB%E5%A2%99%0A%60%60%60

安装工具

创建时间:2024/1/14 12:05
更新时间:2024/1/14 12:05
作者:Chris

1. 安装Maven

cd /opt
curl -OL https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
tar -zxvf apache-maven-3.6.3-bin.tar.gz
mv apache-maven-3.6.3 maven

修改配置

vi maven/config/settting.xml

配置本地仓库

<localRepository>/path/to/local/repo</localRepository>

加入ali镜像

    <mirror>
      <id>alimaven</id>
      <mirrorOf>central</mirrorOf>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    </mirror>
vi /etc/profile
export MVN_HOME=/opt/maven
export PATH=$PATH:$JAVA_HOME/bin:$MVN_HOME/bin
[root@master conf]# source /etc/profile
[root@master conf]# mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /usr/local/maven
Java version: 1.8.0_242, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.el7.x86_64/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-1127.el7.x86_64", arch: "amd64", family: "unix"

2. 安装JDK

cd /opt/
cp /tmp/jdk-8u191-linux-x64.tar.gz  .
tar -zxvf jdk-8u191-linux-x64.tar.gz
mv jdk-8u191-linux-x64 jdk1.8
chmod 777 jdk1.8

vi /ect/profile 在最后添加配置

#安装目录
export JAVA_HOME=/opt/jvm/jdk1.8
#下面都一样啦
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
source /etc/profile
java -version 

the java -version doesn't work after su to another account
need to add in the ==.bashrc== of each account

source /etc/profile

3. 安装Git

sudo yum install -y git

4. 安装RocketMQ

https://rocketmq.apache.org/docs/quick-start/

cd /opt
wget https://github.com/apache/rocketmq/archive/refs/tags/rocketmq-all-4.9.0.tar.gz
cd rocketmq-rocketmq-all-4.9.0
mvn -Prelease-all -DskipTests clean install -U
cd /distribution/target/rocketmq-4.9.0/rocketmq-4.9.0
mkdir -p /data/mq/rocketmq/

配置broker

vi conf/broker.conf
追加如下内容

#name server服务器地址及端口,可以是多个,分号隔开
namesrvAddr=192.168.80.180:9876
#是否自动创建默认topic,生产需保持关闭
autoCreateTopicEnable=false
#brokerIP1:配置broker所在服务器的ip地址,以便Name Server连接
brokerIP1=192.168.80.180

启动nameserver

[root@master]# nohup sh bin/mqnamesrv &
tail -f /logs/rocketmqlogs/nameserver.log

[root@master bin]# jps
3235 Jps
3207 NamesrvStartup

启动broker

-- 无参数启动
nohup sh bin/mqbroker -n master:9876 &

-- 加载参数启动
nohup sh bin/mqbroker -n master:9876 -c conf/broker.conf
autoCreateTopicEnable=true &

tail -f /logs/rocketmqlogs/broker.log

[root@master rocketmq]# jps
3429 Jps
3207 NamesrvStartup
3386 BrokerStartup

rockertmq启动默认设置内存较大会导致启动失败需要手动修改

vi bin/runserver.sh
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"

vi bin/runborker.sh
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m"
[root@master rocketmq]# export NAMESRV_ADDR=localhost:9876
[root@master rocketmq]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

SendResult [sendStatus=SEND_OK, msgId=7F000001109B1B6D35866692827F03E6, offsetMsgId=C0A8657F00002A9F00000000000316F4, messageQueue=MessageQueue [topic=TopicTest, brokerName=master, queueId=1], queueOffset=249]
SendResult [sendStatus=SEND_OK, msgId=7F000001109B1B6D35866692828203E7, offsetMsgId=C0A8657F00002A9F00000000000317BF, messageQueue=MessageQueue [topic=TopicTest, brokerName=master, queueId=2], queueOffset=249]
[root@master rocketmq]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

ConsumeMessageThread_8 Receive New Messages: [MessageExt [brokerName=master, queueId=3, storeSize=203, queueOffset=229, sysFlag=0, bornTimestamp=1647784877377, bornHost=/192.168.101.127:40132, storeTimestamp=1647784877378, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F000000000002D5EE, commitLogOffset=185838, bodyCRC=2121214082, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=250, CONSUME_START_TIME=1647786877924, UNIQ_KEY=7F000001109B1B6D3586669281410394, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 57, 49, 54], transaction}]] 
ConsumeMessageThread_12 Receive New Messages: [MessageExt [brokerName=master, queueId=3, storeSize=203, queueOffset=228, sysFlag=0, bornTimestamp=1647784877348, bornHost=/192.168.101.127:40132, storeTimestamp=1647784877349, storeHost=/192.168.101.127:10911, msgId=C0A8657F00002A9F000000000002D2C2, commitLogOffset=185026, bodyCRC=2030234779, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=250, CONSUME_START_TIME=1647786877846, UNIQ_KEY=7F000001109B1B6D3586669281240390, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 57, 49, 50], transaction}]]

rocketmq服务关闭
先关broker,再关闭nameserver

关闭broker服务 :sh bin/mqshutdown broker
关闭namesrv服务:sh bin/mqshutdown namesrv  

安装可视化界面

https://github.com/apache/rocketmq-externals
下载zip包

unzip rocketmq-externals-master.zip
[root@master rocketmq-externals-master]# cd rocketmq-console/src/main/resources/
vi application.properties

server.port=9877
server.address=0.0.0.0

[root@master rocketmq-console]# mvn clean package -Dmaven.test.skip=true
[root@master rocketmq-console]# cd target/

nohup java -jar rocketmq-console-ng-2.0.0.jar > /data/mq/rocketmq/rocket-console.log 2>&1 &

issue

ava.lang.RuntimeException: org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <null> failed
at com.google.common.base.Throwables.propagate(Throwables.java:160)

solution

文件位于rocketmq-externals/rocketmq-console/src/main/resources下面
修改application.properties
rocketmq.config.namesrvAddr=master:9876
rocketmq.config.isVIPChannel=false
%5Btoc%5D%0A%0A%23%23%201.%20%E5%AE%89%E8%A3%85Maven%0A%0A%60%60%60%0Acd%20%2Fopt%0Acurl%20-OL%20https%3A%2F%2Fmirrors.tuna.tsinghua.edu.cn%2Fapache%2Fmaven%2Fmaven-3%2F3.6.3%2Fbinaries%2Fapache-maven-3.6.3-bin.tar.gz%0Atar%20-zxvf%20apache-maven-3.6.3-bin.tar.gz%0Amv%20apache-maven-3.6.3%20maven%0A%60%60%60%0A%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE%0A%3E%20vi%20maven%2Fconfig%2Fsettting.xml%0A%0A%E9%85%8D%E7%BD%AE%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%0A%3E%20%20%3ClocalRepository%3E%2Fpath%2Fto%2Flocal%2Frepo%3C%2FlocalRepository%3E%20%20%0A%0A%E5%8A%A0%E5%85%A5ali%E9%95%9C%E5%83%8F%0A%60%60%60%0A%20%20%20%20%3Cmirror%3E%0A%20%20%20%20%20%20%3Cid%3Ealimaven%3C%2Fid%3E%0A%20%20%20%20%20%20%3CmirrorOf%3Ecentral%3C%2FmirrorOf%3E%0A%20%20%20%20%20%20%3Cname%3Ealiyun%20maven%3C%2Fname%3E%0A%20%20%20%20%20%20%3Curl%3Ehttp%3A%2F%2Fmaven.aliyun.com%2Fnexus%2Fcontent%2Fgroups%2Fpublic%2F%3C%2Furl%3E%0A%20%20%20%20%3C%2Fmirror%3E%0A%60%60%60%0A%0A%60%60%60%0Avi%20%2Fetc%2Fprofile%0Aexport%20MVN_HOME%3D%2Fopt%2Fmaven%0Aexport%20PATH%3D%24PATH%3A%24JAVA_HOME%2Fbin%3A%24MVN_HOME%2Fbin%0A%60%60%60%0A%0A%0A%60%60%60%0A%5Broot%40master%20conf%5D%23%20source%20%2Fetc%2Fprofile%0A%5Broot%40master%20conf%5D%23%20mvn%20-version%0AApache%20Maven%203.6.3%20(cecedd343002696d0abb50b32b541b8a6ba2883f)%0AMaven%20home%3A%20%2Fusr%2Flocal%2Fmaven%0AJava%20version%3A%201.8.0_242%2C%20vendor%3A%20Oracle%20Corporation%2C%20runtime%3A%20%2Fusr%2Flib%2Fjvm%2Fjava-1.8.0-openjdk-1.8.0.242.b08-1.el7.x86_64%2Fjre%0ADefault%20locale%3A%20zh_CN%2C%20platform%20encoding%3A%20UTF-8%0AOS%20name%3A%20%22linux%22%2C%20version%3A%20%223.10.0-1127.el7.x86_64%22%2C%20arch%3A%20%22amd64%22%2C%20family%3A%20%22unix%22%0A%60%60%60%0A%0A%23%23%202.%20%E5%AE%89%E8%A3%85JDK%0A%0A%60%60%60%0Acd%20%2Fopt%2F%0Acp%20%2Ftmp%2Fjdk-8u191-linux-x64.tar.gz%20%20.%0Atar%20-zxvf%20jdk-8u191-linux-x64.tar.gz%0Amv%20jdk-8u191-linux-x64%20jdk1.8%0Achmod%20777%20jdk1.8%0A%60%60%60%0A%0A%3E%20vi%20%2Fect%2Fprofile%20%E5%9C%A8%E6%9C%80%E5%90%8E%E6%B7%BB%E5%8A%A0%E9%85%8D%E7%BD%AE%0A%0A%60%60%60%0A%23%E5%AE%89%E8%A3%85%E7%9B%AE%E5%BD%95%0Aexport%20JAVA_HOME%3D%2Fopt%2Fjvm%2Fjdk1.8%0A%23%E4%B8%8B%E9%9D%A2%E9%83%BD%E4%B8%80%E6%A0%B7%E5%95%A6%0Aexport%20JRE_HOME%3D%24JAVA_HOME%2Fjre%0Aexport%20CLASSPATH%3D.%3A%24JAVA_HOME%2Flib%3A%24JRE_HOME%2Flib%3A%24CLASSPATH%0Aexport%20PATH%3D%24JAVA_HOME%2Fbin%3A%24JRE_HOME%2Fbin%3A%24PATH%0A%60%60%60%0A%0A%60%60%60%0Asource%20%2Fetc%2Fprofile%0Ajava%20-version%20%0A%60%60%60%0A%0A%3E%20the%20java%20-version%20doesn't%20work%20after%20su%20to%20another%20account%0Aneed%20to%20add%20in%20the%20%3D%3D.bashrc%3D%3D%20of%20each%20account%0A%0A%60%60%60%0Asource%20%2Fetc%2Fprofile%0A%60%60%60%0A%0A%23%23%203.%20%E5%AE%89%E8%A3%85Git%0A%60%60%60%0Asudo%20yum%20install%20-y%20git%0A%60%60%60%0A%0A%0A%23%23%204.%20%E5%AE%89%E8%A3%85RocketMQ%0A%0A%3E%20https%3A%2F%2Frocketmq.apache.org%2Fdocs%2Fquick-start%2F%0A%0A%60%60%60%0Acd%20%2Fopt%0Awget%20https%3A%2F%2Fgithub.com%2Fapache%2Frocketmq%2Farchive%2Frefs%2Ftags%2Frocketmq-all-4.9.0.tar.gz%0Acd%20rocketmq-rocketmq-all-4.9.0%0Amvn%20-Prelease-all%20-DskipTests%20clean%20install%20-U%0Acd%20%2Fdistribution%2Ftarget%2Frocketmq-4.9.0%2Frocketmq-4.9.0%0Amkdir%20-p%20%2Fdata%2Fmq%2Frocketmq%2F%0A%60%60%60%0A%0A%E9%85%8D%E7%BD%AEbroker%0A%3E%20vi%20conf%2Fbroker.conf%0A%E8%BF%BD%E5%8A%A0%E5%A6%82%E4%B8%8B%E5%86%85%E5%AE%B9%0A%0A%60%60%60%0A%23name%20server%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%9C%B0%E5%9D%80%E5%8F%8A%E7%AB%AF%E5%8F%A3%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%98%AF%E5%A4%9A%E4%B8%AA%EF%BC%8C%E5%88%86%E5%8F%B7%E9%9A%94%E5%BC%80%0AnamesrvAddr%3D192.168.80.180%3A9876%0A%23%E6%98%AF%E5%90%A6%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BA%E9%BB%98%E8%AE%A4topic%EF%BC%8C%E7%94%9F%E4%BA%A7%E9%9C%80%E4%BF%9D%E6%8C%81%E5%85%B3%E9%97%AD%0AautoCreateTopicEnable%3Dfalse%0A%23brokerIP1%EF%BC%9A%E9%85%8D%E7%BD%AEbroker%E6%89%80%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84ip%E5%9C%B0%E5%9D%80%EF%BC%8C%E4%BB%A5%E4%BE%BFName%20Server%E8%BF%9E%E6%8E%A5%0AbrokerIP1%3D192.168.80.180%0A%60%60%60%0A%0A%3E%20%E5%90%AF%E5%8A%A8nameserver%0A%0A%60%60%60%0A%5Broot%40master%5D%23%20nohup%20sh%20bin%2Fmqnamesrv%20%26%0Atail%20-f%20%2Flogs%2Frocketmqlogs%2Fnameserver.log%0A%0A%5Broot%40master%20bin%5D%23%20jps%0A3235%20Jps%0A3207%20NamesrvStartup%0A%60%60%60%0A%0A%3E%20%E5%90%AF%E5%8A%A8broker%0A%0A%60%60%60%0A--%20%E6%97%A0%E5%8F%82%E6%95%B0%E5%90%AF%E5%8A%A8%0Anohup%20sh%20bin%2Fmqbroker%20-n%20master%3A9876%20%26%0A%0A--%20%E5%8A%A0%E8%BD%BD%E5%8F%82%E6%95%B0%E5%90%AF%E5%8A%A8%0Anohup%20sh%20bin%2Fmqbroker%20-n%20master%3A9876%20-c%20conf%2Fbroker.conf%0AautoCreateTopicEnable%3Dtrue%20%26%0A%0Atail%20-f%20%2Flogs%2Frocketmqlogs%2Fbroker.log%0A%0A%5Broot%40master%20rocketmq%5D%23%20jps%0A3429%20Jps%0A3207%20NamesrvStartup%0A3386%20BrokerStartup%0A%0A%60%60%60%0A%0A%3E%20rockertmq%E5%90%AF%E5%8A%A8%E9%BB%98%E8%AE%A4%E8%AE%BE%E7%BD%AE%E5%86%85%E5%AD%98%E8%BE%83%E5%A4%A7%E4%BC%9A%E5%AF%BC%E8%87%B4%E5%90%AF%E5%8A%A8%E5%A4%B1%E8%B4%A5%E9%9C%80%E8%A6%81%E6%89%8B%E5%8A%A8%E4%BF%AE%E6%94%B9%0A%0A%60%60%60%0Avi%20bin%2Frunserver.sh%0AJAVA_OPT%3D%22%24%7BJAVA_OPT%7D%20-server%20-Xms512m%20-Xmx512m%20-Xmn256m%20-XX%3AMetaspaceSize%3D128m%20-XX%3AMaxMetaspaceSize%3D320m%22%0A%0Avi%20bin%2Frunborker.sh%0AJAVA_OPT%3D%22%24%7BJAVA_OPT%7D%20-server%20-Xms512m%20-Xmx512m%20-Xmn256m%22%0A%60%60%60%0A%0A%3E%20%0A%0A%60%60%60%0A%5Broot%40master%20rocketmq%5D%23%20export%20NAMESRV_ADDR%3Dlocalhost%3A9876%0A%5Broot%40master%20rocketmq%5D%23%20sh%20bin%2Ftools.sh%20org.apache.rocketmq.example.quickstart.Producer%0A%0ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001109B1B6D35866692827F03E6%2C%20offsetMsgId%3DC0A8657F00002A9F00000000000316F4%2C%20messageQueue%3DMessageQueue%20%5Btopic%3DTopicTest%2C%20brokerName%3Dmaster%2C%20queueId%3D1%5D%2C%20queueOffset%3D249%5D%0ASendResult%20%5BsendStatus%3DSEND_OK%2C%20msgId%3D7F000001109B1B6D35866692828203E7%2C%20offsetMsgId%3DC0A8657F00002A9F00000000000317BF%2C%20messageQueue%3DMessageQueue%20%5Btopic%3DTopicTest%2C%20brokerName%3Dmaster%2C%20queueId%3D2%5D%2C%20queueOffset%3D249%5D%0A%60%60%60%0A%0A%0A%60%60%60%0A%5Broot%40master%20rocketmq%5D%23%20sh%20bin%2Ftools.sh%20org.apache.rocketmq.example.quickstart.Consumer%0A%0AConsumeMessageThread_8%20Receive%20New%20Messages%3A%20%5BMessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D203%2C%20queueOffset%3D229%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1647784877377%2C%20bornHost%3D%2F192.168.101.127%3A40132%2C%20storeTimestamp%3D1647784877378%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F000000000002D5EE%2C%20commitLogOffset%3D185838%2C%20bodyCRC%3D2121214082%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'TopicTest'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D250%2C%20CONSUME_START_TIME%3D1647786877924%2C%20UNIQ_KEY%3D7F000001109B1B6D3586669281410394%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2082%2C%20111%2C%2099%2C%20107%2C%20101%2C%20116%2C%2077%2C%2081%2C%2032%2C%2057%2C%2049%2C%2054%5D%2C%20transactionId%3D'null'%7D%5D%5D%20%0AConsumeMessageThread_12%20Receive%20New%20Messages%3A%20%5BMessageExt%20%5BbrokerName%3Dmaster%2C%20queueId%3D3%2C%20storeSize%3D203%2C%20queueOffset%3D228%2C%20sysFlag%3D0%2C%20bornTimestamp%3D1647784877348%2C%20bornHost%3D%2F192.168.101.127%3A40132%2C%20storeTimestamp%3D1647784877349%2C%20storeHost%3D%2F192.168.101.127%3A10911%2C%20msgId%3DC0A8657F00002A9F000000000002D2C2%2C%20commitLogOffset%3D185026%2C%20bodyCRC%3D2030234779%2C%20reconsumeTimes%3D0%2C%20preparedTransactionOffset%3D0%2C%20toString()%3DMessage%7Btopic%3D'TopicTest'%2C%20flag%3D0%2C%20properties%3D%7BMIN_OFFSET%3D0%2C%20MAX_OFFSET%3D250%2C%20CONSUME_START_TIME%3D1647786877846%2C%20UNIQ_KEY%3D7F000001109B1B6D3586669281240390%2C%20CLUSTER%3DDefaultCluster%2C%20WAIT%3Dtrue%2C%20TAGS%3DTagA%7D%2C%20body%3D%5B72%2C%20101%2C%20108%2C%20108%2C%20111%2C%2032%2C%2082%2C%20111%2C%2099%2C%20107%2C%20101%2C%20116%2C%2077%2C%2081%2C%2032%2C%2057%2C%2049%2C%2050%5D%2C%20transactionId%3D'null'%7D%5D%5D%0A%0A%60%60%60%0A%0A%0A%0A%3E%20rocketmq%E6%9C%8D%E5%8A%A1%E5%85%B3%E9%97%AD%0A%3E%20%E5%85%88%E5%85%B3broker%EF%BC%8C%E5%86%8D%E5%85%B3%E9%97%ADnameserver%0A%60%60%60%0A%E5%85%B3%E9%97%ADbroker%E6%9C%8D%E5%8A%A1%20%EF%BC%9Ash%20bin%2Fmqshutdown%20broker%0A%E5%85%B3%E9%97%ADnamesrv%E6%9C%8D%E5%8A%A1%EF%BC%9Ash%20bin%2Fmqshutdown%20namesrv%20%20%0A%60%60%60%0A%0A%3E%20%E5%AE%89%E8%A3%85%E5%8F%AF%E8%A7%86%E5%8C%96%E7%95%8C%E9%9D%A2%0A%0Ahttps%3A%2F%2Fgithub.com%2Fapache%2Frocketmq-externals%0A%E4%B8%8B%E8%BD%BDzip%E5%8C%85%0A%0A%60%60%60%0Aunzip%20rocketmq-externals-master.zip%0A%5Broot%40master%20rocketmq-externals-master%5D%23%20cd%20rocketmq-console%2Fsrc%2Fmain%2Fresources%2F%0Avi%20application.properties%0A%0Aserver.port%3D9877%0Aserver.address%3D0.0.0.0%0A%0A%5Broot%40master%20rocketmq-console%5D%23%20mvn%20clean%20package%20-Dmaven.test.skip%3Dtrue%0A%5Broot%40master%20rocketmq-console%5D%23%20cd%20target%2F%0A%0Anohup%20java%20-jar%20rocketmq-console-ng-2.0.0.jar%20%3E%20%2Fdata%2Fmq%2Frocketmq%2Frocket-console.log%202%3E%261%20%26%0A%60%60%60%0A%0A%3E%20issue%0A%0A%60%60%60%0Aava.lang.RuntimeException%3A%20org.apache.rocketmq.remoting.exception.RemotingConnectException%3A%20connect%20to%20%3Cnull%3E%20failed%0Aat%20com.google.common.base.Throwables.propagate(Throwables.java%3A160)%0A%60%60%60%0A%0A%3E%20solution%0A%0A%60%60%60%0A%E6%96%87%E4%BB%B6%E4%BD%8D%E4%BA%8Erocketmq-externals%2Frocketmq-console%2Fsrc%2Fmain%2Fresources%E4%B8%8B%E9%9D%A2%0A%E4%BF%AE%E6%94%B9application.properties%0Arocketmq.config.namesrvAddr%3Dmaster%3A9876%0Arocketmq.config.isVIPChannel%3Dfalse%0A%60%60%60%0A%0A

Spring EL

创建时间:2024/2/12 10:11
更新时间:2024/2/16 12:07
作者:Chris

官方文档

https://docs.spring.io/spring-framework/docs/5.1.6.RELEASE/spring-framework-reference/core.html#expressions-evaluation

表达式

字面表达式

/**
 * 字面表达式:
 * 字符串中的内容是最终转换后的结果,字符串定义了什么,最终就可以得到什么。
 * <p>
 * 示例:加#时SpEL表达式才可以解析,不加时是解析不了的,SpEL表达式解析时单引号和双引号在SpEL中的效果是一样的
 * content:'hello'+", Chris", result:'hello'+", Chris", 对象类型:class java.lang.String
 * content:#{'hello'+", Chris"}, result:hello, Chris, 对象类型:class java.lang.String
 * <p>
 * 如果传递的是一些基础的数据内容,也会自动的进行类型转换
 * content:#{1}, result:1, 对象类型:class java.lang.Integer
 * content:#{1.1}, result:1.1, 对象类型:class java.lang.Double
 * content:#{true}, result:true, 对象类型:class java.lang.Boolean
 */
@Test
public void test01() {
    String str1 = "'hello'+\", Chris\"";
    String str2 = "#{'hello'+\", Chris\"}";
    spel(str1);
    spel(str2);

    String str3 = "#{1}";
    String str4 = "#{1.1}";
    String str5 = "#{true}";
    spel(str3);
    spel(str4);
    spel(str5);

}

数学表达式

/**
 * 数学表达式
 * 示例:
 * content:#{1+2-3*4/5}, result:1, 对象类型:class java.lang.Integer
 * content:#{1+2-3*4/5.0}, result:0.6000000000000001, 对象类型:class java.lang.Double
 * content:#{10%3}, result:1, 对象类型:class java.lang.Integer
 * content:#{10 mod 3}, result:1, 对象类型:class java.lang.Integer
 * content:#{10 div 3}, result:3, 对象类型:class java.lang.Integer
 * content:#{10 ^ 3}, result:1000, 对象类型:class java.lang.Integer
 */
@Test
public void test02() {
    spel("#{1+2-3*4/5}");
    spel("#{1+2-3*4/5.0}");
    spel("#{10%3}");
    spel("#{10 mod 3}");
    spel("#{10 div 3}");
    spel("#{10 ^ 3}");
}

关系表达式

/**
 * 关系表达式
 * 示例:
 * content:#{30!=20}, result:true, 对象类型:class java.lang.Boolean
 * content:#{30 NE 20}, result:true, 对象类型:class java.lang.Boolean
 * content:#{'chris' > 'Chris'}, result:true, 对象类型:class java.lang.Boolean
 * content:#{10+20 eq 30}, result:true, 对象类型:class java.lang.Boolean
 */
@Test
public void test03() {
    spel("#{30!=20}");
    spel("#{30 NE 20}");
    spel("#{'chris' > 'Chris'}");
    spel("#{10+20 eq 30}");
}

逻辑表达式

/**
 * 逻辑表达式
 * 示例:
 * content:#{30!=20 || 10==10}, result:true, 对象类型:class java.lang.Boolean
 * content:#{'chris' > 'Chris' && 'Ethan' lt 'ethan'}, result:true, 对象类型:class java.lang.Boolean
 * content:#{10 between {1,100} && 1==1}, result:true, 对象类型:class java.lang.Boolean
 * content:#{'y' between {'a','c'} }, result:false, 对象类型:class java.lang.Boolean
 */
@Test
public void test04() {
    spel("#{30!=20 || 10==10}");
    spel("#{'chris' > 'Chris' && 'Ethan' lt 'ethan'}");
    spel("#{10 between {1,100} && 1==1}");
    spel("#{'y' between {'a','c'} }");
}

三目运算符

/**
 * 三目运算符
 * SpEL中支持三目运算符
 * 示例:
 * content:#{'chris'!=null? 'hello,chris':'who are you?'}, result:hello,chris, 对象类型:class java.lang.String
 * content:#{null==null? 'hello,chris':'who are you?'}, result:hello,chris, 对象类型:class java.lang.String
 * content:#{false ? 'hello,chris':'who are you?'}, result:who are you?, 对象类型:class java.lang.String
 * <p>
 * 同进也支持Groovy中扩展的三目结构,如果判断内容为null,则返回fase的结果,如果不为null,则返回判断内容本身
 * 示例:
 * content:#{null ?:'it is null'}, result:it is null, 对象类型:class java.lang.String
 * content:#{'chris' ?:'it is null'}, result:chris, 对象类型:class java.lang.String
 */
@Test
public void test05() {
    spel("#{'chris'!=null? 'hello,chris':'who are you?'}");
    spel("#{null==null? 'hello,chris':'who are you?'}");
    spel("#{false ? 'hello,chris':'who are you?'}");

    spel("#{null ?:'it is null'}");
    spel("#{'chris' ?:'it is null'}");
}

字符串处理

/**
 * 字符串处理
 * 示例:
 * content:#{'spring express language'[4]}, result:n, 对象类型:class java.lang.String
 * content:#{'spring express language'.substring(4, 'spring express language'.length())}, result:ng express language, 对象类型:class java.lang.String
 * content:#{'www.bing.com'.matches('\w+\.\w+\.\w+')}, result:true, 对象类型:class java.lang.Boolean
 * content:#{'www.bing.com'matches '\w+\.\w+\.\w+'}, result:true, 对象类型:class java.lang.Boolean
 */
@Test
public void test06() {
    spel("#{'spring express language'[4]}");
    spel("#{'spring express language'.substring(4, 'spring express language'.length())}");
    spel("#{'www.bing.com'.matches('\\w+\\.\\w+\\.\\w+')}");
    spel("#{'www.bing.com' matches '\\w+\\.\\w+\\.\\w+'}");
}

StandardEvaluationContext

ExpressionParser parser;

@Before
public void init() {
    // 定义SpEL解析器
    parser = new SpelExpressionParser();
}

@Test
public void test01() {
    String template = "#{#varA+#varB}";
    Expression exp = parser.parseExpression(template, ParserContext.TEMPLATE_EXPRESSION); // 表达式解析

    StandardEvaluationContext context = new StandardEvaluationContext();// 表达式上下文配置

    // 定义变更内容
    context.setVariable("varA", "hello");
    context.setVariable("varB", ", magic SpEL");

    // 字符串类型的计算处理
    String value = exp.getValue(context, String.class);
    log.info("value:{}", value);

    // 数字类型的计算处理
    context.setVariable("varA", 1212);
    context.setVariable("varB", 3.33);
    Double result = exp.getValue(context, Double.class);
    log.info("result:{}", result);
}

@Test
public void test02() {
    // 根变量与普通变量的区别在于其可以直接在实例化表达式解析上下文时进行根变量的配置(构造方法上的特权使用,仅此而已)
    String template = "#{#root.contains('hello')}";

    Expression exp = parser.parseExpression(template, ParserContext.TEMPLATE_EXPRESSION); // 表达式解析
    StandardEvaluationContext context = new StandardEvaluationContext("hello, happy new year");// 表达式上下文配置
    Boolean result = exp.getValue(context, Boolean.class);
    log.info("result:{}", result);
}

/**
 * 对919进行转型操作,将其转换为Integer的对象实例
 */
@Test
public void test03() throws NoSuchMethodException {
    String template = "#{#convert('919')}";
    Expression exp = parser.parseExpression(template, ParserContext.TEMPLATE_EXPRESSION); // 表达式解析

    Method method = Integer.clas s.getMethod("parseInt", String.class);

    StandardEvaluationContext context = new StandardEvaluationContext();// 表达式上下文配置根对象
    context.setVariable("convert", method); // 方法引用的实现

    Integer result = exp.getValue(context, Integer.class);
    log.info("result:{}", result);
}

@Test
public void test04() {
    // java.util.Date类中提供有getTime()方法,所以此处可以直接采用time的标记进行属性表示
    String template = "#{#var.time}";
    Expression exp = parser.parseExpression(template, ParserContext.TEMPLATE_EXPRESSION); // 表达式解析

    StandardEvaluationContext context = new StandardEvaluationContext();// 表达式上下文配置
    context.setVariable("var", new Date());

    Long time = exp.getValue(context, Long.class);
    log.info("result:{}", time);
}


/**
 * 对于SpEL,需要确保对象存在,如果对象不存或为null在则会出下异常
 * org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'time' cannot be found on null
 * <p>
 * 解决方案:在SpEL中使用Groovy表达式进行判断处理
 */
@Test
public void test05() {
    // 首先会判断var对象是否存在,如果不存在则直接返回null,如果存在则继续判断属性是否存在,如果存在则返回属性值,如果不存在则返回null
    String template = "#{#var?.time}";
    Expression exp = parser.parseExpression(template, ParserContext.TEMPLATE_EXPRESSION); // 表达式解析

    StandardEvaluationContext context = new StandardEvaluationContext();// 表达式上下文配置
    context.setVariable("var", null);

    Long time = exp.getValue(context, Long.class);
    log.info("result:{}", time);
}

SpEL反射表达式

/**
 * Java中最大的处理机制在于反射机制,包括JDK之中的内存结构的不断优化实际上也是与反射机制有直接的关联,比如:永久代被替换为元空间
 * <p>
 * Spring中最重要的特点就是通过字符串描述出更多的内容,那么对于反射机制也可以通过字符串的形式进行描述
 * <p>
 * 这种代码操作的核心意义在于:直接在配置文件里面编写的字符串可以定义任意数据类型
 * <p>
 * #{T(java.lang.String)} class表达式:class java.lang.String
 * #{T(java.util.Date)} class表达式:class java.util.Date
 * #{T(java.lang.Integer).MAX_VALUE} class表达式:2147483647
 * #{T(java.lang.Integer).parseInt('123')} class表达式:123
 */
@Test
public void test06() {
    log.info("#{T(java.lang.String)} class表达式:{}", spel("#{T(java.lang.String)}"));
    log.info("#{T(java.util.Date)} class表达式:{}", spel("#{T(java.util.Date)}"));

    // 通过字符串反射定义的静态常量和方法
    log.info("#{T(java.lang.Integer).MAX_VALUE} class表达式:{}", spel("#{T(java.lang.Integer).MAX_VALUE}"));
    log.info("#{T(java.lang.Integer).parseInt('123')} class表达式:{}", spel("#{T(java.lang.Integer).parseInt('123')}"));
}

/**
 * 字符串表达式还可以直接定义对象,比如:#{new com.chris.cloud.spel.Book('Spring开发实战5',64.5)}
 * <p>
 * 直接使用字符串的'new',根据类中提供的双参构造器方法实现对象的实例化,但这里本质上是通过SpEL解析得来的
 */
@Test
public void test07() {
    Object book = spel("#{new com.chris.cloud.spel.Book('Spring开发实战5',64.5)}");
    log.info("book:{}", book);
}

private Object spel(String content) {
Expression exp = parser.parseExpression(content, ParserContext.TEMPLATE_EXPRESSION);
StandardEvaluationContext context = new StandardEvaluationContext();
return exp.getValue(context);
}

%5Btoc%5D%0A%23%23%20%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%0A%60https%3A%2F%2Fdocs.spring.io%2Fspring-framework%2Fdocs%2F5.1.6.RELEASE%2Fspring-framework-reference%2Fcore.html%23expressions-evaluation%60%0A%0A%23%23%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%0A%23%23%23%20%E5%AD%97%E9%9D%A2%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%60%60%60java%0A%2F**%0A%20*%20%E5%AD%97%E9%9D%A2%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9A%0A%20*%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E7%9A%84%E5%86%85%E5%AE%B9%E6%98%AF%E6%9C%80%E7%BB%88%E8%BD%AC%E6%8D%A2%E5%90%8E%E7%9A%84%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%AE%9A%E4%B9%89%E4%BA%86%E4%BB%80%E4%B9%88%EF%BC%8C%E6%9C%80%E7%BB%88%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%BE%97%E5%88%B0%E4%BB%80%E4%B9%88%E3%80%82%0A%20*%20%3Cp%3E%0A%20*%20%E7%A4%BA%E4%BE%8B%EF%BC%9A%E5%8A%A0%23%E6%97%B6SpEL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%89%8D%E5%8F%AF%E4%BB%A5%E8%A7%A3%E6%9E%90%EF%BC%8C%E4%B8%8D%E5%8A%A0%E6%97%B6%E6%98%AF%E8%A7%A3%E6%9E%90%E4%B8%8D%E4%BA%86%E7%9A%84%EF%BC%8CSpEL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%A3%E6%9E%90%E6%97%B6%E5%8D%95%E5%BC%95%E5%8F%B7%E5%92%8C%E5%8F%8C%E5%BC%95%E5%8F%B7%E5%9C%A8SpEL%E4%B8%AD%E7%9A%84%E6%95%88%E6%9E%9C%E6%98%AF%E4%B8%80%E6%A0%B7%E7%9A%84%0A%20*%20content%3A'hello'%2B%22%2C%20Chris%22%2C%20result%3A'hello'%2B%22%2C%20Chris%22%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%20content%3A%23%7B'hello'%2B%22%2C%20Chris%22%7D%2C%20result%3Ahello%2C%20Chris%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%20%3Cp%3E%0A%20*%20%E5%A6%82%E6%9E%9C%E4%BC%A0%E9%80%92%E7%9A%84%E6%98%AF%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E7%9A%84%E6%95%B0%E6%8D%AE%E5%86%85%E5%AE%B9%EF%BC%8C%E4%B9%9F%E4%BC%9A%E8%87%AA%E5%8A%A8%E7%9A%84%E8%BF%9B%E8%A1%8C%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%0A%20*%20content%3A%23%7B1%7D%2C%20result%3A1%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Integer%0A%20*%20content%3A%23%7B1.1%7D%2C%20result%3A1.1%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Double%0A%20*%20content%3A%23%7Btrue%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%2F%0A%40Test%0Apublic%20void%20test01()%20%7B%0A%20%20%20%20String%20str1%20%3D%20%22'hello'%2B%5C%22%2C%20Chris%5C%22%22%3B%0A%20%20%20%20String%20str2%20%3D%20%22%23%7B'hello'%2B%5C%22%2C%20Chris%5C%22%7D%22%3B%0A%20%20%20%20spel(str1)%3B%0A%20%20%20%20spel(str2)%3B%0A%0A%20%20%20%20String%20str3%20%3D%20%22%23%7B1%7D%22%3B%0A%20%20%20%20String%20str4%20%3D%20%22%23%7B1.1%7D%22%3B%0A%20%20%20%20String%20str5%20%3D%20%22%23%7Btrue%7D%22%3B%0A%20%20%20%20spel(str3)%3B%0A%20%20%20%20spel(str4)%3B%0A%20%20%20%20spel(str5)%3B%0A%0A%7D%0A%60%60%60%0A%23%23%23%20%E6%95%B0%E5%AD%A6%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E6%95%B0%E5%AD%A6%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%20*%20%E7%A4%BA%E4%BE%8B%EF%BC%9A%0A%20*%20content%3A%23%7B1%2B2-3*4%2F5%7D%2C%20result%3A1%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Integer%0A%20*%20content%3A%23%7B1%2B2-3*4%2F5.0%7D%2C%20result%3A0.6000000000000001%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Double%0A%20*%20content%3A%23%7B10%253%7D%2C%20result%3A1%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Integer%0A%20*%20content%3A%23%7B10%20mod%203%7D%2C%20result%3A1%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Integer%0A%20*%20content%3A%23%7B10%20div%203%7D%2C%20result%3A3%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Integer%0A%20*%20content%3A%23%7B10%20%5E%203%7D%2C%20result%3A1000%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Integer%0A%20*%2F%0A%40Test%0Apublic%20void%20test02()%20%7B%0A%20%20%20%20spel(%22%23%7B1%2B2-3*4%2F5%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B1%2B2-3*4%2F5.0%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B10%253%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B10%20mod%203%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B10%20div%203%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B10%20%5E%203%7D%22)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%E5%85%B3%E7%B3%BB%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%0A!%5B1b83801e4164f335e58cea3f9d886bd2.png%5D(en-resource%3A%2F%2Fdatabase%2F1514%3A1)%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E5%85%B3%E7%B3%BB%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%20*%20%E7%A4%BA%E4%BE%8B%EF%BC%9A%0A%20*%20content%3A%23%7B30!%3D20%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%20content%3A%23%7B30%20NE%2020%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%20content%3A%23%7B'chris'%20%3E%20'Chris'%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%20content%3A%23%7B10%2B20%20eq%2030%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%2F%0A%40Test%0Apublic%20void%20test03()%20%7B%0A%20%20%20%20spel(%22%23%7B30!%3D20%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B30%20NE%2020%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B'chris'%20%3E%20'Chris'%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B10%2B20%20eq%2030%7D%22)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%E9%80%BB%E8%BE%91%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%0A!%5B0bf92ffb411262e7502b45e877d3186b.png%5D(en-resource%3A%2F%2Fdatabase%2F1516%3A1)%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E9%80%BB%E8%BE%91%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A%20*%20%E7%A4%BA%E4%BE%8B%EF%BC%9A%0A%20*%20content%3A%23%7B30!%3D20%20%7C%7C%2010%3D%3D10%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%20content%3A%23%7B'chris'%20%3E%20'Chris'%20%26%26%20'Ethan'%20lt%20'ethan'%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%20content%3A%23%7B10%20between%20%7B1%2C100%7D%20%26%26%201%3D%3D1%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%20content%3A%23%7B'y'%20between%20%7B'a'%2C'c'%7D%20%7D%2C%20result%3Afalse%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%2F%0A%40Test%0Apublic%20void%20test04()%20%7B%0A%20%20%20%20spel(%22%23%7B30!%3D20%20%7C%7C%2010%3D%3D10%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B'chris'%20%3E%20'Chris'%20%26%26%20'Ethan'%20lt%20'ethan'%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B10%20between%20%7B1%2C100%7D%20%26%26%201%3D%3D1%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B'y'%20between%20%7B'a'%2C'c'%7D%20%7D%22)%3B%0A%7D%0A%60%60%60%0A%0A!%5Bf6e15cd98578ed9bd61615dbba0db5f7.png%5D(en-resource%3A%2F%2Fdatabase%2F1518%3A1)%0A%0A%23%23%23%20%E4%B8%89%E7%9B%AE%E8%BF%90%E7%AE%97%E7%AC%A6%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E4%B8%89%E7%9B%AE%E8%BF%90%E7%AE%97%E7%AC%A6%0A%20*%20SpEL%E4%B8%AD%E6%94%AF%E6%8C%81%E4%B8%89%E7%9B%AE%E8%BF%90%E7%AE%97%E7%AC%A6%0A%20*%20%E7%A4%BA%E4%BE%8B%EF%BC%9A%0A%20*%20content%3A%23%7B'chris'!%3Dnull%3F%20'hello%2Cchris'%3A'who%20are%20you%3F'%7D%2C%20result%3Ahello%2Cchris%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%20content%3A%23%7Bnull%3D%3Dnull%3F%20'hello%2Cchris'%3A'who%20are%20you%3F'%7D%2C%20result%3Ahello%2Cchris%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%20content%3A%23%7Bfalse%20%3F%20'hello%2Cchris'%3A'who%20are%20you%3F'%7D%2C%20result%3Awho%20are%20you%3F%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%20%3Cp%3E%0A%20*%20%E5%90%8C%E8%BF%9B%E4%B9%9F%E6%94%AF%E6%8C%81Groovy%E4%B8%AD%E6%89%A9%E5%B1%95%E7%9A%84%E4%B8%89%E7%9B%AE%E7%BB%93%E6%9E%84%2C%E5%A6%82%E6%9E%9C%E5%88%A4%E6%96%AD%E5%86%85%E5%AE%B9%E4%B8%BAnull%2C%E5%88%99%E8%BF%94%E5%9B%9Efase%E7%9A%84%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E4%B8%BAnull%2C%E5%88%99%E8%BF%94%E5%9B%9E%E5%88%A4%E6%96%AD%E5%86%85%E5%AE%B9%E6%9C%AC%E8%BA%AB%0A%20*%20%E7%A4%BA%E4%BE%8B%EF%BC%9A%0A%20*%20content%3A%23%7Bnull%20%3F%3A'it%20is%20null'%7D%2C%20result%3Ait%20is%20null%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%20content%3A%23%7B'chris'%20%3F%3A'it%20is%20null'%7D%2C%20result%3Achris%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%2F%0A%40Test%0Apublic%20void%20test05()%20%7B%0A%20%20%20%20spel(%22%23%7B'chris'!%3Dnull%3F%20'hello%2Cchris'%3A'who%20are%20you%3F'%7D%22)%3B%0A%20%20%20%20spel(%22%23%7Bnull%3D%3Dnull%3F%20'hello%2Cchris'%3A'who%20are%20you%3F'%7D%22)%3B%0A%20%20%20%20spel(%22%23%7Bfalse%20%3F%20'hello%2Cchris'%3A'who%20are%20you%3F'%7D%22)%3B%0A%0A%20%20%20%20spel(%22%23%7Bnull%20%3F%3A'it%20is%20null'%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B'chris'%20%3F%3A'it%20is%20null'%7D%22)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%A4%84%E7%90%86%0A%0A%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%A4%84%E7%90%86%0A%20*%20%E7%A4%BA%E4%BE%8B%EF%BC%9A%0A%20*%20content%3A%23%7B'spring%20express%20language'%5B4%5D%7D%2C%20result%3An%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%20content%3A%23%7B'spring%20express%20language'.substring(4%2C%20'spring%20express%20language'.length())%7D%2C%20result%3Ang%20express%20language%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.String%0A%20*%20content%3A%23%7B'www.bing.com'.matches('%5Cw%2B%5C.%5Cw%2B%5C.%5Cw%2B')%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%20content%3A%23%7B'www.bing.com'matches%20'%5Cw%2B%5C.%5Cw%2B%5C.%5Cw%2B'%7D%2C%20result%3Atrue%2C%20%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B%3Aclass%20java.lang.Boolean%0A%20*%2F%0A%40Test%0Apublic%20void%20test06()%20%7B%0A%20%20%20%20spel(%22%23%7B'spring%20express%20language'%5B4%5D%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B'spring%20express%20language'.substring(4%2C%20'spring%20express%20language'.length())%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B'www.bing.com'.matches('%5C%5Cw%2B%5C%5C.%5C%5Cw%2B%5C%5C.%5C%5Cw%2B')%7D%22)%3B%0A%20%20%20%20spel(%22%23%7B'www.bing.com'%20matches%20'%5C%5Cw%2B%5C%5C.%5C%5Cw%2B%5C%5C.%5C%5Cw%2B'%7D%22)%3B%0A%7D%0A%60%60%60%0A%0A%23%23%20StandardEvaluationContext%0A%0A%60%60%60java%0AExpressionParser%20parser%3B%0A%0A%40Before%0Apublic%20void%20init()%20%7B%0A%20%20%20%20%2F%2F%20%E5%AE%9A%E4%B9%89SpEL%E8%A7%A3%E6%9E%90%E5%99%A8%0A%20%20%20%20parser%20%3D%20new%20SpelExpressionParser()%3B%0A%7D%0A%0A%40Test%0Apublic%20void%20test01()%20%7B%0A%20%20%20%20String%20template%20%3D%20%22%23%7B%23varA%2B%23varB%7D%22%3B%0A%20%20%20%20Expression%20exp%20%3D%20parser.parseExpression(template%2C%20ParserContext.TEMPLATE_EXPRESSION)%3B%20%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%A3%E6%9E%90%0A%0A%20%20%20%20StandardEvaluationContext%20context%20%3D%20new%20StandardEvaluationContext()%3B%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%8A%E4%B8%8B%E6%96%87%E9%85%8D%E7%BD%AE%0A%0A%20%20%20%20%2F%2F%20%E5%AE%9A%E4%B9%89%E5%8F%98%E6%9B%B4%E5%86%85%E5%AE%B9%0A%20%20%20%20context.setVariable(%22varA%22%2C%20%22hello%22)%3B%0A%20%20%20%20context.setVariable(%22varB%22%2C%20%22%2C%20magic%20SpEL%22)%3B%0A%0A%20%20%20%20%2F%2F%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%B1%BB%E5%9E%8B%E7%9A%84%E8%AE%A1%E7%AE%97%E5%A4%84%E7%90%86%0A%20%20%20%20String%20value%20%3D%20exp.getValue(context%2C%20String.class)%3B%0A%20%20%20%20log.info(%22value%3A%7B%7D%22%2C%20value)%3B%0A%0A%20%20%20%20%2F%2F%20%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B%E7%9A%84%E8%AE%A1%E7%AE%97%E5%A4%84%E7%90%86%0A%20%20%20%20context.setVariable(%22varA%22%2C%201212)%3B%0A%20%20%20%20context.setVariable(%22varB%22%2C%203.33)%3B%0A%20%20%20%20Double%20result%20%3D%20exp.getValue(context%2C%20Double.class)%3B%0A%20%20%20%20log.info(%22result%3A%7B%7D%22%2C%20result)%3B%0A%7D%0A%0A%40Test%0Apublic%20void%20test02()%20%7B%0A%20%20%20%20%2F%2F%20%E6%A0%B9%E5%8F%98%E9%87%8F%E4%B8%8E%E6%99%AE%E9%80%9A%E5%8F%98%E9%87%8F%E7%9A%84%E5%8C%BA%E5%88%AB%E5%9C%A8%E4%BA%8E%E5%85%B6%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E5%9C%A8%E5%AE%9E%E4%BE%8B%E5%8C%96%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%A3%E6%9E%90%E4%B8%8A%E4%B8%8B%E6%96%87%E6%97%B6%E8%BF%9B%E8%A1%8C%E6%A0%B9%E5%8F%98%E9%87%8F%E7%9A%84%E9%85%8D%E7%BD%AE%EF%BC%88%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E4%B8%8A%E7%9A%84%E7%89%B9%E6%9D%83%E4%BD%BF%E7%94%A8%EF%BC%8C%E4%BB%85%E6%AD%A4%E8%80%8C%E5%B7%B2%EF%BC%89%0A%20%20%20%20String%20template%20%3D%20%22%23%7B%23root.contains('hello')%7D%22%3B%0A%0A%20%20%20%20Expression%20exp%20%3D%20parser.parseExpression(template%2C%20ParserContext.TEMPLATE_EXPRESSION)%3B%20%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%A3%E6%9E%90%0A%20%20%20%20StandardEvaluationContext%20context%20%3D%20new%20StandardEvaluationContext(%22hello%2C%20happy%20new%20year%22)%3B%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%8A%E4%B8%8B%E6%96%87%E9%85%8D%E7%BD%AE%0A%20%20%20%20Boolean%20result%20%3D%20exp.getValue(context%2C%20Boolean.class)%3B%0A%20%20%20%20log.info(%22result%3A%7B%7D%22%2C%20result)%3B%0A%7D%0A%0A%2F**%0A%20*%20%E5%AF%B9919%E8%BF%9B%E8%A1%8C%E8%BD%AC%E5%9E%8B%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%B0%86%E5%85%B6%E8%BD%AC%E6%8D%A2%E4%B8%BAInteger%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%AE%9E%E4%BE%8B%0A%20*%2F%0A%40Test%0Apublic%20void%20test03()%20throws%20NoSuchMethodException%20%7B%0A%20%20%20%20String%20template%20%3D%20%22%23%7B%23convert('919')%7D%22%3B%0A%20%20%20%20Expression%20exp%20%3D%20parser.parseExpression(template%2C%20ParserContext.TEMPLATE_EXPRESSION)%3B%20%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%A3%E6%9E%90%0A%0A%20%20%20%20Method%20method%20%3D%20Integer.clas%20s.getMethod(%22parseInt%22%2C%20String.class)%3B%0A%0A%20%20%20%20StandardEvaluationContext%20context%20%3D%20new%20StandardEvaluationContext()%3B%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%8A%E4%B8%8B%E6%96%87%E9%85%8D%E7%BD%AE%E6%A0%B9%E5%AF%B9%E8%B1%A1%0A%20%20%20%20context.setVariable(%22convert%22%2C%20method)%3B%20%2F%2F%20%E6%96%B9%E6%B3%95%E5%BC%95%E7%94%A8%E7%9A%84%E5%AE%9E%E7%8E%B0%0A%0A%20%20%20%20Integer%20result%20%3D%20exp.getValue(context%2C%20Integer.class)%3B%0A%20%20%20%20log.info(%22result%3A%7B%7D%22%2C%20result)%3B%0A%7D%0A%0A%40Test%0Apublic%20void%20test04()%20%7B%0A%20%20%20%20%2F%2F%20java.util.Date%E7%B1%BB%E4%B8%AD%E6%8F%90%E4%BE%9B%E6%9C%89getTime()%E6%96%B9%E6%B3%95%EF%BC%8C%E6%89%80%E4%BB%A5%E6%AD%A4%E5%A4%84%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E9%87%87%E7%94%A8time%E7%9A%84%E6%A0%87%E8%AE%B0%E8%BF%9B%E8%A1%8C%E5%B1%9E%E6%80%A7%E8%A1%A8%E7%A4%BA%0A%20%20%20%20String%20template%20%3D%20%22%23%7B%23var.time%7D%22%3B%0A%20%20%20%20Expression%20exp%20%3D%20parser.parseExpression(template%2C%20ParserContext.TEMPLATE_EXPRESSION)%3B%20%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%A3%E6%9E%90%0A%0A%20%20%20%20StandardEvaluationContext%20context%20%3D%20new%20StandardEvaluationContext()%3B%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%8A%E4%B8%8B%E6%96%87%E9%85%8D%E7%BD%AE%0A%20%20%20%20context.setVariable(%22var%22%2C%20new%20Date())%3B%0A%0A%20%20%20%20Long%20time%20%3D%20exp.getValue(context%2C%20Long.class)%3B%0A%20%20%20%20log.info(%22result%3A%7B%7D%22%2C%20time)%3B%0A%7D%0A%0A%0A%2F**%0A%20*%20%E5%AF%B9%E4%BA%8ESpEL%EF%BC%8C%E9%9C%80%E8%A6%81%E7%A1%AE%E4%BF%9D%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%AF%B9%E8%B1%A1%E4%B8%8D%E5%AD%98%E6%88%96%E4%B8%BAnull%E5%9C%A8%E5%88%99%E4%BC%9A%E5%87%BA%E4%B8%8B%E5%BC%82%E5%B8%B8%0A%20*%20org.springframework.expression.spel.SpelEvaluationException%3A%20EL1007E%3A%20Property%20or%20field%20'time'%20cannot%20be%20found%20on%20null%0A%20*%20%3Cp%3E%0A%20*%20%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%EF%BC%9A%E5%9C%A8SpEL%E4%B8%AD%E4%BD%BF%E7%94%A8Groovy%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%BF%9B%E8%A1%8C%E5%88%A4%E6%96%AD%E5%A4%84%E7%90%86%0A%20*%2F%0A%40Test%0Apublic%20void%20test05()%20%7B%0A%20%20%20%20%2F%2F%20%E9%A6%96%E5%85%88%E4%BC%9A%E5%88%A4%E6%96%ADvar%E5%AF%B9%E8%B1%A1%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%88%99%E7%9B%B4%E6%8E%A5%E8%BF%94%E5%9B%9Enull%2C%E5%A6%82%E6%9E%9C%E5%AD%98%E5%9C%A8%E5%88%99%E7%BB%A7%E7%BB%AD%E5%88%A4%E6%96%AD%E5%B1%9E%E6%80%A7%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%AD%98%E5%9C%A8%E5%88%99%E8%BF%94%E5%9B%9E%E5%B1%9E%E6%80%A7%E5%80%BC%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%88%99%E8%BF%94%E5%9B%9Enull%0A%20%20%20%20String%20template%20%3D%20%22%23%7B%23var%3F.time%7D%22%3B%0A%20%20%20%20Expression%20exp%20%3D%20parser.parseExpression(template%2C%20ParserContext.TEMPLATE_EXPRESSION)%3B%20%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%A3%E6%9E%90%0A%0A%20%20%20%20StandardEvaluationContext%20context%20%3D%20new%20StandardEvaluationContext()%3B%2F%2F%20%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%8A%E4%B8%8B%E6%96%87%E9%85%8D%E7%BD%AE%0A%20%20%20%20context.setVariable(%22var%22%2C%20null)%3B%0A%0A%20%20%20%20Long%20time%20%3D%20exp.getValue(context%2C%20Long.class)%3B%0A%20%20%20%20log.info(%22result%3A%7B%7D%22%2C%20time)%3B%0A%7D%0A%0A%60%60%60%0A%0A%0A%23%23%20SpEL%E5%8F%8D%E5%B0%84%E8%A1%A8%E8%BE%BE%E5%BC%8F%0A!%5B4ee5b39f1d3ec20a9c77f3a0b2b85b15.png%5D(en-resource%3A%2F%2Fdatabase%2F1512%3A1)%0A%0A%0A%60%60%60java%0A%2F**%0A%20*%20Java%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%E5%A4%84%E7%90%86%E6%9C%BA%E5%88%B6%E5%9C%A8%E4%BA%8E%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E5%8C%85%E6%8B%ACJDK%E4%B9%8B%E4%B8%AD%E7%9A%84%E5%86%85%E5%AD%98%E7%BB%93%E6%9E%84%E7%9A%84%E4%B8%8D%E6%96%AD%E4%BC%98%E5%8C%96%E5%AE%9E%E9%99%85%E4%B8%8A%E4%B9%9F%E6%98%AF%E4%B8%8E%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6%E6%9C%89%E7%9B%B4%E6%8E%A5%E7%9A%84%E5%85%B3%E8%81%94%EF%BC%8C%E6%AF%94%E5%A6%82%EF%BC%9A%E6%B0%B8%E4%B9%85%E4%BB%A3%E8%A2%AB%E6%9B%BF%E6%8D%A2%E4%B8%BA%E5%85%83%E7%A9%BA%E9%97%B4%0A%20*%20%3Cp%3E%0A%20*%20Spring%E4%B8%AD%E6%9C%80%E9%87%8D%E8%A6%81%E7%9A%84%E7%89%B9%E7%82%B9%E5%B0%B1%E6%98%AF%E9%80%9A%E8%BF%87%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8F%8F%E8%BF%B0%E5%87%BA%E6%9B%B4%E5%A4%9A%E7%9A%84%E5%86%85%E5%AE%B9%EF%BC%8C%E9%82%A3%E4%B9%88%E5%AF%B9%E4%BA%8E%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6%E4%B9%9F%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%BD%A2%E5%BC%8F%E8%BF%9B%E8%A1%8C%E6%8F%8F%E8%BF%B0%0A%20*%20%3Cp%3E%0A%20*%20%E8%BF%99%E7%A7%8D%E4%BB%A3%E7%A0%81%E6%93%8D%E4%BD%9C%E7%9A%84%E6%A0%B8%E5%BF%83%E6%84%8F%E4%B9%89%E5%9C%A8%E4%BA%8E%EF%BC%9A%E7%9B%B4%E6%8E%A5%E5%9C%A8%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E9%87%8C%E9%9D%A2%E7%BC%96%E5%86%99%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%AF%E4%BB%A5%E5%AE%9A%E4%B9%89%E4%BB%BB%E6%84%8F%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%0A%20*%20%3Cp%3E%0A%20*%20%23%7BT(java.lang.String)%7D%20class%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9Aclass%20java.lang.String%0A%20*%20%23%7BT(java.util.Date)%7D%20class%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9Aclass%20java.util.Date%0A%20*%20%23%7BT(java.lang.Integer).MAX_VALUE%7D%20class%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9A2147483647%0A%20*%20%23%7BT(java.lang.Integer).parseInt('123')%7D%20class%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9A123%0A%20*%2F%0A%40Test%0Apublic%20void%20test06()%20%7B%0A%20%20%20%20log.info(%22%23%7BT(java.lang.String)%7D%20class%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9A%7B%7D%22%2C%20spel(%22%23%7BT(java.lang.String)%7D%22))%3B%0A%20%20%20%20log.info(%22%23%7BT(java.util.Date)%7D%20class%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9A%7B%7D%22%2C%20spel(%22%23%7BT(java.util.Date)%7D%22))%3B%0A%0A%20%20%20%20%2F%2F%20%E9%80%9A%E8%BF%87%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%8D%E5%B0%84%E5%AE%9A%E4%B9%89%E7%9A%84%E9%9D%99%E6%80%81%E5%B8%B8%E9%87%8F%E5%92%8C%E6%96%B9%E6%B3%95%0A%20%20%20%20log.info(%22%23%7BT(java.lang.Integer).MAX_VALUE%7D%20class%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9A%7B%7D%22%2C%20spel(%22%23%7BT(java.lang.Integer).MAX_VALUE%7D%22))%3B%0A%20%20%20%20log.info(%22%23%7BT(java.lang.Integer).parseInt('123')%7D%20class%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9A%7B%7D%22%2C%20spel(%22%23%7BT(java.lang.Integer).parseInt('123')%7D%22))%3B%0A%7D%0A%0A%2F**%0A%20*%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%BF%98%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%EF%BC%8C%E6%AF%94%E5%A6%82%EF%BC%9A%23%7Bnew%20com.chris.cloud.spel.Book('Spring%E5%BC%80%E5%8F%91%E5%AE%9E%E6%88%985'%2C64.5)%7D%0A%20*%20%3Cp%3E%0A%20*%20%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84'new'%EF%BC%8C%E6%A0%B9%E6%8D%AE%E7%B1%BB%E4%B8%AD%E6%8F%90%E4%BE%9B%E7%9A%84%E5%8F%8C%E5%8F%82%E6%9E%84%E9%80%A0%E5%99%A8%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AE%9E%E4%BE%8B%E5%8C%96%EF%BC%8C%E4%BD%86%E8%BF%99%E9%87%8C%E6%9C%AC%E8%B4%A8%E4%B8%8A%E6%98%AF%E9%80%9A%E8%BF%87SpEL%E8%A7%A3%E6%9E%90%E5%BE%97%E6%9D%A5%E7%9A%84%0A%20*%2F%0A%40Test%0Apublic%20void%20test07()%20%7B%0A%20%20%20%20Object%20book%20%3D%20spel(%22%23%7Bnew%20com.chris.cloud.spel.Book('Spring%E5%BC%80%E5%8F%91%E5%AE%9E%E6%88%985'%2C64.5)%7D%22)%3B%0A%20%20%20%20log.info(%22book%3A%7B%7D%22%2C%20book)%3B%0A%7D%0A%0Aprivate%20Object%20spel(String%20content)%20%7B%0AExpression%20exp%20%3D%20parser.parseExpression(content%2C%20ParserContext.TEMPLATE_EXPRESSION)%3B%0AStandardEvaluationContext%20context%20%3D%20new%20StandardEvaluationContext()%3B%0Areturn%20exp.getValue(context)%3B%0A%7D%0A%0A%60%60%60

别离

创建时间:2024/3/1 17:46

小学一走就是半天,
初中一走就是一周,
高中一走就是半月,
大学一走就是半年,
工作一走就是一年,
人生一走就是一辈子,年少时春风得意马蹄疾,不信人间有别离,小时候不理解老人为什么总是在门口静静的坐着,一坐就是半天,只有长大后才明白,目之所及,皆是回忆,心之所想,皆是过往,眼只所看,皆是遗憾,小时候大家都穷,没有别的烦恼。而现在,除了穷,各有各的烦恼。小时候可以无忧无虑的疯,因为小时候的天,都是父母撑起来的,而今没日没夜的忙,因为现在的天要靠自己拼命撑起来,一不注意就要塌了,所以你说呢,到底什么样的终点,才配得上这一路上的颠沛流离,你总是要回家的啊,回家前的喜悦,回家时的无聊,离家时的不舍,离家后的想念,故乡承载不了肉体,远方承载不了灵魂,终是故乡的阑珊灯火,映不出远方的星辰闪烁。有一些人,时不时的总想回一趟老家,老家到底有什么值得留恋的呢?或许只是想看一看过去的自己吧……

mysql 锁

创建时间:2024/3/24 20:07
更新时间:2024/4/5 12:33
作者:Chris

mysql锁

按粒度分类

mysql的锁分为: 全局锁,表锁和行锁。

全局锁

mysql的全局锁是针对整个数据库,最常用的全局锁是读锁和写锁.

读锁(共享锁):阻止其它用户更新数据但允许读取数据。这在你需要在一段时间内保持数据一致性时很有用。

写锁(排它锁):阻止其实用户读取和更新旧的数据。这在你需要批量修改数据并且不希望其它用户在这段时间内干扰你时很有用。

一般情况下是不需要开启全局锁的,只有在全库备份,全库导出时需要开启全局锁

mysql> flush tables with read lock; -- 开启开局锁
mysql> mysqldump -uroot -p dbname tablename > bak.sql -- 将指定数据库的指定表导出到bak.sql, 没有tablename时会导出整个数据库
mssql> unlock tables; -- 释放全局锁

在InnoDB引擎中,因为有mvcc【多版本并发控制】可以在不开启全局锁的情况下保证导出数据的一致性

mysql> mysqldump --single-transaction -uroot -p dbname tablename > bak.sql -- 将指定数据库的指定表导出到bak.sql, 没有tablename时会导出整个数据库

表锁

表锁是mysql最基本的策略,特点是:相对于全局锁,表锁开销少,加锁快,不会出现死锁;锁定粒度大,发生锁冲突的概率高,并发度最低。

表共享读锁(Table Read Lock):又称为表读锁,允许一个事务锁定的表进行读取操作,不允许其它事务进行写操作,但是可以进行读操作。多个读锁之间是不会相互阻塞的。

表独占写锁(Table Write Lock):又称为表写锁,允许一个事务锁定的表进行表读取和表更新操作,不允许其它事务再对该表进行操作,必须等待表写锁结束,写锁会阻塞其他所有锁,包括读锁和写锁。

在mysql中对MyISAM表的读操作会自动加上读锁,对MyISAM的写操作会自动加下写锁。因为是没有事务控制的,在高并发情况下为了保持数据的一致性只能通过对整个表加锁。

InnoDB中在必要的情况会使用表锁,更多是使用行锁来实现MVCC。它能提供更好的并发性和更少的锁冲突。

注意

  1. InnoDB主要使用行级锁,并在一些情况下使用表级锁,比如在执行某些命令时比如alter table时。

  2. MyISAM只支持表级锁

  1. 读密集型应用, 如果你的应用主要是进行读取操作,很少进行写操作,这时加表锁会是一个发的选择, 因为表读锁不为阻塞其它的读锁,所在在这种场景下能提供更高的性能。
  2. 写操作不频繁的场景: 表级锁对写操作的处理并不高效,因为一个写锁会阻塞所有的其它操作,无论它们是读锁还是写锁,但是如果你的应用不需要频繁的写操作,或者可以容忍写操作的延时,那么使用表锁还是可以的。
  3. 数据量不大的简单使用:如查数据库的数据量不是很大,那么即使在写操作中,由于锁定整张表对性能的影响也不大。
  4. 全表更新或删除:在某些情况下可能需要对一张表进行全表更新或者删除操作,比如删除表中的所有记录,或者更新所有记录中其一个字段,这种情况下使用表级锁是合适的。
  1. alter table:更改表结构时mysql会锁定整个表以防止在更改过程中有新的数据写入。

  2. drop table | truncate table:更改表结构时mysql会锁定整个表以防止在删除表,或者删除表中所有数据的过程中有新的数据写入。

  3. lock tables:显式的为一个或者多个表加锁,后面可以跟一个表或者多个表的名称和锁模式,用来指定需要锁定哪些表,以及使用什么样的表模式,如:lock tables t1 write,t2 read; 为t1加表写锁为t2加表读锁

  4. 开启全局锁时会自动对所有表加锁

lock tables employee read; -- 开启表读锁
show open tables where In_use > 0; -- 查询加表锁的表
update employee set name='张三' where id=1; -- Table 'employee' was locked with a READ lock and can't be updated
unlock tables; -- 释放锁

行锁

行锁是mysql粒度最小的锁机制,它可以对某一行数据进行锁定。因此在高并发事务中可以提供更好的并发性和更少的锁冲突。

在mysql中,行级锁主要由InnoDB引擎提供,InnoDB支持两种类型的行级锁:共享锁(S锁)和排他锁(X锁)

共享锁(S锁): 也称为读锁,它允许一个事务读取一行数据,当一行数据被共享锁锁定时,其他事务可以读取这行数据,但不能对其进行修改。

排他锁(X锁): 也称为写锁,它允许一个事务读取和修改一行数据,当一行数据被排他锁锁定时,其他事务不能读取也不能修改这行数据。

在实际的使用过程中InnoDB还提供了一种名称Gap Lock【间隙锁】的特性,不仅可以锁定其一行数据,还可以锁定这行数据前后的'间隙',即这一行之前和之后的一些行数据。间隙锁可以防止其它事务插入新的行到已锁定行的前后,从而可以解决一些并发问题

注意:

  • 行锁只在事务中有效,也就是说,只有在一个事务开始到这个事务提交或者回滚之前,才能对数据进行锁定。

  • 如果是在非事务环境中执行sql,那么InnoDB会在sql语句执行结束后立即释放所有的锁。

  1. 高并发读写操作:在需要高并发的读写操作中,行锁可以提高性能和并发性,因为它允许多个事务并发操作不同的行。
  2. 单行操作:对于需要操作单行数据的sql语句,例如基于主键或唯一索引的 update,delete,insert语句,行级锁可以提供更好的并发性和性能
  3. 短期锁:在需要对数据进行短时间锁定的情况下,行级锁可以防止长时间阻塞其它事务。
  4. 实现并发控制:在需要确保数据一致性和隔离性的事务中,行级锁是实现并发控制的重要机制。
  5. 复杂的事务处理:在需要对多行数据进行复杂的事务处理中,可以使用行锁来锁定这行些,防止在事务处理过程中数据被其它事务修改。
  1. select...for update: 这种查询为会选定的数据添加一个排它锁,这意味着其他事务不能修改这些行,也不对这些行添加共享锁。
  2. select...lock in share mode: 这种查询为会选定的数据添加一个共享锁,这意味着其他事务不能修改这些行,但可以对这些行数据添加共享锁。
  3. insert: 插入操作会对新添加的行添加一个排他锁
  4. update:更新操作会对被更新的行添加一个排他锁
  5. delete:删除操作会对被删除的行数据添加一个排他锁
-- 查询语句结束时后立即释了排他锁,所以第二行语句查询不到行锁
select * from employee where id=1 for update; 
select * from performance_schema.data_locks; -- 查询行锁的命令
start transaction;
select * from employee where id=1 for update; -- 在手动执行完这条sql语句后再去执行查询行锁的命令,可以看到当前行被加了排他锁
update employee set name='chris' where id=1; -- 因为是在同一个事务中,所以是可以读也可以写的,如果在不同的事务中【重新打开一个新的命令窗口】更新是不能成功执行的
commit;

select * from performance_schema.data_locks; -- 查询行锁的命令
  1. 死锁:当两个或者更多的事务在相互等待对方释放资源时就会出现死锁,例如:事务1锁定的行A并试图锁定行B,事务2锁定了行B并试图锁定行A,这就形成了死锁。mysql会检测到死锁并终止其中一个事务,但这仍可能导致性能问题和事务失败。
  2. 锁升级:如果一个事务试图锁定的行过多,InnoDB可能会将锁定从行级升级为表级,这可能更导致更多的锁冲突。
  3. 锁等待:一个事务已经锁定了其行,其它事务就必须等待,会导致性能下降,如果大量的事务在等待就可能导致系统出现性能瓶颈。
  4. 难以调试和排查:由于行锁粒度较小,如果出现性能问题或者锁冲突,就需要复杂的调试和排查工作来找出问题的原因。
  5. 事务隔离级别:不同的事务隔离级别会影响锁的行为和性能,可能需要根据具体的应用场景来调整事务隔离级别。

按模式分类

mysql的锁分为,外观锁和悲观锁

乐观锁

乐观锁【Optimistic Locking】,是一种在数据库操作过程中处理并发问题的的一种技术,它的基本思想是假设在多个事务访问一条数据时,冲突发生的概率低,因此在操作数据时不会立即进行锁定,而是在提交数据更改时检查是否有其它事务修改了这条数据,如果没有则提交,否则回滚事务。

mysql中并没有乐观锁的内置实现,但可以通过一些编程技艺来实现,一种常见的实现是使用版本号或时间戳字段。每当一条记录被修改时,就增加版本号或更新时间戳。在更新记录时先检查版本号或时间戳是否和读取记录时的版本号或时间戳一致,如果一致则执行更新并增加版本或更新时间戳,否则就拒绝更新,这样就保证了只有在当前数据没有被其它其它事务修改时,当前事务的修改才会被提交。

  1. 低冲突环境:在多数据情况下,数据并发修改的冲突较低,即同一时间内,同一条数据不会被多个事务同时修改。

  2. 读多写少的情况:在读操作远多于写操作的情况下,乐观锁可以避免由于频繁的读操作导致的不必要的锁定开销,写少就意味着低冲突,读并不会破坏数据的一致性,所以这种场景也是低冲突场景一种衍生。

  3. 短事务操作:如果数据库事务都是简短并快速完成的,那么使用乐观锁可以减少因为等待锁而导致的时间消耗。例如时隔一秒一个请求的低并发,但处理事务需要一分钟,这种情况下一分钟会积攒60个请求,在乐观锁的情况下这60个请求都会尝试修改并最终都会失败,这样冲突就会变多,所以不仅要事务简短而且最是要快速完成。

create table ipd_spec_core.employee
(
    id              bigint            not null comment '员工ID',
    name            varchar(50)       not null comment '员工名称',
    address         varchar(100)      null comment '员工地址',
    payment_type    tinyint           null comment '支付方式【1:支票邮寄,2:支票暂存出纳处,3:银行账户存入】',
    salary_type     int               null comment '薪水类型【1:钟点工,2:固定工资,3:销售佣金】',
    hourly_rate     decimal(10, 2)    null comment '时薪',
    commission_rate decimal(5, 2)     null comment '佣金率',
    union_member    tinyint           null comment '是否工会成员',
    weekly_dues     decimal(10, 2)    null comment '每周会费',
    create_time     datetime          not null comment '创建时间',
    update_time     datetime          null comment '更新时间',
    del_flag        int               null comment '是否删除【0:未删除,1:删除】',
    version         tinyint default 0 null comment '版本标识',
    primary key ('id')
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '员工表';
select * from employee where id=1;
update employee set name='John',version=version+1 where id=1 and version=0 -- 首先确保修改的记录是读取的版本,然后把版本号加1说明这条记录已经被修改了
update employee set name='Nash',version=version+1 where id=1 and version=0 -- 此时这条sql语句修改时就修改不到数据了

乐观锁的缺点

  1. 冲突检测:在高并发环境下,乐观锁可能会导致大量的冲突。因为乐观锁只有在提交事务时才检查是否有冲突,如果多个事务在同一时间操作同一行数据,那么只有一个事务能提交成功,其它事务都需要回滚并重新尝试。

  2. 处理开销:在冲突发生时,需要进行回滚和重试,这会增加系统开销。

  3. 版本管理:乐观锁通常通过版本或时间戳来检测冲突,这就要求系统能够准确的管理版本,否则会导致错误的冲突检测。

  4. 编程复杂性:使用乐观锁需要更复杂的编程,因为程序需要处理要能发生的冲突和重试。

悲观锁

悲观锁是一种并发控制方法,基于一个假设:认为数据在并发处理过程很可能发生冲突,因此为了保证数据一完整性和一致性,每次读写数据时先加锁,这样可以避免其它事务进行并发的读写操作。

  1. 写操作比较多的场景:如果写的操作比较多,就意味着数据冲突相对较高,预先加锁可以确保数据的完整性和一致性将会是一种好的选择,如果使用乐观锁,将面临非常多的数据竞争问题,竞争失败时会回滚或重试,比较费时。
  2. 并发冲突高的场景:并发冲突高的场景使用悲观锁可以避免回滚和重试,提交系统的整体效率。
  3. 业务需要强一致性的场景:在一些需要保证数据旨一致性的业务场景下,例如银行转帐等金融业务,通常会选择使用悲观锁,以确保在任务情况下数据的一致性和准确性。
  1. select... for update: 这个语句会在所选择的行上设置排他锁(Exclusive Lock), 在锁定期间,其他事务无法修改这些行,也无法在这些行上设置新的排他锁或共享锁。
  2. select... lock in share mode: 这个语句会在所选择的行上设置共享锁(Shared Lock),在锁定期间,其他事务可以读取这些行,但不能修改这些行,也不能设置其它排他锁。
start transaction; -- 开启事务
select * from employee where id=1 for update; -- 给这条数据加悲观锁
update employee set name='Rebecca' where id=1; -- 在其它事务中执行这条语句会阻塞,在本事务中不会阻塞。
commit;
start transaction; -- 开启事务
select * from employee where id=1 lock in share mode; -- 给这条数据加共享锁
update employee set name='Josh' where id=1; -- 在其它事务中执行这条语句会阻塞,在本事务中不会阻塞。
commit;

悲观锁的缺点

  1. 性能开销:悲观锁机制下,锁定资源的操作会影响到系统的性能,因为每次对数据的读写操作都需要进行加锁和解锁的操作,这会增加系统的开销,特别是在高并发的环境下,锁的竞争会严重影响系统的性能。

  2. 并发度降低:由于悲观锁操作数据前就会加锁,这就导致在同一时间,只有一个事务能操作数据其它事务只能等待,大大降低了系统的并发度。

  3. 死锁:悲观锁在并发事务中可能导致死锁的情况发生。当两个或者更多的事务互相等待对方释放锁时,就可能发生死锁。虽然数据库系统通常能够检测并解决死锁,但这会导致事务回滚增加系统的开销。

  4. 锁超时:如果一个事务长时间持有锁而不释放,可能导致其他等待锁的事务超时,这不仅可能导致等待的事务失败,还可能影响整个系统的稳定性。

因此,虽然悲观锁能有效的防止数据冲突,但由于其在并发环境中的限制,以及可能引发的问题,如死锁,锁竞争和锁超时,我们需要根据具体的应用场景和需需求来权衡是否需要使用悲观锁。

意向锁

意向锁分为:意向共享锁和意向排它锁

意向锁是表锁,为了协调行锁和表锁的关系,支持多粒度(表锁与行锁)的锁并存。

当事务A有行锁时,Mysql会自动为整个表添加意向锁,事务B如果想申请整个表的写锁,不需要遍历每一行数据判断是否存在行锁,而直接判断是否存在意向锁。

当我们需要加一个排他锁时,需要根据意向锁去判断表中有没有数据行被锁定(行锁)

  1. 如果意向锁为行锁,则需要遍历每一行数据去确认。
  2. 如果意向锁为表锁,则需要判断一次即可知道表中有没有数据被锁定,提升判断效率和系统性能。
  1. 首先数据库是可以同时支持表锁和行锁并存的,但并不是任何情况下都支持一个表中同时有一个事务A持有行锁,又有一个事务B持有表锁,因为一旦被上了一个表级写锁,肯定不能再上一个行级的锁。
  2. 如果事务A对某一行上锁,其它事务就不可能修改这一行,事务B添加表锁就会冲突。所以没有意向锁时,让行锁和表锁并存就会带来很多多问题,于是就有了意向锁,数据库不需要遍历每一行数据是否有锁,直接判断一次意向锁是否存在即可。
意向共享锁(IS)意向排他锁(IX)
共享锁(S)兼容互斥
排他锁(X)互斥互斥
start transaction;
select * from employee where id=1 for update; -- 开启一个行级的排他锁

select * from performance_schema.data_locks; -- 查询锁
LOCK_TYPE:
	TABLE[表锁],RECORD[行锁]
LOCK_MODE:
	X[排他锁],IX[意向排他锁]
LOCK_DATA: 锁的行数

lock table employee write; -- 此时在其它事务中对于加表写锁时阻塞,加不了表写锁。
start transaction;
select * from employee where id=1 lock in share mode; -- 开启一个行级的排他锁

select * from performance_schema.data_locks; -- 查询锁
LOCK_TYPE:
	TABLE[表锁],RECORD[行锁]
LOCK_MODE:
	S[共享锁],IS[意向共享锁]
LOCK_DATA: 锁的行数

lock table employee read; -- 此时在其它事务中对于加表读锁时可以成功并不会阻塞。

临键锁

临键锁:next-key可以理解为一种特殊的间隙锁,也可以理解为一种特殊的算法。通临键锁可以解决幻读的问题。每个数据行上的非唯一索引列上都会存在一把临键锁,当菶事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据。

需要注意的是,InnoDB中行级锁是基于索引实现的,临键锁只与唯一非索引列有关,在唯一索引列(包括主键列)上不存在临键锁。

idagename
110张三
324李四
532王五
745赵六

该表中age列潜在的临键锁有:

(-∞, 10]
(10,24]
(24,32]
(32,45]
(45,+∞]
start transaction;
select * from user where age=24 for update; -- 把age=24的数据加排他锁,此时在另一个窗口中执行下面的insert请问
commit; -- 只有当这个事务结束后才会释放(24,32]临键锁
insert into user values(100, 26, 'Chris'); -- 此时执行这个insert语句时会被阻塞。

为什么在age=24上加锁会把age=26的数据也锁住,因为在(24,32]之间就存在一把临键锁,所以在写入age=26时会被阻塞,

事务ACID特性

原子性【Atomicity】

当前事务中的操作要么同时成功,要么同时失败。原子性由undo log日志来保证。

一致性【Consistency】

使用事务的最终目的就是为了保证数据的一致性,一致性依赖原子性,隔离性,持久性及业务代码的准确性。

隔离性【Isolation】

当多事务并发执行操作相同数据时,他们内部的操作不能相互干扰。

InnoDB中定义了四种隔离级别,级别越高隔离性越好,但性能越低。而隔离性是由Mysql中的各种锁及MVCC机制来实现的

  1. read-uncommitted【读未提交】: 当前事务读取到其它事务尚未提交的数据, 即会出现【脏读】
  2. read-committed【读已提交】: 当前事务多次查询同一条数据时会出现不同的结果,原因是这种数据在被其它事务不停修改提交,即对当前事务而言会出现【不可重复读】
  3. repeatable-read【可重复读】: 当前事务始终读取第一次查询时数据表里面的值,不受其它事务操作的影响,但如果当前事务中有更新操作则会把其它事务更新的值覆盖掉,即会出现【脏写】
  4. serializable 【串行】: 在不同事务中对同一份数据读写【无论是先写后读,还是先读后写】不允许并行执行,即读取这份数据事务未提交时不允许对这份数据进行更新,反之亦然。

注意:

默认查询操作是不加锁的,但是在【串行】这种事务隔离级别中默认会为查询操作添加一把读锁,这样在多个事务间只能读取这份数据,不能更新这份数据。

持久性【Durability】

RR隔离级别的实现原理

MVCC:多版本并发控制,可以做到读写不阻塞且避免脏读的问题。

read committed 语句级快照

repeatable read 事务级快照

设置事务

SET [GLOBAL | SESSION] TRANSACTION
    transaction_characteristic [, transaction_characteristic] ...
    
transaction_characteristic: {
    ISOLATION LEVEL level | access_mode
}    

level: {
     REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED | SERIALIZABLE
}

access_mode: {
     READ WRITE | READ ONLY
}

transaction_characteristic指定了事务的相关特性,多个transaction_characteristic用逗号隔开。

transaction_characteristic设置了事务的隔离级别和访问方式

Transaction Isolation Levels

使用ISOLATION LEVEL level语句设置事务隔离级别。在SET TRANSACTION中不允许指定多个ISOLATION LEVEL

默认的隔离级别是REPEATABLE READ。一共有四种隔离级别,还包括READ COMMITTED, READ UNCOMMITTED, 和SERIALIZABLE

Transaction Access Mode

使用READ WRITEREAD ONLY设置事务访问模式,在SET TRANSACTION中不允许指定多个访问模式。

默认情况下,事务时READ WRITE模式,在事务中允许对数据库中的表进行读/写操作。

如果事务访问模式被设置为READ ONLY,禁止对数据库中的表进行修改。在这种模式下存储引擎性能有相应提高。

"访问模式"也可以在开启事务(start transaction)的时候指定。

Transaction Characteristic Scope

你可以在当前会话,设置事务的全局属性,也可以只针对当前会话。

  1. GLOBAL关键字
  • 作用全局,后面的所有会话都会受到影响。
  • 当前会话退出,修改仍然生效
  1. SESSION 关键字
  • 作用于当前会话,接下来的所有事务。
  • 事务中允许使用该语句,但不影响当前正在进行的事务。
  • 如果在事务之间执行该语句,将会覆盖之前的事务设置。
  1. 既没有 SESSION关键字也没有 GLOBAL关键字
  • 当前语句只作用于当前会话的下一个事务。
  • 后面的会话(第二个会话开始)将会使用执行语句之前的配置。
  • 事务中不能执行该语句

Sping对事务的支持

prepareTransactinConnection

SET TRANSACTION READ ONLY -- 设置当前事务为只读事务,执行增删改为报错 1920-Cannot execute statement in a READ ONLY transaction

只读事务是由数据库层面支持的,spring没有参与做什么

如果当前事务为只读事务,数据库就可以不需要为写操作消耗性能,比如undo log, 写操作时加的写锁

%5Btoc%5D%0A%23%23%20mysql%E9%94%81%0A%0A%23%23%23%20%E6%8C%89%E7%B2%92%E5%BA%A6%E5%88%86%E7%B1%BB%0A%0A%3E%20mysql%E7%9A%84%E9%94%81%E5%88%86%E4%B8%BA%3A%20%E5%85%A8%E5%B1%80%E9%94%81%EF%BC%8C%E8%A1%A8%E9%94%81%E5%92%8C%E8%A1%8C%E9%94%81%E3%80%82%0A%0A%0A%0A%23%23%23%23%20%E5%85%A8%E5%B1%80%E9%94%81%0A%0A%3E%20mysql%E7%9A%84%E5%85%A8%E5%B1%80%E9%94%81%E6%98%AF%E9%92%88%E5%AF%B9%E6%95%B4%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%8C%E6%9C%80%E5%B8%B8%E7%94%A8%E7%9A%84%E5%85%A8%E5%B1%80%E9%94%81%E6%98%AF%E8%AF%BB%E9%94%81%E5%92%8C%E5%86%99%E9%94%81.%0A%3E%0A%3E%20%E8%AF%BB%E9%94%81(%E5%85%B1%E4%BA%AB%E9%94%81)%EF%BC%9A%E9%98%BB%E6%AD%A2%E5%85%B6%E5%AE%83%E7%94%A8%E6%88%B7%E6%9B%B4%E6%96%B0%E6%95%B0%E6%8D%AE%E4%BD%86%E5%85%81%E8%AE%B8%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE%E3%80%82%E8%BF%99%E5%9C%A8%E4%BD%A0%E9%9C%80%E8%A6%81%E5%9C%A8%E4%B8%80%E6%AE%B5%E6%97%B6%E9%97%B4%E5%86%85%E4%BF%9D%E6%8C%81%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7%E6%97%B6%E5%BE%88%E6%9C%89%E7%94%A8%E3%80%82%0A%3E%0A%3E%20%E5%86%99%E9%94%81(%E6%8E%92%E5%AE%83%E9%94%81)%EF%BC%9A%E9%98%BB%E6%AD%A2%E5%85%B6%E5%AE%9E%E7%94%A8%E6%88%B7%E8%AF%BB%E5%8F%96%E5%92%8C%E6%9B%B4%E6%96%B0%E6%97%A7%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%E8%BF%99%E5%9C%A8%E4%BD%A0%E9%9C%80%E8%A6%81%E6%89%B9%E9%87%8F%E4%BF%AE%E6%94%B9%E6%95%B0%E6%8D%AE%E5%B9%B6%E4%B8%94%E4%B8%8D%E5%B8%8C%E6%9C%9B%E5%85%B6%E5%AE%83%E7%94%A8%E6%88%B7%E5%9C%A8%E8%BF%99%E6%AE%B5%E6%97%B6%E9%97%B4%E5%86%85%E5%B9%B2%E6%89%B0%E4%BD%A0%E6%97%B6%E5%BE%88%E6%9C%89%E7%94%A8%E3%80%82%0A%0A%0A%0A%3E%20%E4%B8%80%E8%88%AC%E6%83%85%E5%86%B5%E4%B8%8B%E6%98%AF%E4%B8%8D%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AF%E5%85%A8%E5%B1%80%E9%94%81%E7%9A%84%EF%BC%8C%E5%8F%AA%E6%9C%89%E5%9C%A8%E5%85%A8%E5%BA%93%E5%A4%87%E4%BB%BD%EF%BC%8C%E5%85%A8%E5%BA%93%E5%AF%BC%E5%87%BA%E6%97%B6%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AF%E5%85%A8%E5%B1%80%E9%94%81%0A%0A%60%60%60mysql%0Amysql%3E%20flush%20tables%20with%20read%20lock%3B%20--%20%E5%BC%80%E5%90%AF%E5%BC%80%E5%B1%80%E9%94%81%0Amysql%3E%20mysqldump%20-uroot%20-p%20dbname%20tablename%20%3E%20bak.sql%20--%20%E5%B0%86%E6%8C%87%E5%AE%9A%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E6%8C%87%E5%AE%9A%E8%A1%A8%E5%AF%BC%E5%87%BA%E5%88%B0bak.sql%EF%BC%8C%20%E6%B2%A1%E6%9C%89tablename%E6%97%B6%E4%BC%9A%E5%AF%BC%E5%87%BA%E6%95%B4%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%BA%93%0Amssql%3E%20unlock%20tables%3B%20--%20%E9%87%8A%E6%94%BE%E5%85%A8%E5%B1%80%E9%94%81%0A%60%60%60%0A%0A%0A%0A%0A%0A%3E%20%E5%9C%A8InnoDB%E5%BC%95%E6%93%8E%E4%B8%AD%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%9C%89mvcc%E3%80%90%E5%A4%9A%E7%89%88%E6%9C%AC%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6%E3%80%91%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%B8%8D%E5%BC%80%E5%90%AF%E5%85%A8%E5%B1%80%E9%94%81%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E4%BF%9D%E8%AF%81%E5%AF%BC%E5%87%BA%E6%95%B0%E6%8D%AE%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%0A%0A%60%60%60mysql%0Amysql%3E%20mysqldump%20--single-transaction%20-uroot%20-p%20dbname%20tablename%20%3E%20bak.sql%20--%20%E5%B0%86%E6%8C%87%E5%AE%9A%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E6%8C%87%E5%AE%9A%E8%A1%A8%E5%AF%BC%E5%87%BA%E5%88%B0bak.sql%EF%BC%8C%20%E6%B2%A1%E6%9C%89tablename%E6%97%B6%E4%BC%9A%E5%AF%BC%E5%87%BA%E6%95%B4%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%BA%93%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E8%A1%A8%E9%94%81%0A%0A%3E%20%E8%A1%A8%E9%94%81%E6%98%AFmysql%E6%9C%80%E5%9F%BA%E6%9C%AC%E7%9A%84%E7%AD%96%E7%95%A5%EF%BC%8C%E7%89%B9%E7%82%B9%E6%98%AF%EF%BC%9A%E7%9B%B8%E5%AF%B9%E4%BA%8E%E5%85%A8%E5%B1%80%E9%94%81%EF%BC%8C%E8%A1%A8%E9%94%81%E5%BC%80%E9%94%80%E5%B0%91%EF%BC%8C%E5%8A%A0%E9%94%81%E5%BF%AB%EF%BC%8C%E4%B8%8D%E4%BC%9A%E5%87%BA%E7%8E%B0%E6%AD%BB%E9%94%81%EF%BC%9B%E9%94%81%E5%AE%9A%E7%B2%92%E5%BA%A6%E5%A4%A7%EF%BC%8C%E5%8F%91%E7%94%9F%E9%94%81%E5%86%B2%E7%AA%81%E7%9A%84%E6%A6%82%E7%8E%87%E9%AB%98%EF%BC%8C%E5%B9%B6%E5%8F%91%E5%BA%A6%E6%9C%80%E4%BD%8E%E3%80%82%0A%0A%3E%20%E8%A1%A8%E5%85%B1%E4%BA%AB%E8%AF%BB%E9%94%81(Table%20Read%20Lock)%EF%BC%9A%E5%8F%88%E7%A7%B0%E4%B8%BA%E8%A1%A8%E8%AF%BB%E9%94%81%EF%BC%8C%E5%85%81%E8%AE%B8%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E9%94%81%E5%AE%9A%E7%9A%84%E8%A1%A8%E8%BF%9B%E8%A1%8C%E8%AF%BB%E5%8F%96%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%B8%8D%E5%85%81%E8%AE%B8%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E8%BF%9B%E8%A1%8C%E5%86%99%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%BD%86%E6%98%AF%E5%8F%AF%E4%BB%A5%E8%BF%9B%E8%A1%8C%E8%AF%BB%E6%93%8D%E4%BD%9C%E3%80%82%E5%A4%9A%E4%B8%AA%E8%AF%BB%E9%94%81%E4%B9%8B%E9%97%B4%E6%98%AF%E4%B8%8D%E4%BC%9A%E7%9B%B8%E4%BA%92%E9%98%BB%E5%A1%9E%E7%9A%84%E3%80%82%0A%3E%0A%3E%20%E8%A1%A8%E7%8B%AC%E5%8D%A0%E5%86%99%E9%94%81(Table%20Write%20Lock)%3A%E5%8F%88%E7%A7%B0%E4%B8%BA%E8%A1%A8%E5%86%99%E9%94%81%EF%BC%8C%E5%85%81%E8%AE%B8%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E9%94%81%E5%AE%9A%E7%9A%84%E8%A1%A8%E8%BF%9B%E8%A1%8C%E8%A1%A8%E8%AF%BB%E5%8F%96%E5%92%8C%E8%A1%A8%E6%9B%B4%E6%96%B0%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%B8%8D%E5%85%81%E8%AE%B8%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E5%86%8D%E5%AF%B9%E8%AF%A5%E8%A1%A8%E8%BF%9B%E8%A1%8C%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%BF%85%E9%A1%BB%E7%AD%89%E5%BE%85%E8%A1%A8%E5%86%99%E9%94%81%E7%BB%93%E6%9D%9F%EF%BC%8C%E5%86%99%E9%94%81%E4%BC%9A%E9%98%BB%E5%A1%9E%E5%85%B6%E4%BB%96%E6%89%80%E6%9C%89%E9%94%81%EF%BC%8C%E5%8C%85%E6%8B%AC%E8%AF%BB%E9%94%81%E5%92%8C%E5%86%99%E9%94%81%E3%80%82%0A%0A%0A%0A%3E%20%E5%9C%A8mysql%E4%B8%AD%E5%AF%B9MyISAM%E8%A1%A8%E7%9A%84%E8%AF%BB%E6%93%8D%E4%BD%9C%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%8A%A0%E4%B8%8A%E8%AF%BB%E9%94%81%EF%BC%8C%E5%AF%B9MyISAM%E7%9A%84%E5%86%99%E6%93%8D%E4%BD%9C%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%8A%A0%E4%B8%8B%E5%86%99%E9%94%81%E3%80%82%E5%9B%A0%E4%B8%BA%E6%98%AF%E6%B2%A1%E6%9C%89%E4%BA%8B%E5%8A%A1%E6%8E%A7%E5%88%B6%E7%9A%84%EF%BC%8C%E5%9C%A8%E9%AB%98%E5%B9%B6%E5%8F%91%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%BA%E4%BA%86%E4%BF%9D%E6%8C%81%E6%95%B0%E6%8D%AE%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%E5%8F%AA%E8%83%BD%E9%80%9A%E8%BF%87%E5%AF%B9%E6%95%B4%E4%B8%AA%E8%A1%A8%E5%8A%A0%E9%94%81%E3%80%82%0A%3E%0A%3E%20InnoDB%E4%B8%AD%E5%9C%A8%E5%BF%85%E8%A6%81%E7%9A%84%E6%83%85%E5%86%B5%E4%BC%9A%E4%BD%BF%E7%94%A8%E8%A1%A8%E9%94%81%EF%BC%8C%E6%9B%B4%E5%A4%9A%E6%98%AF%E4%BD%BF%E7%94%A8%E8%A1%8C%E9%94%81%E6%9D%A5%E5%AE%9E%E7%8E%B0MVCC%E3%80%82%E5%AE%83%E8%83%BD%E6%8F%90%E4%BE%9B%E6%9B%B4%E5%A5%BD%E7%9A%84%E5%B9%B6%E5%8F%91%E6%80%A7%E5%92%8C%E6%9B%B4%E5%B0%91%E7%9A%84%E9%94%81%E5%86%B2%E7%AA%81%E3%80%82%0A%3E%0A%3E%20%0A%3E%0A%3E%20%60%E6%B3%A8%E6%84%8F%60%EF%BC%9A%0A%3E%0A%3E%201.%20InnoDB%E4%B8%BB%E8%A6%81%E4%BD%BF%E7%94%A8%E8%A1%8C%E7%BA%A7%E9%94%81%EF%BC%8C%E5%B9%B6%E5%9C%A8%E4%B8%80%E4%BA%9B%E6%83%85%E5%86%B5%E4%B8%8B%E4%BD%BF%E7%94%A8%E8%A1%A8%E7%BA%A7%E9%94%81%EF%BC%8C%E6%AF%94%E5%A6%82%E5%9C%A8%E6%89%A7%E8%A1%8C%E6%9F%90%E4%BA%9B%E5%91%BD%E4%BB%A4%E6%97%B6%E6%AF%94%E5%A6%82alter%20table%E6%97%B6%E3%80%82%0A%3E%0A%3E%202.%20MyISAM%E5%8F%AA%E6%94%AF%E6%8C%81%E8%A1%A8%E7%BA%A7%E9%94%81%0A%0A%0A%0A-%20%E8%A1%A8%E9%94%81%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%0A%0A%3E1.%20%E8%AF%BB%E5%AF%86%E9%9B%86%E5%9E%8B%E5%BA%94%E7%94%A8%EF%BC%8C%20%E5%A6%82%E6%9E%9C%E4%BD%A0%E7%9A%84%E5%BA%94%E7%94%A8%E4%B8%BB%E8%A6%81%E6%98%AF%E8%BF%9B%E8%A1%8C%E8%AF%BB%E5%8F%96%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%BE%88%E5%B0%91%E8%BF%9B%E8%A1%8C%E5%86%99%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%BF%99%E6%97%B6%E5%8A%A0%E8%A1%A8%E9%94%81%E4%BC%9A%E6%98%AF%E4%B8%80%E4%B8%AA%E5%8F%91%E7%9A%84%E9%80%89%E6%8B%A9%EF%BC%8C%20%E5%9B%A0%E4%B8%BA%E8%A1%A8%E8%AF%BB%E9%94%81%E4%B8%8D%E4%B8%BA%E9%98%BB%E5%A1%9E%E5%85%B6%E5%AE%83%E7%9A%84%E8%AF%BB%E9%94%81%EF%BC%8C%E6%89%80%E5%9C%A8%E5%9C%A8%E8%BF%99%E7%A7%8D%E5%9C%BA%E6%99%AF%E4%B8%8B%E8%83%BD%E6%8F%90%E4%BE%9B%E6%9B%B4%E9%AB%98%E7%9A%84%E6%80%A7%E8%83%BD%E3%80%82%0A%3E2.%20%E5%86%99%E6%93%8D%E4%BD%9C%E4%B8%8D%E9%A2%91%E7%B9%81%E7%9A%84%E5%9C%BA%E6%99%AF%3A%20%E8%A1%A8%E7%BA%A7%E9%94%81%E5%AF%B9%E5%86%99%E6%93%8D%E4%BD%9C%E7%9A%84%E5%A4%84%E7%90%86%E5%B9%B6%E4%B8%8D%E9%AB%98%E6%95%88%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%86%99%E9%94%81%E4%BC%9A%E9%98%BB%E5%A1%9E%E6%89%80%E6%9C%89%E7%9A%84%E5%85%B6%E5%AE%83%E6%93%8D%E4%BD%9C%EF%BC%8C%E6%97%A0%E8%AE%BA%E5%AE%83%E4%BB%AC%E6%98%AF%E8%AF%BB%E9%94%81%E8%BF%98%E6%98%AF%E5%86%99%E9%94%81%EF%BC%8C%E4%BD%86%E6%98%AF%E5%A6%82%E6%9E%9C%E4%BD%A0%E7%9A%84%E5%BA%94%E7%94%A8%E4%B8%8D%E9%9C%80%E8%A6%81%E9%A2%91%E7%B9%81%E7%9A%84%E5%86%99%E6%93%8D%E4%BD%9C%EF%BC%8C%E6%88%96%E8%80%85%E5%8F%AF%E4%BB%A5%E5%AE%B9%E5%BF%8D%E5%86%99%E6%93%8D%E4%BD%9C%E7%9A%84%E5%BB%B6%E6%97%B6%EF%BC%8C%E9%82%A3%E4%B9%88%E4%BD%BF%E7%94%A8%E8%A1%A8%E9%94%81%E8%BF%98%E6%98%AF%E5%8F%AF%E4%BB%A5%E7%9A%84%E3%80%82%0A%3E3.%20%E6%95%B0%E6%8D%AE%E9%87%8F%E4%B8%8D%E5%A4%A7%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%3A%E5%A6%82%E6%9F%A5%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84%E6%95%B0%E6%8D%AE%E9%87%8F%E4%B8%8D%E6%98%AF%E5%BE%88%E5%A4%A7%EF%BC%8C%E9%82%A3%E4%B9%88%E5%8D%B3%E4%BD%BF%E5%9C%A8%E5%86%99%E6%93%8D%E4%BD%9C%E4%B8%AD%EF%BC%8C%E7%94%B1%E4%BA%8E%E9%94%81%E5%AE%9A%E6%95%B4%E5%BC%A0%E8%A1%A8%E5%AF%B9%E6%80%A7%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D%E4%B9%9F%E4%B8%8D%E5%A4%A7%E3%80%82%0A%3E4.%20%E5%85%A8%E8%A1%A8%E6%9B%B4%E6%96%B0%E6%88%96%E5%88%A0%E9%99%A4%EF%BC%9A%E5%9C%A8%E6%9F%90%E4%BA%9B%E6%83%85%E5%86%B5%E4%B8%8B%E5%8F%AF%E8%83%BD%E9%9C%80%E8%A6%81%E5%AF%B9%E4%B8%80%E5%BC%A0%E8%A1%A8%E8%BF%9B%E8%A1%8C%E5%85%A8%E8%A1%A8%E6%9B%B4%E6%96%B0%E6%88%96%E8%80%85%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C%EF%BC%8C%E6%AF%94%E5%A6%82%E5%88%A0%E9%99%A4%E8%A1%A8%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E8%AE%B0%E5%BD%95%EF%BC%8C%E6%88%96%E8%80%85%E6%9B%B4%E6%96%B0%E6%89%80%E6%9C%89%E8%AE%B0%E5%BD%95%E4%B8%AD%E5%85%B6%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%EF%BC%8C%E8%BF%99%E7%A7%8D%E6%83%85%E5%86%B5%E4%B8%8B%E4%BD%BF%E7%94%A8%E8%A1%A8%E7%BA%A7%E9%94%81%E6%98%AF%E5%90%88%E9%80%82%E7%9A%84%E3%80%82%0A%0A%0A%0A-%20%E8%A7%A6%E5%8F%91%E8%A1%A8%E9%94%81%E7%9A%84%E5%91%BD%E4%BB%A4%0A%0A%3E1.%20%60alter%20table%60%EF%BC%9A%E6%9B%B4%E6%94%B9%E8%A1%A8%E7%BB%93%E6%9E%84%E6%97%B6mysql%E4%BC%9A%E9%94%81%E5%AE%9A%E6%95%B4%E4%B8%AA%E8%A1%A8%E4%BB%A5%E9%98%B2%E6%AD%A2%E5%9C%A8%E6%9B%B4%E6%94%B9%E8%BF%87%E7%A8%8B%E4%B8%AD%E6%9C%89%E6%96%B0%E7%9A%84%E6%95%B0%E6%8D%AE%E5%86%99%E5%85%A5%E3%80%82%0A%3E%0A%3E2.%20%60drop%20table%20%7C%20truncate%20table%60%EF%BC%9A%E6%9B%B4%E6%94%B9%E8%A1%A8%E7%BB%93%E6%9E%84%E6%97%B6mysql%E4%BC%9A%E9%94%81%E5%AE%9A%E6%95%B4%E4%B8%AA%E8%A1%A8%E4%BB%A5%E9%98%B2%E6%AD%A2%E5%9C%A8%E5%88%A0%E9%99%A4%E8%A1%A8%EF%BC%8C%E6%88%96%E8%80%85%E5%88%A0%E9%99%A4%E8%A1%A8%E4%B8%AD%E6%89%80%E6%9C%89%E6%95%B0%E6%8D%AE%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%E6%9C%89%E6%96%B0%E7%9A%84%E6%95%B0%E6%8D%AE%E5%86%99%E5%85%A5%E3%80%82%0A%3E%0A%3E3.%20%60lock%20tables%60%EF%BC%9A%E6%98%BE%E5%BC%8F%E7%9A%84%E4%B8%BA%E4%B8%80%E4%B8%AA%E6%88%96%E8%80%85%E5%A4%9A%E4%B8%AA%E8%A1%A8%E5%8A%A0%E9%94%81%EF%BC%8C%E5%90%8E%E9%9D%A2%E5%8F%AF%E4%BB%A5%E8%B7%9F%E4%B8%80%E4%B8%AA%E8%A1%A8%E6%88%96%E8%80%85%E5%A4%9A%E4%B8%AA%E8%A1%A8%E7%9A%84%E5%90%8D%E7%A7%B0%E5%92%8C%E9%94%81%E6%A8%A1%E5%BC%8F%EF%BC%8C%E7%94%A8%E6%9D%A5%E6%8C%87%E5%AE%9A%E9%9C%80%E8%A6%81%E9%94%81%E5%AE%9A%E5%93%AA%E4%BA%9B%E8%A1%A8%EF%BC%8C%E4%BB%A5%E5%8F%8A%E4%BD%BF%E7%94%A8%E4%BB%80%E4%B9%88%E6%A0%B7%E7%9A%84%E8%A1%A8%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%A6%82%EF%BC%9A%60lock%20tables%20t1%20write%2Ct2%20read%3B%60%20%E4%B8%BAt1%E5%8A%A0%E8%A1%A8%E5%86%99%E9%94%81%E4%B8%BAt2%E5%8A%A0%E8%A1%A8%E8%AF%BB%E9%94%81%0A%3E%0A%3E4.%20%E5%BC%80%E5%90%AF%E5%85%A8%E5%B1%80%E9%94%81%E6%97%B6%E4%BC%9A%E8%87%AA%E5%8A%A8%E5%AF%B9%E6%89%80%E6%9C%89%E8%A1%A8%E5%8A%A0%E9%94%81%0A%0A%0A%0A%60%60%60mysql%0Alock%20tables%20employee%20read%3B%20--%20%E5%BC%80%E5%90%AF%E8%A1%A8%E8%AF%BB%E9%94%81%0Ashow%20open%20tables%20where%20In_use%20%3E%200%3B%20--%20%E6%9F%A5%E8%AF%A2%E5%8A%A0%E8%A1%A8%E9%94%81%E7%9A%84%E8%A1%A8%0Aupdate%20employee%20set%20name%3D'%E5%BC%A0%E4%B8%89'%20where%20id%3D1%3B%20--%20Table%20'employee'%20was%20locked%20with%20a%20READ%20lock%20and%20can't%20be%20updated%0Aunlock%20tables%3B%20--%20%E9%87%8A%E6%94%BE%E9%94%81%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E8%A1%8C%E9%94%81%0A%0A%3E%20%E8%A1%8C%E9%94%81%E6%98%AFmysql%E7%B2%92%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E9%94%81%E6%9C%BA%E5%88%B6%EF%BC%8C%E5%AE%83%E5%8F%AF%E4%BB%A5%E5%AF%B9%E6%9F%90%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%E8%BF%9B%E8%A1%8C%E9%94%81%E5%AE%9A%E3%80%82%E5%9B%A0%E6%AD%A4%E5%9C%A8%E9%AB%98%E5%B9%B6%E5%8F%91%E4%BA%8B%E5%8A%A1%E4%B8%AD%E5%8F%AF%E4%BB%A5%E6%8F%90%E4%BE%9B%E6%9B%B4%E5%A5%BD%E7%9A%84%E5%B9%B6%E5%8F%91%E6%80%A7%E5%92%8C%E6%9B%B4%E5%B0%91%E7%9A%84%E9%94%81%E5%86%B2%E7%AA%81%E3%80%82%0A%0A%3E%20%E5%9C%A8mysql%E4%B8%AD%EF%BC%8C%E8%A1%8C%E7%BA%A7%E9%94%81%E4%B8%BB%E8%A6%81%E7%94%B1InnoDB%E5%BC%95%E6%93%8E%E6%8F%90%E4%BE%9B%EF%BC%8CInnoDB%E6%94%AF%E6%8C%81%E4%B8%A4%E7%A7%8D%E7%B1%BB%E5%9E%8B%E7%9A%84%E8%A1%8C%E7%BA%A7%E9%94%81%EF%BC%9A%E5%85%B1%E4%BA%AB%E9%94%81%EF%BC%88S%E9%94%81%EF%BC%89%E5%92%8C%E6%8E%92%E4%BB%96%E9%94%81%EF%BC%88X%E9%94%81%EF%BC%89%0A%3E%0A%3E%20%60%E5%85%B1%E4%BA%AB%E9%94%81%EF%BC%88S%E9%94%81%EF%BC%89%60%3A%20%20%E4%B9%9F%E7%A7%B0%E4%B8%BA%E8%AF%BB%E9%94%81%EF%BC%8C%E5%AE%83%E5%85%81%E8%AE%B8%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E8%AF%BB%E5%8F%96%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%BD%93%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%E8%A2%AB%E5%85%B1%E4%BA%AB%E9%94%81%E9%94%81%E5%AE%9A%E6%97%B6%EF%BC%8C%E5%85%B6%E4%BB%96%E4%BA%8B%E5%8A%A1%E5%8F%AF%E4%BB%A5%E8%AF%BB%E5%8F%96%E8%BF%99%E8%A1%8C%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%BD%86%E4%B8%8D%E8%83%BD%E5%AF%B9%E5%85%B6%E8%BF%9B%E8%A1%8C%E4%BF%AE%E6%94%B9%E3%80%82%0A%3E%0A%3E%20%60%E6%8E%92%E4%BB%96%E9%94%81%EF%BC%88X%E9%94%81%EF%BC%89%60%3A%20%20%E4%B9%9F%E7%A7%B0%E4%B8%BA%E5%86%99%E9%94%81%EF%BC%8C%E5%AE%83%E5%85%81%E8%AE%B8%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E8%AF%BB%E5%8F%96%E5%92%8C%E4%BF%AE%E6%94%B9%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%BD%93%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%E8%A2%AB%E6%8E%92%E4%BB%96%E9%94%81%E9%94%81%E5%AE%9A%E6%97%B6%EF%BC%8C%E5%85%B6%E4%BB%96%E4%BA%8B%E5%8A%A1%E4%B8%8D%E8%83%BD%E8%AF%BB%E5%8F%96%E4%B9%9F%E4%B8%8D%E8%83%BD%E4%BF%AE%E6%94%B9%E8%BF%99%E8%A1%8C%E6%95%B0%E6%8D%AE%E3%80%82%0A%3E%0A%3E%20%E5%9C%A8%E5%AE%9E%E9%99%85%E7%9A%84%E4%BD%BF%E7%94%A8%E8%BF%87%E7%A8%8B%E4%B8%ADInnoDB%E8%BF%98%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E7%A7%8D%E5%90%8D%E7%A7%B0%60Gap%20Lock%E3%80%90%E9%97%B4%E9%9A%99%E9%94%81%E3%80%91%60%E7%9A%84%E7%89%B9%E6%80%A7%EF%BC%8C%E4%B8%8D%E4%BB%85%E5%8F%AF%E4%BB%A5%E9%94%81%E5%AE%9A%E5%85%B6%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%BF%98%E5%8F%AF%E4%BB%A5%E9%94%81%E5%AE%9A%E8%BF%99%E8%A1%8C%E6%95%B0%E6%8D%AE%E5%89%8D%E5%90%8E%E7%9A%84'%E9%97%B4%E9%9A%99'%EF%BC%8C%E5%8D%B3%E8%BF%99%E4%B8%80%E8%A1%8C%E4%B9%8B%E5%89%8D%E5%92%8C%E4%B9%8B%E5%90%8E%E7%9A%84%E4%B8%80%E4%BA%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E3%80%82%E9%97%B4%E9%9A%99%E9%94%81%E5%8F%AF%E4%BB%A5%E9%98%B2%E6%AD%A2%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E6%8F%92%E5%85%A5%E6%96%B0%E7%9A%84%E8%A1%8C%E5%88%B0%E5%B7%B2%E9%94%81%E5%AE%9A%E8%A1%8C%E7%9A%84%E5%89%8D%E5%90%8E%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%8F%AF%E4%BB%A5%E8%A7%A3%E5%86%B3%E4%B8%80%E4%BA%9B%E5%B9%B6%E5%8F%91%E9%97%AE%E9%A2%98%0A%3E%0A%3E%20%0A%3E%0A%3E%20%60%E6%B3%A8%E6%84%8F%60%3A%0A%3E%0A%3E%20-%20%E8%A1%8C%E9%94%81%E5%8F%AA%E5%9C%A8%E4%BA%8B%E5%8A%A1%E4%B8%AD%E6%9C%89%E6%95%88%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E5%8F%AA%E6%9C%89%E5%9C%A8%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%BC%80%E5%A7%8B%E5%88%B0%E8%BF%99%E4%B8%AA%E4%BA%8B%E5%8A%A1%E6%8F%90%E4%BA%A4%E6%88%96%E8%80%85%E5%9B%9E%E6%BB%9A%E4%B9%8B%E5%89%8D%EF%BC%8C%E6%89%8D%E8%83%BD%E5%AF%B9%E6%95%B0%E6%8D%AE%E8%BF%9B%E8%A1%8C%E9%94%81%E5%AE%9A%E3%80%82%0A%3E%0A%3E%20-%20%E5%A6%82%E6%9E%9C%E6%98%AF%E5%9C%A8%E9%9D%9E%E4%BA%8B%E5%8A%A1%E7%8E%AF%E5%A2%83%E4%B8%AD%E6%89%A7%E8%A1%8Csql%EF%BC%8C%E9%82%A3%E4%B9%88InnoDB%E4%BC%9A%E5%9C%A8sql%E8%AF%AD%E5%8F%A5%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9D%9F%E5%90%8E%E7%AB%8B%E5%8D%B3%E9%87%8A%E6%94%BE%E6%89%80%E6%9C%89%E7%9A%84%E9%94%81%E3%80%82%0A%0A%0A%0A%0A%0A-%20%E8%A1%8C%E9%94%81%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%0A%0A%3E%201.%20%E9%AB%98%E5%B9%B6%E5%8F%91%E8%AF%BB%E5%86%99%E6%93%8D%E4%BD%9C%EF%BC%9A%E5%9C%A8%E9%9C%80%E8%A6%81%E9%AB%98%E5%B9%B6%E5%8F%91%E7%9A%84%E8%AF%BB%E5%86%99%E6%93%8D%E4%BD%9C%E4%B8%AD%EF%BC%8C%E8%A1%8C%E9%94%81%E5%8F%AF%E4%BB%A5%E6%8F%90%E9%AB%98%E6%80%A7%E8%83%BD%E5%92%8C%E5%B9%B6%E5%8F%91%E6%80%A7%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%AE%83%E5%85%81%E8%AE%B8%E5%A4%9A%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%B9%B6%E5%8F%91%E6%93%8D%E4%BD%9C%E4%B8%8D%E5%90%8C%E7%9A%84%E8%A1%8C%E3%80%82%0A%3E%202.%20%E5%8D%95%E8%A1%8C%E6%93%8D%E4%BD%9C%EF%BC%9A%E5%AF%B9%E4%BA%8E%E9%9C%80%E8%A6%81%E6%93%8D%E4%BD%9C%E5%8D%95%E8%A1%8C%E6%95%B0%E6%8D%AE%E7%9A%84sql%E8%AF%AD%E5%8F%A5%EF%BC%8C%E4%BE%8B%E5%A6%82%E5%9F%BA%E4%BA%8E%E4%B8%BB%E9%94%AE%E6%88%96%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%E7%9A%84%20update%2Cdelete%2Cinsert%E8%AF%AD%E5%8F%A5%EF%BC%8C%E8%A1%8C%E7%BA%A7%E9%94%81%E5%8F%AF%E4%BB%A5%E6%8F%90%E4%BE%9B%E6%9B%B4%E5%A5%BD%E7%9A%84%E5%B9%B6%E5%8F%91%E6%80%A7%E5%92%8C%E6%80%A7%E8%83%BD%0A%3E%203.%20%E7%9F%AD%E6%9C%9F%E9%94%81%EF%BC%9A%E5%9C%A8%E9%9C%80%E8%A6%81%E5%AF%B9%E6%95%B0%E6%8D%AE%E8%BF%9B%E8%A1%8C%E7%9F%AD%E6%97%B6%E9%97%B4%E9%94%81%E5%AE%9A%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E8%A1%8C%E7%BA%A7%E9%94%81%E5%8F%AF%E4%BB%A5%E9%98%B2%E6%AD%A2%E9%95%BF%E6%97%B6%E9%97%B4%E9%98%BB%E5%A1%9E%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E3%80%82%0A%3E%204.%20%E5%AE%9E%E7%8E%B0%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6%EF%BC%9A%E5%9C%A8%E9%9C%80%E8%A6%81%E7%A1%AE%E4%BF%9D%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7%E5%92%8C%E9%9A%94%E7%A6%BB%E6%80%A7%E7%9A%84%E4%BA%8B%E5%8A%A1%E4%B8%AD%EF%BC%8C%E8%A1%8C%E7%BA%A7%E9%94%81%E6%98%AF%E5%AE%9E%E7%8E%B0%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6%E7%9A%84%E9%87%8D%E8%A6%81%E6%9C%BA%E5%88%B6%E3%80%82%0A%3E%205.%20%E5%A4%8D%E6%9D%82%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%A4%84%E7%90%86%EF%BC%9A%E5%9C%A8%E9%9C%80%E8%A6%81%E5%AF%B9%E5%A4%9A%E8%A1%8C%E6%95%B0%E6%8D%AE%E8%BF%9B%E8%A1%8C%E5%A4%8D%E6%9D%82%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%A4%84%E7%90%86%E4%B8%AD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E8%A1%8C%E9%94%81%E6%9D%A5%E9%94%81%E5%AE%9A%E8%BF%99%E8%A1%8C%E4%BA%9B%EF%BC%8C%E9%98%B2%E6%AD%A2%E5%9C%A8%E4%BA%8B%E5%8A%A1%E5%A4%84%E7%90%86%E8%BF%87%E7%A8%8B%E4%B8%AD%E6%95%B0%E6%8D%AE%E8%A2%AB%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E4%BF%AE%E6%94%B9%E3%80%82%0A%0A%0A%0A-%20%E8%A7%A6%E5%8F%91%E8%A1%8C%E9%94%81%E7%9A%84%E5%91%BD%E4%BB%A4%0A%0A%3E1.%20%60select...for%20update%60%3A%20%E8%BF%99%E7%A7%8D%E6%9F%A5%E8%AF%A2%E4%B8%BA%E4%BC%9A%E9%80%89%E5%AE%9A%E7%9A%84%E6%95%B0%E6%8D%AE%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E6%8E%92%E5%AE%83%E9%94%81%EF%BC%8C%E8%BF%99%E6%84%8F%E5%91%B3%E7%9D%80%E5%85%B6%E4%BB%96%E4%BA%8B%E5%8A%A1%E4%B8%8D%E8%83%BD%E4%BF%AE%E6%94%B9%E8%BF%99%E4%BA%9B%E8%A1%8C%EF%BC%8C%E4%B9%9F%E4%B8%8D%E5%AF%B9%E8%BF%99%E4%BA%9B%E8%A1%8C%E6%B7%BB%E5%8A%A0%E5%85%B1%E4%BA%AB%E9%94%81%E3%80%82%0A%3E2.%20%60select...lock%20in%20share%20mode%60%3A%20%E8%BF%99%E7%A7%8D%E6%9F%A5%E8%AF%A2%E4%B8%BA%E4%BC%9A%E9%80%89%E5%AE%9A%E7%9A%84%E6%95%B0%E6%8D%AE%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E5%85%B1%E4%BA%AB%E9%94%81%EF%BC%8C%E8%BF%99%E6%84%8F%E5%91%B3%E7%9D%80%E5%85%B6%E4%BB%96%E4%BA%8B%E5%8A%A1%E4%B8%8D%E8%83%BD%E4%BF%AE%E6%94%B9%E8%BF%99%E4%BA%9B%E8%A1%8C%EF%BC%8C%E4%BD%86%E5%8F%AF%E4%BB%A5%E5%AF%B9%E8%BF%99%E4%BA%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E6%B7%BB%E5%8A%A0%E5%85%B1%E4%BA%AB%E9%94%81%E3%80%82%0A%3E3.%20insert%3A%20%E6%8F%92%E5%85%A5%E6%93%8D%E4%BD%9C%E4%BC%9A%E5%AF%B9%E6%96%B0%E6%B7%BB%E5%8A%A0%E7%9A%84%E8%A1%8C%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E6%8E%92%E4%BB%96%E9%94%81%0A%3E4.%20update%EF%BC%9A%E6%9B%B4%E6%96%B0%E6%93%8D%E4%BD%9C%E4%BC%9A%E5%AF%B9%E8%A2%AB%E6%9B%B4%E6%96%B0%E7%9A%84%E8%A1%8C%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E6%8E%92%E4%BB%96%E9%94%81%0A%3E5.%20delete%EF%BC%9A%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C%E4%BC%9A%E5%AF%B9%E8%A2%AB%E5%88%A0%E9%99%A4%E7%9A%84%E8%A1%8C%E6%95%B0%E6%8D%AE%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E6%8E%92%E4%BB%96%E9%94%81%0A%0A%0A%0A%60%60%60mysql%0A--%20%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5%E7%BB%93%E6%9D%9F%E6%97%B6%E5%90%8E%E7%AB%8B%E5%8D%B3%E9%87%8A%E4%BA%86%E6%8E%92%E4%BB%96%E9%94%81%EF%BC%8C%E6%89%80%E4%BB%A5%E7%AC%AC%E4%BA%8C%E8%A1%8C%E8%AF%AD%E5%8F%A5%E6%9F%A5%E8%AF%A2%E4%B8%8D%E5%88%B0%E8%A1%8C%E9%94%81%0Aselect%20*%20from%20employee%20where%20id%3D1%20for%20update%3B%20%0Aselect%20*%20from%20performance_schema.data_locks%3B%20--%20%E6%9F%A5%E8%AF%A2%E8%A1%8C%E9%94%81%E7%9A%84%E5%91%BD%E4%BB%A4%0A%60%60%60%0A%0A%0A%0A%60%60%60mysql%0Astart%20transaction%3B%0Aselect%20*%20from%20employee%20where%20id%3D1%20for%20update%3B%20--%20%E5%9C%A8%E6%89%8B%E5%8A%A8%E6%89%A7%E8%A1%8C%E5%AE%8C%E8%BF%99%E6%9D%A1sql%E8%AF%AD%E5%8F%A5%E5%90%8E%E5%86%8D%E5%8E%BB%E6%89%A7%E8%A1%8C%E6%9F%A5%E8%AF%A2%E8%A1%8C%E9%94%81%E7%9A%84%E5%91%BD%E4%BB%A4%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E5%BD%93%E5%89%8D%E8%A1%8C%E8%A2%AB%E5%8A%A0%E4%BA%86%E6%8E%92%E4%BB%96%E9%94%81%0Aupdate%20employee%20set%20name%3D'chris'%20where%20id%3D1%3B%20--%20%E5%9B%A0%E4%B8%BA%E6%98%AF%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E4%B8%AD%EF%BC%8C%E6%89%80%E4%BB%A5%E6%98%AF%E5%8F%AF%E4%BB%A5%E8%AF%BB%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%86%99%E7%9A%84%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BA%8B%E5%8A%A1%E4%B8%AD%E3%80%90%E9%87%8D%E6%96%B0%E6%89%93%E5%BC%80%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E5%91%BD%E4%BB%A4%E7%AA%97%E5%8F%A3%E3%80%91%E6%9B%B4%E6%96%B0%E6%98%AF%E4%B8%8D%E8%83%BD%E6%88%90%E5%8A%9F%E6%89%A7%E8%A1%8C%E7%9A%84%0Acommit%3B%0A%0Aselect%20*%20from%20performance_schema.data_locks%3B%20--%20%E6%9F%A5%E8%AF%A2%E8%A1%8C%E9%94%81%E7%9A%84%E5%91%BD%E4%BB%A4%0A%60%60%60%0A%0A%0A%0A-%20%E8%A1%8C%E9%94%81%E7%9A%84%E9%A3%8E%E9%99%A9%E7%9A%84%E7%BC%BA%E7%82%B9%0A%0A%3E%201.%20%E6%AD%BB%E9%94%81%EF%BC%9A%E5%BD%93%E4%B8%A4%E4%B8%AA%E6%88%96%E8%80%85%E6%9B%B4%E5%A4%9A%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%9C%A8%E7%9B%B8%E4%BA%92%E7%AD%89%E5%BE%85%E5%AF%B9%E6%96%B9%E9%87%8A%E6%94%BE%E8%B5%84%E6%BA%90%E6%97%B6%E5%B0%B1%E4%BC%9A%E5%87%BA%E7%8E%B0%E6%AD%BB%E9%94%81%EF%BC%8C%E4%BE%8B%E5%A6%82%EF%BC%9A%E4%BA%8B%E5%8A%A11%E9%94%81%E5%AE%9A%E7%9A%84%E8%A1%8CA%E5%B9%B6%E8%AF%95%E5%9B%BE%E9%94%81%E5%AE%9A%E8%A1%8CB%EF%BC%8C%E4%BA%8B%E5%8A%A12%E9%94%81%E5%AE%9A%E4%BA%86%E8%A1%8CB%E5%B9%B6%E8%AF%95%E5%9B%BE%E9%94%81%E5%AE%9A%E8%A1%8CA%EF%BC%8C%E8%BF%99%E5%B0%B1%E5%BD%A2%E6%88%90%E4%BA%86%E6%AD%BB%E9%94%81%E3%80%82mysql%E4%BC%9A%E6%A3%80%E6%B5%8B%E5%88%B0%E6%AD%BB%E9%94%81%E5%B9%B6%E7%BB%88%E6%AD%A2%E5%85%B6%E4%B8%AD%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%EF%BC%8C%E4%BD%86%E8%BF%99%E4%BB%8D%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98%E5%92%8C%E4%BA%8B%E5%8A%A1%E5%A4%B1%E8%B4%A5%E3%80%82%0A%3E%202.%20%E9%94%81%E5%8D%87%E7%BA%A7%EF%BC%9A%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E8%AF%95%E5%9B%BE%E9%94%81%E5%AE%9A%E7%9A%84%E8%A1%8C%E8%BF%87%E5%A4%9A%EF%BC%8CInnoDB%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%B0%86%E9%94%81%E5%AE%9A%E4%BB%8E%E8%A1%8C%E7%BA%A7%E5%8D%87%E7%BA%A7%E4%B8%BA%E8%A1%A8%E7%BA%A7%EF%BC%8C%E8%BF%99%E5%8F%AF%E8%83%BD%E6%9B%B4%E5%AF%BC%E8%87%B4%E6%9B%B4%E5%A4%9A%E7%9A%84%E9%94%81%E5%86%B2%E7%AA%81%E3%80%82%0A%3E%203.%20%E9%94%81%E7%AD%89%E5%BE%85%EF%BC%9A%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%B7%B2%E7%BB%8F%E9%94%81%E5%AE%9A%E4%BA%86%E5%85%B6%E8%A1%8C%EF%BC%8C%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E5%B0%B1%E5%BF%85%E9%A1%BB%E7%AD%89%E5%BE%85%EF%BC%8C%E4%BC%9A%E5%AF%BC%E8%87%B4%E6%80%A7%E8%83%BD%E4%B8%8B%E9%99%8D%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%A4%A7%E9%87%8F%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%9C%A8%E7%AD%89%E5%BE%85%E5%B0%B1%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E7%B3%BB%E7%BB%9F%E5%87%BA%E7%8E%B0%E6%80%A7%E8%83%BD%E7%93%B6%E9%A2%88%E3%80%82%0A%3E%204.%20%E9%9A%BE%E4%BB%A5%E8%B0%83%E8%AF%95%E5%92%8C%E6%8E%92%E6%9F%A5%EF%BC%9A%E7%94%B1%E4%BA%8E%E8%A1%8C%E9%94%81%E7%B2%92%E5%BA%A6%E8%BE%83%E5%B0%8F%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%87%BA%E7%8E%B0%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98%E6%88%96%E8%80%85%E9%94%81%E5%86%B2%E7%AA%81%EF%BC%8C%E5%B0%B1%E9%9C%80%E8%A6%81%E5%A4%8D%E6%9D%82%E7%9A%84%E8%B0%83%E8%AF%95%E5%92%8C%E6%8E%92%E6%9F%A5%E5%B7%A5%E4%BD%9C%E6%9D%A5%E6%89%BE%E5%87%BA%E9%97%AE%E9%A2%98%E7%9A%84%E5%8E%9F%E5%9B%A0%E3%80%82%0A%3E%205.%20%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%EF%BC%9A%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E4%BC%9A%E5%BD%B1%E5%93%8D%E9%94%81%E7%9A%84%E8%A1%8C%E4%B8%BA%E5%92%8C%E6%80%A7%E8%83%BD%EF%BC%8C%E5%8F%AF%E8%83%BD%E9%9C%80%E8%A6%81%E6%A0%B9%E6%8D%AE%E5%85%B7%E4%BD%93%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E6%9D%A5%E8%B0%83%E6%95%B4%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E3%80%82%0A%0A%0A%0A%23%23%23%20%E6%8C%89%E6%A8%A1%E5%BC%8F%E5%88%86%E7%B1%BB%0A%0A%3E%20mysql%E7%9A%84%E9%94%81%E5%88%86%E4%B8%BA%2C%E5%A4%96%E8%A7%82%E9%94%81%E5%92%8C%E6%82%B2%E8%A7%82%E9%94%81%0A%0A%0A%0A%23%23%23%23%20%E4%B9%90%E8%A7%82%E9%94%81%0A%0A%3E%20%E4%B9%90%E8%A7%82%E9%94%81%E3%80%90Optimistic%20Locking%E3%80%91%2C%E6%98%AF%E4%B8%80%E7%A7%8D%E5%9C%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C%E8%BF%87%E7%A8%8B%E4%B8%AD%E5%A4%84%E7%90%86%E5%B9%B6%E5%8F%91%E9%97%AE%E9%A2%98%E7%9A%84%E7%9A%84%E4%B8%80%E7%A7%8D%E6%8A%80%E6%9C%AF%EF%BC%8C%E5%AE%83%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%80%9D%E6%83%B3%E6%98%AF%E5%81%87%E8%AE%BE%E5%9C%A8%E5%A4%9A%E4%B8%AA%E4%BA%8B%E5%8A%A1%E8%AE%BF%E9%97%AE%E4%B8%80%E6%9D%A1%E6%95%B0%E6%8D%AE%E6%97%B6%EF%BC%8C%E5%86%B2%E7%AA%81%E5%8F%91%E7%94%9F%E7%9A%84%E6%A6%82%E7%8E%87%E4%BD%8E%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%9C%A8%E6%93%8D%E4%BD%9C%E6%95%B0%E6%8D%AE%E6%97%B6%E4%B8%8D%E4%BC%9A%E7%AB%8B%E5%8D%B3%E8%BF%9B%E8%A1%8C%E9%94%81%E5%AE%9A%EF%BC%8C%E8%80%8C%E6%98%AF%E5%9C%A8%E6%8F%90%E4%BA%A4%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%94%B9%E6%97%B6%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E6%9C%89%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E4%BF%AE%E6%94%B9%E4%BA%86%E8%BF%99%E6%9D%A1%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%88%99%E6%8F%90%E4%BA%A4%EF%BC%8C%E5%90%A6%E5%88%99%E5%9B%9E%E6%BB%9A%E4%BA%8B%E5%8A%A1%E3%80%82%0A%3E%0A%3E%20mysql%E4%B8%AD%E5%B9%B6%E6%B2%A1%E6%9C%89%E4%B9%90%E8%A7%82%E9%94%81%E7%9A%84%E5%86%85%E7%BD%AE%E5%AE%9E%E7%8E%B0%EF%BC%8C%E4%BD%86%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E4%B8%80%E4%BA%9B%E7%BC%96%E7%A8%8B%E6%8A%80%E8%89%BA%E6%9D%A5%E5%AE%9E%E7%8E%B0%EF%BC%8C%E4%B8%80%E7%A7%8D%E5%B8%B8%E8%A7%81%E7%9A%84%E5%AE%9E%E7%8E%B0%E6%98%AF%E4%BD%BF%E7%94%A8%E7%89%88%E6%9C%AC%E5%8F%B7%E6%88%96%E6%97%B6%E9%97%B4%E6%88%B3%E5%AD%97%E6%AE%B5%E3%80%82%E6%AF%8F%E5%BD%93%E4%B8%80%E6%9D%A1%E8%AE%B0%E5%BD%95%E8%A2%AB%E4%BF%AE%E6%94%B9%E6%97%B6%EF%BC%8C%E5%B0%B1%E5%A2%9E%E5%8A%A0%E7%89%88%E6%9C%AC%E5%8F%B7%E6%88%96%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4%E6%88%B3%E3%80%82%E5%9C%A8%E6%9B%B4%E6%96%B0%E8%AE%B0%E5%BD%95%E6%97%B6%E5%85%88%E6%A3%80%E6%9F%A5%E7%89%88%E6%9C%AC%E5%8F%B7%E6%88%96%E6%97%B6%E9%97%B4%E6%88%B3%E6%98%AF%E5%90%A6%E5%92%8C%E8%AF%BB%E5%8F%96%E8%AE%B0%E5%BD%95%E6%97%B6%E7%9A%84%E7%89%88%E6%9C%AC%E5%8F%B7%E6%88%96%E6%97%B6%E9%97%B4%E6%88%B3%E4%B8%80%E8%87%B4%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%80%E8%87%B4%E5%88%99%E6%89%A7%E8%A1%8C%E6%9B%B4%E6%96%B0%E5%B9%B6%E5%A2%9E%E5%8A%A0%E7%89%88%E6%9C%AC%E6%88%96%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4%E6%88%B3%EF%BC%8C%E5%90%A6%E5%88%99%E5%B0%B1%E6%8B%92%E7%BB%9D%E6%9B%B4%E6%96%B0%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%B0%B1%E4%BF%9D%E8%AF%81%E4%BA%86%E5%8F%AA%E6%9C%89%E5%9C%A8%E5%BD%93%E5%89%8D%E6%95%B0%E6%8D%AE%E6%B2%A1%E6%9C%89%E8%A2%AB%E5%85%B6%E5%AE%83%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E4%BF%AE%E6%94%B9%E6%97%B6%EF%BC%8C%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E7%9A%84%E4%BF%AE%E6%94%B9%E6%89%8D%E4%BC%9A%E8%A2%AB%E6%8F%90%E4%BA%A4%E3%80%82%0A%0A%0A%0A-%20%E4%B9%90%E8%A7%82%E9%94%81%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%0A%0A%3E%201.%20%E4%BD%8E%E5%86%B2%E7%AA%81%E7%8E%AF%E5%A2%83%EF%BC%9A%E5%9C%A8%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%B9%B6%E5%8F%91%E4%BF%AE%E6%94%B9%E7%9A%84%E5%86%B2%E7%AA%81%E8%BE%83%E4%BD%8E%EF%BC%8C%E5%8D%B3%E5%90%8C%E4%B8%80%E6%97%B6%E9%97%B4%E5%86%85%EF%BC%8C%E5%90%8C%E4%B8%80%E6%9D%A1%E6%95%B0%E6%8D%AE%E4%B8%8D%E4%BC%9A%E8%A2%AB%E5%A4%9A%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%90%8C%E6%97%B6%E4%BF%AE%E6%94%B9%E3%80%82%0A%3E%0A%3E%202.%20%E8%AF%BB%E5%A4%9A%E5%86%99%E5%B0%91%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%9A%E5%9C%A8%E8%AF%BB%E6%93%8D%E4%BD%9C%E8%BF%9C%E5%A4%9A%E4%BA%8E%E5%86%99%E6%93%8D%E4%BD%9C%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E4%B9%90%E8%A7%82%E9%94%81%E5%8F%AF%E4%BB%A5%E9%81%BF%E5%85%8D%E7%94%B1%E4%BA%8E%E9%A2%91%E7%B9%81%E7%9A%84%E8%AF%BB%E6%93%8D%E4%BD%9C%E5%AF%BC%E8%87%B4%E7%9A%84%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E9%94%81%E5%AE%9A%E5%BC%80%E9%94%80%EF%BC%8C%E5%86%99%E5%B0%91%E5%B0%B1%E6%84%8F%E5%91%B3%E7%9D%80%E4%BD%8E%E5%86%B2%E7%AA%81%EF%BC%8C%E8%AF%BB%E5%B9%B6%E4%B8%8D%E4%BC%9A%E7%A0%B4%E5%9D%8F%E6%95%B0%E6%8D%AE%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%8C%E6%89%80%E4%BB%A5%E8%BF%99%E7%A7%8D%E5%9C%BA%E6%99%AF%E4%B9%9F%E6%98%AF%E4%BD%8E%E5%86%B2%E7%AA%81%E5%9C%BA%E6%99%AF%E4%B8%80%E7%A7%8D%E8%A1%8D%E7%94%9F%E3%80%82%0A%3E%0A%3E%203.%20%E7%9F%AD%E4%BA%8B%E5%8A%A1%E6%93%8D%E4%BD%9C%EF%BC%9A%E5%A6%82%E6%9E%9C%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BA%8B%E5%8A%A1%E9%83%BD%E6%98%AF%E7%AE%80%E7%9F%AD%E5%B9%B6%E5%BF%AB%E9%80%9F%E5%AE%8C%E6%88%90%E7%9A%84%EF%BC%8C%E9%82%A3%E4%B9%88%E4%BD%BF%E7%94%A8%E4%B9%90%E8%A7%82%E9%94%81%E5%8F%AF%E4%BB%A5%E5%87%8F%E5%B0%91%E5%9B%A0%E4%B8%BA%E7%AD%89%E5%BE%85%E9%94%81%E8%80%8C%E5%AF%BC%E8%87%B4%E7%9A%84%E6%97%B6%E9%97%B4%E6%B6%88%E8%80%97%E3%80%82%E4%BE%8B%E5%A6%82%E6%97%B6%E9%9A%94%E4%B8%80%E7%A7%92%E4%B8%80%E4%B8%AA%E8%AF%B7%E6%B1%82%E7%9A%84%E4%BD%8E%E5%B9%B6%E5%8F%91%EF%BC%8C%E4%BD%86%E5%A4%84%E7%90%86%E4%BA%8B%E5%8A%A1%E9%9C%80%E8%A6%81%E4%B8%80%E5%88%86%E9%92%9F%EF%BC%8C%E8%BF%99%E7%A7%8D%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%80%E5%88%86%E9%92%9F%E4%BC%9A%E7%A7%AF%E6%94%9260%E4%B8%AA%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%9C%A8%E4%B9%90%E8%A7%82%E9%94%81%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E8%BF%9960%E4%B8%AA%E8%AF%B7%E6%B1%82%E9%83%BD%E4%BC%9A%E5%B0%9D%E8%AF%95%E4%BF%AE%E6%94%B9%E5%B9%B6%E6%9C%80%E7%BB%88%E9%83%BD%E4%BC%9A%E5%A4%B1%E8%B4%A5%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%86%B2%E7%AA%81%E5%B0%B1%E4%BC%9A%E5%8F%98%E5%A4%9A%EF%BC%8C%E6%89%80%E4%BB%A5%E4%B8%8D%E4%BB%85%E8%A6%81%E4%BA%8B%E5%8A%A1%E7%AE%80%E7%9F%AD%E8%80%8C%E4%B8%94%E6%9C%80%E6%98%AF%E8%A6%81%E5%BF%AB%E9%80%9F%E5%AE%8C%E6%88%90%E3%80%82%0A%0A%0A%0A-%20%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E4%B9%90%E8%A7%82%E9%94%81%0A%0A%0A%0A%60%60%60sql%0Acreate%20table%20ipd_spec_core.employee%0A(%0A%C2%A0%20%C2%A0%20id%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0bigint%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0not%20null%20comment%20'%E5%91%98%E5%B7%A5ID'%2C%0A%C2%A0%20%C2%A0%20name%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0varchar(50)%20%C2%A0%20%C2%A0%20%C2%A0%20not%20null%20comment%20'%E5%91%98%E5%B7%A5%E5%90%8D%E7%A7%B0'%2C%0A%C2%A0%20%C2%A0%20address%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20varchar(100)%20%C2%A0%20%C2%A0%20%C2%A0null%20comment%20'%E5%91%98%E5%B7%A5%E5%9C%B0%E5%9D%80'%2C%0A%C2%A0%20%C2%A0%20payment_type%20%C2%A0%20%C2%A0tinyint%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20null%20comment%20'%E6%94%AF%E4%BB%98%E6%96%B9%E5%BC%8F%E3%80%901%EF%BC%9A%E6%94%AF%E7%A5%A8%E9%82%AE%E5%AF%84%EF%BC%8C2%EF%BC%9A%E6%94%AF%E7%A5%A8%E6%9A%82%E5%AD%98%E5%87%BA%E7%BA%B3%E5%A4%84%EF%BC%8C3%EF%BC%9A%E9%93%B6%E8%A1%8C%E8%B4%A6%E6%88%B7%E5%AD%98%E5%85%A5%E3%80%91'%2C%0A%C2%A0%20%C2%A0%20salary_type%20%C2%A0%20%C2%A0%20int%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20null%20comment%20'%E8%96%AA%E6%B0%B4%E7%B1%BB%E5%9E%8B%E3%80%901%EF%BC%9A%E9%92%9F%E7%82%B9%E5%B7%A5%EF%BC%8C2%EF%BC%9A%E5%9B%BA%E5%AE%9A%E5%B7%A5%E8%B5%84%EF%BC%8C3%EF%BC%9A%E9%94%80%E5%94%AE%E4%BD%A3%E9%87%91%E3%80%91'%2C%0A%C2%A0%20%C2%A0%20hourly_rate%20%C2%A0%20%C2%A0%20decimal(10%2C%202)%20%C2%A0%20%C2%A0null%20comment%20'%E6%97%B6%E8%96%AA'%2C%0A%C2%A0%20%C2%A0%20commission_rate%20decimal(5%2C%202)%20%C2%A0%20%C2%A0%20null%20comment%20'%E4%BD%A3%E9%87%91%E7%8E%87'%2C%0A%C2%A0%20%C2%A0%20union_member%20%C2%A0%20%C2%A0tinyint%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20null%20comment%20'%E6%98%AF%E5%90%A6%E5%B7%A5%E4%BC%9A%E6%88%90%E5%91%98'%2C%0A%C2%A0%20%C2%A0%20weekly_dues%20%C2%A0%20%C2%A0%20decimal(10%2C%202)%20%C2%A0%20%C2%A0null%20comment%20'%E6%AF%8F%E5%91%A8%E4%BC%9A%E8%B4%B9'%2C%0A%C2%A0%20%C2%A0%20create_time%20%C2%A0%20%C2%A0%20datetime%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0not%20null%20comment%20'%E5%88%9B%E5%BB%BA%E6%97%B6%E9%97%B4'%2C%0A%C2%A0%20%C2%A0%20update_time%20%C2%A0%20%C2%A0%20datetime%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0null%20comment%20'%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4'%2C%0A%C2%A0%20%C2%A0%20del_flag%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0int%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20null%20comment%20'%E6%98%AF%E5%90%A6%E5%88%A0%E9%99%A4%E3%80%900%EF%BC%9A%E6%9C%AA%E5%88%A0%E9%99%A4%EF%BC%8C1%EF%BC%9A%E5%88%A0%E9%99%A4%E3%80%91'%2C%0A%C2%A0%20%C2%A0%20version%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20tinyint%20default%200%20null%20comment%20'%E7%89%88%E6%9C%AC%E6%A0%87%E8%AF%86'%2C%0A%C2%A0%20%C2%A0%20primary%20key%20('id')%0A)%20ENGINE%20%3D%20InnoDB%20DEFAULT%20CHARACTER%20SET%20%3D%20utf8mb4%20COLLATE%20%3D%20utf8mb4_0900_ai_ci%20COMMENT%20%3D%20'%E5%91%98%E5%B7%A5%E8%A1%A8'%3B%0A%60%60%60%0A%0A%0A%60%60%60sql%0Aselect%20*%20from%20employee%20where%20id%3D1%3B%0Aupdate%20employee%20set%20name%3D'John'%2Cversion%3Dversion%2B1%20where%20id%3D1%20and%20version%3D0%20--%20%E9%A6%96%E5%85%88%E7%A1%AE%E4%BF%9D%E4%BF%AE%E6%94%B9%E7%9A%84%E8%AE%B0%E5%BD%95%E6%98%AF%E8%AF%BB%E5%8F%96%E7%9A%84%E7%89%88%E6%9C%AC%EF%BC%8C%E7%84%B6%E5%90%8E%E6%8A%8A%E7%89%88%E6%9C%AC%E5%8F%B7%E5%8A%A01%E8%AF%B4%E6%98%8E%E8%BF%99%E6%9D%A1%E8%AE%B0%E5%BD%95%E5%B7%B2%E7%BB%8F%E8%A2%AB%E4%BF%AE%E6%94%B9%E4%BA%86%0Aupdate%20employee%20set%20name%3D'Nash'%2Cversion%3Dversion%2B1%20where%20id%3D1%20and%20version%3D0%20--%20%E6%AD%A4%E6%97%B6%E8%BF%99%E6%9D%A1sql%E8%AF%AD%E5%8F%A5%E4%BF%AE%E6%94%B9%E6%97%B6%E5%B0%B1%E4%BF%AE%E6%94%B9%E4%B8%8D%E5%88%B0%E6%95%B0%E6%8D%AE%E4%BA%86%0A%60%60%60%0A%0A%0A%0A%E4%B9%90%E8%A7%82%E9%94%81%E7%9A%84%E7%BC%BA%E7%82%B9%0A%0A%3E%201.%20%E5%86%B2%E7%AA%81%E6%A3%80%E6%B5%8B%EF%BC%9A%E5%9C%A8%E9%AB%98%E5%B9%B6%E5%8F%91%E7%8E%AF%E5%A2%83%E4%B8%8B%EF%BC%8C%E4%B9%90%E8%A7%82%E9%94%81%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%AF%BC%E8%87%B4%E5%A4%A7%E9%87%8F%E7%9A%84%E5%86%B2%E7%AA%81%E3%80%82%E5%9B%A0%E4%B8%BA%E4%B9%90%E8%A7%82%E9%94%81%E5%8F%AA%E6%9C%89%E5%9C%A8%E6%8F%90%E4%BA%A4%E4%BA%8B%E5%8A%A1%E6%97%B6%E6%89%8D%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E6%9C%89%E5%86%B2%E7%AA%81%EF%BC%8C%E5%A6%82%E6%9E%9C%E5%A4%9A%E4%B8%AA%E4%BA%8B%E5%8A%A1%E5%9C%A8%E5%90%8C%E4%B8%80%E6%97%B6%E9%97%B4%E6%93%8D%E4%BD%9C%E5%90%8C%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%EF%BC%8C%E9%82%A3%E4%B9%88%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E8%83%BD%E6%8F%90%E4%BA%A4%E6%88%90%E5%8A%9F%EF%BC%8C%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E9%83%BD%E9%9C%80%E8%A6%81%E5%9B%9E%E6%BB%9A%E5%B9%B6%E9%87%8D%E6%96%B0%E5%B0%9D%E8%AF%95%E3%80%82%0A%3E%0A%3E%202.%20%E5%A4%84%E7%90%86%E5%BC%80%E9%94%80%EF%BC%9A%E5%9C%A8%E5%86%B2%E7%AA%81%E5%8F%91%E7%94%9F%E6%97%B6%EF%BC%8C%E9%9C%80%E8%A6%81%E8%BF%9B%E8%A1%8C%E5%9B%9E%E6%BB%9A%E5%92%8C%E9%87%8D%E8%AF%95%EF%BC%8C%E8%BF%99%E4%BC%9A%E5%A2%9E%E5%8A%A0%E7%B3%BB%E7%BB%9F%E5%BC%80%E9%94%80%E3%80%82%0A%3E%0A%3E%203.%20%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86%EF%BC%9A%E4%B9%90%E8%A7%82%E9%94%81%E9%80%9A%E5%B8%B8%E9%80%9A%E8%BF%87%E7%89%88%E6%9C%AC%E6%88%96%E6%97%B6%E9%97%B4%E6%88%B3%E6%9D%A5%E6%A3%80%E6%B5%8B%E5%86%B2%E7%AA%81%EF%BC%8C%E8%BF%99%E5%B0%B1%E8%A6%81%E6%B1%82%E7%B3%BB%E7%BB%9F%E8%83%BD%E5%A4%9F%E5%87%86%E7%A1%AE%E7%9A%84%E7%AE%A1%E7%90%86%E7%89%88%E6%9C%AC%EF%BC%8C%E5%90%A6%E5%88%99%E4%BC%9A%E5%AF%BC%E8%87%B4%E9%94%99%E8%AF%AF%E7%9A%84%E5%86%B2%E7%AA%81%E6%A3%80%E6%B5%8B%E3%80%82%0A%3E%0A%3E%204.%20%E7%BC%96%E7%A8%8B%E5%A4%8D%E6%9D%82%E6%80%A7%EF%BC%9A%E4%BD%BF%E7%94%A8%E4%B9%90%E8%A7%82%E9%94%81%E9%9C%80%E8%A6%81%E6%9B%B4%E5%A4%8D%E6%9D%82%E7%9A%84%E7%BC%96%E7%A8%8B%EF%BC%8C%E5%9B%A0%E4%B8%BA%E7%A8%8B%E5%BA%8F%E9%9C%80%E8%A6%81%E5%A4%84%E7%90%86%E8%A6%81%E8%83%BD%E5%8F%91%E7%94%9F%E7%9A%84%E5%86%B2%E7%AA%81%E5%92%8C%E9%87%8D%E8%AF%95%E3%80%82%0A%0A%0A%0A%23%23%23%23%20%E6%82%B2%E8%A7%82%E9%94%81%0A%0A%3E%20%E6%82%B2%E8%A7%82%E9%94%81%E6%98%AF%E4%B8%80%E7%A7%8D%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6%E6%96%B9%E6%B3%95%EF%BC%8C%E5%9F%BA%E4%BA%8E%E4%B8%80%E4%B8%AA%E5%81%87%E8%AE%BE%EF%BC%9A%E8%AE%A4%E4%B8%BA%E6%95%B0%E6%8D%AE%E5%9C%A8%E5%B9%B6%E5%8F%91%E5%A4%84%E7%90%86%E8%BF%87%E7%A8%8B%E5%BE%88%E5%8F%AF%E8%83%BD%E5%8F%91%E7%94%9F%E5%86%B2%E7%AA%81%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%B8%BA%E4%BA%86%E4%BF%9D%E8%AF%81%E6%95%B0%E6%8D%AE%E4%B8%80%E5%AE%8C%E6%95%B4%E6%80%A7%E5%92%8C%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%8C%E6%AF%8F%E6%AC%A1%E8%AF%BB%E5%86%99%E6%95%B0%E6%8D%AE%E6%97%B6%E5%85%88%E5%8A%A0%E9%94%81%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%8F%AF%E4%BB%A5%E9%81%BF%E5%85%8D%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E8%BF%9B%E8%A1%8C%E5%B9%B6%E5%8F%91%E7%9A%84%E8%AF%BB%E5%86%99%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A%0A%0A-%20%E6%82%B2%E8%A7%82%E9%94%81%E9%80%82%E7%94%A8%E7%9A%84%E5%9C%BA%E6%99%AF%0A%0A%3E%201.%20%E5%86%99%E6%93%8D%E4%BD%9C%E6%AF%94%E8%BE%83%E5%A4%9A%E7%9A%84%E5%9C%BA%E6%99%AF%EF%BC%9A%E5%A6%82%E6%9E%9C%E5%86%99%E7%9A%84%E6%93%8D%E4%BD%9C%E6%AF%94%E8%BE%83%E5%A4%9A%EF%BC%8C%E5%B0%B1%E6%84%8F%E5%91%B3%E7%9D%80%E6%95%B0%E6%8D%AE%E5%86%B2%E7%AA%81%E7%9B%B8%E5%AF%B9%E8%BE%83%E9%AB%98%EF%BC%8C%E9%A2%84%E5%85%88%E5%8A%A0%E9%94%81%E5%8F%AF%E4%BB%A5%E7%A1%AE%E4%BF%9D%E6%95%B0%E6%8D%AE%E7%9A%84%E5%AE%8C%E6%95%B4%E6%80%A7%E5%92%8C%E4%B8%80%E8%87%B4%E6%80%A7%E5%B0%86%E4%BC%9A%E6%98%AF%E4%B8%80%E7%A7%8D%E5%A5%BD%E7%9A%84%E9%80%89%E6%8B%A9%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%BD%BF%E7%94%A8%E4%B9%90%E8%A7%82%E9%94%81%EF%BC%8C%E5%B0%86%E9%9D%A2%E4%B8%B4%E9%9D%9E%E5%B8%B8%E5%A4%9A%E7%9A%84%E6%95%B0%E6%8D%AE%E7%AB%9E%E4%BA%89%E9%97%AE%E9%A2%98%EF%BC%8C%E7%AB%9E%E4%BA%89%E5%A4%B1%E8%B4%A5%E6%97%B6%E4%BC%9A%E5%9B%9E%E6%BB%9A%E6%88%96%E9%87%8D%E8%AF%95%EF%BC%8C%E6%AF%94%E8%BE%83%E8%B4%B9%E6%97%B6%E3%80%82%0A%3E%202.%20%E5%B9%B6%E5%8F%91%E5%86%B2%E7%AA%81%E9%AB%98%E7%9A%84%E5%9C%BA%E6%99%AF%EF%BC%9A%E5%B9%B6%E5%8F%91%E5%86%B2%E7%AA%81%E9%AB%98%E7%9A%84%E5%9C%BA%E6%99%AF%E4%BD%BF%E7%94%A8%E6%82%B2%E8%A7%82%E9%94%81%E5%8F%AF%E4%BB%A5%E9%81%BF%E5%85%8D%E5%9B%9E%E6%BB%9A%E5%92%8C%E9%87%8D%E8%AF%95%EF%BC%8C%E6%8F%90%E4%BA%A4%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%95%B4%E4%BD%93%E6%95%88%E7%8E%87%E3%80%82%0A%3E%203.%20%E4%B8%9A%E5%8A%A1%E9%9C%80%E8%A6%81%E5%BC%BA%E4%B8%80%E8%87%B4%E6%80%A7%E7%9A%84%E5%9C%BA%E6%99%AF%EF%BC%9A%E5%9C%A8%E4%B8%80%E4%BA%9B%E9%9C%80%E8%A6%81%E4%BF%9D%E8%AF%81%E6%95%B0%E6%8D%AE%E6%97%A8%E4%B8%80%E8%87%B4%E6%80%A7%E7%9A%84%E4%B8%9A%E5%8A%A1%E5%9C%BA%E6%99%AF%E4%B8%8B%EF%BC%8C%E4%BE%8B%E5%A6%82%E9%93%B6%E8%A1%8C%E8%BD%AC%E5%B8%90%E7%AD%89%E9%87%91%E8%9E%8D%E4%B8%9A%E5%8A%A1%EF%BC%8C%E9%80%9A%E5%B8%B8%E4%BC%9A%E9%80%89%E6%8B%A9%E4%BD%BF%E7%94%A8%E6%82%B2%E8%A7%82%E9%94%81%EF%BC%8C%E4%BB%A5%E7%A1%AE%E4%BF%9D%E5%9C%A8%E4%BB%BB%E5%8A%A1%E6%83%85%E5%86%B5%E4%B8%8B%E6%95%B0%E6%8D%AE%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%E5%92%8C%E5%87%86%E7%A1%AE%E6%80%A7%E3%80%82%0A%0A%0A%0A-%20%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E6%82%B2%E8%A7%82%E9%94%81%0A%0A%3E%201.%20%60select...%20for%20update%60%3A%20%E8%BF%99%E4%B8%AA%E8%AF%AD%E5%8F%A5%E4%BC%9A%E5%9C%A8%E6%89%80%E9%80%89%E6%8B%A9%E7%9A%84%E8%A1%8C%E4%B8%8A%E8%AE%BE%E7%BD%AE%E6%8E%92%E4%BB%96%E9%94%81%EF%BC%88Exclusive%20Lock%EF%BC%89%2C%20%E5%9C%A8%E9%94%81%E5%AE%9A%E6%9C%9F%E9%97%B4%EF%BC%8C%E5%85%B6%E4%BB%96%E4%BA%8B%E5%8A%A1%E6%97%A0%E6%B3%95%E4%BF%AE%E6%94%B9%E8%BF%99%E4%BA%9B%E8%A1%8C%EF%BC%8C%E4%B9%9F%E6%97%A0%E6%B3%95%E5%9C%A8%E8%BF%99%E4%BA%9B%E8%A1%8C%E4%B8%8A%E8%AE%BE%E7%BD%AE%E6%96%B0%E7%9A%84%E6%8E%92%E4%BB%96%E9%94%81%E6%88%96%E5%85%B1%E4%BA%AB%E9%94%81%E3%80%82%0A%3E%202.%20%60select...%20lock%20in%20share%20mode%60%3A%20%E8%BF%99%E4%B8%AA%E8%AF%AD%E5%8F%A5%E4%BC%9A%E5%9C%A8%E6%89%80%E9%80%89%E6%8B%A9%E7%9A%84%E8%A1%8C%E4%B8%8A%E8%AE%BE%E7%BD%AE%E5%85%B1%E4%BA%AB%E9%94%81%EF%BC%88Shared%20Lock%EF%BC%89%2C%E5%9C%A8%E9%94%81%E5%AE%9A%E6%9C%9F%E9%97%B4%EF%BC%8C%E5%85%B6%E4%BB%96%E4%BA%8B%E5%8A%A1%E5%8F%AF%E4%BB%A5%E8%AF%BB%E5%8F%96%E8%BF%99%E4%BA%9B%E8%A1%8C%EF%BC%8C%E4%BD%86%E4%B8%8D%E8%83%BD%E4%BF%AE%E6%94%B9%E8%BF%99%E4%BA%9B%E8%A1%8C%EF%BC%8C%E4%B9%9F%E4%B8%8D%E8%83%BD%E8%AE%BE%E7%BD%AE%E5%85%B6%E5%AE%83%E6%8E%92%E4%BB%96%E9%94%81%E3%80%82%0A%0A%60%60%60mysql%0Astart%20transaction%3B%20--%20%E5%BC%80%E5%90%AF%E4%BA%8B%E5%8A%A1%0Aselect%20*%20from%20employee%20where%20id%3D1%20for%20update%3B%20--%20%E7%BB%99%E8%BF%99%E6%9D%A1%E6%95%B0%E6%8D%AE%E5%8A%A0%E6%82%B2%E8%A7%82%E9%94%81%0Aupdate%20employee%20set%20name%3D'Rebecca'%20where%20id%3D1%3B%20--%20%E5%9C%A8%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E4%B8%AD%E6%89%A7%E8%A1%8C%E8%BF%99%E6%9D%A1%E8%AF%AD%E5%8F%A5%E4%BC%9A%E9%98%BB%E5%A1%9E%EF%BC%8C%E5%9C%A8%E6%9C%AC%E4%BA%8B%E5%8A%A1%E4%B8%AD%E4%B8%8D%E4%BC%9A%E9%98%BB%E5%A1%9E%E3%80%82%0Acommit%3B%0A%60%60%60%0A%0A%60%60%60mysql%0Astart%20transaction%3B%20--%20%E5%BC%80%E5%90%AF%E4%BA%8B%E5%8A%A1%0Aselect%20*%20from%20employee%20where%20id%3D1%20lock%20in%20share%20mode%3B%20--%20%E7%BB%99%E8%BF%99%E6%9D%A1%E6%95%B0%E6%8D%AE%E5%8A%A0%E5%85%B1%E4%BA%AB%E9%94%81%0Aupdate%20employee%20set%20name%3D'Josh'%20where%20id%3D1%3B%20--%20%E5%9C%A8%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E4%B8%AD%E6%89%A7%E8%A1%8C%E8%BF%99%E6%9D%A1%E8%AF%AD%E5%8F%A5%E4%BC%9A%E9%98%BB%E5%A1%9E%EF%BC%8C%E5%9C%A8%E6%9C%AC%E4%BA%8B%E5%8A%A1%E4%B8%AD%E4%B8%8D%E4%BC%9A%E9%98%BB%E5%A1%9E%E3%80%82%0Acommit%3B%0A%60%60%60%0A%0A%0A%0A%E6%82%B2%E8%A7%82%E9%94%81%E7%9A%84%E7%BC%BA%E7%82%B9%0A%0A%3E%201.%20%E6%80%A7%E8%83%BD%E5%BC%80%E9%94%80%EF%BC%9A%E6%82%B2%E8%A7%82%E9%94%81%E6%9C%BA%E5%88%B6%E4%B8%8B%EF%BC%8C%E9%94%81%E5%AE%9A%E8%B5%84%E6%BA%90%E7%9A%84%E6%93%8D%E4%BD%9C%E4%BC%9A%E5%BD%B1%E5%93%8D%E5%88%B0%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%80%A7%E8%83%BD%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%AF%8F%E6%AC%A1%E5%AF%B9%E6%95%B0%E6%8D%AE%E7%9A%84%E8%AF%BB%E5%86%99%E6%93%8D%E4%BD%9C%E9%83%BD%E9%9C%80%E8%A6%81%E8%BF%9B%E8%A1%8C%E5%8A%A0%E9%94%81%E5%92%8C%E8%A7%A3%E9%94%81%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%BF%99%E4%BC%9A%E5%A2%9E%E5%8A%A0%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%BC%80%E9%94%80%EF%BC%8C%E7%89%B9%E5%88%AB%E6%98%AF%E5%9C%A8%E9%AB%98%E5%B9%B6%E5%8F%91%E7%9A%84%E7%8E%AF%E5%A2%83%E4%B8%8B%EF%BC%8C%E9%94%81%E7%9A%84%E7%AB%9E%E4%BA%89%E4%BC%9A%E4%B8%A5%E9%87%8D%E5%BD%B1%E5%93%8D%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%80%A7%E8%83%BD%E3%80%82%0A%3E%0A%3E%202.%20%E5%B9%B6%E5%8F%91%E5%BA%A6%E9%99%8D%E4%BD%8E%EF%BC%9A%E7%94%B1%E4%BA%8E%E6%82%B2%E8%A7%82%E9%94%81%E6%93%8D%E4%BD%9C%E6%95%B0%E6%8D%AE%E5%89%8D%E5%B0%B1%E4%BC%9A%E5%8A%A0%E9%94%81%EF%BC%8C%E8%BF%99%E5%B0%B1%E5%AF%BC%E8%87%B4%E5%9C%A8%E5%90%8C%E4%B8%80%E6%97%B6%E9%97%B4%EF%BC%8C%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E8%83%BD%E6%93%8D%E4%BD%9C%E6%95%B0%E6%8D%AE%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E5%8F%AA%E8%83%BD%E7%AD%89%E5%BE%85%EF%BC%8C%E5%A4%A7%E5%A4%A7%E9%99%8D%E4%BD%8E%E4%BA%86%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%B9%B6%E5%8F%91%E5%BA%A6%E3%80%82%0A%3E%0A%3E%203.%20%E6%AD%BB%E9%94%81%EF%BC%9A%E6%82%B2%E8%A7%82%E9%94%81%E5%9C%A8%E5%B9%B6%E5%8F%91%E4%BA%8B%E5%8A%A1%E4%B8%AD%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E6%AD%BB%E9%94%81%E7%9A%84%E6%83%85%E5%86%B5%E5%8F%91%E7%94%9F%E3%80%82%E5%BD%93%E4%B8%A4%E4%B8%AA%E6%88%96%E8%80%85%E6%9B%B4%E5%A4%9A%E7%9A%84%E4%BA%8B%E5%8A%A1%E4%BA%92%E7%9B%B8%E7%AD%89%E5%BE%85%E5%AF%B9%E6%96%B9%E9%87%8A%E6%94%BE%E9%94%81%E6%97%B6%EF%BC%8C%E5%B0%B1%E5%8F%AF%E8%83%BD%E5%8F%91%E7%94%9F%E6%AD%BB%E9%94%81%E3%80%82%E8%99%BD%E7%84%B6%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B3%BB%E7%BB%9F%E9%80%9A%E5%B8%B8%E8%83%BD%E5%A4%9F%E6%A3%80%E6%B5%8B%E5%B9%B6%E8%A7%A3%E5%86%B3%E6%AD%BB%E9%94%81%EF%BC%8C%E4%BD%86%E8%BF%99%E4%BC%9A%E5%AF%BC%E8%87%B4%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E5%A2%9E%E5%8A%A0%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%BC%80%E9%94%80%E3%80%82%0A%3E%0A%3E%204.%20%E9%94%81%E8%B6%85%E6%97%B6%EF%BC%9A%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1%E9%95%BF%E6%97%B6%E9%97%B4%E6%8C%81%E6%9C%89%E9%94%81%E8%80%8C%E4%B8%8D%E9%87%8A%E6%94%BE%EF%BC%8C%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E5%85%B6%E4%BB%96%E7%AD%89%E5%BE%85%E9%94%81%E7%9A%84%E4%BA%8B%E5%8A%A1%E8%B6%85%E6%97%B6%EF%BC%8C%E8%BF%99%E4%B8%8D%E4%BB%85%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E7%AD%89%E5%BE%85%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%A4%B1%E8%B4%A5%EF%BC%8C%E8%BF%98%E5%8F%AF%E8%83%BD%E5%BD%B1%E5%93%8D%E6%95%B4%E4%B8%AA%E7%B3%BB%E7%BB%9F%E7%9A%84%E7%A8%B3%E5%AE%9A%E6%80%A7%E3%80%82%0A%3E%0A%3E%20%20%20%20%0A%3E%0A%3E%20%E5%9B%A0%E6%AD%A4%EF%BC%8C%E8%99%BD%E7%84%B6%E6%82%B2%E8%A7%82%E9%94%81%E8%83%BD%E6%9C%89%E6%95%88%E7%9A%84%E9%98%B2%E6%AD%A2%E6%95%B0%E6%8D%AE%E5%86%B2%E7%AA%81%EF%BC%8C%E4%BD%86%E7%94%B1%E4%BA%8E%E5%85%B6%E5%9C%A8%E5%B9%B6%E5%8F%91%E7%8E%AF%E5%A2%83%E4%B8%AD%E7%9A%84%E9%99%90%E5%88%B6%EF%BC%8C%E4%BB%A5%E5%8F%8A%E5%8F%AF%E8%83%BD%E5%BC%95%E5%8F%91%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E5%A6%82%E6%AD%BB%E9%94%81%EF%BC%8C%E9%94%81%E7%AB%9E%E4%BA%89%E5%92%8C%E9%94%81%E8%B6%85%E6%97%B6%EF%BC%8C%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E6%A0%B9%E6%8D%AE%E5%85%B7%E4%BD%93%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E5%92%8C%E9%9C%80%E9%9C%80%E6%B1%82%E6%9D%A5%E6%9D%83%E8%A1%A1%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E6%82%B2%E8%A7%82%E9%94%81%E3%80%82%0A%0A%0A%0A%0A%0A%23%23%23%23%20%E6%84%8F%E5%90%91%E9%94%81%0A%0A%3E%20%E6%84%8F%E5%90%91%E9%94%81%E5%88%86%E4%B8%BA%EF%BC%9A%E6%84%8F%E5%90%91%E5%85%B1%E4%BA%AB%E9%94%81%E5%92%8C%E6%84%8F%E5%90%91%E6%8E%92%E5%AE%83%E9%94%81%0A%3E%0A%3E%20%E6%84%8F%E5%90%91%E9%94%81%E6%98%AF%E8%A1%A8%E9%94%81%EF%BC%8C%E4%B8%BA%E4%BA%86%E5%8D%8F%E8%B0%83%E8%A1%8C%E9%94%81%E5%92%8C%E8%A1%A8%E9%94%81%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%94%AF%E6%8C%81%E5%A4%9A%E7%B2%92%E5%BA%A6%EF%BC%88%E8%A1%A8%E9%94%81%E4%B8%8E%E8%A1%8C%E9%94%81%EF%BC%89%E7%9A%84%E9%94%81%E5%B9%B6%E5%AD%98%E3%80%82%0A%0A%0A%0A-%20%E4%BD%9C%E7%94%A8%0A%0A%3E%20%E5%BD%93%E4%BA%8B%E5%8A%A1A%E6%9C%89%E8%A1%8C%E9%94%81%E6%97%B6%EF%BC%8CMysql%E4%BC%9A%E8%87%AA%E5%8A%A8%E4%B8%BA%E6%95%B4%E4%B8%AA%E8%A1%A8%E6%B7%BB%E5%8A%A0%E6%84%8F%E5%90%91%E9%94%81%EF%BC%8C%E4%BA%8B%E5%8A%A1B%E5%A6%82%E6%9E%9C%E6%83%B3%E7%94%B3%E8%AF%B7%E6%95%B4%E4%B8%AA%E8%A1%A8%E7%9A%84%E5%86%99%E9%94%81%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E9%81%8D%E5%8E%86%E6%AF%8F%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E8%A1%8C%E9%94%81%EF%BC%8C%E8%80%8C%E7%9B%B4%E6%8E%A5%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E6%84%8F%E5%90%91%E9%94%81%E3%80%82%0A%0A%0A%0A-%20%E4%B8%BA%E4%BB%80%E4%B9%88%E6%84%8F%E5%90%91%E9%94%81%E6%98%AF%E8%A1%A8%E7%BA%A7%E9%94%81%0A%0A%3E%20%E5%BD%93%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%E5%8A%A0%E4%B8%80%E4%B8%AA%E6%8E%92%E4%BB%96%E9%94%81%E6%97%B6%EF%BC%8C%E9%9C%80%E8%A6%81%E6%A0%B9%E6%8D%AE%E6%84%8F%E5%90%91%E9%94%81%E5%8E%BB%E5%88%A4%E6%96%AD%E8%A1%A8%E4%B8%AD%E6%9C%89%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%E8%A1%8C%E8%A2%AB%E9%94%81%E5%AE%9A%EF%BC%88%E8%A1%8C%E9%94%81%EF%BC%89%0A%3E%0A%3E%201.%20%E5%A6%82%E6%9E%9C%E6%84%8F%E5%90%91%E9%94%81%E4%B8%BA%E8%A1%8C%E9%94%81%EF%BC%8C%E5%88%99%E9%9C%80%E8%A6%81%E9%81%8D%E5%8E%86%E6%AF%8F%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%E5%8E%BB%E7%A1%AE%E8%AE%A4%E3%80%82%0A%3E%202.%20%E5%A6%82%E6%9E%9C%E6%84%8F%E5%90%91%E9%94%81%E4%B8%BA%E8%A1%A8%E9%94%81%EF%BC%8C%E5%88%99%E9%9C%80%E8%A6%81%E5%88%A4%E6%96%AD%E4%B8%80%E6%AC%A1%E5%8D%B3%E5%8F%AF%E7%9F%A5%E9%81%93%E8%A1%A8%E4%B8%AD%E6%9C%89%E6%B2%A1%E6%9C%89%E6%95%B0%E6%8D%AE%E8%A2%AB%E9%94%81%E5%AE%9A%EF%BC%8C%E6%8F%90%E5%8D%87%E5%88%A4%E6%96%AD%E6%95%88%E7%8E%87%E5%92%8C%E7%B3%BB%E7%BB%9F%E6%80%A7%E8%83%BD%E3%80%82%0A%0A%0A%0A-%20%E6%84%8F%E5%90%91%E9%94%81%E6%80%8E%E4%B9%88%E6%94%AF%E6%8C%81%E8%A1%A8%E9%94%81%E5%92%8C%E8%A1%8C%E9%94%81%E5%B9%B6%E5%9C%A8%E7%9A%84%0A%0A%3E%201.%20%E9%A6%96%E5%85%88%E6%95%B0%E6%8D%AE%E5%BA%93%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E6%94%AF%E6%8C%81%E8%A1%A8%E9%94%81%E5%92%8C%E8%A1%8C%E9%94%81%E5%B9%B6%E5%AD%98%E7%9A%84%EF%BC%8C%E4%BD%86%E5%B9%B6%E4%B8%8D%E6%98%AF%E4%BB%BB%E4%BD%95%E6%83%85%E5%86%B5%E4%B8%8B%E9%83%BD%E6%94%AF%E6%8C%81%E4%B8%80%E4%B8%AA%E8%A1%A8%E4%B8%AD%E5%90%8C%E6%97%B6%E6%9C%89%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1A%E6%8C%81%E6%9C%89%E8%A1%8C%E9%94%81%EF%BC%8C%E5%8F%88%E6%9C%89%E4%B8%80%E4%B8%AA%E4%BA%8B%E5%8A%A1B%E6%8C%81%E6%9C%89%E8%A1%A8%E9%94%81%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%B8%80%E6%97%A6%E8%A2%AB%E4%B8%8A%E4%BA%86%E4%B8%80%E4%B8%AA%E8%A1%A8%E7%BA%A7%E5%86%99%E9%94%81%EF%BC%8C%E8%82%AF%E5%AE%9A%E4%B8%8D%E8%83%BD%E5%86%8D%E4%B8%8A%E4%B8%80%E4%B8%AA%E8%A1%8C%E7%BA%A7%E7%9A%84%E9%94%81%E3%80%82%0A%3E%202.%20%E5%A6%82%E6%9E%9C%E4%BA%8B%E5%8A%A1A%E5%AF%B9%E6%9F%90%E4%B8%80%E8%A1%8C%E4%B8%8A%E9%94%81%EF%BC%8C%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E5%B0%B1%E4%B8%8D%E5%8F%AF%E8%83%BD%E4%BF%AE%E6%94%B9%E8%BF%99%E4%B8%80%E8%A1%8C%EF%BC%8C%E4%BA%8B%E5%8A%A1B%E6%B7%BB%E5%8A%A0%E8%A1%A8%E9%94%81%E5%B0%B1%E4%BC%9A%E5%86%B2%E7%AA%81%E3%80%82%E6%89%80%E4%BB%A5%E6%B2%A1%E6%9C%89%E6%84%8F%E5%90%91%E9%94%81%E6%97%B6%EF%BC%8C%E8%AE%A9%E8%A1%8C%E9%94%81%E5%92%8C%E8%A1%A8%E9%94%81%E5%B9%B6%E5%AD%98%E5%B0%B1%E4%BC%9A%E5%B8%A6%E6%9D%A5%E5%BE%88%E5%A4%9A%E5%A4%9A%E9%97%AE%E9%A2%98%EF%BC%8C%E4%BA%8E%E6%98%AF%E5%B0%B1%E6%9C%89%E4%BA%86%E6%84%8F%E5%90%91%E9%94%81%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8D%E9%9C%80%E8%A6%81%E9%81%8D%E5%8E%86%E6%AF%8F%E4%B8%80%E8%A1%8C%E6%95%B0%E6%8D%AE%E6%98%AF%E5%90%A6%E6%9C%89%E9%94%81%EF%BC%8C%E7%9B%B4%E6%8E%A5%E5%88%A4%E6%96%AD%E4%B8%80%E6%AC%A1%E6%84%8F%E5%90%91%E9%94%81%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E5%8D%B3%E5%8F%AF%E3%80%82%0A%0A%0A%0A-%20%E6%84%8F%E5%90%91%E9%94%81%E7%9A%84%E5%85%BC%E5%AE%B9%E4%BA%92%E6%96%A5%E6%80%A7%0A%0A%7C%20%20%20%20%20%20%20%20%20%20%20%7C%20%E6%84%8F%E5%90%91%E5%85%B1%E4%BA%AB%E9%94%81(IS)%20%7C%20%E6%84%8F%E5%90%91%E6%8E%92%E4%BB%96%E9%94%81(IX)%20%7C%0A%7C%20---------%20%7C%20--------------%20%7C%20--------------%20%7C%0A%7C%20%E5%85%B1%E4%BA%AB%E9%94%81(S)%20%7C%20%E5%85%BC%E5%AE%B9%20%20%20%20%20%20%20%20%20%20%20%7C%20%E4%BA%92%E6%96%A5%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%E6%8E%92%E4%BB%96%E9%94%81(X)%20%7C%20%E4%BA%92%E6%96%A5%20%20%20%20%20%20%20%20%20%20%20%7C%20%E4%BA%92%E6%96%A5%20%20%20%20%20%20%20%20%20%20%20%7C%0A%0A%0A%0A%60%60%60mysql%0Astart%20transaction%3B%0Aselect%20*%20from%20employee%20where%20id%3D1%20for%20update%3B%20--%20%E5%BC%80%E5%90%AF%E4%B8%80%E4%B8%AA%E8%A1%8C%E7%BA%A7%E7%9A%84%E6%8E%92%E4%BB%96%E9%94%81%0A%0Aselect%20*%20from%20performance_schema.data_locks%3B%20--%20%E6%9F%A5%E8%AF%A2%E9%94%81%0ALOCK_TYPE%3A%0A%09TABLE%5B%E8%A1%A8%E9%94%81%5D%EF%BC%8CRECORD%5B%E8%A1%8C%E9%94%81%5D%0ALOCK_MODE%3A%0A%09X%5B%E6%8E%92%E4%BB%96%E9%94%81%5D%EF%BC%8CIX%5B%E6%84%8F%E5%90%91%E6%8E%92%E4%BB%96%E9%94%81%5D%0ALOCK_DATA%3A%20%E9%94%81%E7%9A%84%E8%A1%8C%E6%95%B0%0A%0Alock%20table%20employee%20write%3B%20--%20%E6%AD%A4%E6%97%B6%E5%9C%A8%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E4%B8%AD%E5%AF%B9%E4%BA%8E%E5%8A%A0%E8%A1%A8%E5%86%99%E9%94%81%E6%97%B6%E9%98%BB%E5%A1%9E%EF%BC%8C%E5%8A%A0%E4%B8%8D%E4%BA%86%E8%A1%A8%E5%86%99%E9%94%81%E3%80%82%0A%60%60%60%0A%0A%0A%0A%60%60%60mysql%0Astart%20transaction%3B%0Aselect%20*%20from%20employee%20where%20id%3D1%20lock%20in%20share%20mode%3B%20--%20%E5%BC%80%E5%90%AF%E4%B8%80%E4%B8%AA%E8%A1%8C%E7%BA%A7%E7%9A%84%E6%8E%92%E4%BB%96%E9%94%81%0A%0Aselect%20*%20from%20performance_schema.data_locks%3B%20--%20%E6%9F%A5%E8%AF%A2%E9%94%81%0ALOCK_TYPE%3A%0A%09TABLE%5B%E8%A1%A8%E9%94%81%5D%EF%BC%8CRECORD%5B%E8%A1%8C%E9%94%81%5D%0ALOCK_MODE%3A%0A%09S%5B%E5%85%B1%E4%BA%AB%E9%94%81%5D%EF%BC%8CIS%5B%E6%84%8F%E5%90%91%E5%85%B1%E4%BA%AB%E9%94%81%5D%0ALOCK_DATA%3A%20%E9%94%81%E7%9A%84%E8%A1%8C%E6%95%B0%0A%0Alock%20table%20employee%20read%3B%20--%20%E6%AD%A4%E6%97%B6%E5%9C%A8%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E4%B8%AD%E5%AF%B9%E4%BA%8E%E5%8A%A0%E8%A1%A8%E8%AF%BB%E9%94%81%E6%97%B6%E5%8F%AF%E4%BB%A5%E6%88%90%E5%8A%9F%E5%B9%B6%E4%B8%8D%E4%BC%9A%E9%98%BB%E5%A1%9E%E3%80%82%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E4%B8%B4%E9%94%AE%E9%94%81%0A%0A%3E%20%E4%B8%B4%E9%94%AE%E9%94%81%EF%BC%9Anext-key%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BA%E4%B8%80%E7%A7%8D%E7%89%B9%E6%AE%8A%E7%9A%84%E9%97%B4%E9%9A%99%E9%94%81%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BA%E4%B8%80%E7%A7%8D%E7%89%B9%E6%AE%8A%E7%9A%84%E7%AE%97%E6%B3%95%E3%80%82%E9%80%9A%E4%B8%B4%E9%94%AE%E9%94%81%E5%8F%AF%E4%BB%A5%E8%A7%A3%E5%86%B3%E5%B9%BB%E8%AF%BB%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%E6%AF%8F%E4%B8%AA%E6%95%B0%E6%8D%AE%E8%A1%8C%E4%B8%8A%E7%9A%84%E9%9D%9E%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%E5%88%97%E4%B8%8A%E9%83%BD%E4%BC%9A%E5%AD%98%E5%9C%A8%E4%B8%80%E6%8A%8A%E4%B8%B4%E9%94%AE%E9%94%81%EF%BC%8C%E5%BD%93%E8%8F%B6%E4%BA%8B%E5%8A%A1%E6%8C%81%E6%9C%89%E8%AF%A5%E6%95%B0%E6%8D%AE%E8%A1%8C%E7%9A%84%E4%B8%B4%E9%94%AE%E9%94%81%E6%97%B6%EF%BC%8C%E4%BC%9A%E9%94%81%E4%BD%8F%E4%B8%80%E6%AE%B5%60%E5%B7%A6%E5%BC%80%E5%8F%B3%E9%97%AD%E5%8C%BA%E9%97%B4%60%E7%9A%84%E6%95%B0%E6%8D%AE%E3%80%82%0A%3E%0A%3E%20%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%EF%BC%8CInnoDB%E4%B8%AD%E8%A1%8C%E7%BA%A7%E9%94%81%E6%98%AF%E5%9F%BA%E4%BA%8E%E7%B4%A2%E5%BC%95%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8C%E4%B8%B4%E9%94%AE%E9%94%81%E5%8F%AA%E4%B8%8E%E5%94%AF%E4%B8%80%E9%9D%9E%E7%B4%A2%E5%BC%95%E5%88%97%E6%9C%89%E5%85%B3%EF%BC%8C%E5%9C%A8%E5%94%AF%E4%B8%80%E7%B4%A2%E5%BC%95%E5%88%97%EF%BC%88%E5%8C%85%E6%8B%AC%E4%B8%BB%E9%94%AE%E5%88%97%EF%BC%89%E4%B8%8A%E4%B8%8D%E5%AD%98%E5%9C%A8%E4%B8%B4%E9%94%AE%E9%94%81%E3%80%82%0A%0A%7C%20id%20%20%20%7C%20age%20%20%7C%20name%20%7C%0A%7C%20----%20%7C%20----%20%7C%20----%20%7C%0A%7C%201%20%20%20%20%7C%2010%20%20%20%7C%20%E5%BC%A0%E4%B8%89%20%7C%0A%7C%203%20%20%20%20%7C%2024%20%20%20%7C%20%E6%9D%8E%E5%9B%9B%20%7C%0A%7C%205%20%20%20%20%7C%2032%20%20%20%7C%20%E7%8E%8B%E4%BA%94%20%7C%0A%7C%207%20%20%20%20%7C%2045%20%20%20%7C%20%E8%B5%B5%E5%85%AD%20%7C%0A%0A%E8%AF%A5%E8%A1%A8%E4%B8%AD%60age%60%E5%88%97%E6%BD%9C%E5%9C%A8%E7%9A%84%60%E4%B8%B4%E9%94%AE%E9%94%81%60%E6%9C%89%EF%BC%9A%0A%0A%60%60%60%0A(-%E2%88%9E%EF%BC%8C%2010%5D%0A(10%2C24%5D%0A(24%2C32%5D%0A(32%2C45%5D%0A(45%2C%2B%E2%88%9E%5D%0A%60%60%60%0A%0A%0A%0A%60%60%60mysql%0Astart%20transaction%3B%0Aselect%20*%20from%20user%20where%20age%3D24%20for%20update%3B%20--%20%E6%8A%8Aage%3D24%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8A%A0%E6%8E%92%E4%BB%96%E9%94%81%EF%BC%8C%E6%AD%A4%E6%97%B6%E5%9C%A8%E5%8F%A6%E4%B8%80%E4%B8%AA%E7%AA%97%E5%8F%A3%E4%B8%AD%E6%89%A7%E8%A1%8C%E4%B8%8B%E9%9D%A2%E7%9A%84insert%E8%AF%B7%E9%97%AE%0Acommit%3B%20--%20%E5%8F%AA%E6%9C%89%E5%BD%93%E8%BF%99%E4%B8%AA%E4%BA%8B%E5%8A%A1%E7%BB%93%E6%9D%9F%E5%90%8E%E6%89%8D%E4%BC%9A%E9%87%8A%E6%94%BE(24%2C32%5D%E4%B8%B4%E9%94%AE%E9%94%81%0A%60%60%60%0A%0A%0A%0A%60%60%60mysql%0Ainsert%20into%20user%20values(100%2C%2026%2C%20'Chris')%3B%20--%20%E6%AD%A4%E6%97%B6%E6%89%A7%E8%A1%8C%E8%BF%99%E4%B8%AAinsert%E8%AF%AD%E5%8F%A5%E6%97%B6%E4%BC%9A%E8%A2%AB%E9%98%BB%E5%A1%9E%E3%80%82%0A%60%60%60%0A%0A%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9C%A8age%3D24%E4%B8%8A%E5%8A%A0%E9%94%81%E4%BC%9A%E6%8A%8Aage%3D26%E7%9A%84%E6%95%B0%E6%8D%AE%E4%B9%9F%E9%94%81%E4%BD%8F%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%9C%A8(24%2C32%5D%E4%B9%8B%E9%97%B4%E5%B0%B1%E5%AD%98%E5%9C%A8%E4%B8%80%E6%8A%8A%E4%B8%B4%E9%94%AE%E9%94%81%EF%BC%8C%E6%89%80%E4%BB%A5%E5%9C%A8%E5%86%99%E5%85%A5age%3D26%E6%97%B6%E4%BC%9A%E8%A2%AB%E9%98%BB%E5%A1%9E%EF%BC%8C%0A%0A%0A%0A%23%23%23%20%E4%BA%8B%E5%8A%A1ACID%E7%89%B9%E6%80%A7%0A%0A%23%23%23%23%20%E5%8E%9F%E5%AD%90%E6%80%A7%E3%80%90Atomicity%E3%80%91%0A%0A%3E%20%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E4%B8%AD%E7%9A%84%E6%93%8D%E4%BD%9C%E8%A6%81%E4%B9%88%E5%90%8C%E6%97%B6%E6%88%90%E5%8A%9F%EF%BC%8C%E8%A6%81%E4%B9%88%E5%90%8C%E6%97%B6%E5%A4%B1%E8%B4%A5%E3%80%82%E5%8E%9F%E5%AD%90%E6%80%A7%E7%94%B1undo%20log%E6%97%A5%E5%BF%97%E6%9D%A5%E4%BF%9D%E8%AF%81%E3%80%82%0A%0A%23%23%23%23%20%E4%B8%80%E8%87%B4%E6%80%A7%E3%80%90Consistency%E3%80%91%0A%0A%3E%20%E4%BD%BF%E7%94%A8%E4%BA%8B%E5%8A%A1%E7%9A%84%E6%9C%80%E7%BB%88%E7%9B%AE%E7%9A%84%E5%B0%B1%E6%98%AF%E4%B8%BA%E4%BA%86%E4%BF%9D%E8%AF%81%E6%95%B0%E6%8D%AE%E7%9A%84%E4%B8%80%E8%87%B4%E6%80%A7%EF%BC%8C%E4%B8%80%E8%87%B4%E6%80%A7%E4%BE%9D%E8%B5%96%E5%8E%9F%E5%AD%90%E6%80%A7%EF%BC%8C%E9%9A%94%E7%A6%BB%E6%80%A7%EF%BC%8C%E6%8C%81%E4%B9%85%E6%80%A7%E5%8F%8A%E4%B8%9A%E5%8A%A1%E4%BB%A3%E7%A0%81%E7%9A%84%E5%87%86%E7%A1%AE%E6%80%A7%E3%80%82%0A%0A%23%23%23%23%20%E9%9A%94%E7%A6%BB%E6%80%A7%E3%80%90Isolation%E3%80%91%0A%0A%3E%20%E5%BD%93%E5%A4%9A%E4%BA%8B%E5%8A%A1%E5%B9%B6%E5%8F%91%E6%89%A7%E8%A1%8C%E6%93%8D%E4%BD%9C%E7%9B%B8%E5%90%8C%E6%95%B0%E6%8D%AE%E6%97%B6%EF%BC%8C%E4%BB%96%E4%BB%AC%E5%86%85%E9%83%A8%E7%9A%84%E6%93%8D%E4%BD%9C%E4%B8%8D%E8%83%BD%E7%9B%B8%E4%BA%92%E5%B9%B2%E6%89%B0%E3%80%82%0A%3E%0A%3E%20InnoDB%E4%B8%AD%E5%AE%9A%E4%B9%89%E4%BA%86%E5%9B%9B%E7%A7%8D%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%EF%BC%8C%E7%BA%A7%E5%88%AB%E8%B6%8A%E9%AB%98%E9%9A%94%E7%A6%BB%E6%80%A7%E8%B6%8A%E5%A5%BD%EF%BC%8C%E4%BD%86%E6%80%A7%E8%83%BD%E8%B6%8A%E4%BD%8E%E3%80%82%E8%80%8C%E9%9A%94%E7%A6%BB%E6%80%A7%E6%98%AF%E7%94%B1Mysql%E4%B8%AD%E7%9A%84%E5%90%84%E7%A7%8D%E9%94%81%E5%8F%8A%60MVCC%60%E6%9C%BA%E5%88%B6%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9A%84%0A%3E%0A%3E%201.%20%60read-uncommitted%60%E3%80%90%E8%AF%BB%E6%9C%AA%E6%8F%90%E4%BA%A4%E3%80%91%3A%20%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E8%AF%BB%E5%8F%96%E5%88%B0%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E5%B0%9A%E6%9C%AA%E6%8F%90%E4%BA%A4%E7%9A%84%E6%95%B0%E6%8D%AE%2C%20%E5%8D%B3%E4%BC%9A%E5%87%BA%E7%8E%B0%60%E3%80%90%E8%84%8F%E8%AF%BB%E3%80%91%60%0A%3E%202.%20%60read-committed%60%E3%80%90%E8%AF%BB%E5%B7%B2%E6%8F%90%E4%BA%A4%E3%80%91%3A%20%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E5%A4%9A%E6%AC%A1%E6%9F%A5%E8%AF%A2%E5%90%8C%E4%B8%80%E6%9D%A1%E6%95%B0%E6%8D%AE%E6%97%B6%E4%BC%9A%E5%87%BA%E7%8E%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%8E%9F%E5%9B%A0%E6%98%AF%E8%BF%99%E7%A7%8D%E6%95%B0%E6%8D%AE%E5%9C%A8%E8%A2%AB%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E4%B8%8D%E5%81%9C%E4%BF%AE%E6%94%B9%E6%8F%90%E4%BA%A4%EF%BC%8C%E5%8D%B3%E5%AF%B9%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E8%80%8C%E8%A8%80%E4%BC%9A%E5%87%BA%E7%8E%B0%60%E3%80%90%E4%B8%8D%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%E3%80%91%60%0A%3E%203.%20%60repeatable-read%60%E3%80%90%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%E3%80%91%3A%20%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E5%A7%8B%E7%BB%88%E8%AF%BB%E5%8F%96%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%9F%A5%E8%AF%A2%E6%97%B6%E6%95%B0%E6%8D%AE%E8%A1%A8%E9%87%8C%E9%9D%A2%E7%9A%84%E5%80%BC%EF%BC%8C%E4%B8%8D%E5%8F%97%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E6%93%8D%E4%BD%9C%E7%9A%84%E5%BD%B1%E5%93%8D%EF%BC%8C%E4%BD%86%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E4%B8%AD%E6%9C%89%E6%9B%B4%E6%96%B0%E6%93%8D%E4%BD%9C%E5%88%99%E4%BC%9A%E6%8A%8A%E5%85%B6%E5%AE%83%E4%BA%8B%E5%8A%A1%E6%9B%B4%E6%96%B0%E7%9A%84%E5%80%BC%E8%A6%86%E7%9B%96%E6%8E%89%EF%BC%8C%E5%8D%B3%E4%BC%9A%E5%87%BA%E7%8E%B0%60%E3%80%90%E8%84%8F%E5%86%99%E3%80%91%60%0A%3E%204.%20%60serializable%60%20%E3%80%90%E4%B8%B2%E8%A1%8C%E3%80%91%3A%20%E5%9C%A8%E4%B8%8D%E5%90%8C%E4%BA%8B%E5%8A%A1%E4%B8%AD%E5%AF%B9%E5%90%8C%E4%B8%80%E4%BB%BD%E6%95%B0%E6%8D%AE%E8%AF%BB%E5%86%99%E3%80%90%E6%97%A0%E8%AE%BA%E6%98%AF%E5%85%88%E5%86%99%E5%90%8E%E8%AF%BB%EF%BC%8C%E8%BF%98%E6%98%AF%E5%85%88%E8%AF%BB%E5%90%8E%E5%86%99%E3%80%91%E4%B8%8D%E5%85%81%E8%AE%B8%E5%B9%B6%E8%A1%8C%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%8D%B3%E8%AF%BB%E5%8F%96%E8%BF%99%E4%BB%BD%E6%95%B0%E6%8D%AE%E4%BA%8B%E5%8A%A1%E6%9C%AA%E6%8F%90%E4%BA%A4%E6%97%B6%E4%B8%8D%E5%85%81%E8%AE%B8%E5%AF%B9%E8%BF%99%E4%BB%BD%E6%95%B0%E6%8D%AE%E8%BF%9B%E8%A1%8C%E6%9B%B4%E6%96%B0%EF%BC%8C%E5%8F%8D%E4%B9%8B%E4%BA%A6%E7%84%B6%E3%80%82%0A%3E%0A%3E%20%60%E6%B3%A8%E6%84%8F%EF%BC%9A%60%0A%3E%0A%3E%20%E9%BB%98%E8%AE%A4%E6%9F%A5%E8%AF%A2%E6%93%8D%E4%BD%9C%E6%98%AF%E4%B8%8D%E5%8A%A0%E9%94%81%E7%9A%84%EF%BC%8C%E4%BD%86%E6%98%AF%E5%9C%A8%60%E3%80%90%E4%B8%B2%E8%A1%8C%E3%80%91%60%E8%BF%99%E7%A7%8D%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E4%B8%AD%E9%BB%98%E8%AE%A4%E4%BC%9A%E4%B8%BA%E6%9F%A5%E8%AF%A2%E6%93%8D%E4%BD%9C%E6%B7%BB%E5%8A%A0%E4%B8%80%E6%8A%8A%E8%AF%BB%E9%94%81%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%9C%A8%E5%A4%9A%E4%B8%AA%E4%BA%8B%E5%8A%A1%E9%97%B4%E5%8F%AA%E8%83%BD%E8%AF%BB%E5%8F%96%E8%BF%99%E4%BB%BD%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%B8%8D%E8%83%BD%E6%9B%B4%E6%96%B0%E8%BF%99%E4%BB%BD%E6%95%B0%E6%8D%AE%E3%80%82%0A%0A%0A%0A%23%23%23%23%20%E6%8C%81%E4%B9%85%E6%80%A7%E3%80%90Durability%E3%80%91%0A%0A%0A%0A%23%23%23%20RR%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%0A%0A%3E%20MVCC%EF%BC%9A%E5%A4%9A%E7%89%88%E6%9C%AC%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%81%9A%E5%88%B0%E8%AF%BB%E5%86%99%E4%B8%8D%E9%98%BB%E5%A1%9E%E4%B8%94%E9%81%BF%E5%85%8D%E8%84%8F%E8%AF%BB%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%0A%3E%0A%3E%20read%20committed%20%E8%AF%AD%E5%8F%A5%E7%BA%A7%E5%BF%AB%E7%85%A7%0A%3E%0A%3E%20repeatable%20read%20%E4%BA%8B%E5%8A%A1%E7%BA%A7%E5%BF%AB%E7%85%A7%0A%0A!%5B5800a287d6543946e830080d0a5b0688.png%5D(en-resource%3A%2F%2Fdatabase%2F1532%3A0)%0A%0A%0A%0A%0A%23%23%23%20%E8%AE%BE%E7%BD%AE%E4%BA%8B%E5%8A%A1%0A%0A%60%60%60mysql%0ASET%20%5BGLOBAL%20%7C%20SESSION%5D%20TRANSACTION%0A%20%20%20%20transaction_characteristic%20%5B%2C%20transaction_characteristic%5D%20...%0A%20%20%20%20%0Atransaction_characteristic%3A%20%7B%0A%20%20%20%20ISOLATION%20LEVEL%20level%20%7C%20access_mode%0A%7D%20%20%20%20%0A%0Alevel%3A%20%7B%0A%20%20%20%20%20REPEATABLE%20READ%20%7C%20READ%20COMMITTED%20%7C%20READ%20UNCOMMITTED%20%7C%20SERIALIZABLE%0A%7D%0A%0Aaccess_mode%3A%20%7B%0A%20%20%20%20%20READ%20WRITE%20%7C%20READ%20ONLY%0A%7D%0A%60%60%60%0A%0A%0A%0A%3E%20%60transaction_characteristic%60%E6%8C%87%E5%AE%9A%E4%BA%86%E4%BA%8B%E5%8A%A1%E7%9A%84%E7%9B%B8%E5%85%B3%E7%89%B9%E6%80%A7%EF%BC%8C%E5%A4%9A%E4%B8%AA%60transaction_characteristic%60%E7%94%A8%E9%80%97%E5%8F%B7%E9%9A%94%E5%BC%80%E3%80%82%0A%3E%0A%3E%20%60transaction_characteristic%60%E8%AE%BE%E7%BD%AE%E4%BA%86%E4%BA%8B%E5%8A%A1%E7%9A%84%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E5%92%8C%E8%AE%BF%E9%97%AE%E6%96%B9%E5%BC%8F%0A%0A%0A%0A%23%23%23%23%20Transaction%20Isolation%20Levels%0A%0A%3E%20%E4%BD%BF%E7%94%A8%60ISOLATION%20LEVEL%20level%60%E8%AF%AD%E5%8F%A5%E8%AE%BE%E7%BD%AE%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E3%80%82%E5%9C%A8%60SET%20TRANSACTION%60%E4%B8%AD%E4%B8%8D%E5%85%81%E8%AE%B8%E6%8C%87%E5%AE%9A%E5%A4%9A%E4%B8%AA%60ISOLATION%20LEVEL%60%E3%80%82%0A%3E%0A%3E%20%E9%BB%98%E8%AE%A4%E7%9A%84%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E6%98%AF%60REPEATABLE%20READ%60%E3%80%82%E4%B8%80%E5%85%B1%E6%9C%89%E5%9B%9B%E7%A7%8D%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%EF%BC%8C%E8%BF%98%E5%8C%85%E6%8B%AC%60READ%20COMMITTED%60%2C%20%60READ%20UNCOMMITTED%60%2C%20%E5%92%8C%60SERIALIZABLE%60%E3%80%82%0A%0A%0A%0A%23%23%23%23%20Transaction%20Access%20Mode%0A%0A%3E%20%E4%BD%BF%E7%94%A8%60READ%20WRITE%60%E6%88%96%60READ%20ONLY%60%E8%AE%BE%E7%BD%AE%E4%BA%8B%E5%8A%A1%E8%AE%BF%E9%97%AE%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%9C%A8%60SET%20TRANSACTION%60%E4%B8%AD%E4%B8%8D%E5%85%81%E8%AE%B8%E6%8C%87%E5%AE%9A%E5%A4%9A%E4%B8%AA%E8%AE%BF%E9%97%AE%E6%A8%A1%E5%BC%8F%E3%80%82%0A%3E%0A%3E%20%E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E4%BA%8B%E5%8A%A1%E6%97%B6%60READ%20WRITE%60%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%9C%A8%E4%BA%8B%E5%8A%A1%E4%B8%AD%E5%85%81%E8%AE%B8%E5%AF%B9%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E7%9A%84%E8%A1%A8%E8%BF%9B%E8%A1%8C%E8%AF%BB%2F%E5%86%99%E6%93%8D%E4%BD%9C%E3%80%82%0A%3E%0A%3E%20%E5%A6%82%E6%9E%9C%E4%BA%8B%E5%8A%A1%E8%AE%BF%E9%97%AE%E6%A8%A1%E5%BC%8F%E8%A2%AB%E8%AE%BE%E7%BD%AE%E4%B8%BA%60READ%20ONLY%60%EF%BC%8C%E7%A6%81%E6%AD%A2%E5%AF%B9%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E7%9A%84%E8%A1%A8%E8%BF%9B%E8%A1%8C%E4%BF%AE%E6%94%B9%E3%80%82%E5%9C%A8%E8%BF%99%E7%A7%8D%E6%A8%A1%E5%BC%8F%E4%B8%8B%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E%E6%80%A7%E8%83%BD%E6%9C%89%E7%9B%B8%E5%BA%94%E6%8F%90%E9%AB%98%E3%80%82%0A%3E%0A%3E%20%22%E8%AE%BF%E9%97%AE%E6%A8%A1%E5%BC%8F%22%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%BC%80%E5%90%AF%E4%BA%8B%E5%8A%A1(%60start%20transaction%60)%E7%9A%84%E6%97%B6%E5%80%99%E6%8C%87%E5%AE%9A%E3%80%82%0A%0A%0A%0A%23%23%23%23%20Transaction%20Characteristic%20Scope%0A%0A%3E%20%E4%BD%A0%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9D%EF%BC%8C%E8%AE%BE%E7%BD%AE%E4%BA%8B%E5%8A%A1%E7%9A%84%E5%85%A8%E5%B1%80%E5%B1%9E%E6%80%A7%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%8F%AA%E9%92%88%E5%AF%B9%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9D%E3%80%82%0A%3E%0A%3E%201.%20%60GLOBAL%60%E5%85%B3%E9%94%AE%E5%AD%97%0A%3E%0A%3E%20-%20%E4%BD%9C%E7%94%A8%E5%85%A8%E5%B1%80%EF%BC%8C%E5%90%8E%E9%9D%A2%E7%9A%84%E6%89%80%E6%9C%89%E4%BC%9A%E8%AF%9D%E9%83%BD%E4%BC%9A%E5%8F%97%E5%88%B0%E5%BD%B1%E5%93%8D%E3%80%82%0A%3E%20-%20%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9D%E9%80%80%E5%87%BA%EF%BC%8C%E4%BF%AE%E6%94%B9%E4%BB%8D%E7%84%B6%E7%94%9F%E6%95%88%0A%3E%0A%3E%202.%20%60SESSION%60%20%E5%85%B3%E9%94%AE%E5%AD%97%0A%3E%0A%3E%20-%20%E4%BD%9C%E7%94%A8%E4%BA%8E%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9D%EF%BC%8C%E6%8E%A5%E4%B8%8B%E6%9D%A5%E7%9A%84%E6%89%80%E6%9C%89%E4%BA%8B%E5%8A%A1%E3%80%82%0A%3E%20-%20%E4%BA%8B%E5%8A%A1%E4%B8%AD%E5%85%81%E8%AE%B8%E4%BD%BF%E7%94%A8%E8%AF%A5%E8%AF%AD%E5%8F%A5%EF%BC%8C%E4%BD%86%E4%B8%8D%E5%BD%B1%E5%93%8D%E5%BD%93%E5%89%8D%E6%AD%A3%E5%9C%A8%E8%BF%9B%E8%A1%8C%E7%9A%84%E4%BA%8B%E5%8A%A1%E3%80%82%0A%3E%20-%20%E5%A6%82%E6%9E%9C%E5%9C%A8%E4%BA%8B%E5%8A%A1%E4%B9%8B%E9%97%B4%E6%89%A7%E8%A1%8C%E8%AF%A5%E8%AF%AD%E5%8F%A5%EF%BC%8C%E5%B0%86%E4%BC%9A%E8%A6%86%E7%9B%96%E4%B9%8B%E5%89%8D%E7%9A%84%E4%BA%8B%E5%8A%A1%E8%AE%BE%E7%BD%AE%E3%80%82%0A%3E%0A%3E%203.%20%E6%97%A2%E6%B2%A1%E6%9C%89%20%60SESSION%60%E5%85%B3%E9%94%AE%E5%AD%97%E4%B9%9F%E6%B2%A1%E6%9C%89%20%60GLOBAL%60%E5%85%B3%E9%94%AE%E5%AD%97%0A%3E%0A%3E%20-%20%E5%BD%93%E5%89%8D%E8%AF%AD%E5%8F%A5%E5%8F%AA%E4%BD%9C%E7%94%A8%E4%BA%8E%E5%BD%93%E5%89%8D%E4%BC%9A%E8%AF%9D%E7%9A%84%E4%B8%8B**%E4%B8%80%E4%B8%AA**%E4%BA%8B%E5%8A%A1%E3%80%82%0A%3E%20-%20%E5%90%8E%E9%9D%A2%E7%9A%84%E4%BC%9A%E8%AF%9D%EF%BC%88%E7%AC%AC%E4%BA%8C%E4%B8%AA%E4%BC%9A%E8%AF%9D%E5%BC%80%E5%A7%8B%EF%BC%89%E5%B0%86%E4%BC%9A%E4%BD%BF%E7%94%A8%E6%89%A7%E8%A1%8C%E8%AF%AD%E5%8F%A5%E4%B9%8B%E5%89%8D%E7%9A%84%E9%85%8D%E7%BD%AE%E3%80%82%0A%3E%20-%20%E4%BA%8B%E5%8A%A1%E4%B8%AD%E4%B8%8D%E8%83%BD%E6%89%A7%E8%A1%8C%E8%AF%A5%E8%AF%AD%E5%8F%A5%0A%0A%0A%0ASping%E5%AF%B9%E4%BA%8B%E5%8A%A1%E7%9A%84%E6%94%AF%E6%8C%81%0A%0A%3EprepareTransactinConnection%0A%3E%0A%3ESET%20TRANSACTION%20READ%20ONLY%20--%20%E8%AE%BE%E7%BD%AE%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E4%B8%BA%E5%8F%AA%E8%AF%BB%E4%BA%8B%E5%8A%A1%EF%BC%8C%E6%89%A7%E8%A1%8C%E5%A2%9E%E5%88%A0%E6%94%B9%E4%B8%BA%E6%8A%A5%E9%94%99%201920-Cannot%20execute%20statement%20in%20a%20READ%20ONLY%20transaction%0A%3E%0A%3E%E5%8F%AA%E8%AF%BB%E4%BA%8B%E5%8A%A1%E6%98%AF%E7%94%B1%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B1%82%E9%9D%A2%E6%94%AF%E6%8C%81%E7%9A%84%EF%BC%8Cspring%E6%B2%A1%E6%9C%89%E5%8F%82%E4%B8%8E%E5%81%9A%E4%BB%80%E4%B9%88%0A%3E%0A%3E%E5%A6%82%E6%9E%9C%E5%BD%93%E5%89%8D%E4%BA%8B%E5%8A%A1%E4%B8%BA%E5%8F%AA%E8%AF%BB%E4%BA%8B%E5%8A%A1%EF%BC%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%B8%8D%E9%9C%80%E8%A6%81%E4%B8%BA%E5%86%99%E6%93%8D%E4%BD%9C%E6%B6%88%E8%80%97%E6%80%A7%E8%83%BD%EF%BC%8C%E6%AF%94%E5%A6%82undo%20log%EF%BC%8C%20%E5%86%99%E6%93%8D%E4%BD%9C%E6%97%B6%E5%8A%A0%E7%9A%84%E5%86%99%E9%94%81%0A%0A

jvm深度解析

创建时间:2024/4/8 22:06
更新时间:2024/4/8 22:20
作者:Chris

类加载器子系统的作用

  1. Class Loader 只负责class文件加载,至于class文件是否能够运行由Execution Engine决定

  2. 加载的类信息存放于方法区[Method Area]的内存空间,除类信息外,方法区还会存放运行时常量池 [反编译文件中的 Constant Pool] 信息

javap -v classFileName

加载 Loading

  • 通过一个类的全限定名获取此类的二进制字节流
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  • 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区的这个类的各种数据访问入口

链接 Linking

verify

  • 确保Class文件的字节流所包含的信息符合当前虚拟机的要求,保证被加载类的正确性,不会危害虚拟机自身的安全。

prepare

  • 为类变量[static修饰的变量]分配内存,并且设置该变量的默认初始值,即0值。变量的类型不一样,准备阶段设置的默认值也不一样,整形为0
private static int a = 1; // 在准备阶段 a=0 , 在初始化阶段才将 a赋值为1
  • final修饰的static变更实际是一个常量, 在编译时就会分配初始值,并在准备阶段显示赋值。
private final static int a = 5; // 在编译时分配初始值 a=0 , 在准备阶段将a赋值为5
  • 不会为实例变量分配初始化,类变量会分配为方法区中,而实例变量会随着对象一起分配到Java堆中。

resolve

  • 将常量池中的符号引用转为直接引用的过程

    符号引用是用一组符号来描述引用的目标,直接引用就是直接指向目标的指针,相对偏移量或一个间接定位到目标的句柄

    如:

       #1 = Methodref          #6.#23         // java/lang/Object."<init>":()V
       #2 = Fieldref           #24.#25        // java/lang/System.out:Ljava/io/PrintStream;
       #3 = Fieldref           #5.#26         // com/chris/jvm/HelloApp.a:I
       #4 = Methodref          #27.#28        // java/io/PrintStream.println:(I)V
       #5 = Class              #29            // com/chris/jvm/HelloApp
       #6 = Class              #30            // java/lang/Object
    
DELL@Chris MINGW64 /d/code/javademo2023/target/classes/com/chris/jvm (master)
$ javap -v HelloApp.class 
    
Classfile /D:/code/javademo2023/target/classes/com/chris/jvm/HelloApp.class
  Last modified 2023-10-28; size 602 bytes
  MD5 checksum 7ef53c911fc920c2696f59fe86144688
  Compiled from "HelloApp.java"
public class com.chris.jvm.HelloApp
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#23         // java/lang/Object."<init>":()V
   #2 = Fieldref           #24.#25        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Fieldref           #5.#26         // com/chris/jvm/HelloApp.a:I
   #4 = Methodref          #27.#28        // java/io/PrintStream.println:(I)V
   #5 = Class              #29            // com/chris/jvm/HelloApp
   #6 = Class              #30            // java/lang/Object
   #7 = Utf8               a
   #8 = Utf8               I
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               Lcom/chris/jvm/HelloApp;
  #16 = Utf8               main
  #17 = Utf8               ([Ljava/lang/String;)V
  #18 = Utf8               args
  #19 = Utf8               [Ljava/lang/String;
  #20 = Utf8               <clinit>
  #21 = Utf8               SourceFile
  #22 = Utf8               HelloApp.java
  #23 = NameAndType        #9:#10         // "<init>":()V
  #24 = Class              #31            // java/lang/System
  #25 = NameAndType        #32:#33        // out:Ljava/io/PrintStream;
  #26 = NameAndType        #7:#8          // a:I
  #27 = Class              #34            // java/io/PrintStream
  #28 = NameAndType        #35:#36        // println:(I)V
  #29 = Utf8               com/chris/jvm/HelloApp
  #30 = Utf8               java/lang/Object
  #31 = Utf8               java/lang/System
  #32 = Utf8               out
  #33 = Utf8               Ljava/io/PrintStream;
  #34 = Utf8               java/io/PrintStream
  #35 = Utf8               println
  #36 = Utf8               (I)V

初始化 Initializing

  • 初始化阶段就是执行类构造器方法clinit()的过程

  • 这个方法不需要定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来, 如果没有类变量或者静态代码块则在字节码中不会有clinit()方法

  • 构造器方法中的指令按语句在源文件中出现的顺序执行 [这一点很重要]

  • 若该类有父类,JVM会保证子类的clinit()方法执行前,父类的clinit()方法已经执行

public class ClInitTest {

    private static int num = 1;

    static {
        num = 2;
        number = 20;
    }

    private static int number = 10; // liking的prepare阶段先将number分配为0,在Initializing时指令按顺序执行,先将number赋值为20,再将number赋值为10

    public static void main(String[] args) {
        System.out.println(ClInitTest.num);
        System.out.println(ClInitTest.number);
    }
}

结果:
2
10

// 没有类变量或者静态代码块则在字节码中不会有`clinit()`方法
public class ClinitTest2 {
    private int a = 1;


    public static void main(String[] args) {
        int b = 2;
    }
}

类加载器

  • JVM支持两种类加载器: 引导类加载器(Bootstrap ClassLoader) 和自定义类加载器(User-Defined ClassLoader)

  • 所有派生于ClassLoader的类加载器统一划分为自定义类加载器

  • 类加载器不是上下层关系,也不是继承关系,而是包含关系

  • Bootstrap ClassLoader是由C语言实现的,其实都是由Java代码实现的

 public static void main(String[] args) {
        // 获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader); // sun.misc.Launcher$AppClassLoader@18b4aac2

        // 获取系统类加载器的上层加载器,即扩展类加载器
        ClassLoader extClassLoader = systemClassLoader.getParent();
        System.out.println(extClassLoader); // sun.misc.Launcher$ExtClassLoader@3fee733d

        // 获取扩展类加载器的上层加载器, 发现获取不到
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(bootstrapClassLoader); // null


        // 获取自定义类ClassLoaderTest的类加载器, 默认合理使用系统类加载器加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader); // sun.misc.Launcher$AppClassLoader@18b4aac2

        // 获取String类的类加载器,发现获取不到,间接说明了是由引导类加载器加载的,也说明Java的核心类库都是由引导类加载器进行加载的
        ClassLoader classLoader1 = String.class.getClassLoader();
        System.out.println(classLoader1);// null
    }

引导类加载器

  • 使用C/C++语言实现,嵌套在JVM内部

  • 它用来加载Java核心库(JAVA_HOME/jre/lib/rt.jar,resources.jar或 sun.boot.class.path路径下的内容)用于提供JVM自身需要的类

  • 并不继承ClassLoader,没有父类加载器。

  • 加载扩展类和系统类加载器,并指定为他们的父类

扩展类加载器

  • 由Java语言编写

  • 派生于ClassLoader类

  • 父类加载器为启动类加载器

  • 从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录下加载类库,如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。

系统类加载器

  • 由Java语言编写

  • 派生于ClassLoader类

  • 父类加载器为扩展类加载器

  • 它负责加载环境变量classpath或系统属性java.class.path指定路径下的类库

  • 是程序中默认的加载器,一般来说,Java应用的类都是由它来完成加载的

  • 通过ClassLoader.getSystemClassLoader()方法可以获取到该类加载器

	/**
     * file:/C:/Program%20Files/Java/jdk1.8.0_361/jre/lib/resources.jar
     * file:/C:/Program%20Files/Java/jdk1.8.0_361/jre/lib/rt.jar
     * file:/C:/Program%20Files/Java/jdk1.8.0_361/jre/lib/jsse.jar
     * file:/C:/Program%20Files/Java/jdk1.8.0_361/jre/lib/jce.jar
     * file:/C:/Program%20Files/Java/jdk1.8.0_361/jre/lib/charsets.jar
     * file:/C:/Program%20Files/Java/jdk1.8.0_361/jre/lib/jfr.jar
     * file:/C:/Program%20Files/Java/jdk1.8.0_361/jre/classes
     * null
     * ----------------------扩展类加载器------------------------------
     * C:\Program Files\Java\jdk1.8.0_361\jre\lib\ext
     * C:\WINDOWS\Sun\Java\lib\ext
     * sun.misc.Launcher$ExtClassLoader@6433a2
     */
    public static void main(String[] args) {
        // 获取引导类加载器能够加载的API路径
        URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
        Stream.of(urLs).forEach(url -> System.out.println(url.toExternalForm()));

        // 从上面路径中随意选择一个类,来看看他的类加载器是什么:获取为null,说说明是引导类加载器加载的
        ClassLoader classLoader = Provider.class.getClassLoader();
        System.out.println(classLoader);

        System.out.println("----------------------扩展类加载器------------------------------");
        // 扩展类加载器
        String extDirs = System.getProperty("java.ext.dirs");
        Stream.of(extDirs.split(";")).forEach(System.out::println);

        // 从上面路径中随意选择一个类,来看看他的类加载器是什么:获取为sun.misc.Launcher$ExtClassLoader@6433a2,说说明是扩展类加载器加载的
        ClassLoader classLoader1 = ECDSAOperations.class.getClassLoader();
        System.out.println(classLoader1);
    }

自定义类加载器

为什么要自定义类加载器

  • 隔离加载类,例如加载中间件时,出现类名称一样,加载时出现类名冲突,这时就要自定义类加载器。
  • 修改类的加载方式
  • 扩展加载源, 扩展字节码的来源
  • 防止源码泄漏, 对字节码加密,自定义类加载器时再解密。

实现步骤

  • 继承ClassLoader
  • 重写findClass(String name)方法
  • 如果没有复杂的加载需求,可以直接继承URLClassLoader类,这样就避免自己去编写findClass()方法及其获取字节码流的方式,使自定义类加载器更加简洁。

获取ClassLoader的方式

  • 获取当前类的ClassLoader : class.getClassLoader()

  • 获取当前线程上下文的ClassLoader : Thread.currentThread().getContextClassLoader()

  • 获取系统ClassLoader : ClassLoader.getSystemClassLoader

  • 获取调用者的ClassLoader : DriverManager.getCallerClassLoader()

ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();
System.out.println(classLoader);

ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
System.out.println(contextClassLoader);

ClassLoader parent = ClassLoader.getSystemClassLoader().getParent();
System.out.println(parent);

双亲委派机制

  1. JVM对class文件采用按需加载的方式,也就是当需要使用该类时才会将它的class文件加载到内存中生成class对象。而且加载class文件时,JVM采用双亲委派模式

  2. 亲委派模式工作原理

  • 如果一个类加载器收到加载请求,并不是自己先去加载,而是把空上请求交给其父类加载器去执行

  • 如果父类加载器还存在父类加载器,则依次向上委托,到达顶层类加载器

  • 如果父类加载器可以完成加载任务则成功返回,否则交由子类加载器去尝试加载,依次向下委托。

  1. 优势
  • 避免重复加载
  • 保护程序安全,防止核心API被随意篡改

类的主动使用与被动使用

  1. 两个Class文件是否为同一个类两个必要条件

    • 类的完整全类名必须一致,包括包名
    • 加载这个类的ClassLoader实例对象必须相同
  2. 类的主动使用

    • 创建类的实例 即 new一个类实例

    • 访问某个类或接口的静态变量,或者对该静态变量赋值

    • 调用类的静态方法

    • 反射 Class.forName("com.chris.jvm.ClassLoaderTest")

    • 初始化一个类的子类

    • JVM启动时被标明为启动类的类

    • 除上面七种外,其他使用Java类的方式都被看作是对类的被动使用,都不会导致类的初始化

运行时数据区和内部结构

灰色的为单独线程私有的,红色的为多个线程共享的

每个线程:独立包括程序计数器,栈,本地栈

线程间共享:堆,堆外内存(方法区或者叫元空间)

对于JVM的优化重点在于堆空间[95%]和方法区[5%],栈的作用很简单就是进栈和出栈,但是也会出现内存溢出的问题

一个JVM进程对应一个Runtime.class的唯一实例

线程

在Hotspot JVM里面,每个线程都与操作系统的本地线程直接映射

  • 当一个Java线程准备好执行以后,此时一个操作系统的本地线程也同时创建,Java线程执行终止后,本地线程也会回收。
  • 操作系统负责所有线程的安排调度到任何一个可用的CPU上。一旦本地线程初始化成功,它就会调用Java线程中的run方法。

程序计数器

  • 程序计数器又叫PC寄存器, JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟

  • 它用来存储指向下一条指令的地址,任何时间一个线程都只有一个方法在执行,称之为当前方法,程序计数器会存储当前线程正在执行Java方法的JVM指令地址,如果是在执行navtive方法,则是未指定(undefined)

  • JVM不会对PC寄存器进行GC,因为它不会OOM.

左边的数字称为指令地址,右边为操作指令

程序计数器存储的就是其中的某一位指令地址

public class PCRegisterTest {

    @Test
    public void test() {
        int i = 10;
        int j = 20;
        int k = i + j;
        String s = "abc";

        System.out.println(i);
        System.out.println(k);
    }
}

字节码指令
 0 bipush 10
 2 istore_1
 3 bipush 20
 5 istore_2
 6 iload_1
 7 iload_2
 8 iadd
 9 istore_3
10 ldc #2 <abc>
12 astore 4
14 getstatic #3 <java/lang/System.out : Ljava/io/PrintStream;>
17 iload_1
18 invokevirtual #4 <java/io/PrintStream.println : (I)V>
21 getstatic #3 <java/lang/System.out : Ljava/io/PrintStream;>
24 iload_3
25 invokevirtual #4 <java/io/PrintStream.println : (I)V>
28 return
  • 为什么要有PC寄存器

    因为CPU需要不停的在各线程间进行切换,当切换回来的时候主需要知道上次是从哪里开始执行的。JVM的字节码解释器就需要通过改变PC寄存器的值来明确下一条应该执行什么样的字节码指令。

  • 为什么PC寄存器要设置为线程私有的

是什么

  • 栈是运行时的单位,而堆是存储的单位

  • 栈解决的是程序运行的问题,即程序如何运行,或者说如何处理数据

  • 堆解决的是数据存储的问题,即数据怎么放,放在哪里。方法内的基本数据类型放在栈里面,如果是引用数据类型则放在堆里面,栈里面只存对象的引用无忧地址

  • 每个线程在创建时都会创建一个虚拟机栈, 里面是一个个的栈帧[stack frame],一个栈帧对应一个Java方法的调用

  • 在一个活动的线程中,一个时间点上只会有一个活动的栈帧,这个栈帧被称为当前栈帧[current frame],当前栈帧对应的方法称为当前方法[current method],定义方法的类称为当前类[current class]

  • 不同线程间的线帧不能相互引用,即不能在一个栈帧里面引用另外一个线程的栈帧

  • Java方法的结束方式, 第一种:return, 第二种:方法执行中出现未捕获处理的异常,以抛出异常的方法结束

 /**
  * 从打印结果可以看到进栈和出栈的栈帧的执行顺序
  */
@Test
public void method1() {
    System.out.println("method1 begin");
    method2();
    System.out.println("method1 end");
}

private int method2() {
    System.out.println("method2 begin");
    int i = 3;
    int m = (int) method3();
    System.out.println("method2 going to end");

    return i + m;
}

private double method3() {
    System.out.println("method3 begin");
    double j = 20.0;
    System.out.println("method3 going to end");
    return j;
}

结果
method1 begin
method2 begin
method3 begin
method3 going to end
method2 going to end
method1 end

生命周期

栈的生命周期和线程一致,线程结束,为这个线程保创建的栈也就结束

作用

主管Java程序的运行,它保存方法的局部变量[8种基本数据类型和对象的引用地址],部分结果,并参与方法的调用和返回

栈只有两种操作

  • 每个方法执行,伴随着进栈或称为压栈
  • 执行结束后出栈

对于栈来说是不存在垃圾回收[GC],但存在OOM

栈可能出现的异常

JVM规范允许Java栈的大小是动态的或者是固定不变的

  • 如果栈大小是固定不变的,每个线程的栈容量可以在线程创建时独立选定。如果线程请求的栈容量超过JVM允许的最大容量,JVM会抛出一个StackOverflowError异常
  • 如果栈大小是动态扩展的,但在尝试扩展时无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,JVM会抛出一个OutOfMemoryError异常
https://docs.oracle.com/javase/8/index.html
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#CBBFHAJA

-Xss size
Sets the thread stack size (in bytes). Append the letter k or K to indicate KB, m or M to indicate MB, g or G to indicate GB. The default value depends on the platform:

Linux/ARM (32-bit): 320 KB
Linux/i386 (32-bit): 320 KB
Linux/x64 (64-bit): 1024 KB
macOS (64-bit): 1024 KB
Oracle Solaris/i386 (32-bit): 320 KB
Oracle Solaris/x64 (64-bit): 1024 KB
Windows: The default value depends on virtual memory
The following examples set the thread stack size to 1024 KB in different units:

-Xss1m
-Xss1024k
-Xss1048576
This option is similar to -XX:ThreadStackSize.
/**
 * 没有设置栈大小时:11344
 * 11344
 * java.lang.StackOverflowError
 * 	at sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:691)
 * 设置栈大小时:-Xss256k
 * 2263
 * java.lang.StackOverflowError
 * 	at sun.nio.cs.UTF_8.updatePositions(UTF_8.java:77)
 */
@Test
public void testStack() {
    System.out.println(i);
    i++;
    testStack();
}

栈帧的内部结构

每个栈帧中存储着五部分

  • 局部变量表 [Local Variables]或称为本地变量表
  • 操作数栈 [Operand Stack]
  • 动态链接 [Dynamic Linking] 即指向运行时常量池的方法引用
  • 方法返回地址 [Return Address]
  • 一些附加信息
局部变量表 [Local Variables]
  • 是一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量,这些数据类型包括 8种基本数据类型,对象的引用地址[reference]和返回地址[returnAddress]类型
  • 局部变量表建立在线程的栈上,是线程私有数据,因此不存在数据安全问题
  • 局部变量表的大小是在编译期确定下来的,并保存在对应方法的Code属性的maximum local variables数据项中。在方法运行时不会改变局部变量表的大小。

locals=3 main方法中局部变量表长度

public class LocalVariablesTest {

    public static void main(String[] args) {
        LocalVariablesTest test = new LocalVariablesTest();
        int num = 10;
        test.test1();
    }

    public void test1() {
        Date date = new Date();
        String name1 = "my name is chris";
        String info = test2(date, name1);
        System.out.println(date + name1);
    }


    public String test2(Date date, String name) {
        date = null;
        name = "my name is John";
        double weight = 130.5;
        char gender = 'M';
        return date + name;
    }

}

DELL@Chris MINGW64 /d/code/javademo2023/target/classes/com/chris/jvm (master)
$ javap -v LocalVariablesTest.class 
......
public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V  -- 形参是String类型的一维数据,返回值为Void, L为引用类型变量的意思
    flags: ACC_PUBLIC, ACC_STATIC		-- 访问标识为 public static
    Code:
      stack=2, locals=3 -- main方法中局部变量表长度, args_size=1
         0: new           #2                  // class com/chris/jvm/LocalVariablesTest
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: astore_1
         8: bipush        10
        10: istore_2
        11: aload_1
        12: invokevirtual #4                  // Method test1:()V
        15: return
      LineNumberTable:
        line 8: 0
        line 9: 8
        line 10: 11
        line 11: 15
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      16     0  args   [Ljava/lang/String; 				-- String类型的形参叫args
            8       8     1  test   Lcom/chris/jvm/LocalVariablesTest;  -- 引用类型变量test
           11       5     2   num   I 									-- int型的一个变量num

Slot的重复利用

栈帧中的局部变量表中的slot的位置是可以重复利用的,如果一个局部变量过了其作用域,那么在其作用域之后申明的新的局部变量就很有可能会利用过期的局部变量的位置,从而达到节省资源的目的。

@Test
public void test4() {
    int a = 0;
    {
        int b = 0;
        b = a + 1;
    }
    // 变量c是使用前面已经销毁的变量b所占据的slot的位置
    int c = a + 1;
}

变量的分类
  • 按数据类型分: 基本数据类型变量,引用数据类型变量

  • 按在类中的声明的位置分:

    成员变量: 使用前,都经历守默认初始化赋值

    ​ 1. 类变量:在linking的prepare阶段,给类变量默认赋值,在initializing阶段给类变量显示赋值。

    ​ 2. 实例变量:随着对象的创建,会在堆空间中分配实例变量空间

    ​ 局部变量:在使用前必须进行显式赋值!否则,编译不通过。

在栈帧中,与性能调优最为密切的部分就是局部变量表,在方法执行时,JVM使用局部变量表完成方法的传递。

局部变量表也是重要的垃圾回收根节点,只要被局部变量表中直接或间接使用到的对象都不会被回收

操作数栈 [Operand Stack]
  • 每一个独立的栈帧中除了包含局部变量表外,还有一个先进后出的操作数栈,也可以称为表达式栈

  • 操作数栈主要用于保存计算过程中的中间结果

  • 每一个操作数栈都有一个明确的栈深度用于存储数值,其所需要最大深度在编译期就定好了,保存在方法的Code属性中,为max_stack的值

    1. 4个字节类型占用一个栈单位

    2. 8个字节类型占用两个栈单位

  • 虽然操作数栈是一个数组,但是不能采用访问索引的方式进行数据访问,而只能通过入栈[push]和出栈[pop]的操作来完成一次数据访问

@Test
public void test1() {
    byte i = 15;
    int j = 8;
    int k = i + j;
}

// 字节码指令
 0 bipush 15  //把15放到操作数栈中
 2 istore_1   //把操作数栈中的15出栈放到局部变量表索引为1的位置,操作数栈位置就没有15了
 3 bipush 8	  //把8放到操作数栈中
 5 istore_2   //把操作数栈中的8出栈放到局部变量表索引为2的位置,操作数栈位置就没有8了
 6 iload_1	  //把局部变量表中索引为1的15取出来放到操作数栈中
 7 iload_2	  //把局部变量表中索引位置2的8取出来放到操作数栈中
 8 iadd       //把操作数栈中的15和8出栈,相加得到23再放到操作数栈中
 9 istore_3   //把操作数栈中的23出栈放到局部变量表索引为3的位置,操作数栈位置就没有23了
10 return
%0A%0A%23%23%23%20%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%AD%90%E7%B3%BB%E7%BB%9F%E7%9A%84%E4%BD%9C%E7%94%A8%0A!%5Bde3e439b90813dd5f2f765bc2c4295e7.png%5D(en-resource%3A%2F%2Fdatabase%2F1550%3A1)%0A%0A%0A1.%20Class%20Loader%20%E5%8F%AA%E8%B4%9F%E8%B4%A3class%E6%96%87%E4%BB%B6%E5%8A%A0%E8%BD%BD%EF%BC%8C%E8%87%B3%E4%BA%8Eclass%E6%96%87%E4%BB%B6%E6%98%AF%E5%90%A6%E8%83%BD%E5%A4%9F%E8%BF%90%E8%A1%8C%E7%94%B1Execution%20Engine%E5%86%B3%E5%AE%9A%0A%0A2.%20%E5%8A%A0%E8%BD%BD%E7%9A%84%E7%B1%BB%E4%BF%A1%E6%81%AF%E5%AD%98%E6%94%BE%E4%BA%8E%E6%96%B9%E6%B3%95%E5%8C%BA%5BMethod%20Area%5D%E7%9A%84%E5%86%85%E5%AD%98%E7%A9%BA%E9%97%B4%EF%BC%8C%E9%99%A4%E7%B1%BB%E4%BF%A1%E6%81%AF%E5%A4%96%EF%BC%8C%E6%96%B9%E6%B3%95%E5%8C%BA%E8%BF%98%E4%BC%9A%E5%AD%98%E6%94%BE%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0%20%60%5B%E5%8F%8D%E7%BC%96%E8%AF%91%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%20Constant%20Pool%5D%60%20%E4%BF%A1%E6%81%AF%0A%0A%60%60%60java%0Ajavap%20-v%20classFileName%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%8A%A0%E8%BD%BD%20Loading%0A%0A-%20%E9%80%9A%E8%BF%87%E4%B8%80%E4%B8%AA%E7%B1%BB%E7%9A%84%E5%85%A8%E9%99%90%E5%AE%9A%E5%90%8D%E8%8E%B7%E5%8F%96%E6%AD%A4%E7%B1%BB%E7%9A%84%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%AD%97%E8%8A%82%E6%B5%81%0A-%20%E5%B0%86%E8%BF%99%E4%B8%AA%E5%AD%97%E8%8A%82%E6%B5%81%E6%89%80%E4%BB%A3%E8%A1%A8%E7%9A%84%E9%9D%99%E6%80%81%E5%AD%98%E5%82%A8%E7%BB%93%E6%9E%84%E8%BD%AC%E5%8C%96%E4%B8%BA%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%0A-%20%E5%9C%A8%E5%86%85%E5%AD%98%E4%B8%AD%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E4%BB%A3%E8%A1%A8%E8%BF%99%E4%B8%AA%E7%B1%BB%E7%9A%84%20%60java.lang.Class%60%20%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BD%9C%E4%B8%BA%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E8%BF%99%E4%B8%AA%E7%B1%BB%E7%9A%84%E5%90%84%E7%A7%8D%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%E5%85%A5%E5%8F%A3%0A%0A%0A%23%23%23%23%20%E9%93%BE%E6%8E%A5%20Linking%0A%0Averify%20%0A%0A-%20%E7%A1%AE%E4%BF%9DClass%E6%96%87%E4%BB%B6%E7%9A%84%E5%AD%97%E8%8A%82%E6%B5%81%E6%89%80%E5%8C%85%E5%90%AB%E7%9A%84%E4%BF%A1%E6%81%AF%E7%AC%A6%E5%90%88%E5%BD%93%E5%89%8D%E8%99%9A%E6%8B%9F%E6%9C%BA%E7%9A%84%E8%A6%81%E6%B1%82%EF%BC%8C%E4%BF%9D%E8%AF%81%E8%A2%AB%E5%8A%A0%E8%BD%BD%E7%B1%BB%E7%9A%84%E6%AD%A3%E7%A1%AE%E6%80%A7%EF%BC%8C%E4%B8%8D%E4%BC%9A%E5%8D%B1%E5%AE%B3%E8%99%9A%E6%8B%9F%E6%9C%BA%E8%87%AA%E8%BA%AB%E7%9A%84%E5%AE%89%E5%85%A8%E3%80%82%0A%0Aprepare%20%0A%0A-%20%E4%B8%BA%E7%B1%BB%E5%8F%98%E9%87%8F%5Bstatic%E4%BF%AE%E9%A5%B0%E7%9A%84%E5%8F%98%E9%87%8F%5D%E5%88%86%E9%85%8D%E5%86%85%E5%AD%98%EF%BC%8C%E5%B9%B6%E4%B8%94%E8%AE%BE%E7%BD%AE%E8%AF%A5%E5%8F%98%E9%87%8F%E7%9A%84%E9%BB%98%E8%AE%A4%E5%88%9D%E5%A7%8B%E5%80%BC%EF%BC%8C%E5%8D%B30%E5%80%BC%E3%80%82%E5%8F%98%E9%87%8F%E7%9A%84%E7%B1%BB%E5%9E%8B%E4%B8%8D%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%87%86%E5%A4%87%E9%98%B6%E6%AE%B5%E8%AE%BE%E7%BD%AE%E7%9A%84%E9%BB%98%E8%AE%A4%E5%80%BC%E4%B9%9F%E4%B8%8D%E4%B8%80%E6%A0%B7%EF%BC%8C%E6%95%B4%E5%BD%A2%E4%B8%BA0%0A%0A%60%60%60java%0Aprivate%20static%20int%20a%20%3D%201%3B%20%2F%2F%20%E5%9C%A8%E5%87%86%E5%A4%87%E9%98%B6%E6%AE%B5%20a%3D0%20%2C%20%E5%9C%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E9%98%B6%E6%AE%B5%E6%89%8D%E5%B0%86%20a%E8%B5%8B%E5%80%BC%E4%B8%BA1%0A%60%60%60%0A%0A-%20final%E4%BF%AE%E9%A5%B0%E7%9A%84static%E5%8F%98%E6%9B%B4%E5%AE%9E%E9%99%85%E6%98%AF%E4%B8%80%E4%B8%AA%E5%B8%B8%E9%87%8F%EF%BC%8C%20%E5%9C%A8%E7%BC%96%E8%AF%91%E6%97%B6%E5%B0%B1%E4%BC%9A%E5%88%86%E9%85%8D%E5%88%9D%E5%A7%8B%E5%80%BC%EF%BC%8C%E5%B9%B6%E5%9C%A8%E5%87%86%E5%A4%87%E9%98%B6%E6%AE%B5%E6%98%BE%E7%A4%BA%E8%B5%8B%E5%80%BC%E3%80%82%0A%0A%60%60%60java%0Aprivate%20final%20static%20int%20a%20%3D%205%3B%20%2F%2F%20%E5%9C%A8%E7%BC%96%E8%AF%91%E6%97%B6%E5%88%86%E9%85%8D%E5%88%9D%E5%A7%8B%E5%80%BC%20a%3D0%20%2C%20%E5%9C%A8%E5%87%86%E5%A4%87%E9%98%B6%E6%AE%B5%E5%B0%86a%E8%B5%8B%E5%80%BC%E4%B8%BA5%0A%60%60%60%0A%0A-%20%E4%B8%8D%E4%BC%9A%E4%B8%BA%E5%AE%9E%E4%BE%8B%E5%8F%98%E9%87%8F%E5%88%86%E9%85%8D%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%E7%B1%BB%E5%8F%98%E9%87%8F%E4%BC%9A%E5%88%86%E9%85%8D%E4%B8%BA%E6%96%B9%E6%B3%95%E5%8C%BA%E4%B8%AD%EF%BC%8C%E8%80%8C%E5%AE%9E%E4%BE%8B%E5%8F%98%E9%87%8F%E4%BC%9A%E9%9A%8F%E7%9D%80%E5%AF%B9%E8%B1%A1%E4%B8%80%E8%B5%B7%E5%88%86%E9%85%8D%E5%88%B0Java%E5%A0%86%E4%B8%AD%E3%80%82%0A%0Aresolve%0A%0A-%20%E5%B0%86%E5%B8%B8%E9%87%8F%E6%B1%A0%E4%B8%AD%E7%9A%84%E7%AC%A6%E5%8F%B7%E5%BC%95%E7%94%A8%E8%BD%AC%E4%B8%BA%E7%9B%B4%E6%8E%A5%E5%BC%95%E7%94%A8%E7%9A%84%E8%BF%87%E7%A8%8B%0A%0A%20%20%E7%AC%A6%E5%8F%B7%E5%BC%95%E7%94%A8%E6%98%AF%E7%94%A8%E4%B8%80%E7%BB%84%E7%AC%A6%E5%8F%B7%E6%9D%A5%E6%8F%8F%E8%BF%B0%E5%BC%95%E7%94%A8%E7%9A%84%E7%9B%AE%E6%A0%87%EF%BC%8C%E7%9B%B4%E6%8E%A5%E5%BC%95%E7%94%A8%E5%B0%B1%E6%98%AF%E7%9B%B4%E6%8E%A5%E6%8C%87%E5%90%91%E7%9B%AE%E6%A0%87%E7%9A%84%E6%8C%87%E9%92%88%EF%BC%8C%E7%9B%B8%E5%AF%B9%E5%81%8F%E7%A7%BB%E9%87%8F%E6%88%96%E4%B8%80%E4%B8%AA%E9%97%B4%E6%8E%A5%E5%AE%9A%E4%BD%8D%E5%88%B0%E7%9B%AE%E6%A0%87%E7%9A%84%E5%8F%A5%E6%9F%84%0A%0A%20%20%E5%A6%82%EF%BC%9A%0A%0A%20%20%60%60%60java%0A%20%20%20%20%20%231%20%3D%20Methodref%20%20%20%20%20%20%20%20%20%20%236.%2323%20%20%20%20%20%20%20%20%20%2F%2F%20java%2Flang%2FObject.%22%3Cinit%3E%22%3A()V%0A%20%20%20%20%20%232%20%3D%20Fieldref%20%20%20%20%20%20%20%20%20%20%20%2324.%2325%20%20%20%20%20%20%20%20%2F%2F%20java%2Flang%2FSystem.out%3ALjava%2Fio%2FPrintStream%3B%0A%20%20%20%20%20%233%20%3D%20Fieldref%20%20%20%20%20%20%20%20%20%20%20%235.%2326%20%20%20%20%20%20%20%20%20%2F%2F%20com%2Fchris%2Fjvm%2FHelloApp.a%3AI%0A%20%20%20%20%20%234%20%3D%20Methodref%20%20%20%20%20%20%20%20%20%20%2327.%2328%20%20%20%20%20%20%20%20%2F%2F%20java%2Fio%2FPrintStream.println%3A(I)V%0A%20%20%20%20%20%235%20%3D%20Class%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2329%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20com%2Fchris%2Fjvm%2FHelloApp%0A%20%20%20%20%20%236%20%3D%20Class%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2330%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20java%2Flang%2FObject%0A%20%20%60%60%60%0A%0A%20%20%0A%0A%60%60%60java%0ADELL%40Chris%20MINGW64%20%2Fd%2Fcode%2Fjavademo2023%2Ftarget%2Fclasses%2Fcom%2Fchris%2Fjvm%20(master)%0A%24%20javap%20-v%20HelloApp.class%20%0A%20%20%20%20%0AClassfile%20%2FD%3A%2Fcode%2Fjavademo2023%2Ftarget%2Fclasses%2Fcom%2Fchris%2Fjvm%2FHelloApp.class%0A%20%20Last%20modified%202023-10-28%3B%20size%20602%20bytes%0A%20%20MD5%20checksum%207ef53c911fc920c2696f59fe86144688%0A%20%20Compiled%20from%20%22HelloApp.java%22%0Apublic%20class%20com.chris.jvm.HelloApp%0A%20%20minor%20version%3A%200%0A%20%20major%20version%3A%2052%0A%20%20flags%3A%20ACC_PUBLIC%2C%20ACC_SUPER%0AConstant%20pool%3A%0A%20%20%20%231%20%3D%20Methodref%20%20%20%20%20%20%20%20%20%20%236.%2323%20%20%20%20%20%20%20%20%20%2F%2F%20java%2Flang%2FObject.%22%3Cinit%3E%22%3A()V%0A%20%20%20%232%20%3D%20Fieldref%20%20%20%20%20%20%20%20%20%20%20%2324.%2325%20%20%20%20%20%20%20%20%2F%2F%20java%2Flang%2FSystem.out%3ALjava%2Fio%2FPrintStream%3B%0A%20%20%20%233%20%3D%20Fieldref%20%20%20%20%20%20%20%20%20%20%20%235.%2326%20%20%20%20%20%20%20%20%20%2F%2F%20com%2Fchris%2Fjvm%2FHelloApp.a%3AI%0A%20%20%20%234%20%3D%20Methodref%20%20%20%20%20%20%20%20%20%20%2327.%2328%20%20%20%20%20%20%20%20%2F%2F%20java%2Fio%2FPrintStream.println%3A(I)V%0A%20%20%20%235%20%3D%20Class%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2329%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20com%2Fchris%2Fjvm%2FHelloApp%0A%20%20%20%236%20%3D%20Class%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2330%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20java%2Flang%2FObject%0A%20%20%20%237%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%0A%20%20%20%238%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20I%0A%20%20%20%239%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cinit%3E%0A%20%20%2310%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20()V%0A%20%20%2311%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Code%0A%20%20%2312%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20LineNumberTable%0A%20%20%2313%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20LocalVariableTable%0A%20%20%2314%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this%0A%20%20%2315%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Lcom%2Fchris%2Fjvm%2FHelloApp%3B%0A%20%20%2316%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20main%0A%20%20%2317%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%5BLjava%2Flang%2FString%3B)V%0A%20%20%2318%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20args%0A%20%20%2319%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5BLjava%2Flang%2FString%3B%0A%20%20%2320%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cclinit%3E%0A%20%20%2321%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20SourceFile%0A%20%20%2322%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20HelloApp.java%0A%20%20%2323%20%3D%20NameAndType%20%20%20%20%20%20%20%20%239%3A%2310%20%20%20%20%20%20%20%20%20%2F%2F%20%22%3Cinit%3E%22%3A()V%0A%20%20%2324%20%3D%20Class%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2331%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20java%2Flang%2FSystem%0A%20%20%2325%20%3D%20NameAndType%20%20%20%20%20%20%20%20%2332%3A%2333%20%20%20%20%20%20%20%20%2F%2F%20out%3ALjava%2Fio%2FPrintStream%3B%0A%20%20%2326%20%3D%20NameAndType%20%20%20%20%20%20%20%20%237%3A%238%20%20%20%20%20%20%20%20%20%20%2F%2F%20a%3AI%0A%20%20%2327%20%3D%20Class%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2334%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20java%2Fio%2FPrintStream%0A%20%20%2328%20%3D%20NameAndType%20%20%20%20%20%20%20%20%2335%3A%2336%20%20%20%20%20%20%20%20%2F%2F%20println%3A(I)V%0A%20%20%2329%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20com%2Fchris%2Fjvm%2FHelloApp%0A%20%20%2330%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20java%2Flang%2FObject%0A%20%20%2331%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20java%2Flang%2FSystem%0A%20%20%2332%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20out%0A%20%20%2333%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Ljava%2Fio%2FPrintStream%3B%0A%20%20%2334%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20java%2Fio%2FPrintStream%0A%20%20%2335%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20println%0A%20%20%2336%20%3D%20Utf8%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(I)V%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%20Initializing%0A%0A-%20%E5%88%9D%E5%A7%8B%E5%8C%96%E9%98%B6%E6%AE%B5%E5%B0%B1%E6%98%AF%E6%89%A7%E8%A1%8C%E7%B1%BB%E6%9E%84%E9%80%A0%E5%99%A8%E6%96%B9%E6%B3%95%60clinit()%60%E7%9A%84%E8%BF%87%E7%A8%8B%0A%0A-%20%E8%BF%99%E4%B8%AA%E6%96%B9%E6%B3%95%E4%B8%8D%E9%9C%80%E8%A6%81%E5%AE%9A%E4%B9%89%EF%BC%8C%E6%98%AF%60javac%60%E7%BC%96%E8%AF%91%E5%99%A8%E8%87%AA%E5%8A%A8%E6%94%B6%E9%9B%86%E7%B1%BB%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E7%B1%BB%E5%8F%98%E9%87%8F%E7%9A%84%E8%B5%8B%E5%80%BC%E5%8A%A8%E4%BD%9C%E5%92%8C%E9%9D%99%E6%80%81%E4%BB%A3%E7%A0%81%E5%9D%97%E4%B8%AD%E7%9A%84%E8%AF%AD%E5%8F%A5%E5%90%88%E5%B9%B6%E8%80%8C%E6%9D%A5%EF%BC%8C%20%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E7%B1%BB%E5%8F%98%E9%87%8F%E6%88%96%E8%80%85%E9%9D%99%E6%80%81%E4%BB%A3%E7%A0%81%E5%9D%97%E5%88%99%E5%9C%A8%E5%AD%97%E8%8A%82%E7%A0%81%E4%B8%AD%E4%B8%8D%E4%BC%9A%E6%9C%89%60clinit()%60%E6%96%B9%E6%B3%95%0A%0A-%20%E6%9E%84%E9%80%A0%E5%99%A8%E6%96%B9%E6%B3%95%E4%B8%AD%E7%9A%84%E6%8C%87%E4%BB%A4%E6%8C%89%E8%AF%AD%E5%8F%A5%E5%9C%A8%E6%BA%90%E6%96%87%E4%BB%B6%E4%B8%AD%E5%87%BA%E7%8E%B0%E7%9A%84%E9%A1%BA%E5%BA%8F%E6%89%A7%E8%A1%8C%20%5B%E8%BF%99%E4%B8%80%E7%82%B9%E5%BE%88%E9%87%8D%E8%A6%81%5D%0A%0A-%20%E8%8B%A5%E8%AF%A5%E7%B1%BB%E6%9C%89%E7%88%B6%E7%B1%BB%EF%BC%8CJVM%E4%BC%9A%E4%BF%9D%E8%AF%81%E5%AD%90%E7%B1%BB%E7%9A%84%60clinit()%60%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E5%89%8D%EF%BC%8C%E7%88%B6%E7%B1%BB%E7%9A%84%60clinit()%60%E6%96%B9%E6%B3%95%E5%B7%B2%E7%BB%8F%E6%89%A7%E8%A1%8C%0A%0A%60%60%60java%0Apublic%20class%20ClInitTest%20%7B%0A%0A%20%20%20%20private%20static%20int%20num%20%3D%201%3B%0A%0A%20%20%20%20static%20%7B%0A%20%20%20%20%20%20%20%20num%20%3D%202%3B%0A%20%20%20%20%20%20%20%20number%20%3D%2020%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20private%20static%20int%20number%20%3D%2010%3B%20%2F%2F%20liking%E7%9A%84prepare%E9%98%B6%E6%AE%B5%E5%85%88%E5%B0%86number%E5%88%86%E9%85%8D%E4%B8%BA0%EF%BC%8C%E5%9C%A8Initializing%E6%97%B6%E6%8C%87%E4%BB%A4%E6%8C%89%E9%A1%BA%E5%BA%8F%E6%89%A7%E8%A1%8C%EF%BC%8C%E5%85%88%E5%B0%86number%E8%B5%8B%E5%80%BC%E4%B8%BA20%EF%BC%8C%E5%86%8D%E5%B0%86number%E8%B5%8B%E5%80%BC%E4%B8%BA10%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20System.out.println(ClInitTest.num)%3B%0A%20%20%20%20%20%20%20%20System.out.println(ClInitTest.number)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%E7%BB%93%E6%9E%9C%3A%0A2%0A10%0A%60%60%60%0A!%5B995c17ddab3383728768af40a5f92b6e.png%5D(en-resource%3A%2F%2Fdatabase%2F1552%3A0)%0A%0A%0A%60%60%60java%0A%2F%2F%20%E6%B2%A1%E6%9C%89%E7%B1%BB%E5%8F%98%E9%87%8F%E6%88%96%E8%80%85%E9%9D%99%E6%80%81%E4%BB%A3%E7%A0%81%E5%9D%97%E5%88%99%E5%9C%A8%E5%AD%97%E8%8A%82%E7%A0%81%E4%B8%AD%E4%B8%8D%E4%BC%9A%E6%9C%89%60clinit()%60%E6%96%B9%E6%B3%95%0Apublic%20class%20ClinitTest2%20%7B%0A%20%20%20%20private%20int%20a%20%3D%201%3B%0A%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20int%20b%20%3D%202%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A!%5B961763f6a4b943622c065aa72354a773.png%5D(en-resource%3A%2F%2Fdatabase%2F1554%3A0)%0A%0A%23%23%23%20%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A-%20JVM%E6%94%AF%E6%8C%81%E4%B8%A4%E7%A7%8D%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%3A%20%E5%BC%95%E5%AF%BC%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8(Bootstrap%20ClassLoader)%20%E5%92%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8(User-Defined%20ClassLoader)%0A%0A-%20%E6%89%80%E6%9C%89%E6%B4%BE%E7%94%9F%E4%BA%8EClassLoader%E7%9A%84%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E7%BB%9F%E4%B8%80%E5%88%92%E5%88%86%E4%B8%BA%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A-%20%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E4%B8%8D%E6%98%AF%E4%B8%8A%E4%B8%8B%E5%B1%82%E5%85%B3%E7%B3%BB%EF%BC%8C%E4%B9%9F%E4%B8%8D%E6%98%AF%E7%BB%A7%E6%89%BF%E5%85%B3%E7%B3%BB%EF%BC%8C%E8%80%8C%E6%98%AF%E5%8C%85%E5%90%AB%E5%85%B3%E7%B3%BB%0A%0A-%20Bootstrap%20ClassLoader%E6%98%AF%E7%94%B1C%E8%AF%AD%E8%A8%80%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8C%E5%85%B6%E5%AE%9E%E9%83%BD%E6%98%AF%E7%94%B1Java%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0%E7%9A%84%0A%0A%60%60%60java%0A%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%E7%B3%BB%E7%BB%9F%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%20%20%20%20%20%20%20%20ClassLoader%20systemClassLoader%20%3D%20ClassLoader.getSystemClassLoader()%3B%0A%20%20%20%20%20%20%20%20System.out.println(systemClassLoader)%3B%20%2F%2F%20sun.misc.Launcher%24AppClassLoader%4018b4aac2%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%E7%B3%BB%E7%BB%9F%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E7%9A%84%E4%B8%8A%E5%B1%82%E5%8A%A0%E8%BD%BD%E5%99%A8%EF%BC%8C%E5%8D%B3%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%20%20%20%20%20%20%20%20ClassLoader%20extClassLoader%20%3D%20systemClassLoader.getParent()%3B%0A%20%20%20%20%20%20%20%20System.out.println(extClassLoader)%3B%20%2F%2F%20sun.misc.Launcher%24ExtClassLoader%403fee733d%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E7%9A%84%E4%B8%8A%E5%B1%82%E5%8A%A0%E8%BD%BD%E5%99%A8%2C%20%E5%8F%91%E7%8E%B0%E8%8E%B7%E5%8F%96%E4%B8%8D%E5%88%B0%0A%20%20%20%20%20%20%20%20ClassLoader%20bootstrapClassLoader%20%3D%20extClassLoader.getParent()%3B%0A%20%20%20%20%20%20%20%20System.out.println(bootstrapClassLoader)%3B%20%2F%2F%20null%0A%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BBClassLoaderTest%E7%9A%84%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%2C%20%E9%BB%98%E8%AE%A4%E5%90%88%E7%90%86%E4%BD%BF%E7%94%A8%E7%B3%BB%E7%BB%9F%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%8A%A0%E8%BD%BD%0A%20%20%20%20%20%20%20%20ClassLoader%20classLoader%20%3D%20ClassLoaderTest.class.getClassLoader()%3B%0A%20%20%20%20%20%20%20%20System.out.println(classLoader)%3B%20%2F%2F%20sun.misc.Launcher%24AppClassLoader%4018b4aac2%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96String%E7%B1%BB%E7%9A%84%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%EF%BC%8C%E5%8F%91%E7%8E%B0%E8%8E%B7%E5%8F%96%E4%B8%8D%E5%88%B0%EF%BC%8C%E9%97%B4%E6%8E%A5%E8%AF%B4%E6%98%8E%E4%BA%86%E6%98%AF%E7%94%B1%E5%BC%95%E5%AF%BC%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%8A%A0%E8%BD%BD%E7%9A%84%EF%BC%8C%E4%B9%9F%E8%AF%B4%E6%98%8EJava%E7%9A%84%E6%A0%B8%E5%BF%83%E7%B1%BB%E5%BA%93%E9%83%BD%E6%98%AF%E7%94%B1%E5%BC%95%E5%AF%BC%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E8%BF%9B%E8%A1%8C%E5%8A%A0%E8%BD%BD%E7%9A%84%0A%20%20%20%20%20%20%20%20ClassLoader%20classLoader1%20%3D%20String.class.getClassLoader()%3B%0A%20%20%20%20%20%20%20%20System.out.println(classLoader1)%3B%2F%2F%20null%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%BC%95%E5%AF%BC%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A-%20%E4%BD%BF%E7%94%A8C%2FC%2B%2B%E8%AF%AD%E8%A8%80%E5%AE%9E%E7%8E%B0%EF%BC%8C%E5%B5%8C%E5%A5%97%E5%9C%A8JVM%E5%86%85%E9%83%A8%0A%0A-%20%E5%AE%83%E7%94%A8%E6%9D%A5%E5%8A%A0%E8%BD%BDJava%E6%A0%B8%E5%BF%83%E5%BA%93(JAVA_HOME%2Fjre%2Flib%2Frt.jar%2Cresources.jar%E6%88%96%20sun.boot.class.path%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%9A%84%E5%86%85%E5%AE%B9)%E7%94%A8%E4%BA%8E%E6%8F%90%E4%BE%9BJVM%E8%87%AA%E8%BA%AB%E9%9C%80%E8%A6%81%E7%9A%84%E7%B1%BB%0A%0A-%20%E5%B9%B6%E4%B8%8D%E7%BB%A7%E6%89%BFClassLoader%EF%BC%8C%E6%B2%A1%E6%9C%89%E7%88%B6%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E3%80%82%0A%0A-%20%E5%8A%A0%E8%BD%BD%E6%89%A9%E5%B1%95%E7%B1%BB%E5%92%8C%E7%B3%BB%E7%BB%9F%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%EF%BC%8C%E5%B9%B6%E6%8C%87%E5%AE%9A%E4%B8%BA%E4%BB%96%E4%BB%AC%E7%9A%84%E7%88%B6%E7%B1%BB%0A%0A%0A%0A%23%23%23%23%20%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A-%20%E7%94%B1Java%E8%AF%AD%E8%A8%80%E7%BC%96%E5%86%99%0A%0A-%20%E6%B4%BE%E7%94%9F%E4%BA%8EClassLoader%E7%B1%BB%0A%0A-%20%E7%88%B6%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E4%B8%BA%E5%90%AF%E5%8A%A8%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A-%20%E4%BB%8Ejava.ext.dirs%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7%E6%89%80%E6%8C%87%E5%AE%9A%E7%9A%84%E7%9B%AE%E5%BD%95%E4%B8%AD%E5%8A%A0%E8%BD%BD%E7%B1%BB%E5%BA%93%EF%BC%8C%E6%88%96%E4%BB%8EJDK%E7%9A%84%E5%AE%89%E8%A3%85%E7%9B%AE%E5%BD%95%E7%9A%84jre%2Flib%2Fext%E5%AD%90%E7%9B%AE%E5%BD%95%E4%B8%8B%E5%8A%A0%E8%BD%BD%E7%B1%BB%E5%BA%93%EF%BC%8C%E5%A6%82%E6%9E%9C%E7%94%A8%E6%88%B7%E5%88%9B%E5%BB%BA%E7%9A%84JAR%E6%94%BE%E5%9C%A8%E6%AD%A4%E7%9B%AE%E5%BD%95%E4%B8%8B%EF%BC%8C%E4%B9%9F%E4%BC%9A%E8%87%AA%E5%8A%A8%E7%94%B1%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%8A%A0%E8%BD%BD%E3%80%82%0A%0A%0A%0A%23%23%23%23%20%E7%B3%BB%E7%BB%9F%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A-%20%E7%94%B1Java%E8%AF%AD%E8%A8%80%E7%BC%96%E5%86%99%0A%0A-%20%E6%B4%BE%E7%94%9F%E4%BA%8EClassLoader%E7%B1%BB%0A-%20%E7%88%B6%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E4%B8%BA%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A-%20%E5%AE%83%E8%B4%9F%E8%B4%A3%E5%8A%A0%E8%BD%BD%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8Fclasspath%E6%88%96%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7java.class.path%E6%8C%87%E5%AE%9A%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%9A%84%E7%B1%BB%E5%BA%93%0A-%20%E6%98%AF%E7%A8%8B%E5%BA%8F%E4%B8%AD%E9%BB%98%E8%AE%A4%E7%9A%84%E5%8A%A0%E8%BD%BD%E5%99%A8%EF%BC%8C%E4%B8%80%E8%88%AC%E6%9D%A5%E8%AF%B4%EF%BC%8CJava%E5%BA%94%E7%94%A8%E7%9A%84%E7%B1%BB%E9%83%BD%E6%98%AF%E7%94%B1%E5%AE%83%E6%9D%A5%E5%AE%8C%E6%88%90%E5%8A%A0%E8%BD%BD%E7%9A%84%0A-%20%E9%80%9A%E8%BF%87ClassLoader.getSystemClassLoader()%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%8F%96%E5%88%B0%E8%AF%A5%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A%0A%60%60%60java%0A%09%2F**%0A%20%20%20%20%20*%20file%3A%2FC%3A%2FProgram%2520Files%2FJava%2Fjdk1.8.0_361%2Fjre%2Flib%2Fresources.jar%0A%20%20%20%20%20*%20file%3A%2FC%3A%2FProgram%2520Files%2FJava%2Fjdk1.8.0_361%2Fjre%2Flib%2Frt.jar%0A%20%20%20%20%20*%20file%3A%2FC%3A%2FProgram%2520Files%2FJava%2Fjdk1.8.0_361%2Fjre%2Flib%2Fjsse.jar%0A%20%20%20%20%20*%20file%3A%2FC%3A%2FProgram%2520Files%2FJava%2Fjdk1.8.0_361%2Fjre%2Flib%2Fjce.jar%0A%20%20%20%20%20*%20file%3A%2FC%3A%2FProgram%2520Files%2FJava%2Fjdk1.8.0_361%2Fjre%2Flib%2Fcharsets.jar%0A%20%20%20%20%20*%20file%3A%2FC%3A%2FProgram%2520Files%2FJava%2Fjdk1.8.0_361%2Fjre%2Flib%2Fjfr.jar%0A%20%20%20%20%20*%20file%3A%2FC%3A%2FProgram%2520Files%2FJava%2Fjdk1.8.0_361%2Fjre%2Fclasses%0A%20%20%20%20%20*%20null%0A%20%20%20%20%20*%20----------------------%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8------------------------------%0A%20%20%20%20%20*%20C%3A%5CProgram%20Files%5CJava%5Cjdk1.8.0_361%5Cjre%5Clib%5Cext%0A%20%20%20%20%20*%20C%3A%5CWINDOWS%5CSun%5CJava%5Clib%5Cext%0A%20%20%20%20%20*%20sun.misc.Launcher%24ExtClassLoader%406433a2%0A%20%20%20%20%20*%2F%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E8%8E%B7%E5%8F%96%E5%BC%95%E5%AF%BC%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E8%83%BD%E5%A4%9F%E5%8A%A0%E8%BD%BD%E7%9A%84API%E8%B7%AF%E5%BE%84%0A%20%20%20%20%20%20%20%20URL%5B%5D%20urLs%20%3D%20Launcher.getBootstrapClassPath().getURLs()%3B%0A%20%20%20%20%20%20%20%20Stream.of(urLs).forEach(url%20-%3E%20System.out.println(url.toExternalForm()))%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%E4%BB%8E%E4%B8%8A%E9%9D%A2%E8%B7%AF%E5%BE%84%E4%B8%AD%E9%9A%8F%E6%84%8F%E9%80%89%E6%8B%A9%E4%B8%80%E4%B8%AA%E7%B1%BB%EF%BC%8C%E6%9D%A5%E7%9C%8B%E7%9C%8B%E4%BB%96%E7%9A%84%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9A%E8%8E%B7%E5%8F%96%E4%B8%BAnull%EF%BC%8C%E8%AF%B4%E8%AF%B4%E6%98%8E%E6%98%AF%E5%BC%95%E5%AF%BC%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%8A%A0%E8%BD%BD%E7%9A%84%0A%20%20%20%20%20%20%20%20ClassLoader%20classLoader%20%3D%20Provider.class.getClassLoader()%3B%0A%20%20%20%20%20%20%20%20System.out.println(classLoader)%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(%22----------------------%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8------------------------------%22)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%20%20%20%20%20%20%20%20String%20extDirs%20%3D%20System.getProperty(%22java.ext.dirs%22)%3B%0A%20%20%20%20%20%20%20%20Stream.of(extDirs.split(%22%3B%22)).forEach(System.out%3A%3Aprintln)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%E4%BB%8E%E4%B8%8A%E9%9D%A2%E8%B7%AF%E5%BE%84%E4%B8%AD%E9%9A%8F%E6%84%8F%E9%80%89%E6%8B%A9%E4%B8%80%E4%B8%AA%E7%B1%BB%EF%BC%8C%E6%9D%A5%E7%9C%8B%E7%9C%8B%E4%BB%96%E7%9A%84%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9A%E8%8E%B7%E5%8F%96%E4%B8%BAsun.misc.Launcher%24ExtClassLoader%406433a2%EF%BC%8C%E8%AF%B4%E8%AF%B4%E6%98%8E%E6%98%AF%E6%89%A9%E5%B1%95%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%8A%A0%E8%BD%BD%E7%9A%84%0A%20%20%20%20%20%20%20%20ClassLoader%20classLoader1%20%3D%20ECDSAOperations.class.getClassLoader()%3B%0A%20%20%20%20%20%20%20%20System.out.println(classLoader1)%3B%0A%20%20%20%20%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A-%20%E9%9A%94%E7%A6%BB%E5%8A%A0%E8%BD%BD%E7%B1%BB%EF%BC%8C%E4%BE%8B%E5%A6%82%E5%8A%A0%E8%BD%BD%E4%B8%AD%E9%97%B4%E4%BB%B6%E6%97%B6%EF%BC%8C%E5%87%BA%E7%8E%B0%E7%B1%BB%E5%90%8D%E7%A7%B0%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%8A%A0%E8%BD%BD%E6%97%B6%E5%87%BA%E7%8E%B0%E7%B1%BB%E5%90%8D%E5%86%B2%E7%AA%81%EF%BC%8C%E8%BF%99%E6%97%B6%E5%B0%B1%E8%A6%81%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E3%80%82%0A-%20%E4%BF%AE%E6%94%B9%E7%B1%BB%E7%9A%84%E5%8A%A0%E8%BD%BD%E6%96%B9%E5%BC%8F%0A-%20%E6%89%A9%E5%B1%95%E5%8A%A0%E8%BD%BD%E6%BA%90%EF%BC%8C%20%E6%89%A9%E5%B1%95%E5%AD%97%E8%8A%82%E7%A0%81%E7%9A%84%E6%9D%A5%E6%BA%90%0A-%20%E9%98%B2%E6%AD%A2%E6%BA%90%E7%A0%81%E6%B3%84%E6%BC%8F%EF%BC%8C%20%E5%AF%B9%E5%AD%97%E8%8A%82%E7%A0%81%E5%8A%A0%E5%AF%86%EF%BC%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E6%97%B6%E5%86%8D%E8%A7%A3%E5%AF%86%E3%80%82%0A%0A%0A%0A%E5%AE%9E%E7%8E%B0%E6%AD%A5%E9%AA%A4%0A%0A-%20%E7%BB%A7%E6%89%BFClassLoader%0A-%20%E9%87%8D%E5%86%99findClass(String%20name)%E6%96%B9%E6%B3%95%0A-%20%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E5%A4%8D%E6%9D%82%E7%9A%84%E5%8A%A0%E8%BD%BD%E9%9C%80%E6%B1%82%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9B%B4%E6%8E%A5%E7%BB%A7%E6%89%BFURLClassLoader%E7%B1%BB%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%B0%B1%E9%81%BF%E5%85%8D%E8%87%AA%E5%B7%B1%E5%8E%BB%E7%BC%96%E5%86%99findClass()%E6%96%B9%E6%B3%95%E5%8F%8A%E5%85%B6%E8%8E%B7%E5%8F%96%E5%AD%97%E8%8A%82%E7%A0%81%E6%B5%81%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E4%BD%BF%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E6%9B%B4%E5%8A%A0%E7%AE%80%E6%B4%81%E3%80%82%0A%0A%0A%0A%E8%8E%B7%E5%8F%96ClassLoader%E7%9A%84%E6%96%B9%E5%BC%8F%0A%0A-%20%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%B1%BB%E7%9A%84ClassLoader%20%3A%20class.getClassLoader()%0A%0A-%20%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84ClassLoader%20%EF%BC%9A%20Thread.currentThread().getContextClassLoader()%0A%0A-%20%E8%8E%B7%E5%8F%96%E7%B3%BB%E7%BB%9FClassLoader%20%EF%BC%9A%20ClassLoader.getSystemClassLoader%0A%0A-%20%E8%8E%B7%E5%8F%96%E8%B0%83%E7%94%A8%E8%80%85%E7%9A%84ClassLoader%20%EF%BC%9A%20DriverManager.getCallerClassLoader()%0A%0A%0A%0A%60%60%60java%0AClassLoader%20classLoader%20%3D%20Class.forName(%22java.lang.String%22).getClassLoader()%3B%0ASystem.out.println(classLoader)%3B%0A%0AClassLoader%20contextClassLoader%20%3D%20Thread.currentThread().getContextClassLoader()%3B%0ASystem.out.println(contextClassLoader)%3B%0A%0AClassLoader%20parent%20%3D%20ClassLoader.getSystemClassLoader().getParent()%3B%0ASystem.out.println(parent)%3B%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE%E6%9C%BA%E5%88%B6%0A%0A1.%20JVM%E5%AF%B9class%E6%96%87%E4%BB%B6%E9%87%87%E7%94%A8%E6%8C%89%E9%9C%80%E5%8A%A0%E8%BD%BD%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AF%E5%BD%93%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E8%AF%A5%E7%B1%BB%E6%97%B6%E6%89%8D%E4%BC%9A%E5%B0%86%E5%AE%83%E7%9A%84class%E6%96%87%E4%BB%B6%E5%8A%A0%E8%BD%BD%E5%88%B0%E5%86%85%E5%AD%98%E4%B8%AD%E7%94%9F%E6%88%90class%E5%AF%B9%E8%B1%A1%E3%80%82%E8%80%8C%E4%B8%94%E5%8A%A0%E8%BD%BDclass%E6%96%87%E4%BB%B6%E6%97%B6%EF%BC%8CJVM%E9%87%87%E7%94%A8%E5%8F%8C%60%E4%BA%B2%E5%A7%94%E6%B4%BE%E6%A8%A1%E5%BC%8F%60%0A%0A2.%20%60%E4%BA%B2%E5%A7%94%E6%B4%BE%E6%A8%A1%E5%BC%8F%60%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%0A%0A-%20%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E6%94%B6%E5%88%B0%E5%8A%A0%E8%BD%BD%E8%AF%B7%E6%B1%82%EF%BC%8C%E5%B9%B6%E4%B8%8D%E6%98%AF%E8%87%AA%E5%B7%B1%E5%85%88%E5%8E%BB%E5%8A%A0%E8%BD%BD%EF%BC%8C%E8%80%8C%E6%98%AF%E6%8A%8A%E7%A9%BA%E4%B8%8A%E8%AF%B7%E6%B1%82%E4%BA%A4%E7%BB%99%E5%85%B6%E7%88%B6%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%8E%BB%E6%89%A7%E8%A1%8C%0A%0A-%20%E5%A6%82%E6%9E%9C%E7%88%B6%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E8%BF%98%E5%AD%98%E5%9C%A8%E7%88%B6%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%EF%BC%8C%E5%88%99%E4%BE%9D%E6%AC%A1%E5%90%91%E4%B8%8A%E5%A7%94%E6%89%98%EF%BC%8C%E5%88%B0%E8%BE%BE%E9%A1%B6%E5%B1%82%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%0A%0A-%20%E5%A6%82%E6%9E%9C%E7%88%B6%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%8F%AF%E4%BB%A5%E5%AE%8C%E6%88%90%E5%8A%A0%E8%BD%BD%E4%BB%BB%E5%8A%A1%E5%88%99%E6%88%90%E5%8A%9F%E8%BF%94%E5%9B%9E%EF%BC%8C%E5%90%A6%E5%88%99%E4%BA%A4%E7%94%B1%E5%AD%90%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E5%8E%BB%E5%B0%9D%E8%AF%95%E5%8A%A0%E8%BD%BD%EF%BC%8C%E4%BE%9D%E6%AC%A1%E5%90%91%E4%B8%8B%E5%A7%94%E6%89%98%E3%80%82%0A%0A3.%20%E4%BC%98%E5%8A%BF%0A%0A-%20%E9%81%BF%E5%85%8D%E9%87%8D%E5%A4%8D%E5%8A%A0%E8%BD%BD%0A-%20%E4%BF%9D%E6%8A%A4%E7%A8%8B%E5%BA%8F%E5%AE%89%E5%85%A8%EF%BC%8C%E9%98%B2%E6%AD%A2%E6%A0%B8%E5%BF%83API%E8%A2%AB%E9%9A%8F%E6%84%8F%E7%AF%A1%E6%94%B9%0A%0A%0A%0A%23%23%23%23%20%E7%B1%BB%E7%9A%84%E4%B8%BB%E5%8A%A8%E4%BD%BF%E7%94%A8%E4%B8%8E%E8%A2%AB%E5%8A%A8%E4%BD%BF%E7%94%A8%0A%0A1.%20%E4%B8%A4%E4%B8%AAClass%E6%96%87%E4%BB%B6%E6%98%AF%E5%90%A6%E4%B8%BA%E5%90%8C%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%A4%E4%B8%AA%E5%BF%85%E8%A6%81%E6%9D%A1%E4%BB%B6%0A%20%20%20-%20%E7%B1%BB%E7%9A%84%E5%AE%8C%E6%95%B4%E5%85%A8%E7%B1%BB%E5%90%8D%E5%BF%85%E9%A1%BB%E4%B8%80%E8%87%B4%EF%BC%8C%E5%8C%85%E6%8B%AC%E5%8C%85%E5%90%8D%0A%20%20%20-%20%E5%8A%A0%E8%BD%BD%E8%BF%99%E4%B8%AA%E7%B1%BB%E7%9A%84ClassLoader%E5%AE%9E%E4%BE%8B%E5%AF%B9%E8%B1%A1%E5%BF%85%E9%A1%BB%E7%9B%B8%E5%90%8C%0A%0A%0A2.%20%E7%B1%BB%E7%9A%84%E4%B8%BB%E5%8A%A8%E4%BD%BF%E7%94%A8%0A%0A%20%20%20-%20%E5%88%9B%E5%BB%BA%E7%B1%BB%E7%9A%84%E5%AE%9E%E4%BE%8B%20%E5%8D%B3%20new%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%AE%9E%E4%BE%8B%0A%0A%20%20%20-%20%E8%AE%BF%E9%97%AE%E6%9F%90%E4%B8%AA%E7%B1%BB%E6%88%96%E6%8E%A5%E5%8F%A3%E7%9A%84%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%EF%BC%8C%E6%88%96%E8%80%85%E5%AF%B9%E8%AF%A5%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC%0A%0A%20%20%20-%20%E8%B0%83%E7%94%A8%E7%B1%BB%E7%9A%84%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%0A%0A%20%20%20-%20%E5%8F%8D%E5%B0%84%20Class.forName(%22com.chris.jvm.ClassLoaderTest%22)%0A%0A%20%20%20-%20%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%80%E4%B8%AA%E7%B1%BB%E7%9A%84%E5%AD%90%E7%B1%BB%0A%0A%20%20%20-%20JVM%E5%90%AF%E5%8A%A8%E6%97%B6%E8%A2%AB%E6%A0%87%E6%98%8E%E4%B8%BA%E5%90%AF%E5%8A%A8%E7%B1%BB%E7%9A%84%E7%B1%BB%0A%0A%20%20%20-%20%E9%99%A4%E4%B8%8A%E9%9D%A2%E4%B8%83%E7%A7%8D%E5%A4%96%EF%BC%8C%E5%85%B6%E4%BB%96%E4%BD%BF%E7%94%A8Java%E7%B1%BB%E7%9A%84%E6%96%B9%E5%BC%8F%E9%83%BD%E8%A2%AB%E7%9C%8B%E4%BD%9C%E6%98%AF%E5%AF%B9%E7%B1%BB%E7%9A%84%E8%A2%AB%E5%8A%A8%E4%BD%BF%E7%94%A8%EF%BC%8C%60%E9%83%BD%E4%B8%8D%E4%BC%9A%E5%AF%BC%E8%87%B4%E7%B1%BB%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%60%0A%0A%0A%0A%23%23%23%20%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E5%8C%BA%E5%92%8C%E5%86%85%E9%83%A8%E7%BB%93%E6%9E%84%0A%0A%3E%20%E7%81%B0%E8%89%B2%E7%9A%84%E4%B8%BA%E5%8D%95%E7%8B%AC%E7%BA%BF%E7%A8%8B%E7%A7%81%E6%9C%89%E7%9A%84%EF%BC%8C%E7%BA%A2%E8%89%B2%E7%9A%84%E4%B8%BA%E5%A4%9A%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%85%B1%E4%BA%AB%E7%9A%84%0A%3E%0A%3E%20%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%EF%BC%9A%E7%8B%AC%E7%AB%8B%E5%8C%85%E6%8B%AC%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%EF%BC%8C%E6%A0%88%EF%BC%8C%E6%9C%AC%E5%9C%B0%E6%A0%88%0A%3E%0A%3E%20%E7%BA%BF%E7%A8%8B%E9%97%B4%E5%85%B1%E4%BA%AB%EF%BC%9A%E5%A0%86%EF%BC%8C%E5%A0%86%E5%A4%96%E5%86%85%E5%AD%98%EF%BC%88%E6%96%B9%E6%B3%95%E5%8C%BA%E6%88%96%E8%80%85%E5%8F%AB%E5%85%83%E7%A9%BA%E9%97%B4%EF%BC%89%20%0A%3E%0A%3E%20%E5%AF%B9%E4%BA%8EJVM%E7%9A%84%E4%BC%98%E5%8C%96%E9%87%8D%E7%82%B9%E5%9C%A8%E4%BA%8E%E5%A0%86%E7%A9%BA%E9%97%B4%5B95%25%5D%E5%92%8C%E6%96%B9%E6%B3%95%E5%8C%BA%5B5%25%5D%EF%BC%8C%E6%A0%88%E7%9A%84%E4%BD%9C%E7%94%A8%E5%BE%88%E7%AE%80%E5%8D%95%E5%B0%B1%E6%98%AF%E8%BF%9B%E6%A0%88%E5%92%8C%E5%87%BA%E6%A0%88%EF%BC%8C%E4%BD%86%E6%98%AF%E4%B9%9F%E4%BC%9A%E5%87%BA%E7%8E%B0%E5%86%85%E5%AD%98%E6%BA%A2%E5%87%BA%E7%9A%84%E9%97%AE%E9%A2%98%0A%3E%0A%3E%20%E4%B8%80%E4%B8%AAJVM%E8%BF%9B%E7%A8%8B%E5%AF%B9%E5%BA%94%E4%B8%80%E4%B8%AARuntime.class%E7%9A%84%E5%94%AF%E4%B8%80%E5%AE%9E%E4%BE%8B%0A%0A!%5Bb765c3e7f3165e078231a4ed0c6b8e33.png%5D(en-resource%3A%2F%2Fdatabase%2F1556%3A0)%0A%0A%0A%23%23%23%23%20%E7%BA%BF%E7%A8%8B%0A%0A%E5%9C%A8Hotspot%20JVM%E9%87%8C%E9%9D%A2%EF%BC%8C%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%83%BD%E4%B8%8E%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%9C%AC%E5%9C%B0%E7%BA%BF%E7%A8%8B%E7%9B%B4%E6%8E%A5%E6%98%A0%E5%B0%84%0A%0A-%20%E5%BD%93%E4%B8%80%E4%B8%AAJava%E7%BA%BF%E7%A8%8B%E5%87%86%E5%A4%87%E5%A5%BD%E6%89%A7%E8%A1%8C%E4%BB%A5%E5%90%8E%EF%BC%8C%E6%AD%A4%E6%97%B6%E4%B8%80%E4%B8%AA%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%9C%AC%E5%9C%B0%E7%BA%BF%E7%A8%8B%E4%B9%9F%E5%90%8C%E6%97%B6%E5%88%9B%E5%BB%BA%2CJava%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E7%BB%88%E6%AD%A2%E5%90%8E%EF%BC%8C%E6%9C%AC%E5%9C%B0%E7%BA%BF%E7%A8%8B%E4%B9%9F%E4%BC%9A%E5%9B%9E%E6%94%B6%E3%80%82%0A-%20%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E8%B4%9F%E8%B4%A3%E6%89%80%E6%9C%89%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%AE%89%E6%8E%92%E8%B0%83%E5%BA%A6%E5%88%B0%E4%BB%BB%E4%BD%95%E4%B8%80%E4%B8%AA%E5%8F%AF%E7%94%A8%E7%9A%84CPU%E4%B8%8A%E3%80%82%E4%B8%80%E6%97%A6%E6%9C%AC%E5%9C%B0%E7%BA%BF%E7%A8%8B%E5%88%9D%E5%A7%8B%E5%8C%96%E6%88%90%E5%8A%9F%EF%BC%8C%E5%AE%83%E5%B0%B1%E4%BC%9A%E8%B0%83%E7%94%A8Java%E7%BA%BF%E7%A8%8B%E4%B8%AD%E7%9A%84run%E6%96%B9%E6%B3%95%E3%80%82%0A%0A%0A%0A%23%23%23%23%20%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%0A%0A-%20%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%E5%8F%88%E5%8F%ABPC%E5%AF%84%E5%AD%98%E5%99%A8%EF%BC%8C%20JVM%E4%B8%AD%E7%9A%84PC%E5%AF%84%E5%AD%98%E5%99%A8%E6%98%AF%E5%AF%B9%E7%89%A9%E7%90%86PC%E5%AF%84%E5%AD%98%E5%99%A8%E7%9A%84%E4%B8%80%E7%A7%8D%E6%8A%BD%E8%B1%A1%E6%A8%A1%E6%8B%9F%0A%0A-%20%E5%AE%83%E7%94%A8%E6%9D%A5%E5%AD%98%E5%82%A8%E6%8C%87%E5%90%91%E4%B8%8B%E4%B8%80%E6%9D%A1%E6%8C%87%E4%BB%A4%E7%9A%84%E5%9C%B0%E5%9D%80%EF%BC%8C%E4%BB%BB%E4%BD%95%E6%97%B6%E9%97%B4%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%83%BD%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%E5%9C%A8%E6%89%A7%E8%A1%8C%EF%BC%8C%E7%A7%B0%E4%B9%8B%E4%B8%BA%E5%BD%93%E5%89%8D%E6%96%B9%E6%B3%95%EF%BC%8C%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%E4%BC%9A%E5%AD%98%E5%82%A8%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E6%AD%A3%E5%9C%A8%E6%89%A7%E8%A1%8CJava%E6%96%B9%E6%B3%95%E7%9A%84JVM%E6%8C%87%E4%BB%A4%E5%9C%B0%E5%9D%80%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%98%AF%E5%9C%A8%E6%89%A7%E8%A1%8Cnavtive%E6%96%B9%E6%B3%95%EF%BC%8C%E5%88%99%E6%98%AF%E6%9C%AA%E6%8C%87%E5%AE%9A%EF%BC%88undefined)%0A%0A-%20%60JVM%E4%B8%8D%E4%BC%9A%E5%AF%B9PC%E5%AF%84%E5%AD%98%E5%99%A8%E8%BF%9B%E8%A1%8CGC%EF%BC%8C%E5%9B%A0%E4%B8%BA%E5%AE%83%E4%B8%8D%E4%BC%9AOOM.%60%0A%0A%0A%0A%3E%20%E5%B7%A6%E8%BE%B9%E7%9A%84%E6%95%B0%E5%AD%97%E7%A7%B0%E4%B8%BA%E6%8C%87%E4%BB%A4%E5%9C%B0%E5%9D%80%EF%BC%8C%E5%8F%B3%E8%BE%B9%E4%B8%BA%E6%93%8D%E4%BD%9C%E6%8C%87%E4%BB%A4%0A%3E%0A%3E%20%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%E5%AD%98%E5%82%A8%E7%9A%84%E5%B0%B1%E6%98%AF%E5%85%B6%E4%B8%AD%E7%9A%84%E6%9F%90%E4%B8%80%E4%BD%8D%E6%8C%87%E4%BB%A4%E5%9C%B0%E5%9D%80%0A%0A%60%60%60java%0Apublic%20class%20PCRegisterTest%20%7B%0A%0A%20%20%20%20%40Test%0A%20%20%20%20public%20void%20test()%20%7B%0A%20%20%20%20%20%20%20%20int%20i%20%3D%2010%3B%0A%20%20%20%20%20%20%20%20int%20j%20%3D%2020%3B%0A%20%20%20%20%20%20%20%20int%20k%20%3D%20i%20%2B%20j%3B%0A%20%20%20%20%20%20%20%20String%20s%20%3D%20%22abc%22%3B%0A%0A%20%20%20%20%20%20%20%20System.out.println(i)%3B%0A%20%20%20%20%20%20%20%20System.out.println(k)%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%E5%AD%97%E8%8A%82%E7%A0%81%E6%8C%87%E4%BB%A4%0A%200%20bipush%2010%0A%202%20istore_1%0A%203%20bipush%2020%0A%205%20istore_2%0A%206%20iload_1%0A%207%20iload_2%0A%208%20iadd%0A%209%20istore_3%0A10%20ldc%20%232%20%3Cabc%3E%0A12%20astore%204%0A14%20getstatic%20%233%20%3Cjava%2Flang%2FSystem.out%20%3A%20Ljava%2Fio%2FPrintStream%3B%3E%0A17%20iload_1%0A18%20invokevirtual%20%234%20%3Cjava%2Fio%2FPrintStream.println%20%3A%20(I)V%3E%0A21%20getstatic%20%233%20%3Cjava%2Flang%2FSystem.out%20%3A%20Ljava%2Fio%2FPrintStream%3B%3E%0A24%20iload_3%0A25%20invokevirtual%20%234%20%3Cjava%2Fio%2FPrintStream.println%20%3A%20(I)V%3E%0A28%20return%0A%60%60%60%0A%0A%3E%20-%20%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E6%9C%89PC%E5%AF%84%E5%AD%98%E5%99%A8%0A%3E%0A%3E%20%20%20%E5%9B%A0%E4%B8%BACPU%E9%9C%80%E8%A6%81%E4%B8%8D%E5%81%9C%E7%9A%84%E5%9C%A8%E5%90%84%E7%BA%BF%E7%A8%8B%E9%97%B4%E8%BF%9B%E8%A1%8C%E5%88%87%E6%8D%A2%EF%BC%8C%E5%BD%93%E5%88%87%E6%8D%A2%E5%9B%9E%E6%9D%A5%E7%9A%84%E6%97%B6%E5%80%99%E4%B8%BB%E9%9C%80%E8%A6%81%E7%9F%A5%E9%81%93%E4%B8%8A%E6%AC%A1%E6%98%AF%E4%BB%8E%E5%93%AA%E9%87%8C%E5%BC%80%E5%A7%8B%E6%89%A7%E8%A1%8C%E7%9A%84%E3%80%82JVM%E7%9A%84%E5%AD%97%E8%8A%82%E7%A0%81%E8%A7%A3%E9%87%8A%E5%99%A8%E5%B0%B1%E9%9C%80%E8%A6%81%E9%80%9A%E8%BF%87%E6%94%B9%E5%8F%98PC%E5%AF%84%E5%AD%98%E5%99%A8%E7%9A%84%E5%80%BC%E6%9D%A5%E6%98%8E%E7%A1%AE%E4%B8%8B%E4%B8%80%E6%9D%A1%E5%BA%94%E8%AF%A5%E6%89%A7%E8%A1%8C%E4%BB%80%E4%B9%88%E6%A0%B7%E7%9A%84%E5%AD%97%E8%8A%82%E7%A0%81%E6%8C%87%E4%BB%A4%E3%80%82%0A%3E%0A%3E%20-%20%E4%B8%BA%E4%BB%80%E4%B9%88PC%E5%AF%84%E5%AD%98%E5%99%A8%E8%A6%81%E8%AE%BE%E7%BD%AE%E4%B8%BA%E7%BA%BF%E7%A8%8B%E7%A7%81%E6%9C%89%E7%9A%84%0A%3E%0A%3E%20%20%20%0A%0A%0A%23%23%23%20%E6%A0%88%0A%0A%23%23%23%23%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%20-%20%E6%A0%88%E6%98%AF%E8%BF%90%E8%A1%8C%E6%97%B6%E7%9A%84%E5%8D%95%E4%BD%8D%EF%BC%8C%E8%80%8C%E5%A0%86%E6%98%AF%E5%AD%98%E5%82%A8%E7%9A%84%E5%8D%95%E4%BD%8D%0A%3E%0A%3E%20-%20%E6%A0%88%E8%A7%A3%E5%86%B3%E7%9A%84%E6%98%AF%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E5%8D%B3%E7%A8%8B%E5%BA%8F%E5%A6%82%E4%BD%95%E8%BF%90%E8%A1%8C%EF%BC%8C%E6%88%96%E8%80%85%E8%AF%B4%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE%0A%3E%0A%3E%20-%20%E5%A0%86%E8%A7%A3%E5%86%B3%E7%9A%84%E6%98%AF%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E5%8D%B3%E6%95%B0%E6%8D%AE%E6%80%8E%E4%B9%88%E6%94%BE%EF%BC%8C%E6%94%BE%E5%9C%A8%E5%93%AA%E9%87%8C%E3%80%82%60%E6%96%B9%E6%B3%95%E5%86%85%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E6%94%BE%E5%9C%A8%E6%A0%88%E9%87%8C%E9%9D%A2%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%98%AF%E5%BC%95%E7%94%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%88%99%E6%94%BE%E5%9C%A8%E5%A0%86%E9%87%8C%E9%9D%A2%EF%BC%8C%E6%A0%88%E9%87%8C%E9%9D%A2%E5%8F%AA%E5%AD%98%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BC%95%E7%94%A8%E6%97%A0%E5%BF%A7%E5%9C%B0%E5%9D%80%60%0A%3E%20-%20%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%9C%A8%E5%88%9B%E5%BB%BA%E6%97%B6%E9%83%BD%E4%BC%9A%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%A0%88%EF%BC%8C%20%E9%87%8C%E9%9D%A2%E6%98%AF%E4%B8%80%E4%B8%AA%E4%B8%AA%E7%9A%84%E6%A0%88%E5%B8%A7%5Bstack%20frame%5D%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%A0%88%E5%B8%A7%E5%AF%B9%E5%BA%94%E4%B8%80%E4%B8%AAJava%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%0A%3E%20-%20%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%B4%BB%E5%8A%A8%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%B8%AD%EF%BC%8C%E4%B8%80%E4%B8%AA%E6%97%B6%E9%97%B4%E7%82%B9%E4%B8%8A%E5%8F%AA%E4%BC%9A%E6%9C%89%E4%B8%80%E4%B8%AA%E6%B4%BB%E5%8A%A8%E7%9A%84%E6%A0%88%E5%B8%A7%EF%BC%8C%E8%BF%99%E4%B8%AA%E6%A0%88%E5%B8%A7%E8%A2%AB%E7%A7%B0%E4%B8%BA%E5%BD%93%E5%89%8D%E6%A0%88%E5%B8%A7%5Bcurrent%20frame%5D%EF%BC%8C%E5%BD%93%E5%89%8D%E6%A0%88%E5%B8%A7%E5%AF%B9%E5%BA%94%E7%9A%84%E6%96%B9%E6%B3%95%E7%A7%B0%E4%B8%BA%E5%BD%93%E5%89%8D%E6%96%B9%E6%B3%95%5Bcurrent%20method%5D%EF%BC%8C%E5%AE%9A%E4%B9%89%E6%96%B9%E6%B3%95%E7%9A%84%E7%B1%BB%E7%A7%B0%E4%B8%BA%E5%BD%93%E5%89%8D%E7%B1%BB%5Bcurrent%20class%5D%0A%3E%20-%20%E4%B8%8D%E5%90%8C%E7%BA%BF%E7%A8%8B%E9%97%B4%E7%9A%84%E7%BA%BF%E5%B8%A7%E4%B8%8D%E8%83%BD%E7%9B%B8%E4%BA%92%E5%BC%95%E7%94%A8%EF%BC%8C%E5%8D%B3%E4%B8%8D%E8%83%BD%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%A0%88%E5%B8%A7%E9%87%8C%E9%9D%A2%E5%BC%95%E7%94%A8%E5%8F%A6%E5%A4%96%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%9A%84%E6%A0%88%E5%B8%A7%0A%3E%20-%20Java%E6%96%B9%E6%B3%95%E7%9A%84%E7%BB%93%E6%9D%9F%E6%96%B9%E5%BC%8F%EF%BC%8C%20%E7%AC%AC%E4%B8%80%E7%A7%8D%EF%BC%9Areturn%EF%BC%8C%20%E7%AC%AC%E4%BA%8C%E7%A7%8D%EF%BC%9A%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E4%B8%AD%E5%87%BA%E7%8E%B0%E6%9C%AA%E6%8D%95%E8%8E%B7%E5%A4%84%E7%90%86%E7%9A%84%E5%BC%82%E5%B8%B8%EF%BC%8C%E4%BB%A5%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%E7%9A%84%E6%96%B9%E6%B3%95%E7%BB%93%E6%9D%9F%0A%0A%0A%60%60%60java%0A%20%2F**%0A%20%20*%20%E4%BB%8E%E6%89%93%E5%8D%B0%E7%BB%93%E6%9E%9C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E8%BF%9B%E6%A0%88%E5%92%8C%E5%87%BA%E6%A0%88%E7%9A%84%E6%A0%88%E5%B8%A7%E7%9A%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%0A%20%20*%2F%0A%40Test%0Apublic%20void%20method1()%20%7B%0A%20%20%20%20System.out.println(%22method1%20begin%22)%3B%0A%20%20%20%20method2()%3B%0A%20%20%20%20System.out.println(%22method1%20end%22)%3B%0A%7D%0A%0Aprivate%20int%20method2()%20%7B%0A%20%20%20%20System.out.println(%22method2%20begin%22)%3B%0A%20%20%20%20int%20i%20%3D%203%3B%0A%20%20%20%20int%20m%20%3D%20(int)%20method3()%3B%0A%20%20%20%20System.out.println(%22method2%20going%20to%20end%22)%3B%0A%0A%20%20%20%20return%20i%20%2B%20m%3B%0A%7D%0A%0Aprivate%20double%20method3()%20%7B%0A%20%20%20%20System.out.println(%22method3%20begin%22)%3B%0A%20%20%20%20double%20j%20%3D%2020.0%3B%0A%20%20%20%20System.out.println(%22method3%20going%20to%20end%22)%3B%0A%20%20%20%20return%20j%3B%0A%7D%0A%0A%E7%BB%93%E6%9E%9C%0Amethod1%20begin%0Amethod2%20begin%0Amethod3%20begin%0Amethod3%20going%20to%20end%0Amethod2%20going%20to%20end%0Amethod1%20end%0A%60%60%60%0A!%5Bc0a17816fb5ca2038afc2934ddb60a0f.png%5D(en-resource%3A%2F%2Fdatabase%2F1558%3A0)%0A%0A%0A%23%23%23%23%20%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%0A%0A%3E%20%E6%A0%88%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%92%8C%E7%BA%BF%E7%A8%8B%E4%B8%80%E8%87%B4%EF%BC%8C%E7%BA%BF%E7%A8%8B%E7%BB%93%E6%9D%9F%EF%BC%8C%E4%B8%BA%E8%BF%99%E4%B8%AA%E7%BA%BF%E7%A8%8B%E4%BF%9D%E5%88%9B%E5%BB%BA%E7%9A%84%E6%A0%88%E4%B9%9F%E5%B0%B1%E7%BB%93%E6%9D%9F%0A%0A%23%23%23%23%20%E4%BD%9C%E7%94%A8%0A%0A%3E%20%E4%B8%BB%E7%AE%A1Java%E7%A8%8B%E5%BA%8F%E7%9A%84%E8%BF%90%E8%A1%8C%EF%BC%8C%E5%AE%83%E4%BF%9D%E5%AD%98%E6%96%B9%E6%B3%95%E7%9A%84%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%60%5B8%E7%A7%8D%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BC%95%E7%94%A8%E5%9C%B0%E5%9D%80%5D%60%EF%BC%8C%E9%83%A8%E5%88%86%E7%BB%93%E6%9E%9C%EF%BC%8C%E5%B9%B6%E5%8F%82%E4%B8%8E%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%E5%92%8C%E8%BF%94%E5%9B%9E%0A%3E%0A%3E%20%E6%A0%88%E5%8F%AA%E6%9C%89%E4%B8%A4%E7%A7%8D%E6%93%8D%E4%BD%9C%0A%3E%0A%3E%20-%20%E6%AF%8F%E4%B8%AA%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%EF%BC%8C%E4%BC%B4%E9%9A%8F%E7%9D%80%E8%BF%9B%E6%A0%88%E6%88%96%E7%A7%B0%E4%B8%BA%E5%8E%8B%E6%A0%88%0A%3E%20-%20%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9D%9F%E5%90%8E%E5%87%BA%E6%A0%88%0A%3E%0A%3E%20%60%E5%AF%B9%E4%BA%8E%E6%A0%88%E6%9D%A5%E8%AF%B4%E6%98%AF%E4%B8%8D%E5%AD%98%E5%9C%A8%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%5BGC%5D%2C%E4%BD%86%E5%AD%98%E5%9C%A8OOM%60%0A%0A%0A%0A%23%23%23%23%20%E6%A0%88%E5%8F%AF%E8%83%BD%E5%87%BA%E7%8E%B0%E7%9A%84%E5%BC%82%E5%B8%B8%0A%0AJVM%E8%A7%84%E8%8C%83%E5%85%81%E8%AE%B8Java%E6%A0%88%E7%9A%84%E5%A4%A7%E5%B0%8F%E6%98%AF%E5%8A%A8%E6%80%81%E7%9A%84%E6%88%96%E8%80%85%E6%98%AF%E5%9B%BA%E5%AE%9A%E4%B8%8D%E5%8F%98%E7%9A%84%0A%0A-%20%E5%A6%82%E6%9E%9C%E6%A0%88%E5%A4%A7%E5%B0%8F%E6%98%AF%E5%9B%BA%E5%AE%9A%E4%B8%8D%E5%8F%98%E7%9A%84%EF%BC%8C%E6%AF%8F%E4%B8%AA%E7%BA%BF%E7%A8%8B%E7%9A%84%E6%A0%88%E5%AE%B9%E9%87%8F%E5%8F%AF%E4%BB%A5%E5%9C%A8%E7%BA%BF%E7%A8%8B%E5%88%9B%E5%BB%BA%E6%97%B6%E7%8B%AC%E7%AB%8B%E9%80%89%E5%AE%9A%E3%80%82%E5%A6%82%E6%9E%9C%E7%BA%BF%E7%A8%8B%E8%AF%B7%E6%B1%82%E7%9A%84%E6%A0%88%E5%AE%B9%E9%87%8F%E8%B6%85%E8%BF%87JVM%E5%85%81%E8%AE%B8%E7%9A%84%E6%9C%80%E5%A4%A7%E5%AE%B9%E9%87%8F%EF%BC%8CJVM%E4%BC%9A%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%60StackOverflowError%60%E5%BC%82%E5%B8%B8%0A-%20%E5%A6%82%E6%9E%9C%E6%A0%88%E5%A4%A7%E5%B0%8F%E6%98%AF%E5%8A%A8%E6%80%81%E6%89%A9%E5%B1%95%E7%9A%84%EF%BC%8C%E4%BD%86%E5%9C%A8%E5%B0%9D%E8%AF%95%E6%89%A9%E5%B1%95%E6%97%B6%E6%97%A0%E6%B3%95%E7%94%B3%E8%AF%B7%E5%88%B0%E8%B6%B3%E5%A4%9F%E7%9A%84%E5%86%85%E5%AD%98%EF%BC%8C%E6%88%96%E8%80%85%E5%9C%A8%E5%88%9B%E5%BB%BA%E6%96%B0%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%97%B6%E6%B2%A1%E6%9C%89%E8%B6%B3%E5%A4%9F%E7%9A%84%E5%86%85%E5%AD%98%E5%8E%BB%E5%88%9B%E5%BB%BA%E5%AF%B9%E5%BA%94%E7%9A%84%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%A0%88%EF%BC%8CJVM%E4%BC%9A%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%60OutOfMemoryError%60%E5%BC%82%E5%B8%B8%0A%0A%60%60%60java%0Ahttps%3A%2F%2Fdocs.oracle.com%2Fjavase%2F8%2Findex.html%0Ahttps%3A%2F%2Fdocs.oracle.com%2Fjavase%2F8%2Fdocs%2Ftechnotes%2Ftools%2Funix%2Fjava.html%23CBBFHAJA%0A%0A-Xss%20size%0ASets%20the%20thread%20stack%20size%20(in%20bytes).%20Append%20the%20letter%20k%20or%20K%20to%20indicate%20KB%2C%20m%20or%20M%20to%20indicate%20MB%2C%20g%20or%20G%20to%20indicate%20GB.%20The%20default%20value%20depends%20on%20the%20platform%3A%0A%0ALinux%2FARM%20(32-bit)%3A%20320%20KB%0ALinux%2Fi386%20(32-bit)%3A%20320%20KB%0ALinux%2Fx64%20(64-bit)%3A%201024%20KB%0AmacOS%20(64-bit)%3A%201024%20KB%0AOracle%20Solaris%2Fi386%20(32-bit)%3A%20320%20KB%0AOracle%20Solaris%2Fx64%20(64-bit)%3A%201024%20KB%0AWindows%3A%20The%20default%20value%20depends%20on%20virtual%20memory%0AThe%20following%20examples%20set%20the%20thread%20stack%20size%20to%201024%20KB%20in%20different%20units%3A%0A%0A-Xss1m%0A-Xss1024k%0A-Xss1048576%0AThis%20option%20is%20similar%20to%20-XX%3AThreadStackSize.%0A%60%60%60%0A%0A%0A%0A%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E6%B2%A1%E6%9C%89%E8%AE%BE%E7%BD%AE%E6%A0%88%E5%A4%A7%E5%B0%8F%E6%97%B6%EF%BC%9A11344%0A%20*%2011344%0A%20*%20java.lang.StackOverflowError%0A%20*%20%09at%20sun.nio.cs.UTF_8%24Encoder.encodeLoop(UTF_8.java%3A691)%0A%20*%20%E8%AE%BE%E7%BD%AE%E6%A0%88%E5%A4%A7%E5%B0%8F%E6%97%B6%EF%BC%9A-Xss256k%0A%20*%202263%0A%20*%20java.lang.StackOverflowError%0A%20*%20%09at%20sun.nio.cs.UTF_8.updatePositions(UTF_8.java%3A77)%0A%20*%2F%0A%40Test%0Apublic%20void%20testStack()%20%7B%0A%20%20%20%20System.out.println(i)%3B%0A%20%20%20%20i%2B%2B%3B%0A%20%20%20%20testStack()%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%23%23%20%E6%A0%88%E5%B8%A7%E7%9A%84%E5%86%85%E9%83%A8%E7%BB%93%E6%9E%84%0A%0A%3E%20%E6%AF%8F%E4%B8%AA%E6%A0%88%E5%B8%A7%E4%B8%AD%E5%AD%98%E5%82%A8%E7%9D%80%E4%BA%94%E9%83%A8%E5%88%86%0A%3E%0A%3E%20-%20%60%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%20%5BLocal%20Variables%5D%60%E6%88%96%E7%A7%B0%E4%B8%BA%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E8%A1%A8%0A%3E%20-%20%60%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%20%20%5BOperand%20Stack%5D%60%0A%3E%20-%20%E5%8A%A8%E6%80%81%E9%93%BE%E6%8E%A5%20%5BDynamic%20Linking%5D%20%E5%8D%B3%E6%8C%87%E5%90%91%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0%E7%9A%84%E6%96%B9%E6%B3%95%E5%BC%95%E7%94%A8%0A%3E%20-%20%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%9C%B0%E5%9D%80%20%5BReturn%20Address%5D%0A%3E%20-%20%E4%B8%80%E4%BA%9B%E9%99%84%E5%8A%A0%E4%BF%A1%E6%81%AF%0A%0A%0A%0A%23%23%23%23%23%20%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%20%5BLocal%20Variables%5D%0A%0A-%20%E6%98%AF%E4%B8%80%E4%B8%AA%E6%95%B0%E5%AD%97%E6%95%B0%E7%BB%84%EF%BC%8C%E4%B8%BB%E8%A6%81%E7%94%A8%E4%BA%8E%E5%AD%98%E5%82%A8%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E5%92%8C%E5%AE%9A%E4%B9%89%E5%9C%A8%E6%96%B9%E6%B3%95%E4%BD%93%E5%86%85%E7%9A%84%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%EF%BC%8C%E8%BF%99%E4%BA%9B%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%8C%85%E6%8B%AC%208%E7%A7%8D%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BC%95%E7%94%A8%E5%9C%B0%E5%9D%80%5Breference%5D%E5%92%8C%E8%BF%94%E5%9B%9E%E5%9C%B0%E5%9D%80%5BreturnAddress%5D%E7%B1%BB%E5%9E%8B%0A-%20%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E5%BB%BA%E7%AB%8B%E5%9C%A8%E7%BA%BF%E7%A8%8B%E7%9A%84%E6%A0%88%E4%B8%8A%EF%BC%8C%E6%98%AF%E7%BA%BF%E7%A8%8B%E7%A7%81%E6%9C%89%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98%0A-%20%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E7%9A%84%E5%A4%A7%E5%B0%8F%E6%98%AF%E5%9C%A8%E7%BC%96%E8%AF%91%E6%9C%9F%E7%A1%AE%E5%AE%9A%E4%B8%8B%E6%9D%A5%E7%9A%84%EF%BC%8C%E5%B9%B6%E4%BF%9D%E5%AD%98%E5%9C%A8%E5%AF%B9%E5%BA%94%E6%96%B9%E6%B3%95%E7%9A%84Code%E5%B1%9E%E6%80%A7%E7%9A%84maximum%20local%20variables%E6%95%B0%E6%8D%AE%E9%A1%B9%E4%B8%AD%E3%80%82%E5%9C%A8%E6%96%B9%E6%B3%95%E8%BF%90%E8%A1%8C%E6%97%B6%E4%B8%8D%E4%BC%9A%E6%94%B9%E5%8F%98%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E7%9A%84%E5%A4%A7%E5%B0%8F%E3%80%82%0A%0A%0A%0A%3E%20locals%3D3%20main%E6%96%B9%E6%B3%95%E4%B8%AD%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E9%95%BF%E5%BA%A6%0A%0A%60%60%60java%0Apublic%20class%20LocalVariablesTest%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20LocalVariablesTest%20test%20%3D%20new%20LocalVariablesTest()%3B%0A%20%20%20%20%20%20%20%20int%20num%20%3D%2010%3B%0A%20%20%20%20%20%20%20%20test.test1()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20void%20test1()%20%7B%0A%20%20%20%20%20%20%20%20Date%20date%20%3D%20new%20Date()%3B%0A%20%20%20%20%20%20%20%20String%20name1%20%3D%20%22my%20name%20is%20chris%22%3B%0A%20%20%20%20%20%20%20%20String%20info%20%3D%20test2(date%2C%20name1)%3B%0A%20%20%20%20%20%20%20%20System.out.println(date%20%2B%20name1)%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20public%20String%20test2(Date%20date%2C%20String%20name)%20%7B%0A%20%20%20%20%20%20%20%20date%20%3D%20null%3B%0A%20%20%20%20%20%20%20%20name%20%3D%20%22my%20name%20is%20John%22%3B%0A%20%20%20%20%20%20%20%20double%20weight%20%3D%20130.5%3B%0A%20%20%20%20%20%20%20%20char%20gender%20%3D%20'M'%3B%0A%20%20%20%20%20%20%20%20return%20date%20%2B%20name%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%0ADELL%40Chris%20MINGW64%20%2Fd%2Fcode%2Fjavademo2023%2Ftarget%2Fclasses%2Fcom%2Fchris%2Fjvm%20(master)%0A%24%20javap%20-v%20LocalVariablesTest.class%20%0A......%0Apublic%20static%20void%20main(java.lang.String%5B%5D)%3B%0A%20%20%20%20descriptor%3A%20(%5BLjava%2Flang%2FString%3B)V%20%20--%20%E5%BD%A2%E5%8F%82%E6%98%AFString%E7%B1%BB%E5%9E%8B%E7%9A%84%E4%B8%80%E7%BB%B4%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%BF%94%E5%9B%9E%E5%80%BC%E4%B8%BAVoid%2C%20L%E4%B8%BA%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E7%9A%84%E6%84%8F%E6%80%9D%0A%20%20%20%20flags%3A%20ACC_PUBLIC%2C%20ACC_STATIC%09%09--%20%E8%AE%BF%E9%97%AE%E6%A0%87%E8%AF%86%E4%B8%BA%20public%20static%0A%20%20%20%20Code%3A%0A%20%20%20%20%20%20stack%3D2%2C%20locals%3D3%20--%20main%E6%96%B9%E6%B3%95%E4%B8%AD%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E9%95%BF%E5%BA%A6%2C%20args_size%3D1%0A%20%20%20%20%20%20%20%20%200%3A%20new%20%20%20%20%20%20%20%20%20%20%20%232%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20class%20com%2Fchris%2Fjvm%2FLocalVariablesTest%0A%20%20%20%20%20%20%20%20%203%3A%20dup%0A%20%20%20%20%20%20%20%20%204%3A%20invokespecial%20%233%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Method%20%22%3Cinit%3E%22%3A()V%0A%20%20%20%20%20%20%20%20%207%3A%20astore_1%0A%20%20%20%20%20%20%20%20%208%3A%20bipush%20%20%20%20%20%20%20%2010%0A%20%20%20%20%20%20%20%2010%3A%20istore_2%0A%20%20%20%20%20%20%20%2011%3A%20aload_1%0A%20%20%20%20%20%20%20%2012%3A%20invokevirtual%20%234%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Method%20test1%3A()V%0A%20%20%20%20%20%20%20%2015%3A%20return%0A%20%20%20%20%20%20LineNumberTable%3A%0A%20%20%20%20%20%20%20%20line%208%3A%200%0A%20%20%20%20%20%20%20%20line%209%3A%208%0A%20%20%20%20%20%20%20%20line%2010%3A%2011%0A%20%20%20%20%20%20%20%20line%2011%3A%2015%0A%20%20%20%20%20%20LocalVariableTable%3A%0A%20%20%20%20%20%20%20%20Start%20%20Length%20%20Slot%20%20Name%20%20%20Signature%0A%20%20%20%20%20%20%20%20%20%20%20%200%20%20%20%20%20%2016%20%20%20%20%200%20%20args%20%20%20%5BLjava%2Flang%2FString%3B%20%09%09%09%09--%20String%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%BD%A2%E5%8F%82%E5%8F%ABargs%0A%20%20%20%20%20%20%20%20%20%20%20%208%20%20%20%20%20%20%208%20%20%20%20%201%20%20test%20%20%20Lcom%2Fchris%2Fjvm%2FLocalVariablesTest%3B%20%20--%20%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8Ftest%0A%20%20%20%20%20%20%20%20%20%20%2011%20%20%20%20%20%20%205%20%20%20%20%202%20%20%20num%20%20%20I%20%09%09%09%09%09%09%09%09%09--%20int%E5%9E%8B%E7%9A%84%E4%B8%80%E4%B8%AA%E5%8F%98%E9%87%8Fnum%0A%60%60%60%0A%0A!%5B1e49d4bded8b339eb41c27cbefe5ac2f.png%5D(en-resource%3A%2F%2Fdatabase%2F1560%3A0)%0A%0A%0A%0A%23%23%23%23%23%20Slot%E7%9A%84%E9%87%8D%E5%A4%8D%E5%88%A9%E7%94%A8%0A%0A%3E%20%E6%A0%88%E5%B8%A7%E4%B8%AD%E7%9A%84%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E4%B8%AD%E7%9A%84slot%E7%9A%84%E4%BD%8D%E7%BD%AE%E6%98%AF%E5%8F%AF%E4%BB%A5%E9%87%8D%E5%A4%8D%E5%88%A9%E7%94%A8%E7%9A%84%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%80%E4%B8%AA%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%BF%87%E4%BA%86%E5%85%B6%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%8C%E9%82%A3%E4%B9%88%E5%9C%A8%E5%85%B6%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B9%8B%E5%90%8E%E7%94%B3%E6%98%8E%E7%9A%84%E6%96%B0%E7%9A%84%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E5%B0%B1%E5%BE%88%E6%9C%89%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%88%A9%E7%94%A8%E8%BF%87%E6%9C%9F%E7%9A%84%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E7%9A%84%E4%BD%8D%E7%BD%AE%EF%BC%8C%E4%BB%8E%E8%80%8C%E8%BE%BE%E5%88%B0%E8%8A%82%E7%9C%81%E8%B5%84%E6%BA%90%E7%9A%84%E7%9B%AE%E7%9A%84%E3%80%82%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20test4()%20%7B%0A%20%20%20%20int%20a%20%3D%200%3B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20int%20b%20%3D%200%3B%0A%20%20%20%20%20%20%20%20b%20%3D%20a%20%2B%201%3B%0A%20%20%20%20%7D%0A%20%20%20%20%2F%2F%20%E5%8F%98%E9%87%8Fc%E6%98%AF%E4%BD%BF%E7%94%A8%E5%89%8D%E9%9D%A2%E5%B7%B2%E7%BB%8F%E9%94%80%E6%AF%81%E7%9A%84%E5%8F%98%E9%87%8Fb%E6%89%80%E5%8D%A0%E6%8D%AE%E7%9A%84slot%E7%9A%84%E4%BD%8D%E7%BD%AE%0A%20%20%20%20int%20c%20%3D%20a%20%2B%201%3B%0A%7D%0A%60%60%60%0A%0A!%5B478f847804f71271318ab8f663c0394e.png%5D(en-resource%3A%2F%2Fdatabase%2F1562%3A0)%0A%0A%0A%0A%23%23%23%23%23%20%E5%8F%98%E9%87%8F%E7%9A%84%E5%88%86%E7%B1%BB%0A%0A-%20%E6%8C%89%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%88%86%EF%BC%9A%20%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%EF%BC%8C%E5%BC%95%E7%94%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%0A%0A-%20%E6%8C%89%E5%9C%A8%E7%B1%BB%E4%B8%AD%E7%9A%84%E5%A3%B0%E6%98%8E%E7%9A%84%E4%BD%8D%E7%BD%AE%E5%88%86%EF%BC%9A%0A%0A%20%20%20%20%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%EF%BC%9A%20%E4%BD%BF%E7%94%A8%E5%89%8D%EF%BC%8C%E9%83%BD%E7%BB%8F%E5%8E%86%E5%AE%88%E9%BB%98%E8%AE%A4%E5%88%9D%E5%A7%8B%E5%8C%96%E8%B5%8B%E5%80%BC%0A%0A%20%20%E2%80%8B%09%091.%20%E7%B1%BB%E5%8F%98%E9%87%8F%EF%BC%9A%E5%9C%A8linking%E7%9A%84prepare%E9%98%B6%E6%AE%B5%EF%BC%8C%E7%BB%99%E7%B1%BB%E5%8F%98%E9%87%8F%E9%BB%98%E8%AE%A4%E8%B5%8B%E5%80%BC%EF%BC%8C%E5%9C%A8initializing%E9%98%B6%E6%AE%B5%E7%BB%99%E7%B1%BB%E5%8F%98%E9%87%8F%E6%98%BE%E7%A4%BA%E8%B5%8B%E5%80%BC%E3%80%82%0A%0A%20%20%E2%80%8B%09%092.%20%E5%AE%9E%E4%BE%8B%E5%8F%98%E9%87%8F%EF%BC%9A%E9%9A%8F%E7%9D%80%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%88%9B%E5%BB%BA%EF%BC%8C%E4%BC%9A%E5%9C%A8%E5%A0%86%E7%A9%BA%E9%97%B4%E4%B8%AD%E5%88%86%E9%85%8D%E5%AE%9E%E4%BE%8B%E5%8F%98%E9%87%8F%E7%A9%BA%E9%97%B4%0A%0A%20%20%E2%80%8B%09%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%EF%BC%9A%E5%9C%A8%E4%BD%BF%E7%94%A8%E5%89%8D%E5%BF%85%E9%A1%BB%E8%BF%9B%E8%A1%8C%E6%98%BE%E5%BC%8F%E8%B5%8B%E5%80%BC%EF%BC%81%E5%90%A6%E5%88%99%EF%BC%8C%E7%BC%96%E8%AF%91%E4%B8%8D%E9%80%9A%E8%BF%87%E3%80%82%0A%0A%0A%0A%3E%20%E5%9C%A8%E6%A0%88%E5%B8%A7%E4%B8%AD%EF%BC%8C%E4%B8%8E%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98%E6%9C%80%E4%B8%BA%E5%AF%86%E5%88%87%E7%9A%84%E9%83%A8%E5%88%86%E5%B0%B1%E6%98%AF%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%EF%BC%8C%E5%9C%A8%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E6%97%B6%EF%BC%8CJVM%E4%BD%BF%E7%94%A8%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E5%AE%8C%E6%88%90%E6%96%B9%E6%B3%95%E7%9A%84%E4%BC%A0%E9%80%92%E3%80%82%0A%3E%0A%3E%20%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E4%B9%9F%E6%98%AF%E9%87%8D%E8%A6%81%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%A0%B9%E8%8A%82%E7%82%B9%EF%BC%8C%E5%8F%AA%E8%A6%81%E8%A2%AB%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E4%B8%AD%E7%9B%B4%E6%8E%A5%E6%88%96%E9%97%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E5%88%B0%E7%9A%84%E5%AF%B9%E8%B1%A1%E9%83%BD%E4%B8%8D%E4%BC%9A%E8%A2%AB%E5%9B%9E%E6%94%B6%0A%0A%0A%0A%23%23%23%23%23%20%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%20%5BOperand%20Stack%5D%0A%0A-%20%E6%AF%8F%E4%B8%80%E4%B8%AA%E7%8B%AC%E7%AB%8B%E7%9A%84%E6%A0%88%E5%B8%A7%E4%B8%AD%E9%99%A4%E4%BA%86%E5%8C%85%E5%90%AB%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E5%A4%96%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%80%E4%B8%AA%E5%85%88%E8%BF%9B%E5%90%8E%E5%87%BA%E7%9A%84%60%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%60%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%A7%B0%E4%B8%BA%60%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%A0%88%60%0A%0A-%20%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%BB%E8%A6%81%E7%94%A8%E4%BA%8E%E4%BF%9D%E5%AD%98%E8%AE%A1%E7%AE%97%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%9A%84%E4%B8%AD%E9%97%B4%E7%BB%93%E6%9E%9C%0A%0A-%20%E6%AF%8F%E4%B8%80%E4%B8%AA%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E9%83%BD%E6%9C%89%E4%B8%80%E4%B8%AA%E6%98%8E%E7%A1%AE%E7%9A%84%E6%A0%88%E6%B7%B1%E5%BA%A6%E7%94%A8%E4%BA%8E%E5%AD%98%E5%82%A8%E6%95%B0%E5%80%BC%EF%BC%8C%E5%85%B6%E6%89%80%E9%9C%80%E8%A6%81%E6%9C%80%E5%A4%A7%E6%B7%B1%E5%BA%A6%E5%9C%A8%E7%BC%96%E8%AF%91%E6%9C%9F%E5%B0%B1%E5%AE%9A%E5%A5%BD%E4%BA%86%EF%BC%8C%E4%BF%9D%E5%AD%98%E5%9C%A8%E6%96%B9%E6%B3%95%E7%9A%84Code%E5%B1%9E%E6%80%A7%E4%B8%AD%EF%BC%8C%E4%B8%BAmax_stack%E7%9A%84%E5%80%BC%0A%0A%20%201.%204%E4%B8%AA%E5%AD%97%E8%8A%82%E7%B1%BB%E5%9E%8B%E5%8D%A0%E7%94%A8%E4%B8%80%E4%B8%AA%E6%A0%88%E5%8D%95%E4%BD%8D%0A%0A%20%202.%208%E4%B8%AA%E5%AD%97%E8%8A%82%E7%B1%BB%E5%9E%8B%E5%8D%A0%E7%94%A8%E4%B8%A4%E4%B8%AA%E6%A0%88%E5%8D%95%E4%BD%8D%0A%0A-%20%E8%99%BD%E7%84%B6%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E6%98%AF%E4%B8%80%E4%B8%AA%E6%95%B0%E7%BB%84%EF%BC%8C%E4%BD%86%E6%98%AF%E4%B8%8D%E8%83%BD%E9%87%87%E7%94%A8%E8%AE%BF%E9%97%AE%E7%B4%A2%E5%BC%95%E7%9A%84%E6%96%B9%E5%BC%8F%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%EF%BC%8C%E8%80%8C%E5%8F%AA%E8%83%BD%E9%80%9A%E8%BF%87%E5%85%A5%E6%A0%88%5Bpush%5D%E5%92%8C%E5%87%BA%E6%A0%88%5Bpop%5D%E7%9A%84%E6%93%8D%E4%BD%9C%E6%9D%A5%E5%AE%8C%E6%88%90%E4%B8%80%E6%AC%A1%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%0A%0A%0A%0A%60%60%60java%0A%40Test%0Apublic%20void%20test1()%20%7B%0A%20%20%20%20byte%20i%20%3D%2015%3B%0A%20%20%20%20int%20j%20%3D%208%3B%0A%20%20%20%20int%20k%20%3D%20i%20%2B%20j%3B%0A%7D%0A%0A%2F%2F%20%E5%AD%97%E8%8A%82%E7%A0%81%E6%8C%87%E4%BB%A4%0A%200%20bipush%2015%20%20%2F%2F%E6%8A%8A15%E6%94%BE%E5%88%B0%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%0A%202%20istore_1%20%20%20%2F%2F%E6%8A%8A%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%E7%9A%8415%E5%87%BA%E6%A0%88%E6%94%BE%E5%88%B0%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E7%B4%A2%E5%BC%95%E4%B8%BA1%E7%9A%84%E4%BD%8D%E7%BD%AE%EF%BC%8C%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%BD%8D%E7%BD%AE%E5%B0%B1%E6%B2%A1%E6%9C%8915%E4%BA%86%0A%203%20bipush%208%09%20%20%2F%2F%E6%8A%8A8%E6%94%BE%E5%88%B0%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%0A%205%20istore_2%20%20%20%2F%2F%E6%8A%8A%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%E7%9A%848%E5%87%BA%E6%A0%88%E6%94%BE%E5%88%B0%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E7%B4%A2%E5%BC%95%E4%B8%BA2%E7%9A%84%E4%BD%8D%E7%BD%AE%EF%BC%8C%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%BD%8D%E7%BD%AE%E5%B0%B1%E6%B2%A1%E6%9C%898%E4%BA%86%0A%206%20iload_1%09%20%20%2F%2F%E6%8A%8A%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E4%B8%AD%E7%B4%A2%E5%BC%95%E4%B8%BA1%E7%9A%8415%E5%8F%96%E5%87%BA%E6%9D%A5%E6%94%BE%E5%88%B0%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%0A%207%20iload_2%09%20%20%2F%2F%E6%8A%8A%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E4%B8%AD%E7%B4%A2%E5%BC%95%E4%BD%8D%E7%BD%AE2%E7%9A%848%E5%8F%96%E5%87%BA%E6%9D%A5%E6%94%BE%E5%88%B0%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%0A%208%20iadd%20%20%20%20%20%20%20%2F%2F%E6%8A%8A%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%E7%9A%8415%E5%92%8C8%E5%87%BA%E6%A0%88%EF%BC%8C%E7%9B%B8%E5%8A%A0%E5%BE%97%E5%88%B023%E5%86%8D%E6%94%BE%E5%88%B0%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%0A%209%20istore_3%20%20%20%2F%2F%E6%8A%8A%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%B8%AD%E7%9A%8423%E5%87%BA%E6%A0%88%E6%94%BE%E5%88%B0%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%A1%A8%E7%B4%A2%E5%BC%95%E4%B8%BA3%E7%9A%84%E4%BD%8D%E7%BD%AE%EF%BC%8C%E6%93%8D%E4%BD%9C%E6%95%B0%E6%A0%88%E4%BD%8D%E7%BD%AE%E5%B0%B1%E6%B2%A1%E6%9C%8923%E4%BA%86%0A10%20return%0A%60%60%60%0A%0A

git lfs

创建时间:2024/4/16 7:08
更新时间:2024/4/16 7:08
作者:Chris

https://git-lfs.github.com/

C:\Program Files\Git\bin\Git LFS

cd 'D:\evernote-git'
git lfs install
git lsf track *
git add .gitattributes
git commit -m 'add gitattributes'
git push origin

git add -A
git commit -m 'update large file'
git push origin
https%3A%2F%2Fgit-lfs.github.com%2F%0A%0A%0A%60%60%60%0AC%3A%5CProgram%20Files%5CGit%5Cbin%5CGit%20LFS%0A%0Acd%20'D%3A%5Cevernote-git'%0Agit%20lfs%20install%0Agit%20lsf%20track%20*%0Agit%20add%20.gitattributes%0Agit%20commit%20-m%20'add%20gitattributes'%0Agit%20push%20origin%0A%0Agit%20add%20-A%0Agit%20commit%20-m%20'update%20large%20file'%0Agit%20push%20origin%0A%60%60%60

InheritableThreadLocal

创建时间:2024/5/26 14:04
更新时间:2024/5/26 14:05
作者:Chris

[toc

]

是什么

在 Java 多线程编程中,InheritableThreadLocal 类是一个重要的类,它提供了一种线程本地变量的机制,并且支持线程之间的继承。

通过 InheritableThreadLocal 类,程序员可以在多线程环境下轻松地实现线程间数据的传递,并且可以实现线程间数据的继承传递。

InheritableThreadLocal 类是 Java.lang 包中的一部分,它提供了一种线程本地变量的机制,并且支持线程之间的继承。

特性

  • 可以创建和管理线程本地变量。
  • 提供了 initialValue() 方法用于初始化线程本地变量的值。
  • 支持线程之间的继承,即子线程可以继承父线程中的线程本地变量。

怎么玩

private static final InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>(); //创建 InheritableThreadLocal 对象
threadLocal.set("value"); //设置线程本地变量的值
String value = threadLocal.get(); //获取线程本地变量的值
/**
 * 可以在父线程中设置线程本地变量的值,然后在子线程中获取这个值,从而实现线程之间数据的传递和共享。
 */
@Test
public void testInheritableThreadLocal01() throws InterruptedException {
    threadLocal.set("value");
    Thread thread = new Thread(() -> {
        String value = threadLocal.get();
        System.out.println("Value in child thread: " + value);
    });
    thread.start();
    TimeUnit.SECONDS.sleep(3);
}
/**
 * InheritableThreadLocal 类支持线程之间的继承,即子线程可以继承父线程中的线程本地变量。
 * 这意味着可以在父线程中设置线程本地变量的值,在子线程中直接获取到这个值。
 */
@Test
public void testInheritableThreadLocal02() {
    Thread parentThread = new Thread(() -> {
        threadLocal.set("value");
        Thread childThread = new Thread(() -> {
            String value = threadLocal.get();
            System.out.println("Value in child thread: " + value);
        });
        childThread.start();
    });
    parentThread.start();
}

最佳实践

注意线程安全性

在使用 InheritableThreadLocal 类时,要注意线程安全性。

尽管 InheritableThreadLocal 类提供了一种线程本地变量的机制,但是在多线程环境下仍然需要注意线程安全问题,尤其是在设置和获取线程本地变量的过程中。

避免内存泄漏

使用完毕的 InheritableThreadLocal 对象应该及时清理,以避免内存泄漏问题。尤其是在长时间运行的应用程序中,如果不及时清理 InheritableThreadLocal 对象,可能会导致内存泄漏和性能下降。

%5Btoc%5D%0A%23%23%20%E6%98%AF%E4%BB%80%E4%B9%88%0A%0A%3E%0A%3E%E5%9C%A8%20Java%20%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B%E4%B8%AD%EF%BC%8CInheritableThreadLocal%20%E7%B1%BB%E6%98%AF%E4%B8%80%E4%B8%AA%E9%87%8D%E8%A6%81%E7%9A%84%E7%B1%BB%EF%BC%8C%E5%AE%83%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E7%A7%8D%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%94%AF%E6%8C%81%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E7%9A%84%E7%BB%A7%E6%89%BF%E3%80%82%0A%3E%0A%3E%E9%80%9A%E8%BF%87%20InheritableThreadLocal%20%E7%B1%BB%EF%BC%8C%E7%A8%8B%E5%BA%8F%E5%91%98%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%8E%AF%E5%A2%83%E4%B8%8B%E8%BD%BB%E6%9D%BE%E5%9C%B0%E5%AE%9E%E7%8E%B0%E7%BA%BF%E7%A8%8B%E9%97%B4%E6%95%B0%E6%8D%AE%E7%9A%84%E4%BC%A0%E9%80%92%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%E7%BA%BF%E7%A8%8B%E9%97%B4%E6%95%B0%E6%8D%AE%E7%9A%84%E7%BB%A7%E6%89%BF%E4%BC%A0%E9%80%92%E3%80%82%0A%3E%0A%3EInheritableThreadLocal%20%E7%B1%BB%E6%98%AF%20Java.lang%20%E5%8C%85%E4%B8%AD%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%EF%BC%8C%E5%AE%83%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E7%A7%8D%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%94%AF%E6%8C%81%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E7%9A%84%E7%BB%A7%E6%89%BF%E3%80%82%0A%0A%0A%0A%23%23%20%E7%89%B9%E6%80%A7%0A%0A%3E-%20%E5%8F%AF%E4%BB%A5%E5%88%9B%E5%BB%BA%E5%92%8C%E7%AE%A1%E7%90%86%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E3%80%82%0A%3E-%20%E6%8F%90%E4%BE%9B%E4%BA%86%20initialValue()%20%E6%96%B9%E6%B3%95%E7%94%A8%E4%BA%8E%E5%88%9D%E5%A7%8B%E5%8C%96%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%E3%80%82%0A%3E-%20%E6%94%AF%E6%8C%81%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E7%9A%84%E7%BB%A7%E6%89%BF%EF%BC%8C%E5%8D%B3%E5%AD%90%E7%BA%BF%E7%A8%8B%E5%8F%AF%E4%BB%A5%E7%BB%A7%E6%89%BF%E7%88%B6%E7%BA%BF%E7%A8%8B%E4%B8%AD%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E3%80%82%0A%0A%23%23%20%E6%80%8E%E4%B9%88%E7%8E%A9%0A%0A%60%60%60java%0Aprivate%20static%20final%20InheritableThreadLocal%3CString%3E%20threadLocal%20%3D%20new%20InheritableThreadLocal%3C%3E()%3B%20%2F%2F%E5%88%9B%E5%BB%BA%20InheritableThreadLocal%20%E5%AF%B9%E8%B1%A1%0AthreadLocal.set(%22value%22)%3B%20%2F%2F%E8%AE%BE%E7%BD%AE%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%0AString%20value%20%3D%20threadLocal.get()%3B%20%2F%2F%E8%8E%B7%E5%8F%96%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%0A%60%60%60%0A%0A%0A%0A%60%60%60java%0A%2F**%0A%20*%20%E5%8F%AF%E4%BB%A5%E5%9C%A8%E7%88%B6%E7%BA%BF%E7%A8%8B%E4%B8%AD%E8%AE%BE%E7%BD%AE%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%EF%BC%8C%E7%84%B6%E5%90%8E%E5%9C%A8%E5%AD%90%E7%BA%BF%E7%A8%8B%E4%B8%AD%E8%8E%B7%E5%8F%96%E8%BF%99%E4%B8%AA%E5%80%BC%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%AE%9E%E7%8E%B0%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E6%95%B0%E6%8D%AE%E7%9A%84%E4%BC%A0%E9%80%92%E5%92%8C%E5%85%B1%E4%BA%AB%E3%80%82%0A%20*%2F%0A%40Test%0Apublic%20void%20testInheritableThreadLocal01()%20throws%20InterruptedException%20%7B%0A%20%20%20%20threadLocal.set(%22value%22)%3B%0A%20%20%20%20Thread%20thread%20%3D%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20String%20value%20%3D%20threadLocal.get()%3B%0A%20%20%20%20%20%20%20%20System.out.println(%22Value%20in%20child%20thread%3A%20%22%20%2B%20value)%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20thread.start()%3B%0A%20%20%20%20TimeUnit.SECONDS.sleep(3)%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%60%60%60java%0A%2F**%0A%20*%20InheritableThreadLocal%20%E7%B1%BB%E6%94%AF%E6%8C%81%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E7%9A%84%E7%BB%A7%E6%89%BF%EF%BC%8C%E5%8D%B3%E5%AD%90%E7%BA%BF%E7%A8%8B%E5%8F%AF%E4%BB%A5%E7%BB%A7%E6%89%BF%E7%88%B6%E7%BA%BF%E7%A8%8B%E4%B8%AD%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E3%80%82%0A%20*%20%E8%BF%99%E6%84%8F%E5%91%B3%E7%9D%80%E5%8F%AF%E4%BB%A5%E5%9C%A8%E7%88%B6%E7%BA%BF%E7%A8%8B%E4%B8%AD%E8%AE%BE%E7%BD%AE%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E5%80%BC%EF%BC%8C%E5%9C%A8%E5%AD%90%E7%BA%BF%E7%A8%8B%E4%B8%AD%E7%9B%B4%E6%8E%A5%E8%8E%B7%E5%8F%96%E5%88%B0%E8%BF%99%E4%B8%AA%E5%80%BC%E3%80%82%0A%20*%2F%0A%40Test%0Apublic%20void%20testInheritableThreadLocal02()%20%7B%0A%20%20%20%20Thread%20parentThread%20%3D%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20threadLocal.set(%22value%22)%3B%0A%20%20%20%20%20%20%20%20Thread%20childThread%20%3D%20new%20Thread(()%20-%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20String%20value%20%3D%20threadLocal.get()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22Value%20in%20child%20thread%3A%20%22%20%2B%20value)%3B%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20childThread.start()%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20parentThread.start()%3B%0A%7D%0A%60%60%60%0A%0A%0A%0A%23%23%20%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5%0A%0A%23%23%23%20%E6%B3%A8%E6%84%8F%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E6%80%A7%0A%0A%3E%20%E5%9C%A8%E4%BD%BF%E7%94%A8%20InheritableThreadLocal%20%E7%B1%BB%E6%97%B6%EF%BC%8C%E8%A6%81%E6%B3%A8%E6%84%8F%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E6%80%A7%E3%80%82%0A%3E%0A%3E%20%E5%B0%BD%E7%AE%A1%20InheritableThreadLocal%20%E7%B1%BB%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E7%A7%8D%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E4%BD%86%E6%98%AF%E5%9C%A8%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%8E%AF%E5%A2%83%E4%B8%8B%E4%BB%8D%E7%84%B6%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98%EF%BC%8C%E5%B0%A4%E5%85%B6%E6%98%AF%E5%9C%A8%E8%AE%BE%E7%BD%AE%E5%92%8C%E8%8E%B7%E5%8F%96%E7%BA%BF%E7%A8%8B%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E8%BF%87%E7%A8%8B%E4%B8%AD%E3%80%82%0A%0A%0A%0A%23%23%23%20%E9%81%BF%E5%85%8D%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%0A%0A%3E%E4%BD%BF%E7%94%A8%E5%AE%8C%E6%AF%95%E7%9A%84%20InheritableThreadLocal%20%E5%AF%B9%E8%B1%A1%E5%BA%94%E8%AF%A5%E5%8F%8A%E6%97%B6%E6%B8%85%E7%90%86%EF%BC%8C%E4%BB%A5%E9%81%BF%E5%85%8D%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E9%97%AE%E9%A2%98%E3%80%82%E5%B0%A4%E5%85%B6%E6%98%AF%E5%9C%A8%E9%95%BF%E6%97%B6%E9%97%B4%E8%BF%90%E8%A1%8C%E7%9A%84%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E4%B8%AD%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%8F%8A%E6%97%B6%E6%B8%85%E7%90%86%20InheritableThreadLocal%20%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%AF%BC%E8%87%B4%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E5%92%8C%E6%80%A7%E8%83%BD%E4%B8%8B%E9%99%8D%E3%80%82%0A%0A

Lua

创建时间:2024/9/14 22:00
更新时间:2024/9/14 23:40
作者:Chris

官方文档

https://www.lua.org/manual/5.4/

变量

  1. 使用local声名局部变量,只有在当前方法或者当前文件中使用

  2. 没有加local都是全局变量,可以以当前处理或者被引用的文件中使用

a=1
b=2
local a=1 
print(a,b)

没有被声名过的变量都是nil,这种变量只有一种值就是nil,相关于其它语言中的null

print(x) -- x没有被声名过
[14:45:35] nil
a,b,c=1,4
print(a,b,c) -- c没有被赋值
[14:47:59] 1	4	nil

类型

Lua里面所有的数字类型统一叫作number

a=0x11  --十六进制表示激动
b=2e10  --科学记数法
print(a,b)

[14:51:41] 17	20000000000.0
  1. 可以通过单引号或者双引号,声明一个字符类型变量
  2. 支持转义字符
  3. 支持多行文本 [[]]
  4. 连接两个字符串变量使用..
  5. 在字符串前端加#表示字符串的长度
  6. Lua里面的字符串可以包含任意数值
a='dsdfdfdf'
b="sdrfdwee3455455"
c=[[233re
fatfs.debug(fgfg
d
ddfdf
)]]
d=a..'-'..b
print(a,b,c)
print(d)
print(#c)

[15:01:58] dsdfdfdf	sdrfdwee3455455	233re
fatfs.debug(fgfg
d
ddfdf
)
[15:01:58] dsdfdfdf-sdrfdwee3455455
[15:08:18] 32

local s = string.char(0x30,0x31,0x32,0x33) --可以把ascii值变成字符串
print(s)
print(string.byte(s,2))	--获取s中的第2个字符的数字编码, 0x31的十进制就是49
[22:51:39] 49
[22:48:34] 0123
a=tostring(1233) -- 将数值转换成字符串
b=tonumber("23445") -- 将字符串转换成数值
c=tonumber("xccx") -- 如果转换失败结果是nil
print(a,b,c)

[15:05:53] 1233	23445	nil

运算符

print(a+b)
print(10^5) --输出10的5次方

[14:55:22] 20000000017.0
[14:55:22] 100000.0

Function

-- 声明一个函数printParams,有三个入参
function printParams(a,b,c)
    print(a,b,c)
end

printParams(1,'a') -- 调用时可以只传入两个参数,没有传入的参数值就是nil

-- 声明一个函数printParams2,有三个入参
printParams2 = function(a,b,c)
    print(a,b,c)
end

printParams2(3,4,'h')
result = printParams(1,2,3) -- 函数默认返回值为nil
print(result)

[16:02:51] 1	2	3
[16:02:51] nil


function func2(a,b,c) -- 函数可以返回一个值,也可以返回多个值
    return a,b
end

print(func2(1,2,3))

[16:07:04] 1	2

local i,j=func2(5,6,7); -- 可以把返回多个值按顺序赋值给不同的变量
print(i,j)

[16:09:54] 5	6

Table

t1={1,"adad",'ccedsd', function() end, 2^2, {1,2,3}} -- 声明一个table,类似于一个数组,但里面可以放多种类型的数据, table的下标是从1开始
print(t1[2]) -- 打印第2个元素
print(#t1) -- 打印table的长度
t1[#t1+1]='add-'..#t1+1  --给下标为#t1+1的元素赋值,相当于在最后新增一个元素
print(t1[#t1])

[16:34:20] adad
[16:34:20] 6
[16:34:20] add-7

table.insert(t1, 'add-2') -- 在table最后插入一个元素
table.insert(t1, 1, 'add-1') -- 在table指定位置插入一个元素,其它元素后移
print(t1[#t1],t1[1],t1[2])

[16:36:14] add-2	add-1	1

local s  = table.remove(t1, 1)  -- 移除tabl指定位置的元素,并将移除后的元素返回
print(s, t1[1])

[16:38:00] add-1	1
a = {
    a=1,
    b=2,
    c="sdsd",
    d=function() end,
    [";x"]=1234
}
print(a['a'], a["b"], a.c, a[";x"]) -- 可以通过下标获取下标对应的值,如果下标符合变量命名规范可以用.的方式引用,特殊字符下标只能用引号的方式访问

[17:02:22] 1	2	sdsd	1234

a['a1']='a1-001'; -- 新增一个字符下标为a1的元素度赋值
print(a.a1, a.a2) -- 不存的下标元素返回nil
[17:19:05] a1-001	nil
v_1=123
print(_G['v_1']) -- 声明的所有全局变量都在全局表_G中

[17:50:48] 123


print(_G['table'], _G['table']['insert']) -- table.insert 中的table其实也是一个全局变量,它有一个下标为insert的元素

[17:53:57] table: 0x10	function: 0x17a  -- table其实也是一个全局变量,它的类型为table,它有一个下标为insert的元素,类型为function

布尔值

  1. 在Lua中只有 false 和 nil 代表 假,其它都代表真

  2. 在Java里面0代表假,非0代表真,但在Lua里面0代表真因为它不是nil

bln_a = true
bln_b = false
print(bln_a, bln_b)
print(1>2,1<2,1>=2,1<=2,1==2,1~=2) -- ~= 为不等于

[17:59:37] true	false
[17:59:37] false	true	false	true	false	true

print(bln_a and bln_b, bln_a or bln_b, not bln_a, not bln_b) -- 与,或,非

[18:03:34] false	true	false	true

a=nil  -- false
b=0	-- true
print(a and b)
print(a or b)
print(not a)

[22:09:27] nil
[22:09:27] 0
[22:09:27] true
-- 可以看出,and或者or并不都返回ture或false,只有not返回true或false
-- 利用这一特征,可以用and或or来实现短路求值
print(b>10 and 'yes' or 'no') --如果b>10则返回yes,否则返回no

[22:18:12] no

分支判断

a=2
if a>10 then
    print("a>10")
else
    print("no")
end

[22:24:52] no

if a>10 then
    print("a>10")
elseif a<10 then
    print("a<10")
else
    print("a is equal to 10")    
end

[22:24:52] a<10


if 0 then
    print('0 is true')
else
    print('0 is false')    
end

[22:26:14] 0 is true

循环

for i=1,10 do --在循环中定义一个变量i,并给i定义初始值和结束值,变量i只有在循环中使用,出了循环就无法再使用了
    print(i)
end

[22:33:26] 1
[22:33:26] 2
[22:33:26] 3
[22:33:26] 4
[22:33:26] 5
[22:33:26] 6
[22:33:26] 7
[22:33:26] 8
[22:33:26] 9
[22:33:26] 10

for i=1,10,2 do  --在循环中定义一个变量i,并给i定义初始值,结束值和步长,每循环一次就会对i+2
    print(i)
end

[22:33:26] 1
[22:33:26] 3
[22:33:26] 5
[22:33:26] 7
[22:33:26] 9

for i=10,1,-1 do  --在循环中定义一个变量i,并给i定义初始值,结束值和步长,步长也可以是负值,每循环一次就会对i-1
    print(i)
end

[22:33:26] 10
[22:33:26] 9
[22:33:26] 8
[22:33:26] 7
[22:33:26] 6
[22:33:26] 5
[22:33:26] 4
[22:33:26] 3
[22:33:26] 2
[22:33:26] 1

for i=1,10 do --在循环中定义一个变量i,并给i定义初始值,结束值,并判断如果i=5时就退出循环
    print(i)
    if i==5 then break end
end

[22:33:26] 1
[22:33:26] 2
[22:33:26] 3
[22:33:26] 4
[22:33:26] 5
local n =10
while n>1 do
    print(n)
    n=n-1
end

[22:40:07] 10
[22:40:07] 9
[22:40:07] 8
[22:40:07] 7
[22:40:07] 6
[22:40:07] 5
[22:40:07] 4
[22:40:07] 3
[22:40:07] 2

local m=10
while m>0 do
    if m==5 then break end
    print(m)
    m=m-1
end

[22:44:09] 10
[22:44:09] 9
[22:44:09] 8
[22:44:09] 7
[22:44:09] 6
%5Btoc%5D%0A%23%23%20%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%0A%0Ahttps%3A%2F%2Fwww.lua.org%2Fmanual%2F5.4%2F%0A%0A%0A%23%23%20%E5%8F%98%E9%87%8F%0A%0A%3E%201.%20%E4%BD%BF%E7%94%A8local%E5%A3%B0%E5%90%8D%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%2C%E5%8F%AA%E6%9C%89%E5%9C%A8%E5%BD%93%E5%89%8D%E6%96%B9%E6%B3%95%E6%88%96%E8%80%85%E5%BD%93%E5%89%8D%E6%96%87%E4%BB%B6%E4%B8%AD%E4%BD%BF%E7%94%A8%0A%3E%0A%3E%202.%20%E6%B2%A1%E6%9C%89%E5%8A%A0local%E9%83%BD%E6%98%AF%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BB%A5%E5%BD%93%E5%89%8D%E5%A4%84%E7%90%86%E6%88%96%E8%80%85%E8%A2%AB%E5%BC%95%E7%94%A8%E7%9A%84%E6%96%87%E4%BB%B6%E4%B8%AD%E4%BD%BF%E7%94%A8%0A%0A%60%60%60lua%0Aa%3D1%0Ab%3D2%0Alocal%20a%3D1%20%0Aprint(a%2Cb)%0A%60%60%60%0A%0A%0A%0A-%20nil%0A%0A%3E%20%E6%B2%A1%E6%9C%89%E8%A2%AB%E5%A3%B0%E5%90%8D%E8%BF%87%E7%9A%84%E5%8F%98%E9%87%8F%E9%83%BD%E6%98%AFnil%2C%E8%BF%99%E7%A7%8D%E5%8F%98%E9%87%8F%E5%8F%AA%E6%9C%89%E4%B8%80%E7%A7%8D%E5%80%BC%E5%B0%B1%E6%98%AFnil%2C%E7%9B%B8%E5%85%B3%E4%BA%8E%E5%85%B6%E5%AE%83%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84null%0A%0A%60%60%60lua%0Aprint(x)%20--%20x%E6%B2%A1%E6%9C%89%E8%A2%AB%E5%A3%B0%E5%90%8D%E8%BF%87%0A%5B14%3A45%3A35%5D%20nil%0A%60%60%60%0A%0A%0A%0A-%20%E5%A4%9A%E9%87%8D%E8%B5%8B%E5%80%BC%0A%0A%60%60%60lua%0Aa%2Cb%2Cc%3D1%2C4%0Aprint(a%2Cb%2Cc)%20--%20c%E6%B2%A1%E6%9C%89%E8%A2%AB%E8%B5%8B%E5%80%BC%0A%5B14%3A47%3A59%5D%201%094%09nil%0A%60%60%60%0A%0A%23%23%20%E7%B1%BB%E5%9E%8B%0A%0A-%20number%E7%B1%BB%E5%9E%8B%0A%0ALua%E9%87%8C%E9%9D%A2%E6%89%80%E6%9C%89%E7%9A%84%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B%E7%BB%9F%E4%B8%80%E5%8F%AB%E4%BD%9Cnumber%0A%0A%60%60%60lua%0Aa%3D0x11%20%20--%E5%8D%81%E5%85%AD%E8%BF%9B%E5%88%B6%E8%A1%A8%E7%A4%BA%E6%BF%80%E5%8A%A8%0Ab%3D2e10%20%20--%E7%A7%91%E5%AD%A6%E8%AE%B0%E6%95%B0%E6%B3%95%0Aprint(a%2Cb)%0A%0A%5B14%3A51%3A41%5D%2017%0920000000000.0%0A%60%60%60%0A%0A%0A%0A-%20String%E7%B1%BB%E5%9E%8B%0A%0A%3E1.%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%8D%95%E5%BC%95%E5%8F%B7%E6%88%96%E8%80%85%E5%8F%8C%E5%BC%95%E5%8F%B7%EF%BC%8C%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%0A%3E2.%20%E6%94%AF%E6%8C%81%E8%BD%AC%E4%B9%89%E5%AD%97%E7%AC%A6%0A%3E3.%20%E6%94%AF%E6%8C%81%E5%A4%9A%E8%A1%8C%E6%96%87%E6%9C%AC%20%60%5B%5B%5D%5D%60%0A%3E4.%20%E8%BF%9E%E6%8E%A5%E4%B8%A4%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%98%E9%87%8F%E4%BD%BF%E7%94%A8%60..%60%0A%3E5.%20%E5%9C%A8%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%89%8D%E7%AB%AF%E5%8A%A0%60%23%60%E8%A1%A8%E7%A4%BA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E9%95%BF%E5%BA%A6%0A%3E6.%20Lua%E9%87%8C%E9%9D%A2%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%AF%E4%BB%A5%E5%8C%85%E5%90%AB%E4%BB%BB%E6%84%8F%E6%95%B0%E5%80%BC%0A%0A%60%60%60lua%0Aa%3D'dsdfdfdf'%0Ab%3D%22sdrfdwee3455455%22%0Ac%3D%5B%5B233re%0Afatfs.debug(fgfg%0Ad%0Addfdf%0A)%5D%5D%0Ad%3Da..'-'..b%0Aprint(a%2Cb%2Cc)%0Aprint(d)%0Aprint(%23c)%0A%0A%5B15%3A01%3A58%5D%20dsdfdfdf%09sdrfdwee3455455%09233re%0Afatfs.debug(fgfg%0Ad%0Addfdf%0A)%0A%5B15%3A01%3A58%5D%20dsdfdfdf-sdrfdwee3455455%0A%5B15%3A08%3A18%5D%2032%0A%0Alocal%20s%20%3D%20string.char(0x30%2C0x31%2C0x32%2C0x33)%20--%E5%8F%AF%E4%BB%A5%E6%8A%8Aascii%E5%80%BC%E5%8F%98%E6%88%90%E5%AD%97%E7%AC%A6%E4%B8%B2%0Aprint(s)%0Aprint(string.byte(s%2C2))%09--%E8%8E%B7%E5%8F%96s%E4%B8%AD%E7%9A%84%E7%AC%AC2%E4%B8%AA%E5%AD%97%E7%AC%A6%E7%9A%84%E6%95%B0%E5%AD%97%E7%BC%96%E7%A0%81%EF%BC%8C%200x31%E7%9A%84%E5%8D%81%E8%BF%9B%E5%88%B6%E5%B0%B1%E6%98%AF49%0A%5B22%3A51%3A39%5D%2049%0A%5B22%3A48%3A34%5D%200123%0A%60%60%60%0A%0A%0A%0A-%20%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%0A%0A%60%60%60lua%0Aa%3Dtostring(1233)%20--%20%E5%B0%86%E6%95%B0%E5%80%BC%E8%BD%AC%E6%8D%A2%E6%88%90%E5%AD%97%E7%AC%A6%E4%B8%B2%0Ab%3Dtonumber(%2223445%22)%20--%20%E5%B0%86%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E6%8D%A2%E6%88%90%E6%95%B0%E5%80%BC%0Ac%3Dtonumber(%22xccx%22)%20--%20%E5%A6%82%E6%9E%9C%E8%BD%AC%E6%8D%A2%E5%A4%B1%E8%B4%A5%E7%BB%93%E6%9E%9C%E6%98%AFnil%0Aprint(a%2Cb%2Cc)%0A%0A%5B15%3A05%3A53%5D%201233%0923445%09nil%0A%60%60%60%0A%0A%0A%0A%23%23%20%E8%BF%90%E7%AE%97%E7%AC%A6%0A%0A-%20%E7%AE%97%E6%95%B0%E8%BF%90%E7%AE%97%E7%AC%A6%0A%0A%60%60%60lua%0Aprint(a%2Bb)%0Aprint(10%5E5)%20--%E8%BE%93%E5%87%BA10%E7%9A%845%E6%AC%A1%E6%96%B9%0A%0A%5B14%3A55%3A22%5D%2020000000017.0%0A%5B14%3A55%3A22%5D%20100000.0%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%20Function%0A%0A%60%60%60lua%0A--%20%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0printParams%EF%BC%8C%E6%9C%89%E4%B8%89%E4%B8%AA%E5%85%A5%E5%8F%82%0Afunction%20printParams(a%2Cb%2Cc)%0A%20%20%20%20print(a%2Cb%2Cc)%0Aend%0A%0AprintParams(1%2C'a')%20--%20%E8%B0%83%E7%94%A8%E6%97%B6%E5%8F%AF%E4%BB%A5%E5%8F%AA%E4%BC%A0%E5%85%A5%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E6%B2%A1%E6%9C%89%E4%BC%A0%E5%85%A5%E7%9A%84%E5%8F%82%E6%95%B0%E5%80%BC%E5%B0%B1%E6%98%AFnil%0A%0A--%20%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0printParams2%EF%BC%8C%E6%9C%89%E4%B8%89%E4%B8%AA%E5%85%A5%E5%8F%82%0AprintParams2%20%3D%20function(a%2Cb%2Cc)%0A%20%20%20%20print(a%2Cb%2Cc)%0Aend%0A%0AprintParams2(3%2C4%2C'h')%0A%60%60%60%0A%0A%0A%0A%0A%0A%60%60%60lua%0Aresult%20%3D%20printParams(1%2C2%2C3)%20--%20%E5%87%BD%E6%95%B0%E9%BB%98%E8%AE%A4%E8%BF%94%E5%9B%9E%E5%80%BC%E4%B8%BAnil%0Aprint(result)%0A%0A%5B16%3A02%3A51%5D%201%092%093%0A%5B16%3A02%3A51%5D%20nil%0A%0A%0Afunction%20func2(a%2Cb%2Cc)%20--%20%E5%87%BD%E6%95%B0%E5%8F%AF%E4%BB%A5%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E5%80%BC%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E8%BF%94%E5%9B%9E%E5%A4%9A%E4%B8%AA%E5%80%BC%0A%20%20%20%20return%20a%2Cb%0Aend%0A%0Aprint(func2(1%2C2%2C3))%0A%0A%5B16%3A07%3A04%5D%201%092%0A%0Alocal%20i%2Cj%3Dfunc2(5%2C6%2C7)%3B%20--%20%E5%8F%AF%E4%BB%A5%E6%8A%8A%E8%BF%94%E5%9B%9E%E5%A4%9A%E4%B8%AA%E5%80%BC%E6%8C%89%E9%A1%BA%E5%BA%8F%E8%B5%8B%E5%80%BC%E7%BB%99%E4%B8%8D%E5%90%8C%E7%9A%84%E5%8F%98%E9%87%8F%0Aprint(i%2Cj)%0A%0A%5B16%3A09%3A54%5D%205%096%0A%60%60%60%0A%0A%0A%0A%23%23%20Table%0A%0A-%20%E6%95%B0%E5%AD%97%E4%B8%8B%E6%A0%87%E7%9A%84table%0A%0A%60%60%60lua%0At1%3D%7B1%2C%22adad%22%2C'ccedsd'%2C%20function()%20end%2C%202%5E2%2C%20%7B1%2C2%2C3%7D%7D%20--%20%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AAtable%EF%BC%8C%E7%B1%BB%E4%BC%BC%E4%BA%8E%E4%B8%80%E4%B8%AA%E6%95%B0%E7%BB%84%EF%BC%8C%E4%BD%86%E9%87%8C%E9%9D%A2%E5%8F%AF%E4%BB%A5%E6%94%BE%E5%A4%9A%E7%A7%8D%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%20table%E7%9A%84%E4%B8%8B%E6%A0%87%E6%98%AF%E4%BB%8E1%E5%BC%80%E5%A7%8B%0Aprint(t1%5B2%5D)%20--%20%E6%89%93%E5%8D%B0%E7%AC%AC2%E4%B8%AA%E5%85%83%E7%B4%A0%0Aprint(%23t1)%20--%20%E6%89%93%E5%8D%B0table%E7%9A%84%E9%95%BF%E5%BA%A6%0At1%5B%23t1%2B1%5D%3D'add-'..%23t1%2B1%20%20--%E7%BB%99%E4%B8%8B%E6%A0%87%E4%B8%BA%23t1%2B1%E7%9A%84%E5%85%83%E7%B4%A0%E8%B5%8B%E5%80%BC%EF%BC%8C%E7%9B%B8%E5%BD%93%E4%BA%8E%E5%9C%A8%E6%9C%80%E5%90%8E%E6%96%B0%E5%A2%9E%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%0Aprint(t1%5B%23t1%5D)%0A%0A%5B16%3A34%3A20%5D%20adad%0A%5B16%3A34%3A20%5D%206%0A%5B16%3A34%3A20%5D%20add-7%0A%0Atable.insert(t1%2C%20'add-2')%20--%20%E5%9C%A8table%E6%9C%80%E5%90%8E%E6%8F%92%E5%85%A5%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%0Atable.insert(t1%2C%201%2C%20'add-1')%20--%20%E5%9C%A8table%E6%8C%87%E5%AE%9A%E4%BD%8D%E7%BD%AE%E6%8F%92%E5%85%A5%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%EF%BC%8C%E5%85%B6%E5%AE%83%E5%85%83%E7%B4%A0%E5%90%8E%E7%A7%BB%0Aprint(t1%5B%23t1%5D%2Ct1%5B1%5D%2Ct1%5B2%5D)%0A%0A%5B16%3A36%3A14%5D%20add-2%09add-1%091%0A%0Alocal%20s%20%20%3D%20table.remove(t1%2C%201)%20%20--%20%E7%A7%BB%E9%99%A4tabl%E6%8C%87%E5%AE%9A%E4%BD%8D%E7%BD%AE%E7%9A%84%E5%85%83%E7%B4%A0%EF%BC%8C%E5%B9%B6%E5%B0%86%E7%A7%BB%E9%99%A4%E5%90%8E%E7%9A%84%E5%85%83%E7%B4%A0%E8%BF%94%E5%9B%9E%0Aprint(s%2C%20t1%5B1%5D)%0A%0A%5B16%3A38%3A00%5D%20add-1%091%0A%60%60%60%0A%0A%0A%0A-%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%8B%E6%A0%87%E7%9A%84table%0A%0A%60%60%60lua%0Aa%20%3D%20%7B%0A%20%20%20%20a%3D1%2C%0A%20%20%20%20b%3D2%2C%0A%20%20%20%20c%3D%22sdsd%22%2C%0A%20%20%20%20d%3Dfunction()%20end%2C%0A%20%20%20%20%5B%22%3Bx%22%5D%3D1234%0A%7D%0Aprint(a%5B'a'%5D%2C%20a%5B%22b%22%5D%2C%20a.c%2C%20a%5B%22%3Bx%22%5D)%20--%20%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E4%B8%8B%E6%A0%87%E8%8E%B7%E5%8F%96%E4%B8%8B%E6%A0%87%E5%AF%B9%E5%BA%94%E7%9A%84%E5%80%BC%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8B%E6%A0%87%E7%AC%A6%E5%90%88%E5%8F%98%E9%87%8F%E5%91%BD%E5%90%8D%E8%A7%84%E8%8C%83%E5%8F%AF%E4%BB%A5%E7%94%A8.%E7%9A%84%E6%96%B9%E5%BC%8F%E5%BC%95%E7%94%A8%EF%BC%8C%E7%89%B9%E6%AE%8A%E5%AD%97%E7%AC%A6%E4%B8%8B%E6%A0%87%E5%8F%AA%E8%83%BD%E7%94%A8%E5%BC%95%E5%8F%B7%E7%9A%84%E6%96%B9%E5%BC%8F%E8%AE%BF%E9%97%AE%0A%0A%5B17%3A02%3A22%5D%201%092%09sdsd%091234%0A%0Aa%5B'a1'%5D%3D'a1-001'%3B%20--%20%E6%96%B0%E5%A2%9E%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%8B%E6%A0%87%E4%B8%BAa1%E7%9A%84%E5%85%83%E7%B4%A0%E5%BA%A6%E8%B5%8B%E5%80%BC%0Aprint(a.a1%2C%20a.a2)%20--%20%E4%B8%8D%E5%AD%98%E7%9A%84%E4%B8%8B%E6%A0%87%E5%85%83%E7%B4%A0%E8%BF%94%E5%9B%9Enil%0A%5B17%3A19%3A05%5D%20a1-001%09nil%0A%60%60%60%0A%0A%0A%0A-%20%E5%85%A8%E5%B1%80%E8%A1%A8%20%60_G%60%0A%0A%60%60%60lua%0Av_1%3D123%0Aprint(_G%5B'v_1'%5D)%20--%20%E5%A3%B0%E6%98%8E%E7%9A%84%E6%89%80%E6%9C%89%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E9%83%BD%E5%9C%A8%E5%85%A8%E5%B1%80%E8%A1%A8_G%E4%B8%AD%0A%0A%5B17%3A50%3A48%5D%20123%0A%0A%0Aprint(_G%5B'table'%5D%2C%20_G%5B'table'%5D%5B'insert'%5D)%20--%20table.insert%20%E4%B8%AD%E7%9A%84table%E5%85%B6%E5%AE%9E%E4%B9%9F%E6%98%AF%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%EF%BC%8C%E5%AE%83%E6%9C%89%E4%B8%80%E4%B8%AA%E4%B8%8B%E6%A0%87%E4%B8%BAinsert%E7%9A%84%E5%85%83%E7%B4%A0%0A%0A%5B17%3A53%3A57%5D%20table%3A%200x10%09function%3A%200x17a%20%20--%20table%E5%85%B6%E5%AE%9E%E4%B9%9F%E6%98%AF%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%EF%BC%8C%E5%AE%83%E7%9A%84%E7%B1%BB%E5%9E%8B%E4%B8%BAtable%EF%BC%8C%E5%AE%83%E6%9C%89%E4%B8%80%E4%B8%AA%E4%B8%8B%E6%A0%87%E4%B8%BAinsert%E7%9A%84%E5%85%83%E7%B4%A0%EF%BC%8C%E7%B1%BB%E5%9E%8B%E4%B8%BAfunction%0A%60%60%60%0A%0A%0A%0A%23%23%20%E5%B8%83%E5%B0%94%E5%80%BC%0A%0A%3E%201.%20%E5%9C%A8Lua%E4%B8%AD%E5%8F%AA%E6%9C%89%20false%20%E5%92%8C%20nil%20%E4%BB%A3%E8%A1%A8%20%E5%81%87%EF%BC%8C%E5%85%B6%E5%AE%83%E9%83%BD%E4%BB%A3%E8%A1%A8%E7%9C%9F%0A%3E%0A%3E%202.%20%E5%9C%A8Java%E9%87%8C%E9%9D%A20%E4%BB%A3%E8%A1%A8%E5%81%87%EF%BC%8C%E9%9D%9E0%E4%BB%A3%E8%A1%A8%E7%9C%9F%EF%BC%8C%E4%BD%86%E5%9C%A8Lua%E9%87%8C%E9%9D%A20%E4%BB%A3%E8%A1%A8%E7%9C%9F%E5%9B%A0%E4%B8%BA%E5%AE%83%E4%B8%8D%E6%98%AFnil%0A%0A%60%60%60lua%0Abln_a%20%3D%20true%0Abln_b%20%3D%20false%0Aprint(bln_a%2C%20bln_b)%0Aprint(1%3E2%2C1%3C2%2C1%3E%3D2%2C1%3C%3D2%2C1%3D%3D2%2C1~%3D2)%20--%20~%3D%20%E4%B8%BA%E4%B8%8D%E7%AD%89%E4%BA%8E%0A%0A%5B17%3A59%3A37%5D%20true%09false%0A%5B17%3A59%3A37%5D%20false%09true%09false%09true%09false%09true%0A%0Aprint(bln_a%20and%20bln_b%2C%20bln_a%20or%20bln_b%2C%20not%20bln_a%2C%20not%20bln_b)%20--%20%E4%B8%8E%EF%BC%8C%E6%88%96%EF%BC%8C%E9%9D%9E%0A%0A%5B18%3A03%3A34%5D%20false%09true%09false%09true%0A%0A%60%60%60%0A%0A%0A%0A%60%60%60lua%0Aa%3Dnil%20%20--%20false%0Ab%3D0%09--%20true%0Aprint(a%20and%20b)%0Aprint(a%20or%20b)%0Aprint(not%20a)%0A%0A%5B22%3A09%3A27%5D%20nil%0A%5B22%3A09%3A27%5D%200%0A%5B22%3A09%3A27%5D%20true%0A--%20%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%87%BA%EF%BC%8Cand%E6%88%96%E8%80%85or%E5%B9%B6%E4%B8%8D%E9%83%BD%E8%BF%94%E5%9B%9Eture%E6%88%96false%2C%E5%8F%AA%E6%9C%89not%E8%BF%94%E5%9B%9Etrue%E6%88%96false%0A--%20%E5%88%A9%E7%94%A8%E8%BF%99%E4%B8%80%E7%89%B9%E5%BE%81%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%94%A8and%E6%88%96or%E6%9D%A5%E5%AE%9E%E7%8E%B0%E7%9F%AD%E8%B7%AF%E6%B1%82%E5%80%BC%0Aprint(b%3E10%20and%20'yes'%20or%20'no')%20--%E5%A6%82%E6%9E%9Cb%3E10%E5%88%99%E8%BF%94%E5%9B%9Eyes%2C%E5%90%A6%E5%88%99%E8%BF%94%E5%9B%9Eno%0A%0A%5B22%3A18%3A12%5D%20no%0A%60%60%60%0A%0A%0A%0A%0A%0A%23%23%20%E5%88%86%E6%94%AF%E5%88%A4%E6%96%AD%0A%0A%60%60%60lua%0Aa%3D2%0Aif%20a%3E10%20then%0A%20%20%20%20print(%22a%3E10%22)%0Aelse%0A%20%20%20%20print(%22no%22)%0Aend%0A%0A%5B22%3A24%3A52%5D%20no%0A%0Aif%20a%3E10%20then%0A%20%20%20%20print(%22a%3E10%22)%0Aelseif%20a%3C10%20then%0A%20%20%20%20print(%22a%3C10%22)%0Aelse%0A%20%20%20%20print(%22a%20is%20equal%20to%2010%22)%20%20%20%20%0Aend%0A%0A%5B22%3A24%3A52%5D%20a%3C10%0A%0A%0Aif%200%20then%0A%20%20%20%20print('0%20is%20true')%0Aelse%0A%20%20%20%20print('0%20is%20false')%20%20%20%20%0Aend%0A%0A%5B22%3A26%3A14%5D%200%20is%20true%0A%60%60%60%0A%0A%0A%0A%23%23%20%E5%BE%AA%E7%8E%AF%0A%0A%60%60%60lua%0Afor%20i%3D1%2C10%20do%20--%E5%9C%A8%E5%BE%AA%E7%8E%AF%E4%B8%AD%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E5%8F%98%E9%87%8Fi%EF%BC%8C%E5%B9%B6%E7%BB%99i%E5%AE%9A%E4%B9%89%E5%88%9D%E5%A7%8B%E5%80%BC%E5%92%8C%E7%BB%93%E6%9D%9F%E5%80%BC%EF%BC%8C%E5%8F%98%E9%87%8Fi%E5%8F%AA%E6%9C%89%E5%9C%A8%E5%BE%AA%E7%8E%AF%E4%B8%AD%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%87%BA%E4%BA%86%E5%BE%AA%E7%8E%AF%E5%B0%B1%E6%97%A0%E6%B3%95%E5%86%8D%E4%BD%BF%E7%94%A8%E4%BA%86%0A%20%20%20%20print(i)%0Aend%0A%0A%5B22%3A33%3A26%5D%201%0A%5B22%3A33%3A26%5D%202%0A%5B22%3A33%3A26%5D%203%0A%5B22%3A33%3A26%5D%204%0A%5B22%3A33%3A26%5D%205%0A%5B22%3A33%3A26%5D%206%0A%5B22%3A33%3A26%5D%207%0A%5B22%3A33%3A26%5D%208%0A%5B22%3A33%3A26%5D%209%0A%5B22%3A33%3A26%5D%2010%0A%0Afor%20i%3D1%2C10%2C2%20do%20%20--%E5%9C%A8%E5%BE%AA%E7%8E%AF%E4%B8%AD%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E5%8F%98%E9%87%8Fi%EF%BC%8C%E5%B9%B6%E7%BB%99i%E5%AE%9A%E4%B9%89%E5%88%9D%E5%A7%8B%E5%80%BC%EF%BC%8C%E7%BB%93%E6%9D%9F%E5%80%BC%E5%92%8C%E6%AD%A5%E9%95%BF%EF%BC%8C%E6%AF%8F%E5%BE%AA%E7%8E%AF%E4%B8%80%E6%AC%A1%E5%B0%B1%E4%BC%9A%E5%AF%B9i%2B2%0A%20%20%20%20print(i)%0Aend%0A%0A%5B22%3A33%3A26%5D%201%0A%5B22%3A33%3A26%5D%203%0A%5B22%3A33%3A26%5D%205%0A%5B22%3A33%3A26%5D%207%0A%5B22%3A33%3A26%5D%209%0A%0Afor%20i%3D10%2C1%2C-1%20do%20%20--%E5%9C%A8%E5%BE%AA%E7%8E%AF%E4%B8%AD%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E5%8F%98%E9%87%8Fi%EF%BC%8C%E5%B9%B6%E7%BB%99i%E5%AE%9A%E4%B9%89%E5%88%9D%E5%A7%8B%E5%80%BC%EF%BC%8C%E7%BB%93%E6%9D%9F%E5%80%BC%E5%92%8C%E6%AD%A5%E9%95%BF%EF%BC%8C%E6%AD%A5%E9%95%BF%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%98%AF%E8%B4%9F%E5%80%BC%EF%BC%8C%E6%AF%8F%E5%BE%AA%E7%8E%AF%E4%B8%80%E6%AC%A1%E5%B0%B1%E4%BC%9A%E5%AF%B9i-1%0A%20%20%20%20print(i)%0Aend%0A%0A%5B22%3A33%3A26%5D%2010%0A%5B22%3A33%3A26%5D%209%0A%5B22%3A33%3A26%5D%208%0A%5B22%3A33%3A26%5D%207%0A%5B22%3A33%3A26%5D%206%0A%5B22%3A33%3A26%5D%205%0A%5B22%3A33%3A26%5D%204%0A%5B22%3A33%3A26%5D%203%0A%5B22%3A33%3A26%5D%202%0A%5B22%3A33%3A26%5D%201%0A%0Afor%20i%3D1%2C10%20do%20--%E5%9C%A8%E5%BE%AA%E7%8E%AF%E4%B8%AD%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E5%8F%98%E9%87%8Fi%EF%BC%8C%E5%B9%B6%E7%BB%99i%E5%AE%9A%E4%B9%89%E5%88%9D%E5%A7%8B%E5%80%BC%EF%BC%8C%E7%BB%93%E6%9D%9F%E5%80%BC%EF%BC%8C%E5%B9%B6%E5%88%A4%E6%96%AD%E5%A6%82%E6%9E%9Ci%3D5%E6%97%B6%E5%B0%B1%E9%80%80%E5%87%BA%E5%BE%AA%E7%8E%AF%0A%20%20%20%20print(i)%0A%20%20%20%20if%20i%3D%3D5%20then%20break%20end%0Aend%0A%0A%5B22%3A33%3A26%5D%201%0A%5B22%3A33%3A26%5D%202%0A%5B22%3A33%3A26%5D%203%0A%5B22%3A33%3A26%5D%204%0A%5B22%3A33%3A26%5D%205%0A%60%60%60%0A%0A%0A%0A%0A%0A%60%60%60lua%0Alocal%20n%20%3D10%0Awhile%20n%3E1%20do%0A%20%20%20%20print(n)%0A%20%20%20%20n%3Dn-1%0Aend%0A%0A%5B22%3A40%3A07%5D%2010%0A%5B22%3A40%3A07%5D%209%0A%5B22%3A40%3A07%5D%208%0A%5B22%3A40%3A07%5D%207%0A%5B22%3A40%3A07%5D%206%0A%5B22%3A40%3A07%5D%205%0A%5B22%3A40%3A07%5D%204%0A%5B22%3A40%3A07%5D%203%0A%5B22%3A40%3A07%5D%202%0A%0Alocal%20m%3D10%0Awhile%20m%3E0%20do%0A%20%20%20%20if%20m%3D%3D5%20then%20break%20end%0A%20%20%20%20print(m)%0A%20%20%20%20m%3Dm-1%0Aend%0A%0A%5B22%3A44%3A09%5D%2010%0A%5B22%3A44%3A09%5D%209%0A%5B22%3A44%3A09%5D%208%0A%5B22%3A44%3A09%5D%207%0A%5B22%3A44%3A09%5D%206%0A%60%60%60%0A%0A

《矛盾论》

创建时间:2024/9/21 22:11
更新时间:2024/9/21 22:50

大千世界,事物变幻多端,令人眼花缭乱,犹如雾里看花,懵懵懂懂。

然而,有些人却自以为是,认为自己看清了世界,因为自己参与其中,亲身感受到了。

实则不然,待自己参与其中,处置问题时,才发现事情不是我们最初想像的那样简单。

那么,如何才能更准确的认清这个世界呢?

要想认清世界,靠个人摸索,不仅效率低下,还劳累耗时。如果借助工具,往往能达到事半功倍的效果。

《矛盾论》就为我们认清世界,提供了最好的工具。我将其中的核心思想提炼出十六个字,深入理解和把.   握这十六个字,就能拥有理清世界的洞察力。


一、对立统一

《矛盾论》开篇指出:

事物的矛盾法则,即对立统一的法则,是唯物辩证法的最根本的法则。

那么,什么是矛盾?

矛盾,是事物自身或事物之间,包含的既对立又统一的关系。

矛盾无处不在,无时不有,它既是事物内部的对立关系,也是事物之间的对立关系。这种对立关系既是对抗性的,也是统一性的。

也就是事物自身存在矛盾,事物之间存在矛盾,这种关系是既对立又统一的关系。

对立指的是矛盾的两个方面,存在的对立关系,

例如,上下,生死,失败成功等。

统一指的是矛盾的两个方面,存在的统一关系。

例如,没有上,也无所谓下,没有生,也无所谓死,没有失败,也无所谓成功等。

学习中,我们不仅要阅读,听讲,还要书写,表达,学习这件事就存在矛盾,输入与输出,被动与主动,学习中的输入与输出,既是对立的,又是统一的。


二、普遍特殊

矛盾具有普遍性和特殊性。

矛盾的普遍性

矛盾存在于一切事物的发展过程中。

无论是自然界,还是人类社会,又或者是思维领域,都存在着矛盾

事物的发展过程中都存在着矛盾。这些矛盾有可能是显性的,有可能是隐性的,他们都以一定的方式影响着事物的发展方向。

比如,在自然环境界中,动物与环境之间、动物种群内部,都存在着矛盾,这些矛盾推动了物种的进化。

在人类社会中,存在不同利益群体之间的矛盾推动着社会的发展。

在思维领域,新观点与旧观点之间的矛盾,推动着人们认识的发展。

每一事物的发展过程中存在着自始至终的矛盾运动

这表明矛盾贯穿于事物发展的过程中。

事物的发展就是一个产生矛盾,解决矛盾,又产生新的矛盾,又解决新的矛盾,这样不断循环的过程。

这样的矛盾运动,推动着事物的发展。

比如,从出生到成年的过程中,每一个人都会不断的遇到问题和挑战,这些问题和挑战往往呈现出一种矛盾的状态,也就是两种或多种,相互冲突的想法,需求和欲望等。

在这个过程中,人们就在不断的成长,包括身体的成长,还有智力的成长,认知水平的提升等。

比如,学走路的孩子,又想学走路,又担心摔跤。还有学习,又想学习,又担心学不会,等等。

矛盾的普遍性或绝对性的两个重要特征:横向上的广泛性和纵向上的持续性。这两个特征一起构成了矛盾推动事物发展的基本原则。


矛盾的特殊性

任何运动形式内部都包含着特殊的矛盾。

无论是自然界中的物理运动,还是人类社会中的生产活动,内部都包含着特殊的矛盾

这些特殊的矛盾推动着事物的运动变化和发展。

这种特殊性,就构成了一事物区别于他事物的特殊本质,也使不同的事物呈现各自独特的运动形式。

事物内部的,决定事物特殊运动方式的,特殊矛盾,构成了事物的特殊本质。

事物的本质是指事物本身所固有的,决定事物现状的根本属性。

也就是说,因为,不同事物内部存在着的,不同的特殊矛盾,才使得这些事物,在属性上,在现状上,在发展上,表现出各自的独特性。

特殊的矛盾就是我们认识和区分不同事物的重要依据。

学习的标志在于输出,没有输出谈不上学习,即学习要主动。


三、主要次要

复杂的事物的发展过程中,有许多的矛盾存在,其中必有一种矛盾是主要的矛盾,其它矛盾则为次要矛盾。

矛盾着的两方面中,必有一方面是主要的,它方面是次要的。

在复杂的事物的发展过程中,存在着许多的矛盾,并非单一的矛盾在起作用。这些矛盾相互交织,相互影响,共同促进事物的发展。在这些矛盾中,存在着一种主要的矛盾,对事物的发展起支配地位,对事物的发展起决定作用。

在矛盾着的两方面中,必有一方面是主要的,它方面是次要的。主要的方面也就是矛盾起主导作用的方面。

矛盾的主要方面,对事物的发展起主导作用,处于支配地位,决定事物的性质。

在实际中要准确的把握事物的性质,就需要深入分析矛盾,抓住主要矛盾的主要方面,了解主要方面在矛盾中的地位和作用。

次要方面处于从属地位,次要影响事物的性质,这种影响,是在主要方面的主导下进行的。

在解决矛盾时,我们就需要抓住主要矛盾的主要方面,同时也要注意次要方面,从而全面准确的把握事物的性质。

在抗日战争时期,中日民族矛盾上升为主要矛盾,这使得所有面临日本侵略的阶级、阶层、党派等有了团结起来的基础,从而形成抗日民族统一战线。


四、内因外因

矛盾还分为内部矛盾和外部矛盾,两者分别联系内因和外因,推动事物的发展。

内部矛盾,即内因,是指事物内部各个方面之间的矛盾。它是事物自身发展的内在动力,是事物存在和发展的根据。

外部矛盾,即外因,是指一事物与其他事物之间的矛盾。它是事物发展的外部原因,是事物存在和发展的条件。外部矛盾通过对内部矛盾的作用,引发事物自身内部矛盾的变化,从而推动事物的发展。需要注意的是,外因必须通过内因才能起作用。

以学习为例,一个人能否学有所成,最根本的因素在于自身的努力和学习方法,这是内因;而外部环境、机会、他人的帮助等,都是外因。

当外因作用于内因,内因有所变化,外因才起作用,学习的发展以内因为根据。

一个人的学习成果,主要取决于他的学习态度和方法,但外在的学习资源和反馈等外部因素,也会在一定程度上影响他的学习效果。

这能很好的解释,同班同学学习成绩差距明显的原因。

外因是条件,内因是根据,共同推动事物的发展。


《矛盾论》中的这十六个字,对立统一、普遍特殊、主要次要、内因外因,不仅揭示了世界的运行规律,也为我们提供了应对生活和工作挑战的有效方法。

通过深入理解和应用这些法则,我们能更准确地认识世界,从而在复杂的环境中找到解决问题的方案。

无论是在处理人际关系、学习上的困境还是工作中的挑战时,这些法则都能帮助我们更清晰地看待问题并做出明智的决策。


《矛盾论》的精髓

创建时间:2024/9/21 22:44
更新时间:2024/9/21 22:50
作者:Chris
来源:https://mp.weixin.qq.com/s?__biz=MzkyODQ2NTQwMw==&mid=2247485878&idx=1&sn=f8b25680b91e077a55472ece0c6872d8&chksm=c3dab2ca6f2f601010c5f030bbac8febb86be3c62205c05b768f964e5622bc3183ad599d0e0d&mpshare=1&scene=24&srcid=0920EvoUUcXm4KBDMw5LZDk9&sharer_shareinfo=df4c0f195cd9c44f35956712abb8536b&sharer_shareinfo_first=df4c0f195cd9c44f35956712abb8536b&key=daf9bdc5abc4e8d09eaf73d6db0bdac808e0e4a70244646dab301ac8c47affb6d1577bd8191232f152b48a85d6c56547ea56219d4ce9b32000ae31da7bf2fa3df5f94c656b06b5fbeaffc55e12cc094c0eba1e6c8ca973d7ea042c62574125ccb11540b7c55f68930b4ee45d1503192c91ee72f20c8d4dd1b223832e28b1d946&ascene=0&uin=MjAxNTE3NjAwNA%3D%3D&devicetype=Windows+11+x64&version=63090c0f&lang=en&countrycode=CN&exportkey=n_ChQIAhIQ3TzzQC8Tw5FbVOmZ9XGV2xLjAQIE97dBBAEAAAAAAPlOLHaT294AAAAOpnltbLcz9gKNyK89dVj0flw1NQQ4rgvSA3b479lDKCoCc7sBYEFu%2FpTMC1VG%2BD1lSaha6hTziGJeBv%2FZvr9qVpjHcMz4SCXokkA2MkANw3Fo%2FJ8BalGn%2Buj5WZ23A7tDWS8%2FyQOrbmztokZAhWB8jRm%2BaKMs%2B8Qh1taut%2FLlbt9NTLuoUS0tBB4pFSLEDJohOeju9wmt%2BUZ%2FtgdqjmaGCgsR3blVEA4sR41litEro7Wc3wI6hTHRKrrzGDU3HdSAn4alxzFhEF8WJa8T&acctmode=0&pass_ticket=SBINs609KPbeWDgQIzyu4F5vxSxIlxRDXK2X%2BDiHMaPw%2FP9RAqIE%2BdLUcYrujCVf&wx_header=1&fasttmpl_type=0&fasttmpl_fullversion=7392080-en_US-zip&fasttmpl_flag=1


《矛盾论》的精髓是什么?是矛盾的普遍性和特殊性的辩证统一的关系吗?是内因和外因的辩证统一的关系吗?是主要的矛盾和矛盾的主要方面吗?我的回答都不是,他们只是矛盾法则的重要组成部分,并不是《矛盾论》的精髓。
《矛盾论》论述的精髓在于具体问题具体分析,具问题具体解决
    讲到的矛盾法则即对立统一法则,都是让人们学会具体问题具体分析,具体问题具体解决。矛盾分析的越透彻,特殊的情况越明确,就能从根本上解决具体的问题。

    无论是论述内因和外因的相互关系,还是矛盾的普遍性和特殊性的辩证关系即共性和个性的关系,以及矛盾发展的不平衡性,都是为了指出分析事物发展的具体情况,再做具体的分析,得出具体的方案、政策、策略、计划等。四渡赤水为什么是毛泽东同志的得意之笔?就是在险象环生的形势下,根据当时当地的情况,遇到具体问题,做具体的分析,再给出具体的解决方案和策略,立即行动,马上去实践,很快得到结果,符合预期的结果就坚持下去,不符合预期的结果,马上根据具体情况,具体分析,给出具体行动计划,又在实践中检验和发展。每天遇到的都是不一样的情况和问题,都要做具体情况的分析,并且给出具体的行动计划和策略,又会马上实践去检验,得到结果。不这样做就处于被动地位,就会被消灭的危险,形势逼人。每天面对的都是死亡的考验,每天都有红军牺牲,少有迟疑就会全军覆没,这是最考验领导智慧的时刻,运用最成熟的思维就是具体问题,具体分析,给出具体的解决方案和策略,立马通过实践来检验和发展,形成完整的闭关流程,不断提高分析解决问题的能力。

    具体问题,具体分析,具体解决问题,是《矛盾论》的精髓,学习矛盾法则就要学会具体情况,具体分析,具体解决问题。我们生活中遇到的问题,都是具体的问题,中年失业?中年创业?中年人的压力?都是具体的问题,要做具体分析,给出具体的解决办法,再去勇敢的实践,检验这个办法的结果。


@Import

创建时间:2024/9/22 9:52
更新时间:2024/9/22 9:53
作者:Chris

IoC容器的扫描起点

@SpringBootApplication

想让一个类被扫描并实例化成Bean交给IoC容器托管,除了给那些类标注相关的注解(比如@Component)之外,还需要将其放在主类(也就是标注了@SpringBootApplication的类)所在的包或者其子包层级下,这样在IoC容器初始化时,我们的类才会被扫描到。

@SpringBootApplication事实上标注了IoC容器创建Bean时扫描的起点,不过@SpringBootApplication是一个复杂的复合注解

而事实上,真正起到标注扫描起点作用的注解是@ComponentScan,当该注解标注在一个类上时,这个类就会被标记为IoC容器的扫描起点

@ComponentScan

标注了@ComponentScan注解的类,IoC容器初始化时,就会递归扫描位于类所以的包中及其下所有子包中标注了相关注解(例如@Component@Service)的类,并将它们实例化为Bean放入IoC容器托管

无论是@ComponentScan还是@SpringBootApplication注解,都是可以指定扫描位置的

@SpringBootApplication(scanBasePackages = "com.chris.demo.mainmodule")
public class MainModuleApplication {
// ...
}

这表示启动程序时指定扫描软件包com.chris.demo.mainmodule中及其所有子包下对应的类,只不过平时大多数时候我们都缺省这个参数,这样默认情况下,@ComponentScan或者@SpringBootApplication就是以自身为起点向下扫描当前包以及所有的子包中的类了

当主功能中主类位于软件包com.chris.demo.mainmodule中,那么启动时就会扫描该软件包及其子包下的类,不可能说扫描到功能1中的软件包com.chris.demo.function.one

  1. 可以在@SpringBootApplication注解中指定scanBasePackages字段将两个子模块的包路径加进去就行了

  2. 使用@Import

@Import

  1. @Import注解通常标注在配置类上,它可以在IoC容器初始化当前配置类的同时,将其它的指定类也引入进来并初始化为Bean.
@Configuration
@Import(DemoFunction.class)
public class FunctionImportConfig {
}
  1. FunctionImportConfig是一个配置类,该类会在IoC容器初始化时被扫描并初始化为Bean,在IoC容器扫描这个FunctionImportConfig的同时,也会读取到它上面的@Import注解,而@Import注解中指定了类DemoFunction,这就可以使得DemoFunction类也被加入扫描的候选类,最终也被实例化为Bean并交给IoC容器.

  2. 无论被标注@Import的类放在哪里,主要这个类能被扫描到,且标注了@Configuration等注解、能被实例化为Bean,那么其上的@Import注解中指定的类也会被扫描以及初始化为Bean的候选

被导入的DemoFunction类也是有要求的,它必须是一个配置类,且分下面两种情况

  1. 被导入的DemoFunction@Configuration标注的类:Spring会将这个DemoFuntion配置类初始化为Bean并加载到IoC容器中,这意味着只有该配置类本身、以及其中显示声明的Bean才会被加载到容器中,其他未声明的bean则不会被加载

  2. 被导入的DemoFunction@ComponentScan标注的类:Spring则会在导入该配置类同时,还会根据@ComponentScan指定的扫描包路径,扫描其指定的全部包下对应的类(标注了@Component等等注解的)并初始化为Bean,默认则是将该类及其所在包的所有子包下的相关类初始化为Bean

  1. 功能模块1,该模块作为一个功能,不需要作为一个完整的Spring Boot应用程序启动,因此该模块中不需要主类,只编写起点配置类和功能代码(比如Service层的类)即可,删除功能模块1的全部依赖,然后只加一个spring-boot-starter作为一些注解的基本支持即可
package com.chris.demo.function.one;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan
public class FunctionOneApplication {
}


@Slf4j
@Service
public class FunctionOneService {
 @PostConstruct
 private void init() {
  log.info("功能1,启动!"); // 被初始化为Bean时打印一句话,让我们知道该类被扫描并且被初始化即可
 }
}
  1. 回到主模块,在其中将功能模块1以依赖形式引入

  1. 然后在主模块中创建一个配置类,使用@Import导入功能模块1中的扫描起点
package com.gitee.swsk33.mainmodule.config;

import com.chris.demo.function.one.FunctionOneApplication;
import com.chris.demo.function.two.FunctionTwoApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * 用于导入其它模块的配置,使得其它模块中的Bean也能够交给IoC托管
 */
@Configuration
@Import(FunctionOneApplication.class)
public class FunctionImportConfig {
}


  1. 事实上,@Import可以导入多个类,传入数组形式即可,这里我们只导入模块1的起点类

小结

  1. 首先初始化主模块中的配置类FunctionImportConfig,同时读取到该配置类上的@Import注解中指定的模块1中的类FunctionOneApplication

  2. 模块1中的类FunctionOneApplication@ComponentScan标注,因此新增扫描起点,将FunctionOneApplication所在的包及其所有子包也加入扫描路径

  3. 这样不仅仅主模块自身,还有模块1下所有标注了对应注解的类都被扫描并初始化为了Bean,并加入了IoC容器中

  4. 这样,我们就可以在主模块中,自动装配模块1中的类了

封装@Import注解

  1. @EnableAsync以及@EnableDiscoveryClient这些注解,都是基于@Import实现的,当我们给自己项目的主类或者某个配置类打上该注解时,就能够启用某些功能,反之对应功能不会加载。
  2. 定义一个注解类,然后在这个注解类上标注@Import注解,并在其中指定需要导入的类,比如功能1的扫描起点
package com.chris.demo.main.module.annotation;

import com.chris.demo.function.one.FunctionOneApplication;
import org.springframework.context.annotation.Import;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(FunctionOneApplication.class)
public @interface EnableFunctionOne {
}
  1. 可以删除之前主模块中的FunctionImportConfig,而是在主模块启动类上标注我们这个自定义注解,启动项目,可以达到相同的效果
  2. 这也说明Spring在扫描注解时是会递归解析注解的,当其扫描到读取到主类的@EnableFunctionOne时,也会读取到@EnableFunctionOne中的@Import注解,并获取要导入的类的信息,完成导入
  3. 还可以尝试将这个@EnableFunctionOne放在别的地方,比如某个配置类上,也可以起到一样的效果

动态导入

@Import中指定的类,可以有三种:

  • @Configuration或者@ComponentScan标注的配置类
  • 实现了ImportSelector接口的类
  • 实现了ImportBeanDefinitionRegistrar接口的类

ImportSelector

  1. ImportSelector接口是Spring中的一个扩展接口,用于动态地控制哪些配置类应该被导入。通过实现ImportSelector接口可以根据特定的条件或逻辑在运行时决定要导入的配置类。
  2. 这个接口定义了一个方法selectImports,该方法返回一个字符串数组,数组中就包含了需要导入的配置类的全限定类名。Spring在加载配置类时会调用selectImports方法,并根据方法返回的类名动态地导入对应的类并初始化为Bean.
  3. 需要注意的是:
  • 实现ImportSelector接口的类无需标注@Component等注解
  • 接口方法selectImports返回的需要导入的类,也无需一定要是配置类,而可以是任何标注了@Component等等相关Bean注解的类

应用程序初始化时,在加载FunctionImportConfig配置类时,读取@Import注解,而其中指定的类是一个实现了ImportSelector的类,那么这时Spring框架就会执行实现了ImportSelector的类中的接口方法selectImports,并获取其返回值,根据返回值指定的全限定类名引入相关的类,并初始化为Bean.

package com.chris.demo.main.module.selector;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

/**
 * 实现ImportSelector接口后,可在其中自定义条件决定是否导入特定的类
 */
public class DemoImportSelector implements ImportSelector {

 /**
  * 自定义导入某些类的逻辑
  *
  * @param importingClassMetadata 表示被标注@Import注解的类的元数据信息
  * @return 将需要导入的类的全限定名放在字符串数据返回,则会导入返回的数组中指定的类
  */
 @Override
 public String[] selectImports(AnnotationMetadata importingClassMetadata) {
  // 打印被标注@Import的类的元数据
  System.out.println("被标注@Import的类名:" + importingClassMetadata.getClassName());
  // 直接引入第一个和第二个功能的主类
  return new String[]{
    "com.chris.demo.function.one.FunctionOneApplication",
    "com.chris.demo.function.two.FunctionTwoApplication"
  };
 }

}

/**
 * 再创建一个配置类使用@Import导入上述实现了ImportSelector接口的类即可
*/
package com.chris.demo.mainm.odule.config;

import com.gitee.swsk33.mainmodule.selector.DemoImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;


/**
 * 指定导入实现了ImportSelector的类,然后就会根据其中selectImports方法返回值,实现自定义导入指定类
 */
@Configuration
@Import(DemoImportSelector.class)
public class FunctionImportConfig {
}

ImportBeanDefinitionRegistrar

  1. ImportBeanDefinitionRegistrar接口是Spring中的另一个扩展接口,它允许我们在运行时动态地注册BeanDefinition,从而实现更高级的配置管理。

  2. ImportSelector不同的是,ImportBeanDefinitionRegistrar不仅可以导入配置类,还可以动态地注册Bean定义.

  3. ImportBeanDefinitionRegistrar接口定义了一个方法registerBeanDefinitions,该方法接受两个参数:

  • AnnotationMetadata 用于获取当前类的注解信息
  • BeanDefinitionRegistry 用于注册Bean定义
package com.chris.demo.main.module.selector;

import com.gitee.swsk33.functionone.FunctionOneApplication;
import com.gitee.swsk33.functiontwo.FunctionTwoApplication;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

/**
 * 实现ImportBeanDefinitionRegistrar接口后,可在其中使用自定义的逻辑,实现动态地将对应类注册为Bean
 */
public class DemoImportSelector implements ImportBeanDefinitionRegistrar {

 /**
  * 定义一个自定义逻辑,在其中可以动态地将对应的类注册为Bean
  *
  * @param importingClassMetadata 标注了@Import注解的类的元数据
  * @param registry               用于将指定类注册到IoC容器
  */
 @Override
 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  // 注册两个功能模块中标注了@ComponentScan的类为Bean
  
  // 定义一个Bean定义对象,传入第一个模块的@ComponentScan配置类
  GenericBeanDefinition functionOneScanBean = new GenericBeanDefinition();
  functionOneScanBean.setBeanClass(FunctionOneApplication.class);
     
  // 表示第二个模块的Bean定义对象
  GenericBeanDefinition functionTwoScanBean = new GenericBeanDefinition();
  functionTwoScanBean.setBeanClass(FunctionTwoApplication.class);
     
  // 将两个定义对象进行注册,这样上述两个类就会被注册为Bean
  registry.registerBeanDefinition("functionOneComponentScan", functionOneScanBean);
  registry.registerBeanDefinition("functionTwoComponentScan", functionTwoScanBean);
 }

}

package com.chris.demo.main.module.config;

import com.chris.demo.main.module.selector.DemoImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;


/**
 * 指定导入实现了ImportSelector的类,然后就会根据其中selectImports方法返回值,实现自定义导入指定类
 */
@Configuration
@Import(DemoImportSelector.class)
public class FunctionImportConfig {
}

结合Spring Bean条件注解

可以借助Spring Bean的条件注解来通过配置或者其它方式来控制@Import是否触发生效。比如说在标注@Import的配置类上使用@ConditionalOnProperty注解

package com.chris.demo.main.module.config;

import com.chris.demo.functionone.FunctionOneApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * 用于导入其它模块的配置,使得其它模块中的Bean也能够交给IoC托管
 * 还可以借助Spring的条件注解例如@ConditionalOnProperty,实现通过配置或者其它条件动态控制这个配置类是否加载,进而实现控制@Import是否生效
 */
@Configuration
@Import(FunctionOneApplication.class)
@ConditionalOnProperty(prefix = "com.chris.demo.function-one", name = "enabled")
public class FunctionImportConfig {
}

// 通过application.properties控制是否导入功能模块1了
# 开启功能1
com.gitee.swsk33.function-one.enabled=true

总结

可见借助@Import注解,可以很方便地实现自定义导入对应的配置类,甚至是新增扫描起点,这对于我们Spring Boot模块化开发是一个有利的工具。

也可见该注解功能非常强大,可以通过实现对应接口方法,完成灵活地自定义导入。

%5Btoc%5D%0A%0A%23%23%20IoC%E5%AE%B9%E5%99%A8%E7%9A%84%E6%89%AB%E6%8F%8F%E8%B5%B7%E7%82%B9%0A%0A%23%23%23%20%60%40SpringBootApplication%60%0A%0A%3E%E6%83%B3%E8%AE%A9%E4%B8%80%E4%B8%AA%E7%B1%BB%E8%A2%AB%E6%89%AB%E6%8F%8F%E5%B9%B6%E5%AE%9E%E4%BE%8B%E5%8C%96%E6%88%90Bean%E4%BA%A4%E7%BB%99IoC%E5%AE%B9%E5%99%A8%E6%89%98%E7%AE%A1%EF%BC%8C%E9%99%A4%E4%BA%86%E7%BB%99%E9%82%A3%E4%BA%9B%E7%B1%BB%E6%A0%87%E6%B3%A8%E7%9B%B8%E5%85%B3%E7%9A%84%E6%B3%A8%E8%A7%A3%EF%BC%88%E6%AF%94%E5%A6%82%60%40Component%60%EF%BC%89%E4%B9%8B%E5%A4%96%EF%BC%8C%E8%BF%98%E9%9C%80%E8%A6%81%E5%B0%86%E5%85%B6%E6%94%BE%E5%9C%A8%E4%B8%BB%E7%B1%BB%EF%BC%88%E4%B9%9F%E5%B0%B1%E6%98%AF%E6%A0%87%E6%B3%A8%E4%BA%86%60%40SpringBootApplication%60%E7%9A%84%E7%B1%BB%EF%BC%89%E6%89%80%E5%9C%A8%E7%9A%84%E5%8C%85%E6%88%96%E8%80%85%E5%85%B6%E5%AD%90%E5%8C%85%E5%B1%82%E7%BA%A7%E4%B8%8B%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%9C%A8IoC%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%EF%BC%8C%E6%88%91%E4%BB%AC%E7%9A%84%E7%B1%BB%E6%89%8D%E4%BC%9A%E8%A2%AB%E6%89%AB%E6%8F%8F%E5%88%B0%E3%80%82%0A%3E%0A%3E%60%40SpringBootApplication%60%E4%BA%8B%E5%AE%9E%E4%B8%8A%E6%A0%87%E6%B3%A8%E4%BA%86IoC%E5%AE%B9%E5%99%A8%E5%88%9B%E5%BB%BABean%E6%97%B6%E6%89%AB%E6%8F%8F%E7%9A%84%E8%B5%B7%E7%82%B9%EF%BC%8C%E4%B8%8D%E8%BF%87%60%40SpringBootApplication%60%E6%98%AF%E4%B8%80%E4%B8%AA%E5%A4%8D%E6%9D%82%E7%9A%84%E5%A4%8D%E5%90%88%E6%B3%A8%E8%A7%A3%0A%3E%0A%3E%E8%80%8C%E4%BA%8B%E5%AE%9E%E4%B8%8A%EF%BC%8C%E7%9C%9F%E6%AD%A3%E8%B5%B7%E5%88%B0%E6%A0%87%E6%B3%A8%E6%89%AB%E6%8F%8F%E8%B5%B7%E7%82%B9%E4%BD%9C%E7%94%A8%E7%9A%84%E6%B3%A8%E8%A7%A3%E6%98%AF%60%40ComponentScan%60%EF%BC%8C%E5%BD%93%E8%AF%A5%E6%B3%A8%E8%A7%A3%E6%A0%87%E6%B3%A8%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%B1%BB%E4%B8%8A%E6%97%B6%EF%BC%8C%E8%BF%99%E4%B8%AA%E7%B1%BB%E5%B0%B1%E4%BC%9A%E8%A2%AB%E6%A0%87%E8%AE%B0%E4%B8%BAIoC%E5%AE%B9%E5%99%A8%E7%9A%84%E6%89%AB%E6%8F%8F%E8%B5%B7%E7%82%B9%0A%0A%0A%0A%23%23%23%20%60%40ComponentScan%60%0A%0A%3E%E6%A0%87%E6%B3%A8%E4%BA%86%60%40ComponentScan%60%E6%B3%A8%E8%A7%A3%E7%9A%84%E7%B1%BB%EF%BC%8CIoC%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%EF%BC%8C%E5%B0%B1%E4%BC%9A%E9%80%92%E5%BD%92%E6%89%AB%E6%8F%8F%E4%BD%8D%E4%BA%8E%E7%B1%BB%E6%89%80%E4%BB%A5%E7%9A%84%E5%8C%85%E4%B8%AD%E5%8F%8A%E5%85%B6%E4%B8%8B%E6%89%80%E6%9C%89%E5%AD%90%E5%8C%85%E4%B8%AD%E6%A0%87%E6%B3%A8%E4%BA%86%E7%9B%B8%E5%85%B3%E6%B3%A8%E8%A7%A3%EF%BC%88%E4%BE%8B%E5%A6%82%60%40Component%60%E3%80%81%60%40Service%60%EF%BC%89%E7%9A%84%E7%B1%BB%EF%BC%8C%E5%B9%B6%E5%B0%86%E5%AE%83%E4%BB%AC%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%BABean%E6%94%BE%E5%85%A5IoC%E5%AE%B9%E5%99%A8%E6%89%98%E7%AE%A1%0A%3E%0A%3E%E6%97%A0%E8%AE%BA%E6%98%AF%60%40ComponentScan%60%E8%BF%98%E6%98%AF%60%40SpringBootApplication%60%E6%B3%A8%E8%A7%A3%EF%BC%8C%E9%83%BD%E6%98%AF%E5%8F%AF%E4%BB%A5%E6%8C%87%E5%AE%9A%E6%89%AB%E6%8F%8F%E4%BD%8D%E7%BD%AE%E7%9A%84%0A%3E%0A%3E%60%60%60java%0A%3E%40SpringBootApplication(scanBasePackages%20%3D%20%22com.chris.demo.mainmodule%22)%0A%3Epublic%20class%20MainModuleApplication%20%7B%0A%3E%20%2F%2F%20...%0A%3E%7D%0A%3E%60%60%60%0A%3E%0A%3E%E8%BF%99%E8%A1%A8%E7%A4%BA%E5%90%AF%E5%8A%A8%E7%A8%8B%E5%BA%8F%E6%97%B6%E6%8C%87%E5%AE%9A%E6%89%AB%E6%8F%8F%E8%BD%AF%E4%BB%B6%E5%8C%85%60com.chris.demo.mainmodule%60%E4%B8%AD%E5%8F%8A%E5%85%B6%E6%89%80%E6%9C%89%E5%AD%90%E5%8C%85%E4%B8%8B%E5%AF%B9%E5%BA%94%E7%9A%84%E7%B1%BB%EF%BC%8C%E5%8F%AA%E4%B8%8D%E8%BF%87%E5%B9%B3%E6%97%B6%E5%A4%A7%E5%A4%9A%E6%95%B0%E6%97%B6%E5%80%99%E6%88%91%E4%BB%AC%E9%83%BD%E7%BC%BA%E7%9C%81%E8%BF%99%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%8C%E8%BF%99%E6%A0%B7%E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%60%40ComponentScan%60%E6%88%96%E8%80%85%60%40SpringBootApplication%60%E5%B0%B1%E6%98%AF%E4%BB%A5%E8%87%AA%E8%BA%AB%E4%B8%BA%E8%B5%B7%E7%82%B9%E5%90%91%E4%B8%8B%E6%89%AB%E6%8F%8F%E5%BD%93%E5%89%8D%E5%8C%85%E4%BB%A5%E5%8F%8A%E6%89%80%E6%9C%89%E7%9A%84%E5%AD%90%E5%8C%85%E4%B8%AD%E7%9A%84%E7%B1%BB%E4%BA%86%0A%0A%0A%0A%3E%E5%BD%93%E4%B8%BB%E5%8A%9F%E8%83%BD%E4%B8%AD%E4%B8%BB%E7%B1%BB%E4%BD%8D%E4%BA%8E%E8%BD%AF%E4%BB%B6%E5%8C%85%60com.chris.demo.mainmodule%60%E4%B8%AD%EF%BC%8C%E9%82%A3%E4%B9%88%E5%90%AF%E5%8A%A8%E6%97%B6%E5%B0%B1%E4%BC%9A%E6%89%AB%E6%8F%8F%E8%AF%A5%E8%BD%AF%E4%BB%B6%E5%8C%85%E5%8F%8A%E5%85%B6%E5%AD%90%E5%8C%85%E4%B8%8B%E7%9A%84%E7%B1%BB%EF%BC%8C%E4%B8%8D%E5%8F%AF%E8%83%BD%E8%AF%B4%E6%89%AB%E6%8F%8F%E5%88%B0%E5%8A%9F%E8%83%BD1%E4%B8%AD%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%60com.chris.demo.function.one%60%E6%97%B6%0A%3E%0A%3E1.%20%E5%8F%AF%E4%BB%A5%E5%9C%A8%60%40SpringBootApplication%60%E6%B3%A8%E8%A7%A3%E4%B8%AD%E6%8C%87%E5%AE%9A%60scanBasePackages%60%E5%AD%97%E6%AE%B5%E5%B0%86%E4%B8%A4%E4%B8%AA%E5%AD%90%E6%A8%A1%E5%9D%97%E7%9A%84%E5%8C%85%E8%B7%AF%E5%BE%84%E5%8A%A0%E8%BF%9B%E5%8E%BB%E5%B0%B1%E8%A1%8C%E4%BA%86%0A%3E%0A%3E2.%20%E4%BD%BF%E7%94%A8%60%40Import%60%0A%0A%0A%0A%23%23%20%60%40Import%60%0A%0A%3E1.%20%60%40Import%60%E6%B3%A8%E8%A7%A3%E9%80%9A%E5%B8%B8%E6%A0%87%E6%B3%A8%E5%9C%A8%E9%85%8D%E7%BD%AE%E7%B1%BB%E4%B8%8A%EF%BC%8C%E5%AE%83%E5%8F%AF%E4%BB%A5%E5%9C%A8IoC%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E5%BD%93%E5%89%8D%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%9A%84%E5%90%8C%E6%97%B6%EF%BC%8C%E5%B0%86%E5%85%B6%E5%AE%83%E7%9A%84%E6%8C%87%E5%AE%9A%E7%B1%BB%E4%B9%9F%E5%BC%95%E5%85%A5%E8%BF%9B%E6%9D%A5%E5%B9%B6%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean.%0A%3E%0A%3E%60%60%60java%0A%3E%40Configuration%0A%3E%40Import(DemoFunction.class)%0A%3Epublic%20class%20FunctionImportConfig%20%7B%0A%3E%7D%0A%3E%60%60%60%0A%3E%0A%3E2.%20%60FunctionImportConfig%60%E6%98%AF%E4%B8%80%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E8%AF%A5%E7%B1%BB%E4%BC%9A%E5%9C%A8IoC%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%E8%A2%AB%E6%89%AB%E6%8F%8F%E5%B9%B6%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean%EF%BC%8C%E5%9C%A8IoC%E5%AE%B9%E5%99%A8%E6%89%AB%E6%8F%8F%E8%BF%99%E4%B8%AA%60FunctionImportConfig%60%E7%9A%84%E5%90%8C%E6%97%B6%EF%BC%8C%E4%B9%9F%E4%BC%9A%E8%AF%BB%E5%8F%96%E5%88%B0%E5%AE%83%E4%B8%8A%E9%9D%A2%E7%9A%84%40Import%E6%B3%A8%E8%A7%A3%EF%BC%8C%E8%80%8C%60%40Import%60%E6%B3%A8%E8%A7%A3%E4%B8%AD%E6%8C%87%E5%AE%9A%E4%BA%86%E7%B1%BB%60DemoFunction%60%EF%BC%8C%E8%BF%99%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BD%BF%E5%BE%97%60DemoFunction%60%E7%B1%BB%E4%B9%9F%E8%A2%AB%E5%8A%A0%E5%85%A5%E6%89%AB%E6%8F%8F%E7%9A%84%E5%80%99%E9%80%89%E7%B1%BB%EF%BC%8C%E6%9C%80%E7%BB%88%E4%B9%9F%E8%A2%AB%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%BABean%E5%B9%B6%E4%BA%A4%E7%BB%99IoC%E5%AE%B9%E5%99%A8.%0A%3E%0A%3E3.%20%E6%97%A0%E8%AE%BA%E8%A2%AB%E6%A0%87%E6%B3%A8%60%40Import%60%E7%9A%84%E7%B1%BB%E6%94%BE%E5%9C%A8%E5%93%AA%E9%87%8C%EF%BC%8C%E4%B8%BB%E8%A6%81%E8%BF%99%E4%B8%AA%E7%B1%BB%E8%83%BD%E8%A2%AB%E6%89%AB%E6%8F%8F%E5%88%B0%EF%BC%8C%E4%B8%94%E6%A0%87%E6%B3%A8%E4%BA%86%60%40Configuration%60%E7%AD%89%E6%B3%A8%E8%A7%A3%E3%80%81%E8%83%BD%E8%A2%AB%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%BABean%EF%BC%8C%E9%82%A3%E4%B9%88%E5%85%B6%E4%B8%8A%E7%9A%84%60%40Import%60%E6%B3%A8%E8%A7%A3%E4%B8%AD%E6%8C%87%E5%AE%9A%E7%9A%84%E7%B1%BB%E4%B9%9F%E4%BC%9A%E8%A2%AB%E6%89%AB%E6%8F%8F%E4%BB%A5%E5%8F%8A%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean%E7%9A%84%E5%80%99%E9%80%89%0A%0A%0A%0A%3E%E8%A2%AB%E5%AF%BC%E5%85%A5%E7%9A%84%60DemoFunction%60%E7%B1%BB%E4%B9%9F%E6%98%AF%E6%9C%89%E8%A6%81%E6%B1%82%E7%9A%84%EF%BC%8C%E5%AE%83%E5%BF%85%E9%A1%BB%E6%98%AF%E4%B8%80%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E4%B8%94%E5%88%86%E4%B8%8B%E9%9D%A2%E4%B8%A4%E7%A7%8D%E6%83%85%E5%86%B5%0A%3E%0A%3E1.%20%E8%A2%AB%E5%AF%BC%E5%85%A5%E7%9A%84%60DemoFunction%60%E6%98%AF%60%40Configuration%60%E6%A0%87%E6%B3%A8%E7%9A%84%E7%B1%BB%EF%BC%9ASpring%E4%BC%9A%E5%B0%86%E8%BF%99%E4%B8%AA%60DemoFuntion%60%E9%85%8D%E7%BD%AE%E7%B1%BB%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean%E5%B9%B6%E5%8A%A0%E8%BD%BD%E5%88%B0IoC%E5%AE%B9%E5%99%A8%E4%B8%AD%EF%BC%8C%E8%BF%99%E6%84%8F%E5%91%B3%E7%9D%80%E5%8F%AA%E6%9C%89%E8%AF%A5%E9%85%8D%E7%BD%AE%E7%B1%BB%E6%9C%AC%E8%BA%AB%E3%80%81%E4%BB%A5%E5%8F%8A%E5%85%B6%E4%B8%AD%E6%98%BE%E7%A4%BA%E5%A3%B0%E6%98%8E%E7%9A%84Bean%E6%89%8D%E4%BC%9A%E8%A2%AB%E5%8A%A0%E8%BD%BD%E5%88%B0%E5%AE%B9%E5%99%A8%E4%B8%AD%EF%BC%8C%E5%85%B6%E4%BB%96%E6%9C%AA%E5%A3%B0%E6%98%8E%E7%9A%84bean%E5%88%99%E4%B8%8D%E4%BC%9A%E8%A2%AB%E5%8A%A0%E8%BD%BD%0A%3E%0A%3E2.%20%E8%A2%AB%E5%AF%BC%E5%85%A5%E7%9A%84%60DemoFunction%60%E6%98%AF%60%40ComponentScan%60%E6%A0%87%E6%B3%A8%E7%9A%84%E7%B1%BB%EF%BC%9ASpring%E5%88%99%E4%BC%9A%E5%9C%A8%E5%AF%BC%E5%85%A5%E8%AF%A5%E9%85%8D%E7%BD%AE%E7%B1%BB%E5%90%8C%E6%97%B6%EF%BC%8C%E8%BF%98%E4%BC%9A%E6%A0%B9%E6%8D%AE%60%40ComponentScan%60%E6%8C%87%E5%AE%9A%E7%9A%84%E6%89%AB%E6%8F%8F%E5%8C%85%E8%B7%AF%E5%BE%84%EF%BC%8C%E6%89%AB%E6%8F%8F%E5%85%B6%E6%8C%87%E5%AE%9A%E7%9A%84%E5%85%A8%E9%83%A8%E5%8C%85%E4%B8%8B%E5%AF%B9%E5%BA%94%E7%9A%84%E7%B1%BB%EF%BC%88%E6%A0%87%E6%B3%A8%E4%BA%86%60%40Component%60%E7%AD%89%E7%AD%89%E6%B3%A8%E8%A7%A3%E7%9A%84%EF%BC%89%E5%B9%B6%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean%EF%BC%8C%60%E9%BB%98%E8%AE%A4%E5%88%99%E6%98%AF%E5%B0%86%E8%AF%A5%E7%B1%BB%E5%8F%8A%E5%85%B6%E6%89%80%E5%9C%A8%E5%8C%85%E7%9A%84%E6%89%80%E6%9C%89%E5%AD%90%E5%8C%85%E4%B8%8B%E7%9A%84%E7%9B%B8%E5%85%B3%E7%B1%BB%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean%60%0A%0A%0A%0A%3E1.%20%E5%8A%9F%E8%83%BD%E6%A8%A1%E5%9D%971%EF%BC%8C%E8%AF%A5%E6%A8%A1%E5%9D%97%E4%BD%9C%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%8A%9F%E8%83%BD%EF%BC%8C%E4%B8%8D%E9%9C%80%E8%A6%81%E4%BD%9C%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%AE%8C%E6%95%B4%E7%9A%84Spring%20Boot%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E5%90%AF%E5%8A%A8%EF%BC%8C%E5%9B%A0%E6%AD%A4%E8%AF%A5%E6%A8%A1%E5%9D%97%E4%B8%AD%E4%B8%8D%E9%9C%80%E8%A6%81%E4%B8%BB%E7%B1%BB%EF%BC%8C%E5%8F%AA%E7%BC%96%E5%86%99%E8%B5%B7%E7%82%B9%E9%85%8D%E7%BD%AE%E7%B1%BB%E5%92%8C%E5%8A%9F%E8%83%BD%E4%BB%A3%E7%A0%81%EF%BC%88%E6%AF%94%E5%A6%82Service%E5%B1%82%E7%9A%84%E7%B1%BB%EF%BC%89%E5%8D%B3%E5%8F%AF%EF%BC%8C%E5%88%A0%E9%99%A4%E5%8A%9F%E8%83%BD%E6%A8%A1%E5%9D%971%E7%9A%84%E5%85%A8%E9%83%A8%E4%BE%9D%E8%B5%96%EF%BC%8C%E7%84%B6%E5%90%8E%E5%8F%AA%E5%8A%A0%E4%B8%80%E4%B8%AA%60spring-boot-starter%60%E4%BD%9C%E4%B8%BA%E4%B8%80%E4%BA%9B%E6%B3%A8%E8%A7%A3%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%94%AF%E6%8C%81%E5%8D%B3%E5%8F%AF%0A%3E%0A%3E%20%20%20%60%60%60java%0A%3E%20%20%20package%C2%A0com.chris.demo.function.one%3B%0A%3E%20%20%20%0A%3E%20%20%20import%C2%A0org.springframework.context.annotation.ComponentScan%3B%0A%3E%20%20%20%0A%3E%20%20%20%40ComponentScan%0A%3E%20%20%20public%C2%A0class%C2%A0FunctionOneApplication%C2%A0%7B%0A%3E%20%20%20%7D%0A%3E%20%20%20%0A%3E%20%20%20%0A%3E%20%20%20%40Slf4j%0A%3E%20%20%20%40Service%0A%3E%20%20%20public%C2%A0class%C2%A0FunctionOneService%C2%A0%7B%0A%3E%20%20%20%C2%A0%40PostConstruct%0A%3E%20%20%20%C2%A0private%C2%A0void%C2%A0init()%C2%A0%7B%0A%3E%20%20%20%C2%A0%C2%A0log.info(%22%E5%8A%9F%E8%83%BD1%EF%BC%8C%E5%90%AF%E5%8A%A8%EF%BC%81%22)%3B%20%2F%2F%20%E8%A2%AB%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean%E6%97%B6%E6%89%93%E5%8D%B0%E4%B8%80%E5%8F%A5%E8%AF%9D%EF%BC%8C%E8%AE%A9%E6%88%91%E4%BB%AC%E7%9F%A5%E9%81%93%E8%AF%A5%E7%B1%BB%E8%A2%AB%E6%89%AB%E6%8F%8F%E5%B9%B6%E4%B8%94%E8%A2%AB%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8D%B3%E5%8F%AF%0A%3E%20%20%20%C2%A0%7D%0A%3E%20%20%20%7D%0A%3E%20%20%20%60%60%60%0A%3E%0A%3E%20%20%20%0A%3E%0A%3E2.%20%E5%9B%9E%E5%88%B0%E4%B8%BB%E6%A8%A1%E5%9D%97%EF%BC%8C%E5%9C%A8%E5%85%B6%E4%B8%AD%E5%B0%86%E5%8A%9F%E8%83%BD%E6%A8%A1%E5%9D%971%E4%BB%A5%E4%BE%9D%E8%B5%96%E5%BD%A2%E5%BC%8F%E5%BC%95%E5%85%A5%0A%3E%0A%3E%20%20%20%60%60%60java%0A%3E%20%20%20%0A%3E%20%20%20%60%60%60%0A%3E%0A%3E%20%20%20%0A%3E%0A%3E3.%20%E7%84%B6%E5%90%8E%E5%9C%A8%E4%B8%BB%E6%A8%A1%E5%9D%97%E4%B8%AD%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E4%BD%BF%E7%94%A8%60%40Import%60%E5%AF%BC%E5%85%A5%E5%8A%9F%E8%83%BD%E6%A8%A1%E5%9D%971%E4%B8%AD%E7%9A%84%E6%89%AB%E6%8F%8F%E8%B5%B7%E7%82%B9%0A%3E%0A%3E%20%20%20%60%60%60java%0A%3E%20%20%20package%C2%A0com.gitee.swsk33.mainmodule.config%3B%0A%3E%20%20%20%0A%3E%20%20%20import%C2%A0com.chris.demo.function.one.FunctionOneApplication%3B%0A%3E%20%20%20import%C2%A0com.chris.demo.function.two.FunctionTwoApplication%3B%0A%3E%20%20%20import%C2%A0org.springframework.context.annotation.Configuration%3B%0A%3E%20%20%20import%C2%A0org.springframework.context.annotation.Import%3B%0A%3E%20%20%20%0A%3E%20%20%20%2F**%0A%3E%20%20%20%C2%A0*%C2%A0%E7%94%A8%E4%BA%8E%E5%AF%BC%E5%85%A5%E5%85%B6%E5%AE%83%E6%A8%A1%E5%9D%97%E7%9A%84%E9%85%8D%E7%BD%AE%EF%BC%8C%E4%BD%BF%E5%BE%97%E5%85%B6%E5%AE%83%E6%A8%A1%E5%9D%97%E4%B8%AD%E7%9A%84Bean%E4%B9%9F%E8%83%BD%E5%A4%9F%E4%BA%A4%E7%BB%99IoC%E6%89%98%E7%AE%A1%0A%3E%20%20%20%C2%A0*%2F%0A%3E%20%20%20%40Configuration%0A%3E%20%20%20%40Import(FunctionOneApplication.class)%0A%3E%20%20%20public%C2%A0class%C2%A0FunctionImportConfig%C2%A0%7B%0A%3E%20%20%20%7D%0A%3E%20%20%20%60%60%60%0A%3E%0A%3E%60%60%60java%0A%3E%0A%3E%0A%3E%60%60%60%0A%3E%0A%3E4.%20%E4%BA%8B%E5%AE%9E%E4%B8%8A%EF%BC%8C%40Import%E5%8F%AF%E4%BB%A5%E5%AF%BC%E5%85%A5%E5%A4%9A%E4%B8%AA%E7%B1%BB%EF%BC%8C%E4%BC%A0%E5%85%A5%E6%95%B0%E7%BB%84%E5%BD%A2%E5%BC%8F%E5%8D%B3%E5%8F%AF%EF%BC%8C%E8%BF%99%E9%87%8C%E6%88%91%E4%BB%AC%E5%8F%AA%E5%AF%BC%E5%85%A5%E6%A8%A1%E5%9D%971%E7%9A%84%E8%B5%B7%E7%82%B9%E7%B1%BB%0A%0A%0A%0A%E5%B0%8F%E7%BB%93%0A%0A%3E1.%20%E9%A6%96%E5%85%88%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BB%E6%A8%A1%E5%9D%97%E4%B8%AD%E7%9A%84%E9%85%8D%E7%BD%AE%E7%B1%BB%60FunctionImportConfig%60%EF%BC%8C%E5%90%8C%E6%97%B6%E8%AF%BB%E5%8F%96%E5%88%B0%E8%AF%A5%E9%85%8D%E7%BD%AE%E7%B1%BB%E4%B8%8A%E7%9A%84%60%40Import%60%E6%B3%A8%E8%A7%A3%E4%B8%AD%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%971%E4%B8%AD%E7%9A%84%E7%B1%BB%60FunctionOneApplication%60%0A%3E%0A%3E2.%20%E6%A8%A1%E5%9D%971%E4%B8%AD%E7%9A%84%E7%B1%BB%60FunctionOneApplication%60%E8%A2%AB%60%40ComponentScan%60%E6%A0%87%E6%B3%A8%EF%BC%8C%E5%9B%A0%E6%AD%A4**%E6%96%B0%E5%A2%9E%E6%89%AB%E6%8F%8F%E8%B5%B7%E7%82%B9**%EF%BC%8C%E5%B0%86%60FunctionOneApplication%60%E6%89%80%E5%9C%A8%E7%9A%84%E5%8C%85%E5%8F%8A%E5%85%B6%E6%89%80%E6%9C%89%E5%AD%90%E5%8C%85%E4%B9%9F%E5%8A%A0%E5%85%A5%E6%89%AB%E6%8F%8F%E8%B7%AF%E5%BE%84%0A%3E%0A%3E3.%20%E8%BF%99%E6%A0%B7%E4%B8%8D%E4%BB%85%E4%BB%85%E4%B8%BB%E6%A8%A1%E5%9D%97%E8%87%AA%E8%BA%AB%EF%BC%8C%E8%BF%98%E6%9C%89%E6%A8%A1%E5%9D%971%E4%B8%8B%E6%89%80%E6%9C%89%E6%A0%87%E6%B3%A8%E4%BA%86%E5%AF%B9%E5%BA%94%E6%B3%A8%E8%A7%A3%E7%9A%84%E7%B1%BB%E9%83%BD%E8%A2%AB%E6%89%AB%E6%8F%8F%E5%B9%B6%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BA%E4%BA%86Bean%EF%BC%8C%E5%B9%B6%E5%8A%A0%E5%85%A5%E4%BA%86IoC%E5%AE%B9%E5%99%A8%E4%B8%AD%0A%3E%0A%3E4.%20%E8%BF%99%E6%A0%B7%EF%BC%8C%E6%88%91%E4%BB%AC%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%B8%BB%E6%A8%A1%E5%9D%97%E4%B8%AD%EF%BC%8C%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%E6%A8%A1%E5%9D%971%E4%B8%AD%E7%9A%84%E7%B1%BB%E4%BA%86%0A%0A%0A%0A%0A%0A%23%23%20%E5%B0%81%E8%A3%85%40Import%E6%B3%A8%E8%A7%A3%0A%0A%0A%0A%3E1.%20%60%40EnableAsync%60%E4%BB%A5%E5%8F%8A%60%40EnableDiscoveryClient%60%E8%BF%99%E4%BA%9B%E6%B3%A8%E8%A7%A3%EF%BC%8C%E9%83%BD%E6%98%AF%E5%9F%BA%E4%BA%8E%60%40Import%60%E5%AE%9E%E7%8E%B0%E7%9A%84%EF%BC%8C%E5%BD%93%E6%88%91%E4%BB%AC%E7%BB%99%E8%87%AA%E5%B7%B1%E9%A1%B9%E7%9B%AE%E7%9A%84%E4%B8%BB%E7%B1%BB%E6%88%96%E8%80%85%E6%9F%90%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%E6%89%93%E4%B8%8A%E8%AF%A5%E6%B3%A8%E8%A7%A3%E6%97%B6%EF%BC%8C%E5%B0%B1%E8%83%BD%E5%A4%9F%E5%90%AF%E7%94%A8%E6%9F%90%E4%BA%9B%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%8F%8D%E4%B9%8B%E5%AF%B9%E5%BA%94%E5%8A%9F%E8%83%BD%E4%B8%8D%E4%BC%9A%E5%8A%A0%E8%BD%BD%E3%80%82%0A%3E2.%20%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E6%B3%A8%E8%A7%A3%E7%B1%BB%EF%BC%8C%E7%84%B6%E5%90%8E%E5%9C%A8%E8%BF%99%E4%B8%AA%E6%B3%A8%E8%A7%A3%E7%B1%BB%E4%B8%8A%E6%A0%87%E6%B3%A8%60%40Import%60%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%B9%B6%E5%9C%A8%E5%85%B6%E4%B8%AD%E6%8C%87%E5%AE%9A%E9%9C%80%E8%A6%81%E5%AF%BC%E5%85%A5%E7%9A%84%E7%B1%BB%EF%BC%8C%E6%AF%94%E5%A6%82%E5%8A%9F%E8%83%BD1%E7%9A%84%E6%89%AB%E6%8F%8F%E8%B5%B7%E7%82%B9%0A%3E%0A%3E%60%60%60java%0A%3Epackage%C2%A0com.chris.demo.main.module.annotation%3B%0A%3E%0A%3Eimport%C2%A0com.chris.demo.function.one.FunctionOneApplication%3B%0A%3Eimport%C2%A0org.springframework.context.annotation.Import%3B%0A%3E%0A%3Eimport%C2%A0java.lang.annotation.ElementType%3B%0A%3Eimport%C2%A0java.lang.annotation.Retention%3B%0A%3Eimport%C2%A0java.lang.annotation.RetentionPolicy%3B%0A%3Eimport%C2%A0java.lang.annotation.Target%3B%0A%3E%0A%3E%40Target(ElementType.TYPE)%0A%3E%40Retention(RetentionPolicy.RUNTIME)%0A%3E%40Import(FunctionOneApplication.class)%0A%3Epublic%C2%A0%40interface%C2%A0EnableFunctionOne%C2%A0%7B%0A%3E%7D%0A%3E%60%60%60%0A%3E%0A%3E3.%20%E5%8F%AF%E4%BB%A5%E5%88%A0%E9%99%A4%E4%B9%8B%E5%89%8D%E4%B8%BB%E6%A8%A1%E5%9D%97%E4%B8%AD%E7%9A%84%60FunctionImportConfig%60%EF%BC%8C%E8%80%8C%E6%98%AF%E5%9C%A8%E4%B8%BB%E6%A8%A1%E5%9D%97%E5%90%AF%E5%8A%A8%E7%B1%BB%E4%B8%8A%E6%A0%87%E6%B3%A8%E6%88%91%E4%BB%AC%E8%BF%99%E4%B8%AA%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3%2C%E5%90%AF%E5%8A%A8%E9%A1%B9%E7%9B%AE%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%BE%BE%E5%88%B0%E7%9B%B8%E5%90%8C%E7%9A%84%E6%95%88%E6%9E%9C%0A%3E4.%20%E8%BF%99%E4%B9%9F%E8%AF%B4%E6%98%8ESpring%E5%9C%A8%E6%89%AB%E6%8F%8F%E6%B3%A8%E8%A7%A3%E6%97%B6%E6%98%AF%E4%BC%9A%E9%80%92%E5%BD%92%E8%A7%A3%E6%9E%90%E6%B3%A8%E8%A7%A3%E7%9A%84%EF%BC%8C%E5%BD%93%E5%85%B6%E6%89%AB%E6%8F%8F%E5%88%B0%E8%AF%BB%E5%8F%96%E5%88%B0%E4%B8%BB%E7%B1%BB%E7%9A%84%60%40EnableFunctionOne%60%E6%97%B6%EF%BC%8C%E4%B9%9F%E4%BC%9A%E8%AF%BB%E5%8F%96%E5%88%B0%60%40EnableFunctionOne%60%E4%B8%AD%E7%9A%84%60%40Import%60%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%B9%B6%E8%8E%B7%E5%8F%96%E8%A6%81%E5%AF%BC%E5%85%A5%E7%9A%84%E7%B1%BB%E7%9A%84%E4%BF%A1%E6%81%AF%EF%BC%8C%E5%AE%8C%E6%88%90%E5%AF%BC%E5%85%A5%0A%3E5.%20%E8%BF%98%E5%8F%AF%E4%BB%A5%E5%B0%9D%E8%AF%95%E5%B0%86%E8%BF%99%E4%B8%AA%60%40EnableFunctionOne%60%E6%94%BE%E5%9C%A8%E5%88%AB%E7%9A%84%E5%9C%B0%E6%96%B9%EF%BC%8C%E6%AF%94%E5%A6%82%E6%9F%90%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%E4%B8%8A%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E8%B5%B7%E5%88%B0%E4%B8%80%E6%A0%B7%E7%9A%84%E6%95%88%E6%9E%9C%0A%0A%0A%0A%23%23%20%E5%8A%A8%E6%80%81%E5%AF%BC%E5%85%A5%0A%0A%3E%60%40Import%60%E4%B8%AD%E6%8C%87%E5%AE%9A%E7%9A%84%E7%B1%BB%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%9C%89%E4%B8%89%E7%A7%8D%EF%BC%9A%0A%3E%0A%3E-%20%60%40Configuration%60%E6%88%96%E8%80%85%60%40ComponentScan%60%E6%A0%87%E6%B3%A8%E7%9A%84%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%3E-%20%E5%AE%9E%E7%8E%B0%E4%BA%86%60ImportSelector%60%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%0A%3E-%20%E5%AE%9E%E7%8E%B0%E4%BA%86%60ImportBeanDefinitionRegistrar%60%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%0A%3E%0A%3E%0A%0A%0A%0A%23%23%23%20%60ImportSelector%60%0A%0A%3E1.%20%60ImportSelector%60%E6%8E%A5%E5%8F%A3%E6%98%AFSpring%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AA%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%8C%E7%94%A8%E4%BA%8E%E5%8A%A8%E6%80%81%E5%9C%B0%E6%8E%A7%E5%88%B6%E5%93%AA%E4%BA%9B%E9%85%8D%E7%BD%AE%E7%B1%BB%E5%BA%94%E8%AF%A5%E8%A2%AB%E5%AF%BC%E5%85%A5%E3%80%82%E9%80%9A%E8%BF%87%E5%AE%9E%E7%8E%B0%60ImportSelector%60%E6%8E%A5%E5%8F%A3%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E7%89%B9%E5%AE%9A%E7%9A%84%E6%9D%A1%E4%BB%B6%E6%88%96%E9%80%BB%E8%BE%91%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E5%86%B3%E5%AE%9A%E8%A6%81%E5%AF%BC%E5%85%A5%E7%9A%84%E9%85%8D%E7%BD%AE%E7%B1%BB%E3%80%82%0A%3E2.%20%E8%BF%99%E4%B8%AA%E6%8E%A5%E5%8F%A3%E5%AE%9A%E4%B9%89%E4%BA%86%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%60selectImports%60%EF%BC%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%95%B0%E7%BB%84%EF%BC%8C%E6%95%B0%E7%BB%84%E4%B8%AD%E5%B0%B1%E5%8C%85%E5%90%AB%E4%BA%86%E9%9C%80%E8%A6%81%E5%AF%BC%E5%85%A5%E7%9A%84%E9%85%8D%E7%BD%AE%E7%B1%BB%E7%9A%84%E5%85%A8%E9%99%90%E5%AE%9A%E7%B1%BB%E5%90%8D%E3%80%82Spring%E5%9C%A8%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE%E7%B1%BB%E6%97%B6%E4%BC%9A%E8%B0%83%E7%94%A8%60selectImports%60%E6%96%B9%E6%B3%95%EF%BC%8C%E5%B9%B6%E6%A0%B9%E6%8D%AE%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E7%9A%84%E7%B1%BB%E5%90%8D%E5%8A%A8%E6%80%81%E5%9C%B0%E5%AF%BC%E5%85%A5%E5%AF%B9%E5%BA%94%E7%9A%84%E7%B1%BB%E5%B9%B6%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean.%0A%3E3.%20%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%EF%BC%9A%0A%3E%20%20%20-%20%E5%AE%9E%E7%8E%B0%60ImportSelector%60%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%E6%97%A0%E9%9C%80%E6%A0%87%E6%B3%A8%60%40Component%60%E7%AD%89%E6%B3%A8%E8%A7%A3%0A%3E%20%20%20-%20%E6%8E%A5%E5%8F%A3%E6%96%B9%E6%B3%95%60selectImports%60%E8%BF%94%E5%9B%9E%E7%9A%84%E9%9C%80%E8%A6%81%E5%AF%BC%E5%85%A5%E7%9A%84%E7%B1%BB%EF%BC%8C%E4%B9%9F%E6%97%A0%E9%9C%80%E4%B8%80%E5%AE%9A%E8%A6%81%E6%98%AF%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E8%80%8C%E5%8F%AF%E4%BB%A5%E6%98%AF%E4%BB%BB%E4%BD%95%E6%A0%87%E6%B3%A8%E4%BA%86%60%40Component%60%E7%AD%89%E7%AD%89%E7%9B%B8%E5%85%B3Bean%E6%B3%A8%E8%A7%A3%E7%9A%84%E7%B1%BB%0A%0A%3E%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%EF%BC%8C%E5%9C%A8%E5%8A%A0%E8%BD%BD%60FunctionImportConfig%60%E9%85%8D%E7%BD%AE%E7%B1%BB%E6%97%B6%EF%BC%8C%E8%AF%BB%E5%8F%96%60%40Import%60%E6%B3%A8%E8%A7%A3%EF%BC%8C%E8%80%8C%E5%85%B6%E4%B8%AD%E6%8C%87%E5%AE%9A%E7%9A%84%E7%B1%BB%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%8E%B0%E4%BA%86%60ImportSelector%60%E7%9A%84%E7%B1%BB%EF%BC%8C%E9%82%A3%E4%B9%88%E8%BF%99%E6%97%B6Spring%E6%A1%86%E6%9E%B6%E5%B0%B1%E4%BC%9A%E6%89%A7%E8%A1%8C%E5%AE%9E%E7%8E%B0%E4%BA%86%60ImportSelector%60%E7%9A%84%E7%B1%BB%E4%B8%AD%E7%9A%84%E6%8E%A5%E5%8F%A3%E6%96%B9%E6%B3%95%60selectImports%60%EF%BC%8C%E5%B9%B6%E8%8E%B7%E5%8F%96%E5%85%B6%E8%BF%94%E5%9B%9E%E5%80%BC%EF%BC%8C%E6%A0%B9%E6%8D%AE%E8%BF%94%E5%9B%9E%E5%80%BC%E6%8C%87%E5%AE%9A%E7%9A%84%E5%85%A8%E9%99%90%E5%AE%9A%E7%B1%BB%E5%90%8D%E5%BC%95%E5%85%A5%E7%9B%B8%E5%85%B3%E7%9A%84%E7%B1%BB%EF%BC%8C%E5%B9%B6%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%BABean.%0A%3E%0A%3E%0A%3E%0A%3E%60%60%60java%0A%3Epackage%C2%A0com.chris.demo.main.module.selector%3B%0A%3E%0A%3Eimport%C2%A0org.springframework.context.annotation.ImportSelector%3B%0A%3Eimport%C2%A0org.springframework.core.type.AnnotationMetadata%3B%0A%3E%0A%3E%2F**%0A%3E%C2%A0*%C2%A0%E5%AE%9E%E7%8E%B0ImportSelector%E6%8E%A5%E5%8F%A3%E5%90%8E%EF%BC%8C%E5%8F%AF%E5%9C%A8%E5%85%B6%E4%B8%AD%E8%87%AA%E5%AE%9A%E4%B9%89%E6%9D%A1%E4%BB%B6%E5%86%B3%E5%AE%9A%E6%98%AF%E5%90%A6%E5%AF%BC%E5%85%A5%E7%89%B9%E5%AE%9A%E7%9A%84%E7%B1%BB%0A%3E%C2%A0*%2F%0A%3Epublic%C2%A0class%C2%A0DemoImportSelector%C2%A0implements%C2%A0ImportSelector%C2%A0%7B%0A%3E%0A%3E%C2%A0%2F**%0A%3E%C2%A0%C2%A0*%C2%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%BC%E5%85%A5%E6%9F%90%E4%BA%9B%E7%B1%BB%E7%9A%84%E9%80%BB%E8%BE%91%0A%3E%C2%A0%C2%A0*%0A%3E%C2%A0%C2%A0*%C2%A0%40param%C2%A0importingClassMetadata%C2%A0%E8%A1%A8%E7%A4%BA%E8%A2%AB%E6%A0%87%E6%B3%A8%40Import%E6%B3%A8%E8%A7%A3%E7%9A%84%E7%B1%BB%E7%9A%84%E5%85%83%E6%95%B0%E6%8D%AE%E4%BF%A1%E6%81%AF%0A%3E%C2%A0%C2%A0*%C2%A0%40return%C2%A0%E5%B0%86%E9%9C%80%E8%A6%81%E5%AF%BC%E5%85%A5%E7%9A%84%E7%B1%BB%E7%9A%84%E5%85%A8%E9%99%90%E5%AE%9A%E5%90%8D%E6%94%BE%E5%9C%A8%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%95%B0%E6%8D%AE%E8%BF%94%E5%9B%9E%EF%BC%8C%E5%88%99%E4%BC%9A%E5%AF%BC%E5%85%A5%E8%BF%94%E5%9B%9E%E7%9A%84%E6%95%B0%E7%BB%84%E4%B8%AD%E6%8C%87%E5%AE%9A%E7%9A%84%E7%B1%BB%0A%3E%C2%A0%C2%A0*%2F%0A%3E%C2%A0%40Override%0A%3E%C2%A0public%C2%A0String%5B%5D%C2%A0selectImports(AnnotationMetadata%C2%A0importingClassMetadata)%C2%A0%7B%0A%3E%C2%A0%C2%A0%2F%2F%C2%A0%E6%89%93%E5%8D%B0%E8%A2%AB%E6%A0%87%E6%B3%A8%40Import%E7%9A%84%E7%B1%BB%E7%9A%84%E5%85%83%E6%95%B0%E6%8D%AE%0A%3E%C2%A0%C2%A0System.out.println(%22%E8%A2%AB%E6%A0%87%E6%B3%A8%40Import%E7%9A%84%E7%B1%BB%E5%90%8D%EF%BC%9A%22%C2%A0%2B%C2%A0importingClassMetadata.getClassName())%3B%0A%3E%C2%A0%C2%A0%2F%2F%C2%A0%E7%9B%B4%E6%8E%A5%E5%BC%95%E5%85%A5%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%92%8C%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%8A%9F%E8%83%BD%E7%9A%84%E4%B8%BB%E7%B1%BB%0A%3E%C2%A0%C2%A0return%C2%A0new%C2%A0String%5B%5D%7B%0A%3E%C2%A0%C2%A0%C2%A0%C2%A0%22com.chris.demo.function.one.FunctionOneApplication%22%2C%0A%3E%C2%A0%C2%A0%C2%A0%C2%A0%22com.chris.demo.function.two.FunctionTwoApplication%22%0A%3E%C2%A0%C2%A0%7D%3B%0A%3E%C2%A0%7D%0A%3E%0A%3E%7D%0A%3E%0A%3E%2F**%0A%3E%C2%A0*%C2%A0%E5%86%8D%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%E4%BD%BF%E7%94%A8%40Import%E5%AF%BC%E5%85%A5%E4%B8%8A%E8%BF%B0%E5%AE%9E%E7%8E%B0%E4%BA%86ImportSelector%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%B1%BB%E5%8D%B3%E5%8F%AF%0A%3E*%2F%0A%3Epackage%C2%A0com.chris.demo.mainm.odule.config%3B%0A%3E%0A%3Eimport%C2%A0com.gitee.swsk33.mainmodule.selector.DemoImportSelector%3B%0A%3Eimport%C2%A0org.springframework.context.annotation.Configuration%3B%0A%3Eimport%C2%A0org.springframework.context.annotation.Import%3B%0A%3E%0A%3E%0A%3E%2F**%0A%3E%C2%A0*%C2%A0%E6%8C%87%E5%AE%9A%E5%AF%BC%E5%85%A5%E5%AE%9E%E7%8E%B0%E4%BA%86ImportSelector%E7%9A%84%E7%B1%BB%EF%BC%8C%E7%84%B6%E5%90%8E%E5%B0%B1%E4%BC%9A%E6%A0%B9%E6%8D%AE%E5%85%B6%E4%B8%ADselectImports%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%80%BC%EF%BC%8C%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%BC%E5%85%A5%E6%8C%87%E5%AE%9A%E7%B1%BB%0A%3E%C2%A0*%2F%0A%3E%40Configuration%0A%3E%40Import(DemoImportSelector.class)%0A%3Epublic%C2%A0class%C2%A0FunctionImportConfig%C2%A0%7B%0A%3E%7D%0A%3E%60%60%60%0A%3E%0A%3E%0A%0A%0A%0A%23%23%23%20%60ImportBeanDefinitionRegistrar%60%0A%0A%3E1.%20%60ImportBeanDefinitionRegistrar%60%E6%8E%A5%E5%8F%A3%E6%98%AFSpring%E4%B8%AD%E7%9A%84%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%AE%83%E5%85%81%E8%AE%B8%E6%88%91%E4%BB%AC%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E5%8A%A8%E6%80%81%E5%9C%B0%E6%B3%A8%E5%86%8C%60BeanDefinition%60%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%AE%9E%E7%8E%B0%E6%9B%B4%E9%AB%98%E7%BA%A7%E7%9A%84%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86%E3%80%82%0A%3E%0A%3E2.%20%E4%B8%8E%60ImportSelector%60%E4%B8%8D%E5%90%8C%E7%9A%84%E6%98%AF%EF%BC%8C%60ImportBeanDefinitionRegistrar%60%E4%B8%8D%E4%BB%85%E5%8F%AF%E4%BB%A5%E5%AF%BC%E5%85%A5%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E8%BF%98%E5%8F%AF%E4%BB%A5%E5%8A%A8%E6%80%81%E5%9C%B0%E6%B3%A8%E5%86%8CBean%E5%AE%9A%E4%B9%89.%0A%3E%0A%3E3.%20%60ImportBeanDefinitionRegistrar%60%E6%8E%A5%E5%8F%A3%E5%AE%9A%E4%B9%89%E4%BA%86%E4%B8%80%E4%B8%AA%E6%96%B9%E6%B3%95%60registerBeanDefinitions%60%EF%BC%8C%E8%AF%A5%E6%96%B9%E6%B3%95%E6%8E%A5%E5%8F%97%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%9A%0A%3E%0A%3E%20%20%20-%20%60AnnotationMetadata%60%20%E7%94%A8%E4%BA%8E%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%B1%BB%E7%9A%84%E6%B3%A8%E8%A7%A3%E4%BF%A1%E6%81%AF%0A%3E%20%20%20-%20%60BeanDefinitionRegistry%60%20%E7%94%A8%E4%BA%8E%E6%B3%A8%E5%86%8CBean%E5%AE%9A%E4%B9%89%0A%3E%0A%3E%20%20%20%60%60%60java%0A%3E%20%20%20package%C2%A0com.chris.demo.main.module.selector%3B%0A%3E%20%20%20%0A%3E%20%20%20import%C2%A0com.gitee.swsk33.functionone.FunctionOneApplication%3B%0A%3E%20%20%20import%C2%A0com.gitee.swsk33.functiontwo.FunctionTwoApplication%3B%0A%3E%20%20%20import%C2%A0org.springframework.beans.factory.support.BeanDefinitionRegistry%3B%0A%3E%20%20%20import%C2%A0org.springframework.beans.factory.support.GenericBeanDefinition%3B%0A%3E%20%20%20import%C2%A0org.springframework.context.annotation.ImportBeanDefinitionRegistrar%3B%0A%3E%20%20%20import%C2%A0org.springframework.core.type.AnnotationMetadata%3B%0A%3E%20%20%20%0A%3E%20%20%20%2F**%0A%3E%20%20%20%C2%A0*%C2%A0%E5%AE%9E%E7%8E%B0ImportBeanDefinitionRegistrar%E6%8E%A5%E5%8F%A3%E5%90%8E%EF%BC%8C%E5%8F%AF%E5%9C%A8%E5%85%B6%E4%B8%AD%E4%BD%BF%E7%94%A8%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E9%80%BB%E8%BE%91%EF%BC%8C%E5%AE%9E%E7%8E%B0%E5%8A%A8%E6%80%81%E5%9C%B0%E5%B0%86%E5%AF%B9%E5%BA%94%E7%B1%BB%E6%B3%A8%E5%86%8C%E4%B8%BABean%0A%3E%20%20%20%C2%A0*%2F%0A%3E%20%20%20public%C2%A0class%C2%A0DemoImportSelector%C2%A0implements%C2%A0ImportBeanDefinitionRegistrar%C2%A0%7B%0A%3E%20%20%20%0A%3E%20%20%20%C2%A0%2F**%0A%3E%20%20%20%C2%A0%C2%A0*%C2%A0%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E8%87%AA%E5%AE%9A%E4%B9%89%E9%80%BB%E8%BE%91%EF%BC%8C%E5%9C%A8%E5%85%B6%E4%B8%AD%E5%8F%AF%E4%BB%A5%E5%8A%A8%E6%80%81%E5%9C%B0%E5%B0%86%E5%AF%B9%E5%BA%94%E7%9A%84%E7%B1%BB%E6%B3%A8%E5%86%8C%E4%B8%BABean%0A%3E%20%20%20%C2%A0%C2%A0*%0A%3E%20%20%20%C2%A0%C2%A0*%C2%A0%40param%C2%A0importingClassMetadata%C2%A0%E6%A0%87%E6%B3%A8%E4%BA%86%40Import%E6%B3%A8%E8%A7%A3%E7%9A%84%E7%B1%BB%E7%9A%84%E5%85%83%E6%95%B0%E6%8D%AE%0A%3E%20%20%20%C2%A0%C2%A0*%C2%A0%40param%C2%A0registry%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E7%94%A8%E4%BA%8E%E5%B0%86%E6%8C%87%E5%AE%9A%E7%B1%BB%E6%B3%A8%E5%86%8C%E5%88%B0IoC%E5%AE%B9%E5%99%A8%0A%3E%20%20%20%C2%A0%C2%A0*%2F%0A%3E%20%20%20%C2%A0%40Override%0A%3E%20%20%20%C2%A0public%C2%A0void%C2%A0registerBeanDefinitions(AnnotationMetadata%C2%A0importingClassMetadata%2C%C2%A0BeanDefinitionRegistry%C2%A0registry)%C2%A0%7B%0A%3E%20%20%20%C2%A0%C2%A0%2F%2F%C2%A0%E6%B3%A8%E5%86%8C%E4%B8%A4%E4%B8%AA%E5%8A%9F%E8%83%BD%E6%A8%A1%E5%9D%97%E4%B8%AD%E6%A0%87%E6%B3%A8%E4%BA%86%40ComponentScan%E7%9A%84%E7%B1%BB%E4%B8%BABean%0A%3E%20%20%20%20%20%0A%3E%20%20%20%C2%A0%C2%A0%2F%2F%C2%A0%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AABean%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%EF%BC%8C%E4%BC%A0%E5%85%A5%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%A8%A1%E5%9D%97%E7%9A%84%40ComponentScan%E9%85%8D%E7%BD%AE%E7%B1%BB%0A%3E%20%20%20%C2%A0%C2%A0GenericBeanDefinition%C2%A0functionOneScanBean%C2%A0%3D%C2%A0new%C2%A0GenericBeanDefinition()%3B%0A%3E%20%20%20%C2%A0%C2%A0functionOneScanBean.setBeanClass(FunctionOneApplication.class)%3B%0A%3E%20%20%20%20%20%20%20%20%0A%3E%20%20%20%C2%A0%C2%A0%2F%2F%C2%A0%E8%A1%A8%E7%A4%BA%E7%AC%AC%E4%BA%8C%E4%B8%AA%E6%A8%A1%E5%9D%97%E7%9A%84Bean%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%0A%3E%20%20%20%C2%A0%C2%A0GenericBeanDefinition%C2%A0functionTwoScanBean%C2%A0%3D%C2%A0new%C2%A0GenericBeanDefinition()%3B%0A%3E%20%20%20%C2%A0%C2%A0functionTwoScanBean.setBeanClass(FunctionTwoApplication.class)%3B%0A%3E%20%20%20%20%20%20%20%20%0A%3E%20%20%20%C2%A0%C2%A0%2F%2F%C2%A0%E5%B0%86%E4%B8%A4%E4%B8%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E8%BF%9B%E8%A1%8C%E6%B3%A8%E5%86%8C%EF%BC%8C%E8%BF%99%E6%A0%B7%E4%B8%8A%E8%BF%B0%E4%B8%A4%E4%B8%AA%E7%B1%BB%E5%B0%B1%E4%BC%9A%E8%A2%AB%E6%B3%A8%E5%86%8C%E4%B8%BABean%0A%3E%20%20%20%C2%A0%C2%A0registry.registerBeanDefinition(%22functionOneComponentScan%22%2C%C2%A0functionOneScanBean)%3B%0A%3E%20%20%20%C2%A0%C2%A0registry.registerBeanDefinition(%22functionTwoComponentScan%22%2C%C2%A0functionTwoScanBean)%3B%0A%3E%20%20%20%C2%A0%7D%0A%3E%20%20%20%0A%3E%20%20%20%7D%0A%3E%20%20%20%0A%3E%20%20%20package%C2%A0com.chris.demo.main.module.config%3B%0A%3E%20%20%20%0A%3E%20%20%20import%C2%A0com.chris.demo.main.module.selector.DemoImportSelector%3B%0A%3E%20%20%20import%C2%A0org.springframework.context.annotation.Configuration%3B%0A%3E%20%20%20import%C2%A0org.springframework.context.annotation.Import%3B%0A%3E%20%20%20%0A%3E%20%20%20%0A%3E%20%20%20%2F**%0A%3E%20%20%20%C2%A0*%C2%A0%E6%8C%87%E5%AE%9A%E5%AF%BC%E5%85%A5%E5%AE%9E%E7%8E%B0%E4%BA%86ImportSelector%E7%9A%84%E7%B1%BB%EF%BC%8C%E7%84%B6%E5%90%8E%E5%B0%B1%E4%BC%9A%E6%A0%B9%E6%8D%AE%E5%85%B6%E4%B8%ADselectImports%E6%96%B9%E6%B3%95%E8%BF%94%E5%9B%9E%E5%80%BC%EF%BC%8C%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%BC%E5%85%A5%E6%8C%87%E5%AE%9A%E7%B1%BB%0A%3E%20%20%20%C2%A0*%2F%0A%3E%20%20%20%40Configuration%0A%3E%20%20%20%40Import(DemoImportSelector.class)%0A%3E%20%20%20public%C2%A0class%C2%A0FunctionImportConfig%C2%A0%7B%0A%3E%20%20%20%7D%0A%3E%20%20%20%60%60%60%0A%3E%0A%3E%20%20%20%0A%0A%0A%0A%0A%0A%23%23%20%E7%BB%93%E5%90%88Spring%20Bean%E6%9D%A1%E4%BB%B6%E6%B3%A8%E8%A7%A3%0A%0A%3E%E5%8F%AF%E4%BB%A5%E5%80%9F%E5%8A%A9Spring%20Bean%E7%9A%84%E6%9D%A1%E4%BB%B6%E6%B3%A8%E8%A7%A3%E6%9D%A5%E9%80%9A%E8%BF%87%E9%85%8D%E7%BD%AE%E6%88%96%E8%80%85%E5%85%B6%E5%AE%83%E6%96%B9%E5%BC%8F%E6%9D%A5%E6%8E%A7%E5%88%B6%60%40Import%60%E6%98%AF%E5%90%A6%E8%A7%A6%E5%8F%91%E7%94%9F%E6%95%88%E3%80%82%E6%AF%94%E5%A6%82%E8%AF%B4%E5%9C%A8%E6%A0%87%E6%B3%A8%60%40Import%60%E7%9A%84%E9%85%8D%E7%BD%AE%E7%B1%BB%E4%B8%8A%E4%BD%BF%E7%94%A8%60%40ConditionalOnProperty%60%E6%B3%A8%E8%A7%A3%0A%3E%0A%3E%60%60%60java%0A%3Epackage%C2%A0com.chris.demo.main.module.config%3B%0A%3E%0A%3Eimport%C2%A0com.chris.demo.functionone.FunctionOneApplication%3B%0A%3Eimport%C2%A0org.springframework.boot.autoconfigure.condition.ConditionalOnProperty%3B%0A%3Eimport%C2%A0org.springframework.context.annotation.Configuration%3B%0A%3Eimport%C2%A0org.springframework.context.annotation.Import%3B%0A%3E%0A%3E%2F**%0A%3E%C2%A0*%C2%A0%E7%94%A8%E4%BA%8E%E5%AF%BC%E5%85%A5%E5%85%B6%E5%AE%83%E6%A8%A1%E5%9D%97%E7%9A%84%E9%85%8D%E7%BD%AE%EF%BC%8C%E4%BD%BF%E5%BE%97%E5%85%B6%E5%AE%83%E6%A8%A1%E5%9D%97%E4%B8%AD%E7%9A%84Bean%E4%B9%9F%E8%83%BD%E5%A4%9F%E4%BA%A4%E7%BB%99IoC%E6%89%98%E7%AE%A1%0A%3E%C2%A0*%C2%A0%E8%BF%98%E5%8F%AF%E4%BB%A5%E5%80%9F%E5%8A%A9Spring%E7%9A%84%E6%9D%A1%E4%BB%B6%E6%B3%A8%E8%A7%A3%E4%BE%8B%E5%A6%82%40ConditionalOnProperty%EF%BC%8C%E5%AE%9E%E7%8E%B0%E9%80%9A%E8%BF%87%E9%85%8D%E7%BD%AE%E6%88%96%E8%80%85%E5%85%B6%E5%AE%83%E6%9D%A1%E4%BB%B6%E5%8A%A8%E6%80%81%E6%8E%A7%E5%88%B6%E8%BF%99%E4%B8%AA%E9%85%8D%E7%BD%AE%E7%B1%BB%E6%98%AF%E5%90%A6%E5%8A%A0%E8%BD%BD%EF%BC%8C%E8%BF%9B%E8%80%8C%E5%AE%9E%E7%8E%B0%E6%8E%A7%E5%88%B6%40Import%E6%98%AF%E5%90%A6%E7%94%9F%E6%95%88%0A%3E%C2%A0*%2F%0A%3E%40Configuration%0A%3E%40Import(FunctionOneApplication.class)%0A%3E%40ConditionalOnProperty(prefix%C2%A0%3D%C2%A0%22com.chris.demo.function-one%22%2C%C2%A0name%C2%A0%3D%C2%A0%22enabled%22)%0A%3Epublic%C2%A0class%C2%A0FunctionImportConfig%C2%A0%7B%0A%3E%7D%0A%3E%0A%3E%2F%2F%20%E9%80%9A%E8%BF%87application.properties%E6%8E%A7%E5%88%B6%E6%98%AF%E5%90%A6%E5%AF%BC%E5%85%A5%E5%8A%9F%E8%83%BD%E6%A8%A1%E5%9D%971%E4%BA%86%0A%3E%23%C2%A0%E5%BC%80%E5%90%AF%E5%8A%9F%E8%83%BD1%0A%3Ecom.gitee.swsk33.function-one.enabled%3Dtrue%0A%3E%60%60%60%0A%3E%0A%3E%0A%0A%0A%0A%23%23%20%E6%80%BB%E7%BB%93%0A%0A%3E%E5%8F%AF%E8%A7%81%E5%80%9F%E5%8A%A9%60%40Import%60%E6%B3%A8%E8%A7%A3%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%BE%88%E6%96%B9%E4%BE%BF%E5%9C%B0%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%BC%E5%85%A5%E5%AF%B9%E5%BA%94%E7%9A%84%E9%85%8D%E7%BD%AE%E7%B1%BB%EF%BC%8C%E7%94%9A%E8%87%B3%E6%98%AF%E6%96%B0%E5%A2%9E%E6%89%AB%E6%8F%8F%E8%B5%B7%E7%82%B9%EF%BC%8C%E8%BF%99%E5%AF%B9%E4%BA%8E%E6%88%91%E4%BB%ACSpring%20Boot%E6%A8%A1%E5%9D%97%E5%8C%96%E5%BC%80%E5%8F%91%E6%98%AF%E4%B8%80%E4%B8%AA%E6%9C%89%E5%88%A9%E7%9A%84%E5%B7%A5%E5%85%B7%E3%80%82%0A%3E%0A%3E%E4%B9%9F%E5%8F%AF%E8%A7%81%E8%AF%A5%E6%B3%A8%E8%A7%A3%E5%8A%9F%E8%83%BD%E9%9D%9E%E5%B8%B8%E5%BC%BA%E5%A4%A7%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E5%AE%9E%E7%8E%B0%E5%AF%B9%E5%BA%94%E6%8E%A5%E5%8F%A3%E6%96%B9%E6%B3%95%EF%BC%8C%E5%AE%8C%E6%88%90%E7%81%B5%E6%B4%BB%E5%9C%B0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%BC%E5%85%A5%E3%80%82%0A%0A